waf: fix the include path workaround
[ladish.git] / wscript
blob37eb27513ef15a8143ee3e6ab346997507b93af8
1 #! /usr/bin/env python
2 # encoding: utf-8
4 import os
5 import Options
6 import Utils
7 import shutil
8 import re
9 import waflib
11 parallel_debug = False
13 APPNAME='ladish'
14 VERSION='0.3-rc'
15 DBUS_NAME_BASE = 'org.ladish'
16 RELEASE = False
18 # these variables are mandatory ('/' are converted automatically)
19 top = '.'
20 out = 'build'
22 from Logs import pprint
24 def display_msg(conf, msg="", status = None, color = None):
25 if status:
26 conf.msg(msg, status, color)
27 else:
28 pprint('NORMAL', msg)
30 def display_raw_text(conf, text, color = 'NORMAL'):
31 pprint(color, text, sep = '')
33 def display_line(conf, text, color = 'NORMAL'):
34 pprint(color, text, sep = os.linesep)
36 def yesno(bool):
37 if bool:
38 return "yes"
39 else:
40 return "no"
42 def options(opt):
43 opt.tool_options('compiler_cc')
44 opt.tool_options('compiler_cxx')
45 opt.tool_options('boost')
46 opt.tool_options('python')
47 opt.add_option('--enable-pkg-config-dbus-service-dir', action='store_true', default=False, help='force D-Bus service install dir to be one returned by pkg-config')
48 opt.add_option('--enable-liblash', action='store_true', default=False, help='Build LASH compatibility library')
49 opt.add_option('--enable-pylash', action='store_true', default=False, help='Build python bindings for LASH compatibility library')
50 opt.add_option('--debug', action='store_true', default=False, dest='debug', help="Build debuggable binaries")
51 opt.add_option('--doxygen', action='store_true', default=False, help='Enable build of doxygen documentation')
52 opt.add_option('--distnodeps', action='store_true', default=False, help="When creating distribution tarball, don't package git submodules")
53 if parallel_debug:
54 opt.load('parallel_debug')
56 def add_cflag(conf, flag):
57 conf.env.append_unique('CXXFLAGS', flag)
58 conf.env.append_unique('CCFLAGS', flag)
60 def add_linkflag(conf, flag):
61 conf.env.append_unique('LINKFLAGS', flag)
63 def check_gcc_optimizations_enabled(flags):
64 gcc_optimizations_enabled = False
65 for flag in flags:
66 if len(flag) < 2 or flag[0] != '-' or flag[1] != 'O':
67 continue
68 if len(flag) == 2:
69 gcc_optimizations_enabled = True;
70 else:
71 gcc_optimizations_enabled = flag[2] != '0';
72 return gcc_optimizations_enabled
74 def create_service_taskgen(bld, target, opath, binary):
75 bld(
76 features = 'subst', # the feature 'subst' overrides the source/target processing
77 source = os.path.join('daemon', 'dbus.service.in'), # list of string or nodes
78 target = target, # list of strings or nodes
79 install_path = bld.env['DBUS_SERVICES_DIR'] + os.path.sep,
80 # variables to use in the substitution
81 dbus_object_path = opath,
82 daemon_bin_path = os.path.join(bld.env['PREFIX'], 'bin', binary))
84 def configure(conf):
85 conf.check_tool('compiler_cc')
86 conf.check_tool('compiler_cxx')
87 conf.check_tool('boost')
88 conf.check_tool('python')
89 if parallel_debug:
90 conf.load('parallel_debug')
92 conf.env['LIB_DL'] = ['dl']
94 conf.check_cfg(
95 package = 'jack',
96 mandatory = True,
97 errmsg = "not installed, see http://jackaudio.org/",
98 args = '--cflags --libs')
100 conf.check_cfg(
101 package = 'dbus-1',
102 atleast_version = '1.0.0',
103 mandatory = True,
104 errmsg = "not installed, see http://dbus.freedesktop.org/",
105 args = '--cflags --libs')
107 dbus_dir = conf.check_cfg(package='dbus-1', args='--variable=session_bus_services_dir', msg="Retrieving D-Bus services dir")
108 if not dbus_dir:
109 return
111 dbus_dir = dbus_dir.strip()
112 conf.env['DBUS_SERVICES_DIR_REAL'] = dbus_dir
114 if Options.options.enable_pkg_config_dbus_service_dir:
115 conf.env['DBUS_SERVICES_DIR'] = dbus_dir
116 else:
117 conf.env['DBUS_SERVICES_DIR'] = os.path.join(os.path.normpath(conf.env['PREFIX']), 'share', 'dbus-1', 'services')
119 conf.env['LIBDIR'] = os.path.join(os.path.normpath(conf.env['PREFIX']), 'lib')
121 conf.env['BUILD_DOXYGEN_DOCS'] = Options.options.doxygen
123 conf.check_cfg(
124 package = 'uuid',
125 mandatory = True,
126 errmsg = "not installed, see http://e2fsprogs.sourceforge.net/",
127 args = '--cflags --libs')
129 conf.check(
130 header_name='expat.h',
131 mandatory = True,
132 errmsg = "not installed, see http://expat.sourceforge.net/")
134 conf.env['LIB_EXPAT'] = ['expat']
136 build_gui = True
138 if build_gui and not conf.check_cfg(
139 package = 'glib-2.0',
140 mandatory = False,
141 errmsg = "not installed, see http://www.gtk.org/",
142 args = '--cflags --libs'):
143 build_gui = False
145 if build_gui and not conf.check_cfg(
146 package = 'dbus-glib-1',
147 mandatory = False,
148 errmsg = "not installed, see http://dbus.freedesktop.org/",
149 args = '--cflags --libs'):
150 build_gui = False
152 if build_gui and not conf.check_cfg(
153 package = 'gtk+-2.0',
154 mandatory = False,
155 atleast_version = '2.20.0',
156 errmsg = "not installed, see http://www.gtk.org/",
157 args = '--cflags --libs'):
158 build_gui = False
160 if build_gui and not conf.check_cfg(
161 package = 'flowcanvas',
162 mandatory = False,
163 atleast_version = '0.6.4',
164 errmsg = "not installed, see http://drobilla.net/software/flowcanvas/",
165 args = '--cflags --libs'):
166 build_gui = False
168 if build_gui:
169 # We need the boost headers package (e.g. libboost-dev)
170 # shared_ptr.hpp and weak_ptr.hpp
171 build_gui = conf.check_boost(errmsg="not found, see http://boost.org/")
173 conf.env['BUILD_GLADISH'] = build_gui
175 conf.env['BUILD_LIBLASH'] = Options.options.enable_liblash
176 conf.env['BUILD_PYLASH'] = Options.options.enable_pylash
177 if conf.env['BUILD_PYLASH'] and not conf.env['BUILD_LIBLASH']:
178 conf.fatal("pylash build was requested but liblash was not")
179 conf.env['BUILD_PYLASH'] = False
180 if conf.env['BUILD_PYLASH']:
181 conf.check_python_version()
182 conf.check_python_headers()
184 conf.env['BUILD_WERROR'] = not RELEASE
185 if conf.env['BUILD_WERROR']:
186 add_cflag(conf, '-Wall')
187 add_cflag(conf, '-Werror')
188 # for pre gcc-4.4, enable optimizations so use of uninitialized variables gets detected
189 try:
190 is_gcc = conf.env['CC_NAME'] == 'gcc'
191 if is_gcc:
192 gcc_ver = []
193 for n in conf.env['CC_VERSION']:
194 gcc_ver.append(int(n))
195 if gcc_ver[0] < 4 or gcc_ver[1] < 4:
196 #print "optimize force enable is required"
197 if not check_gcc_optimizations_enabled(conf.env['CCFLAGS']):
198 if Options.options.debug:
199 print "C optimization must be forced in order to enable -Wuninitialized"
200 print "However this will not be made because debug compilation is enabled"
201 else:
202 print "C optimization forced in order to enable -Wuninitialized"
203 conf.env.append_unique('CCFLAGS', "-O")
204 except:
205 pass
207 conf.env['BUILD_DEBUG'] = Options.options.debug
208 if conf.env['BUILD_DEBUG']:
209 add_cflag(conf, '-g')
210 add_cflag(conf, '-O0')
211 add_linkflag(conf, '-g')
213 conf.env['DATA_DIR'] = os.path.normpath(os.path.join(conf.env['PREFIX'], 'share', APPNAME))
215 # write some parts of the configure environment to the config.h file
216 conf.define('DATA_DIR', conf.env['DATA_DIR'])
217 conf.define('PACKAGE_VERSION', VERSION)
218 conf.define('DBUS_NAME_BASE', DBUS_NAME_BASE)
219 conf.define('DBUS_BASE_PATH', '/' + DBUS_NAME_BASE.replace('.', '/'))
220 conf.define('BASE_NAME', APPNAME)
221 conf.define('_GNU_SOURCE', 1)
222 conf.write_config_header('config.h')
224 display_msg(conf)
226 display_msg(conf, "==================")
227 version_msg = APPNAME + "-" + VERSION
229 if os.access('version.h', os.R_OK):
230 data = file('version.h').read()
231 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
232 if m != None:
233 version_msg += " exported from " + m.group(1)
234 elif os.access('.git', os.R_OK):
235 version_msg += " git revision will checked and eventually updated during build"
237 display_msg(conf, version_msg)
239 display_msg(conf)
240 display_msg(conf, "Install prefix", conf.env['PREFIX'], 'CYAN')
242 display_msg(conf, 'Build gladish', yesno(conf.env['BUILD_GLADISH']))
243 display_msg(conf, 'Build liblash', yesno(Options.options.enable_liblash))
244 display_msg(conf, 'Build pylash', yesno(conf.env['BUILD_PYLASH']))
245 display_msg(conf, 'Treat warnings as errors', yesno(conf.env['BUILD_WERROR']))
246 display_msg(conf, 'Debuggable binaries', yesno(conf.env['BUILD_DEBUG']))
247 display_msg(conf, 'Build doxygen documentation', yesno(conf.env['BUILD_DOXYGEN_DOCS']))
249 if conf.env['DBUS_SERVICES_DIR'] != conf.env['DBUS_SERVICES_DIR_REAL']:
250 display_msg(conf)
251 display_line(conf, "WARNING: D-Bus session services directory as reported by pkg-config is", 'RED')
252 display_raw_text(conf, "WARNING:", 'RED')
253 display_line(conf, conf.env['DBUS_SERVICES_DIR_REAL'], 'CYAN')
254 display_line(conf, 'WARNING: but service file will be installed in', 'RED')
255 display_raw_text(conf, "WARNING:", 'RED')
256 display_line(conf, conf.env['DBUS_SERVICES_DIR'], 'CYAN')
257 display_line(conf, 'WARNING: You may need to adjust your D-Bus configuration after installing ladish', 'RED')
258 display_line(conf, 'WARNING: You can override dbus service install directory', 'RED')
259 display_line(conf, 'WARNING: with --enable-pkg-config-dbus-service-dir option to this script', 'RED')
261 display_msg(conf, 'C compiler flags', repr(conf.env['CCFLAGS']))
262 display_msg(conf, 'C++ compiler flags', repr(conf.env['CXXFLAGS']))
264 if not conf.env['BUILD_GLADISH']:
265 display_msg(conf)
266 display_line(conf, "WARNING: The GUI frontend will not built", 'RED')
268 display_msg(conf)
270 def git_ver(self):
271 bld = self.generator.bld
272 header = self.outputs[0].abspath()
273 if os.access('../version.h', os.R_OK):
274 shutil.copy('../version.h', header)
275 data = file(header).read()
276 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
277 if m != None:
278 self.ver = m.group(1)
279 pprint('BLUE', "tarball from git revision " + self.ver)
280 else:
281 self.ver = "tarball"
282 return
284 if bld.srcnode.find_node('.git'):
285 self.ver = bld.cmd_and_log("LANG= git rev-parse HEAD", quiet=waflib.Context.BOTH).splitlines()[0]
286 if bld.cmd_and_log("LANG= git diff-index --name-only HEAD", quiet=waflib.Context.BOTH).splitlines():
287 self.ver += "-dirty"
289 pprint('BLUE', "git revision " + self.ver)
290 else:
291 self.ver = "unknown"
293 fi = open(header, 'w')
294 fi.write('#define GIT_VERSION "%s"\n' % self.ver)
295 fi.close()
297 def build(bld):
298 if not bld.env['DATA_DIR']:
299 raise "DATA_DIR is emtpy"
301 bld(rule=git_ver, target='version.h', update_outputs=True, always=True, ext_out=['.h'])
303 daemon = bld.program(source = [], features = 'c cprogram', includes = [bld.path.get_bld()])
304 daemon.target = 'ladishd'
305 daemon.uselib = 'DBUS-1 UUID EXPAT'
306 daemon.ver_header = 'version.h'
307 daemon.env.append_value("LINKFLAGS", ["-lutil", "-ldl", "-Wl,-E"])
309 for source in [
310 'main.c',
311 'loader.c',
312 'log.c',
313 'sigsegv.c',
314 'proctitle.c',
315 'appdb.c',
316 'procfs.c',
317 'control.c',
318 'studio.c',
319 'graph.c',
320 'client.c',
321 'port.c',
322 'virtualizer.c',
323 'dict.c',
324 'graph_dict.c',
325 'escape.c',
326 'studio_jack_conf.c',
327 'save.c',
328 'load.c',
329 'cmd_load_studio.c',
330 'cmd_new_studio.c',
331 'cmd_rename_studio.c',
332 'cmd_save_studio.c',
333 'cmd_start_studio.c',
334 'cmd_stop_studio.c',
335 'cmd_unload_studio.c',
336 'cmd_new_app.c',
337 'cmd_change_app_state.c',
338 'cmd_remove_app.c',
339 'cmd_create_room.c',
340 'cmd_delete_room.c',
341 'cmd_save_project.c',
342 'cmd_unload_project.c',
343 'cmd_load_project.c',
344 'cmd_exit.c',
345 'cqueue.c',
346 'app_supervisor.c',
347 'room.c',
348 'room_save.c',
349 'room_load.c',
350 'recent_store.c',
351 'recent_projects.c',
353 daemon.source.append(os.path.join("daemon", source))
355 for source in [
356 'jack_proxy.c',
357 'graph_proxy.c',
358 'a2j_proxy.c',
359 "jmcore_proxy.c",
360 "notify_proxy.c",
361 "conf_proxy.c",
363 daemon.source.append(os.path.join("proxies", source))
365 for source in [
366 'signal.c',
367 'method.c',
368 'error.c',
369 'object_path.c',
370 'interface.c',
371 'helpers.c',
373 daemon.source.append(os.path.join("dbus", source))
375 for source in [
376 'time.c',
377 'dirhelpers.c',
378 'catdup.c',
380 daemon.source.append(os.path.join("common", source))
382 daemon.source.append(os.path.join("alsapid", "helper.c"))
384 # process dbus.service.in -> ladish.service
385 create_service_taskgen(bld, DBUS_NAME_BASE + '.service', DBUS_NAME_BASE, daemon.target)
387 #####################################################
388 # jmcore
389 jmcore = bld.program(source = [], features = 'c cprogram', includes = [bld.path.get_bld()])
390 jmcore.target = 'jmcore'
391 jmcore.uselib = 'DBUS-1 JACK'
392 jmcore.defines = ['LOG_OUTPUT_STDOUT']
393 jmcore.source = ['jmcore.c']
395 for source in [
396 #'signal.c',
397 'method.c',
398 'error.c',
399 'object_path.c',
400 'interface.c',
401 'helpers.c',
403 jmcore.source.append(os.path.join("dbus", source))
405 create_service_taskgen(bld, DBUS_NAME_BASE + '.jmcore.service', DBUS_NAME_BASE + ".jmcore", jmcore.target)
407 #####################################################
408 # conf
409 ladiconfd = bld.program(source = [], features = 'c cprogram', includes = [bld.path.get_bld()])
410 ladiconfd.target = 'ladiconfd'
411 ladiconfd.uselib = 'DBUS-1'
412 ladiconfd.defines = ['LOG_OUTPUT_STDOUT']
413 ladiconfd.source = ['conf.c']
415 for source in [
416 'dirhelpers.c',
417 'catdup.c',
419 ladiconfd.source.append(os.path.join("common", source))
421 for source in [
422 'signal.c',
423 'method.c',
424 'error.c',
425 'object_path.c',
426 'interface.c',
427 'helpers.c',
429 ladiconfd.source.append(os.path.join("dbus", source))
431 create_service_taskgen(bld, DBUS_NAME_BASE + '.conf.service', DBUS_NAME_BASE + ".conf", ladiconfd.target)
433 #####################################################
434 # alsapid
435 bld.shlib(source = [os.path.join("alsapid", 'lib.c'), os.path.join("alsapid", "helper.c")], target = 'alsapid', uselib = 'DL')
437 #####################################################
438 # liblash
439 if bld.env['BUILD_LIBLASH']:
440 liblash = bld.shlib(source = [], features = 'c cshlib', includes = [bld.path.get_bld()])
441 liblash.uselib = 'DBUS-1'
442 liblash.target = 'lash'
443 liblash.vnum = "1.1.1"
444 liblash.defines = ['LOG_OUTPUT_STDOUT']
445 liblash.source = [os.path.join("lash_compat", "liblash", 'lash.c'), os.path.join("common", "catdup.c")]
447 bld.install_files('${PREFIX}/include/lash', bld.path.ant_glob('lash_compat/liblash/lash/*.h'))
449 # process lash-1.0.pc.in -> lash-1.0.pc
450 bld(
451 features = 'subst', # the feature 'subst' overrides the source/target processing
452 source = os.path.join("lash_compat", 'lash-1.0.pc.in'), # list of string or nodes
453 target = 'lash-1.0.pc', # list of strings or nodes
454 install_path = '${LIBDIR}/pkgconfig/',
455 # variables to use in the substitution
456 prefix = bld.env['PREFIX'],
457 exec_prefix = bld.env['PREFIX'],
458 libdir = bld.env['LIBDIR'],
459 includedir = os.path.normpath(bld.env['PREFIX'] + '/include'))
461 #####################################################
462 # pylash
463 if bld.env['BUILD_PYLASH']:
464 pylash = bld.shlib(features = 'c cshlib pyext', source = [])
465 pylash.target = '_lash'
466 pylash.use = 'lash'
467 pylash.install_path = '${PYTHONDIR}'
469 for source in [
470 'lash.c',
471 'lash_wrap.c',
473 pylash.source.append(os.path.join("lash_compat", "pylash", source))
475 bld.install_files('${PYTHONDIR}', os.path.join("lash_compat", "pylash", "lash.py"))
477 #####################################################
478 # gladish
479 if bld.env['BUILD_GLADISH']:
480 gladish = bld.program(source = [], features = 'c cxx cxxprogram', includes = [bld.path.get_bld()])
481 gladish.target = 'gladish'
482 gladish.defines = ['LOG_OUTPUT_STDOUT']
483 gladish.uselib = 'DBUS-1 DBUS-GLIB-1 FLOWCANVAS'
485 gladish.source = []
487 for source in [
488 'main.c',
489 'load_project_dialog.c',
490 'save_project_dialog.c',
491 'world_tree.c',
492 'graph_view.c',
493 'canvas.cpp',
494 'graph_canvas.c',
495 'gtk_builder.c',
496 'ask_dialog.c',
497 'create_room_dialog.c',
498 'menu.c',
499 'dynmenu.c',
500 'toolbar.c',
501 'about.c',
502 'dbus.c',
503 'studio.c',
504 'studio_list.c',
505 'dialogs.c',
506 'jack.c',
507 'control.c',
508 'pixbuf.c',
509 'room.c',
510 'statusbar.c',
511 'action.c',
512 'settings.c',
513 'zoom.c',
515 gladish.source.append(os.path.join("gui", source))
517 for source in [
518 'jack_proxy.c',
519 'graph_proxy.c',
520 'studio_proxy.c',
521 'control_proxy.c',
522 'app_supervisor_proxy.c',
523 "room_proxy.c",
524 "conf_proxy.c",
526 gladish.source.append(os.path.join("proxies", source))
528 for source in [
529 'method.c',
530 'helpers.c',
532 gladish.source.append(os.path.join("dbus", source))
534 for source in [
535 'catdup.c',
537 gladish.source.append(os.path.join("common", source))
539 # GtkBuilder UI definitions (XML)
540 bld.install_files('${DATA_DIR}', 'gui/gladish.ui')
542 bld.install_files('${PREFIX}/bin', 'ladish_control', chmod=0755)
544 # 'Desktop' file (menu entry, icon, etc)
545 bld.install_files('${PREFIX}/share/applications/', 'gui/gladish.desktop', chmod=0644)
547 # Icons
548 icon_sizes = ['16x16', '22x22', '24x24', '32x32', '48x48', '256x256']
549 for icon_size in icon_sizes:
550 bld.path.ant_glob('art/' + icon_size + '/apps/*.png')
551 bld.install_files('${PREFIX}/share/icons/hicolor/' + icon_size + '/apps/', 'art/' + icon_size + '/apps/gladish.png')
553 status_images = []
554 for status in ["down", "unloaded", "started", "stopped", "warning", "error"]:
555 status_images.append("art/status_" + status + ".png")
557 bld.install_files('${DATA_DIR}', status_images)
558 bld.install_files('${DATA_DIR}', "art/ladish-logo-128x128.png")
559 bld.install_files('${DATA_DIR}', ["COPYING", "AUTHORS", "README", "NEWS"])
561 if bld.env['BUILD_DOXYGEN_DOCS'] == True:
562 html_docs_source_dir = "build/default/html"
563 if bld.cmd == 'clean':
564 if os.access(html_docs_source_dir, os.R_OK):
565 pprint('CYAN', "Removing doxygen generated documentation...")
566 shutil.rmtree(html_docs_source_dir)
567 pprint('CYAN', "Removing doxygen generated documentation done.")
568 elif bld.cmd == 'build':
569 if not os.access(html_docs_source_dir, os.R_OK):
570 os.popen("doxygen").read()
571 else:
572 pprint('CYAN', "doxygen documentation already built.")
574 def get_tags_dirs():
575 source_root = os.path.dirname(Utils.g_module.root_path)
576 if 'relpath' in os.path.__all__:
577 source_root = os.path.relpath(source_root)
578 paths = source_root
579 paths += " " + os.path.join(source_root, "common")
580 paths += " " + os.path.join(source_root, "dbus")
581 paths += " " + os.path.join(source_root, "proxies")
582 paths += " " + os.path.join(source_root, "daemon")
583 paths += " " + os.path.join(source_root, "gui")
584 paths += " " + os.path.join(source_root, "example-apps")
585 paths += " " + os.path.join(source_root, "lib")
586 paths += " " + os.path.join(source_root, "lash_compat", "liblash")
587 paths += " " + os.path.join(source_root, "lash_compat", "liblash", "lash")
588 return paths
590 def gtags(ctx):
591 '''build tag files for GNU global'''
592 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | gtags --statistics -f -" % get_tags_dirs()
593 #print("Running: %s" % cmd)
594 os.system(cmd)
596 def etags(ctx):
597 '''build TAGS file using etags'''
598 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | etags -" % get_tags_dirs()
599 #print("Running: %s" % cmd)
600 os.system(cmd)
601 os.system("stat -c '%y' TAGS")
603 def dist_hook():
604 #print repr(Options.options)
605 if Options.options.distnodeps:
606 shutil.rmtree('laditools')
607 shutil.rmtree('flowcanvas')
608 shutil.rmtree('jack2')
609 shutil.rmtree('a2jmidid')
610 nodist_files = ['.gitmodules', 'GTAGS', 'GRTAGS', 'GPATH', 'GSYMS'] # waf does not ignore these file
611 for nodist_file in nodist_files:
612 if os.access(nodist_file, os.F_OK):
613 os.remove(nodist_file)
614 shutil.copy('../build/default/version.h', "./")