3 # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
8 # Radosław Szkodziński, 2010
11 At this point, vala is still unstable, so do not expect
12 this tool to be too stable either (apis, etc)
16 from waflib import Build, Context, Errors, Logs, Node, Options, Task, Utils
17 from waflib.TaskGen import extension, taskgen_method
18 from waflib.Configure import conf
20 class valac(Task.Task):
24 #run_str = "${VALAC} ${VALAFLAGS}" # ideally
25 #vars = ['VALAC_VERSION']
26 vars = ["VALAC", "VALAC_VERSION", "VALAFLAGS"]
30 cmd = self.env.VALAC + self.env.VALAFLAGS
31 resources = getattr(self, 'vala_exclude', [])
32 cmd.extend([a.abspath() for a in self.inputs if a not in resources])
33 ret = self.exec_command(cmd, cwd=self.vala_dir_node.abspath())
38 if self.generator.dump_deps_node:
39 self.generator.dump_deps_node.write('\n'.join(self.generator.packages))
44 def init_vala_task(self):
46 Initializes the vala task with the relevant data (acts as a constructor)
48 self.profile = getattr(self, 'profile', 'gobject')
50 self.packages = packages = Utils.to_list(getattr(self, 'packages', []))
51 self.use = Utils.to_list(getattr(self, 'use', []))
52 if packages and not self.use:
53 self.use = packages[:] # copy
55 if self.profile == 'gobject':
56 if not 'GOBJECT' in self.use:
57 self.use.append('GOBJECT')
60 self.env.append_value('VALAFLAGS', flags)
63 addflags('--profile=%s' % self.profile)
65 valatask = self.valatask
68 if hasattr(self, 'vala_dir'):
69 if isinstance(self.vala_dir, str):
70 valatask.vala_dir_node = self.path.get_bld().make_node(self.vala_dir)
72 valatask.vala_dir_node.mkdir()
74 raise self.bld.fatal('Cannot create the vala dir %r' % valatask.vala_dir_node)
76 valatask.vala_dir_node = self.vala_dir
78 valatask.vala_dir_node = self.path.get_bld()
79 addflags('--directory=%s' % valatask.vala_dir_node.abspath())
81 if hasattr(self, 'thread'):
82 if self.profile == 'gobject':
83 if not 'GTHREAD' in self.use:
84 self.use.append('GTHREAD')
86 #Vala doesn't have threading support for dova nor posix
87 Logs.warn('Profile %s means no threading support', self.profile)
93 self.is_lib = 'cprogram' not in self.features
95 addflags('--library=%s' % self.target)
97 h_node = valatask.vala_dir_node.find_or_declare('%s.h' % self.target)
98 valatask.outputs.append(h_node)
99 addflags('--header=%s' % h_node.name)
101 valatask.outputs.append(valatask.vala_dir_node.find_or_declare('%s.vapi' % self.target))
103 if getattr(self, 'gir', None):
104 gir_node = valatask.vala_dir_node.find_or_declare('%s.gir' % self.gir)
105 addflags('--gir=%s' % gir_node.name)
106 valatask.outputs.append(gir_node)
108 self.vala_target_glib = getattr(self, 'vala_target_glib', getattr(Options.options, 'vala_target_glib', None))
109 if self.vala_target_glib:
110 addflags('--target-glib=%s' % self.vala_target_glib)
112 addflags(['--define=%s' % x for x in Utils.to_list(getattr(self, 'vala_defines', []))])
114 packages_private = Utils.to_list(getattr(self, 'packages_private', []))
115 addflags(['--pkg=%s' % x for x in packages_private])
117 def _get_api_version():
119 if hasattr(Context.g_module, 'API_VERSION'):
120 version = Context.g_module.API_VERSION.split(".")
121 if version[0] == "0":
122 api_version = "0." + version[1]
124 api_version = version[0] + ".0"
127 self.includes = Utils.to_list(getattr(self, 'includes', []))
128 valatask.install_path = getattr(self, 'install_path', '')
130 valatask.vapi_path = getattr(self, 'vapi_path', '${DATAROOTDIR}/vala/vapi')
131 valatask.pkg_name = getattr(self, 'pkg_name', self.env.PACKAGE)
132 valatask.header_path = getattr(self, 'header_path', '${INCLUDEDIR}/%s-%s' % (valatask.pkg_name, _get_api_version()))
133 valatask.install_binding = getattr(self, 'install_binding', True)
135 self.vapi_dirs = vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', []))
138 if hasattr(self, 'use'):
139 local_packages = Utils.to_list(self.use)[:] # make sure to have a copy
141 while len(local_packages) > 0:
142 package = local_packages.pop()
147 # check if the package exists
149 package_obj = self.bld.get_tgen_by_name(package)
150 except Errors.WafError:
153 # in practice the other task is already processed
154 # but this makes it explicit
156 package_name = package_obj.target
157 task = getattr(package_obj, 'valatask', None)
159 for output in task.outputs:
160 if output.name == package_name + ".vapi":
161 valatask.set_run_after(task)
162 if package_name not in packages:
163 packages.append(package_name)
164 if output.parent not in vapi_dirs:
165 vapi_dirs.append(output.parent)
166 if output.parent not in self.includes:
167 self.includes.append(output.parent)
169 if hasattr(package_obj, 'use'):
170 lst = self.to_list(package_obj.use)
172 local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages
174 addflags(['--pkg=%s' % p for p in packages])
176 for vapi_dir in vapi_dirs:
177 if isinstance(vapi_dir, Node.Node):
180 v_node = self.path.find_dir(vapi_dir)
182 Logs.warn('Unable to locate Vala API directory: %r', vapi_dir)
184 addflags('--vapidir=%s' % v_node.abspath())
186 self.dump_deps_node = None
187 if self.is_lib and self.packages:
188 self.dump_deps_node = valatask.vala_dir_node.find_or_declare('%s.deps' % self.target)
189 valatask.outputs.append(self.dump_deps_node)
191 if self.is_lib and valatask.install_binding:
192 headers_list = [o for o in valatask.outputs if o.suffix() == ".h"]
194 self.install_vheader = self.add_install_files(install_to=valatask.header_path, install_from=headers_list)
196 vapi_list = [o for o in valatask.outputs if (o.suffix() in (".vapi", ".deps"))]
198 self.install_vapi = self.add_install_files(install_to=valatask.vapi_path, install_from=vapi_list)
200 gir_list = [o for o in valatask.outputs if o.suffix() == '.gir']
202 self.install_gir = self.add_install_files(
203 install_to=getattr(self, 'gir_path', '${DATAROOTDIR}/gir-1.0'), install_from=gir_list)
205 if hasattr(self, 'vala_resources'):
206 nodes = self.to_nodes(self.vala_resources)
207 valatask.vala_exclude = getattr(valatask, 'vala_exclude', []) + nodes
208 valatask.inputs.extend(nodes)
210 addflags(['--gresources', x.abspath()])
212 @extension('.vala', '.gs')
213 def vala_file(self, node):
215 Compile a vala file and bind the task to *self.valatask*. If an existing vala task is already set, add the node
216 to its inputs. The typical example is::
220 packages = 'gtk+-2.0',
221 target = 'vala-gtk-example',
223 source = 'vala-gtk-example.vala foo.vala',
224 vala_defines = ['DEBUG'] # adds --define=<xyz> values to the command-line
226 # the following arguments are for libraries
231 # disable installing of gir, vapi and header
232 #install_binding = False
234 # profile = 'xyz' # adds --profile=<xyz> to enable profiling
235 # thread = True, # adds --thread, except if profile is on or not on 'gobject'
236 # vala_target_glib = 'xyz' # adds --target-glib=<xyz>, can be given through the command-line option --vala-target-glib=<xyz>
240 :param node: vala file
241 :type node: :py:class:`waflib.Node.Node`
245 valatask = self.valatask
246 except AttributeError:
247 valatask = self.valatask = self.create_task('valac')
248 self.init_vala_task()
250 valatask.inputs.append(node)
251 name = node.name[:node.name.rfind('.')] + '.c'
252 c_node = valatask.vala_dir_node.find_or_declare(name)
253 valatask.outputs.append(c_node)
254 self.source.append(c_node)
257 def vapi_file(self, node):
259 valatask = self.valatask
260 except AttributeError:
261 valatask = self.valatask = self.create_task('valac')
262 self.init_vala_task()
263 valatask.inputs.append(node)
266 def find_valac(self, valac_name, min_version):
268 Find the valac program, and execute it to store the version
269 number in *conf.env.VALAC_VERSION*
271 :param valac_name: program name
272 :type valac_name: string or list of string
273 :param min_version: minimum version acceptable
274 :type min_version: tuple of int
276 valac = self.find_program(valac_name, var='VALAC')
278 output = self.cmd_and_log(valac + ['--version'])
279 except Errors.WafError:
282 ver = re.search(r'\d+.\d+.\d+', output).group().split('.')
283 valac_version = tuple([int(x) for x in ver])
285 self.msg('Checking for %s version >= %r' % (valac_name, min_version),
286 valac_version, valac_version and valac_version >= min_version)
287 if valac and valac_version < min_version:
288 self.fatal("%s version %r is too old, need >= %r" % (valac_name, valac_version, min_version))
290 self.env.VALAC_VERSION = valac_version
294 def check_vala(self, min_version=(0,8,0), branch=None):
296 Check if vala compiler from a given branch exists of at least a given
299 :param min_version: minimum version acceptable (0.8.0)
300 :type min_version: tuple
301 :param branch: first part of the version number, in case a snapshot is used (0, 8)
302 :type branch: tuple of int
304 if self.env.VALA_MINVER:
305 min_version = self.env.VALA_MINVER
306 if self.env.VALA_MINVER_BRANCH:
307 branch = self.env.VALA_MINVER_BRANCH
309 branch = min_version[:2]
311 find_valac(self, 'valac-%d.%d' % (branch[0], branch[1]), min_version)
312 except self.errors.ConfigurationError:
313 find_valac(self, 'valac', min_version)
316 def check_vala_deps(self):
318 Load the gobject and gthread packages if they are missing.
320 if not self.env.HAVE_GOBJECT:
321 pkg_args = {'package': 'gobject-2.0',
322 'uselib_store': 'GOBJECT',
323 'args': '--cflags --libs'}
324 if getattr(Options.options, 'vala_target_glib', None):
325 pkg_args['atleast_version'] = Options.options.vala_target_glib
326 self.check_cfg(**pkg_args)
328 if not self.env.HAVE_GTHREAD:
329 pkg_args = {'package': 'gthread-2.0',
330 'uselib_store': 'GTHREAD',
331 'args': '--cflags --libs'}
332 if getattr(Options.options, 'vala_target_glib', None):
333 pkg_args['atleast_version'] = Options.options.vala_target_glib
334 self.check_cfg(**pkg_args)
338 Use the following to enforce minimum vala version::
341 conf.env.VALA_MINVER = (0, 10, 0)
344 self.load('gnu_dirs')
345 self.check_vala_deps()
347 self.add_os_flags('VALAFLAGS')
348 self.env.append_unique('VALAFLAGS', ['-C'])
352 Load the :py:mod:`waflib.Tools.gnu_dirs` tool and add the ``--vala-target-glib`` command-line option
355 valaopts = opt.add_option_group('Vala Compiler Options')
356 valaopts.add_option('--vala-target-glib', default=None,
357 dest='vala_target_glib', metavar='MAJOR.MINOR',
358 help='Target version of glib for Vala GObject code generation')