You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

308 lines
10 KiB

#!/usr/bin/env python
# encoding: utf-8
# Ali Sabil, 2007
import os.path, shutil
import Task, Runner, Utils, Logs, Build, Node, Options
from TaskGen import extension, after, before
EXT_VALA = ['.vala', '.gs']
class valac_task(Task.Task):
vars = ("VALAC", "VALAC_VERSION", "VALAFLAGS")
before = ("cc", "cxx")
def run(self):
env = self.env
inputs = [a.srcpath(env) for a in self.inputs]
valac = env['VALAC']
vala_flags = env.get_flat('VALAFLAGS')
top_src = self.generator.bld.srcnode.abspath()
top_bld = self.generator.bld.srcnode.abspath(env)
if env['VALAC_VERSION'] > (0, 1, 6):
cmd = [valac, '-C', '--quiet', vala_flags]
else:
cmd = [valac, '-C', vala_flags]
if self.threading:
cmd.append('--thread')
if self.profile:
cmd.append('--profile=%s' % self.profile)
if self.target_glib:
cmd.append('--target-glib=%s' % self.target_glib)
features = self.generator.features
if 'cshlib' in features or 'cstaticlib' in features:
output_dir = self.outputs[0].bld_dir(env)
cmd.append('--library ' + self.target)
if env['VALAC_VERSION'] >= (0, 7, 0):
cmd.append('--header ' + os.path.join(output_dir, self.target + '.h'))
self.outputs.append(self.generator.path.find_or_declare(self.target + '.h'))
cmd.append('--basedir ' + top_src)
cmd.append('-d ' + top_bld)
if env['VALAC_VERSION'] > (0, 7, 2) and hasattr(self, 'gir'):
cmd.append('--gir=%s.gir' % self.gir)
else:
output_dir = self.outputs[0].bld_dir(env)
cmd.append('-d %s' % output_dir)
for vapi_dir in self.vapi_dirs:
cmd.append('--vapidir=%s' % vapi_dir)
for package in self.packages:
cmd.append('--pkg %s' % package)
for package in self.packages_private:
cmd.append('--pkg %s' % package)
cmd.append(" ".join(inputs))
result = self.generator.bld.exec_command(" ".join(cmd))
if not 'cprogram' in features:
# generate the .deps file
if self.packages:
filename = os.path.join(self.generator.path.abspath(env), "%s.deps" % self.target)
deps = open(filename, 'w')
for package in self.packages:
deps.write(package + '\n')
deps.close()
# handle vala 0.1.6 who doesn't honor --directory for the generated .vapi
self._fix_output("../%s.vapi" % self.target)
# handle vala >= 0.1.7 who has a weid definition for --directory
self._fix_output("%s.vapi" % self.target)
# handle vala >= 0.2.0 who doesn't honor --directory for the generated .gidl
self._fix_output("%s.gidl" % self.target)
# handle vala >= 0.3.6 who doesn't honor --directory for the generated .gir
self._fix_output("%s.gir" % self.target)
if hasattr(self, 'gir'):
self._fix_output("%s.gir" % self.gir)
first = None
for node in self.outputs:
if not first:
first = node
else:
if first.parent.id != node.parent.id:
# issue #483
if env['VALAC_VERSION'] < (0, 7, 0):
shutil.move(first.parent.abspath(self.env) + os.sep + node.name, node.abspath(self.env))
return result
def install(self):
bld = self.generator.bld
features = self.generator.features
if self.attr("install_path") and ("cshlib" in features or "cstaticlib" in features):
headers_list = [o for o in self.outputs if o.suffix() == ".h"]
vapi_list = [o for o in self.outputs if (o.suffix() in (".vapi", ".deps"))]
gir_list = [o for o in self.outputs if o.suffix() == ".gir"]
for header in headers_list:
top_src = self.generator.bld.srcnode
package = self.env['PACKAGE']
try:
api_version = Utils.g_module.API_VERSION
except AttributeError:
version = Utils.g_module.VERSION.split(".")
if version[0] == "0":
api_version = "0." + version[1]
else:
api_version = version[0] + ".0"
install_path = '${INCLUDEDIR}/%s-%s/%s' % (package, api_version, header.relpath_gen(top_src))
bld.install_as(install_path, header, self.env)
bld.install_files('${DATAROOTDIR}/vala/vapi', vapi_list, self.env)
bld.install_files('${DATAROOTDIR}/gir-1.0', gir_list, self.env)
def _fix_output(self, output):
top_bld = self.generator.bld.srcnode.abspath(self.env)
try:
src = os.path.join(top_bld, output)
dst = self.generator.path.abspath (self.env)
shutil.move(src, dst)
except:
pass
@extension(EXT_VALA)
def vala_file(self, node):
valatask = getattr(self, "valatask", None)
# there is only one vala task and it compiles all vala files .. :-/
if not valatask:
valatask = self.create_task('valac')
self.valatask = valatask
self.includes = Utils.to_list(getattr(self, 'includes', []))
self.uselib = self.to_list(self.uselib)
valatask.packages = []
valatask.packages_private = Utils.to_list(getattr(self, 'packages_private', []))
valatask.vapi_dirs = []
valatask.target = self.target
valatask.threading = False
valatask.install_path = self.install_path
valatask.profile = getattr (self, 'profile', 'gobject')
valatask.target_glib = None #Deprecated
packages = Utils.to_list(getattr(self, 'packages', []))
vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', []))
includes = []
if hasattr(self, 'uselib_local'):
local_packages = Utils.to_list(self.uselib_local)
seen = []
while len(local_packages) > 0:
package = local_packages.pop()
if package in seen:
continue
seen.append(package)
# check if the package exists
package_obj = self.name_to_obj(package)
if not package_obj:
raise Utils.WafError("object '%s' was not found in uselib_local (required by '%s')" % (package, self.name))
package_name = package_obj.target
package_node = package_obj.path
package_dir = package_node.relpath_gen(self.path)
for task in package_obj.tasks:
for output in task.outputs:
if output.name == package_name + ".vapi":
valatask.set_run_after(task)
if package_name not in packages:
packages.append(package_name)
if package_dir not in vapi_dirs:
vapi_dirs.append(package_dir)
if package_dir not in includes:
includes.append(package_dir)
if hasattr(package_obj, 'uselib_local'):
lst = self.to_list(package_obj.uselib_local)
lst.reverse()
local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages
valatask.packages = packages
for vapi_dir in vapi_dirs:
try:
valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath())
valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath(self.env))
except AttributeError:
Logs.warn("Unable to locate Vala API directory: '%s'" % vapi_dir)
self.includes.append(node.bld.srcnode.abspath())
self.includes.append(node.bld.srcnode.abspath(self.env))
for include in includes:
try:
self.includes.append(self.path.find_dir(include).abspath())
self.includes.append(self.path.find_dir(include).abspath(self.env))
except AttributeError:
Logs.warn("Unable to locate include directory: '%s'" % include)
if valatask.profile == 'gobject':
if hasattr(self, 'target_glib'):
Logs.warn ('target_glib on vala tasks is deprecated --vala-target-glib=MAJOR.MINOR from the vala tool options')
if getattr(Options.options, 'vala_target_glib', None):
valatask.target_glib = Options.options.vala_target_glib
if not 'GOBJECT' in self.uselib:
self.uselib.append('GOBJECT')
if hasattr(self, 'threading'):
if valatask.profile == 'gobject':
valatask.threading = self.threading
if not 'GTHREAD' in self.uselib:
self.uselib.append('GTHREAD')
else:
#Vala doesn't have threading support for dova nor posix
Logs.warn("Profile %s does not have threading support" % valatask.profile)
if hasattr(self, 'gir'):
valatask.gir = self.gir
env = valatask.env
output_nodes = []
c_node = node.change_ext('.c')
output_nodes.append(c_node)
self.allnodes.append(c_node)
if env['VALAC_VERSION'] < (0, 7, 0):
output_nodes.append(node.change_ext('.h'))
else:
if not 'cprogram' in self.features:
output_nodes.append(self.path.find_or_declare('%s.h' % self.target))
if not 'cprogram' in self.features:
output_nodes.append(self.path.find_or_declare('%s.vapi' % self.target))
if env['VALAC_VERSION'] > (0, 7, 2):
if hasattr(self, 'gir'):
output_nodes.append(self.path.find_or_declare('%s.gir' % self.gir))
elif env['VALAC_VERSION'] > (0, 3, 5):
output_nodes.append(self.path.find_or_declare('%s.gir' % self.target))
elif env['VALAC_VERSION'] > (0, 1, 7):
output_nodes.append(self.path.find_or_declare('%s.gidl' % self.target))
if valatask.packages:
output_nodes.append(self.path.find_or_declare('%s.deps' % self.target))
valatask.inputs.append(node)
valatask.outputs.extend(output_nodes)
def detect(conf):
min_version = (0, 1, 6)
min_version_str = "%d.%d.%d" % min_version
valac = conf.find_program('valac', var='VALAC', mandatory=True)
if not conf.env["HAVE_GOBJECT"]:
pkg_args = {'package': 'gobject-2.0',
'uselib_store': 'GOBJECT',
'args': '--cflags --libs'}
if getattr(Options.options, 'vala_target_glib', None):
pkg_args['atleast_version'] = Options.options.vala_target_glib
conf.check_cfg(**pkg_args)
if not conf.env["HAVE_GTHREAD"]:
pkg_args = {'package': 'gthread-2.0',
'uselib_store': 'GTHREAD',
'args': '--cflags --libs'}
if getattr(Options.options, 'vala_target_glib', None):
pkg_args['atleast_version'] = Options.options.vala_target_glib
conf.check_cfg(**pkg_args)
try:
output = Utils.cmd_output(valac + " --version", silent=True)
version = output.split(' ', 1)[-1].strip().split(".")[0:3]
version = [int(x) for x in version]
valac_version = tuple(version)
except Exception:
valac_version = (0, 0, 0)
conf.check_message('program version',
'valac >= ' + min_version_str,
valac_version >= min_version,
"%d.%d.%d" % valac_version)
conf.check_tool('gnu_dirs')
if valac_version < min_version:
conf.fatal("valac version too old to be used with this tool")
return
conf.env['VALAC_VERSION'] = valac_version
conf.env['VALAFLAGS'] = ''
def set_options (opt):
valaopts = opt.add_option_group('Vala Compiler Options')
valaopts.add_option ('--vala-target-glib', default=None,
dest='vala_target_glib', metavar='MAJOR.MINOR',
help='Target version of glib for Vala GObject code generation')