Allow non-default timeout when using dbus_call()
[ladish.git] / wscript
blobe1781e3ba83fdd04ce7cb12fdec48147d82c8c38
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.load('compiler_c')
44 opt.load('compiler_cxx')
45 opt.load('boost')
46 opt.load('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('CFLAGS', 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.load('compiler_c')
86 conf.load('compiler_cxx')
87 conf.load('boost')
88 conf.load('python')
89 if parallel_debug:
90 conf.load('parallel_debug')
92 # dladdr() is used by daemon/sigsegv.c
93 # dlvsym() is used by the alsapid library
94 conf.check_cc(msg="Checking for libdl", lib=['dl'], uselib_store='DL')
96 # forkpty() is used by ladishd
97 conf.check_cc(msg="Checking for libutil", lib=['util'], uselib_store='UTIL')
99 conf.check_cfg(
100 package = 'jack',
101 mandatory = True,
102 errmsg = "not installed, see http://jackaudio.org/",
103 args = '--cflags --libs')
105 conf.check_cfg(
106 package = 'dbus-1',
107 atleast_version = '1.0.0',
108 mandatory = True,
109 errmsg = "not installed, see http://dbus.freedesktop.org/",
110 args = '--cflags --libs')
112 dbus_dir = conf.check_cfg(package='dbus-1', args='--variable=session_bus_services_dir', msg="Retrieving D-Bus services dir")
113 if not dbus_dir:
114 return
116 dbus_dir = dbus_dir.strip()
117 conf.env['DBUS_SERVICES_DIR_REAL'] = dbus_dir
119 if Options.options.enable_pkg_config_dbus_service_dir:
120 conf.env['DBUS_SERVICES_DIR'] = dbus_dir
121 else:
122 conf.env['DBUS_SERVICES_DIR'] = os.path.join(os.path.normpath(conf.env['PREFIX']), 'share', 'dbus-1', 'services')
124 conf.env['LIBDIR'] = os.path.join(os.path.normpath(conf.env['PREFIX']), 'lib')
126 conf.env['BUILD_DOXYGEN_DOCS'] = Options.options.doxygen
128 conf.check_cfg(
129 package = 'uuid',
130 mandatory = True,
131 errmsg = "not installed, see http://e2fsprogs.sourceforge.net/",
132 args = '--cflags --libs')
134 conf.check(
135 header_name='expat.h',
136 mandatory = True,
137 errmsg = "not installed, see http://expat.sourceforge.net/")
139 conf.env['LIB_EXPAT'] = ['expat']
141 build_gui = True
143 if build_gui and not conf.check_cfg(
144 package = 'glib-2.0',
145 mandatory = False,
146 errmsg = "not installed, see http://www.gtk.org/",
147 args = '--cflags --libs'):
148 build_gui = False
150 if build_gui and not conf.check_cfg(
151 package = 'dbus-glib-1',
152 mandatory = False,
153 errmsg = "not installed, see http://dbus.freedesktop.org/",
154 args = '--cflags --libs'):
155 build_gui = False
157 if build_gui and not conf.check_cfg(
158 package = 'gtk+-2.0',
159 mandatory = False,
160 atleast_version = '2.20.0',
161 errmsg = "not installed, see http://www.gtk.org/",
162 args = '--cflags --libs'):
163 build_gui = False
165 if build_gui and not conf.check_cfg(
166 package = 'flowcanvas',
167 mandatory = False,
168 atleast_version = '0.6.4',
169 errmsg = "not installed, see http://drobilla.net/software/flowcanvas/",
170 args = '--cflags --libs'):
171 build_gui = False
173 if build_gui:
174 # We need the boost headers package (e.g. libboost-dev)
175 # shared_ptr.hpp and weak_ptr.hpp
176 build_gui = conf.check_boost(errmsg="not found, see http://boost.org/")
178 conf.env['BUILD_GLADISH'] = build_gui
180 conf.env['BUILD_LIBLASH'] = Options.options.enable_liblash
181 conf.env['BUILD_PYLASH'] = Options.options.enable_pylash
182 if conf.env['BUILD_PYLASH'] and not conf.env['BUILD_LIBLASH']:
183 conf.fatal("pylash build was requested but liblash was not")
184 conf.env['BUILD_PYLASH'] = False
185 if conf.env['BUILD_PYLASH']:
186 conf.check_python_version()
187 conf.check_python_headers()
189 conf.env['BUILD_WERROR'] = not RELEASE
190 if conf.env['BUILD_WERROR']:
191 add_cflag(conf, '-Wall')
192 add_cflag(conf, '-Werror')
193 # for pre gcc-4.4, enable optimizations so use of uninitialized variables gets detected
194 try:
195 is_gcc = conf.env['CC_NAME'] == 'gcc'
196 if is_gcc:
197 gcc_ver = []
198 for n in conf.env['CC_VERSION']:
199 gcc_ver.append(int(n))
200 if gcc_ver[0] < 4 or gcc_ver[1] < 4:
201 #print "optimize force enable is required"
202 if not check_gcc_optimizations_enabled(conf.env['CFLAGS']):
203 if Options.options.debug:
204 print "C optimization must be forced in order to enable -Wuninitialized"
205 print "However this will not be made because debug compilation is enabled"
206 else:
207 print "C optimization forced in order to enable -Wuninitialized"
208 conf.env.append_unique('CFLAGS', "-O")
209 except:
210 pass
212 conf.env['BUILD_DEBUG'] = Options.options.debug
213 if conf.env['BUILD_DEBUG']:
214 add_cflag(conf, '-g')
215 add_cflag(conf, '-O0')
216 add_linkflag(conf, '-g')
218 conf.env['DATA_DIR'] = os.path.normpath(os.path.join(conf.env['PREFIX'], 'share', APPNAME))
220 # write some parts of the configure environment to the config.h file
221 conf.define('DATA_DIR', conf.env['DATA_DIR'])
222 conf.define('PACKAGE_VERSION', VERSION)
223 conf.define('DBUS_NAME_BASE', DBUS_NAME_BASE)
224 conf.define('DBUS_BASE_PATH', '/' + DBUS_NAME_BASE.replace('.', '/'))
225 conf.define('BASE_NAME', APPNAME)
226 conf.define('_GNU_SOURCE', 1)
227 conf.write_config_header('config.h')
229 display_msg(conf)
231 display_msg(conf, "==================")
232 version_msg = APPNAME + "-" + VERSION
234 if os.access('version.h', os.R_OK):
235 data = file('version.h').read()
236 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
237 if m != None:
238 version_msg += " exported from " + m.group(1)
239 elif os.access('.git', os.R_OK):
240 version_msg += " git revision will checked and eventually updated during build"
242 display_msg(conf, version_msg)
244 display_msg(conf)
245 display_msg(conf, "Install prefix", conf.env['PREFIX'], 'CYAN')
247 display_msg(conf, 'Build gladish', yesno(conf.env['BUILD_GLADISH']))
248 display_msg(conf, 'Build liblash', yesno(Options.options.enable_liblash))
249 display_msg(conf, 'Build pylash', yesno(conf.env['BUILD_PYLASH']))
250 display_msg(conf, 'Treat warnings as errors', yesno(conf.env['BUILD_WERROR']))
251 display_msg(conf, 'Debuggable binaries', yesno(conf.env['BUILD_DEBUG']))
252 display_msg(conf, 'Build doxygen documentation', yesno(conf.env['BUILD_DOXYGEN_DOCS']))
254 if conf.env['DBUS_SERVICES_DIR'] != conf.env['DBUS_SERVICES_DIR_REAL']:
255 display_msg(conf)
256 display_line(conf, "WARNING: D-Bus session services directory as reported by pkg-config is", 'RED')
257 display_raw_text(conf, "WARNING:", 'RED')
258 display_line(conf, conf.env['DBUS_SERVICES_DIR_REAL'], 'CYAN')
259 display_line(conf, 'WARNING: but service file will be installed in', 'RED')
260 display_raw_text(conf, "WARNING:", 'RED')
261 display_line(conf, conf.env['DBUS_SERVICES_DIR'], 'CYAN')
262 display_line(conf, 'WARNING: You may need to adjust your D-Bus configuration after installing ladish', 'RED')
263 display_line(conf, 'WARNING: You can override dbus service install directory', 'RED')
264 display_line(conf, 'WARNING: with --enable-pkg-config-dbus-service-dir option to this script', 'RED')
266 display_msg(conf, 'C compiler flags', repr(conf.env['CFLAGS']))
267 display_msg(conf, 'C++ compiler flags', repr(conf.env['CXXFLAGS']))
269 if not conf.env['BUILD_GLADISH']:
270 display_msg(conf)
271 display_line(conf, "WARNING: The GUI frontend will not built", 'RED')
273 display_msg(conf)
275 def git_ver(self):
276 bld = self.generator.bld
277 header = self.outputs[0].abspath()
278 if os.access('../version.h', os.R_OK):
279 shutil.copy('../version.h', header)
280 data = file(header).read()
281 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
282 if m != None:
283 self.ver = m.group(1)
284 pprint('BLUE', "tarball from git revision " + self.ver)
285 else:
286 self.ver = "tarball"
287 return
289 if bld.srcnode.find_node('.git'):
290 self.ver = bld.cmd_and_log("LANG= git rev-parse HEAD", quiet=waflib.Context.BOTH).splitlines()[0]
291 if bld.cmd_and_log("LANG= git diff-index --name-only HEAD", quiet=waflib.Context.BOTH).splitlines():
292 self.ver += "-dirty"
294 pprint('BLUE', "git revision " + self.ver)
295 else:
296 self.ver = "unknown"
298 fi = open(header, 'w')
299 fi.write('#define GIT_VERSION "%s"\n' % self.ver)
300 fi.close()
302 def build(bld):
303 if not bld.env['DATA_DIR']:
304 raise "DATA_DIR is emtpy"
306 bld(rule=git_ver, target='version.h', update_outputs=True, always=True, ext_out=['.h'])
308 daemon = bld.program(source = [], features = 'c cprogram', includes = [bld.path.get_bld()])
309 daemon.target = 'ladishd'
310 daemon.uselib = 'DBUS-1 UUID EXPAT DL UTIL'
311 daemon.ver_header = 'version.h'
312 # Make backtrace function lookup to work for functions in the executable itself
313 daemon.env.append_value("LINKFLAGS", ["-Wl,-E"])
315 for source in [
316 'main.c',
317 'loader.c',
318 'log.c',
319 'sigsegv.c',
320 'proctitle.c',
321 'appdb.c',
322 'procfs.c',
323 'control.c',
324 'studio.c',
325 'graph.c',
326 'client.c',
327 'port.c',
328 'virtualizer.c',
329 'dict.c',
330 'graph_dict.c',
331 'escape.c',
332 'studio_jack_conf.c',
333 'studio_list.c',
334 'save.c',
335 'load.c',
336 'cmd_load_studio.c',
337 'cmd_new_studio.c',
338 'cmd_rename_studio.c',
339 'cmd_save_studio.c',
340 'cmd_start_studio.c',
341 'cmd_stop_studio.c',
342 'cmd_unload_studio.c',
343 'cmd_new_app.c',
344 'cmd_change_app_state.c',
345 'cmd_remove_app.c',
346 'cmd_create_room.c',
347 'cmd_delete_room.c',
348 'cmd_save_project.c',
349 'cmd_unload_project.c',
350 'cmd_load_project.c',
351 'cmd_exit.c',
352 'cqueue.c',
353 'app_supervisor.c',
354 'room.c',
355 'room_save.c',
356 'room_load.c',
357 'recent_store.c',
358 'recent_projects.c',
360 daemon.source.append(os.path.join("daemon", source))
362 for source in [
363 'jack_proxy.c',
364 'graph_proxy.c',
365 'a2j_proxy.c',
366 "jmcore_proxy.c",
367 "notify_proxy.c",
368 "conf_proxy.c",
370 daemon.source.append(os.path.join("proxies", source))
372 for source in [
373 'signal.c',
374 'method.c',
375 'error.c',
376 'object_path.c',
377 'interface.c',
378 'helpers.c',
380 daemon.source.append(os.path.join("dbus", source))
382 for source in [
383 'time.c',
384 'dirhelpers.c',
385 'catdup.c',
387 daemon.source.append(os.path.join("common", source))
389 daemon.source.append(os.path.join("alsapid", "helper.c"))
391 # process dbus.service.in -> ladish.service
392 create_service_taskgen(bld, DBUS_NAME_BASE + '.service', DBUS_NAME_BASE, daemon.target)
394 #####################################################
395 # jmcore
396 jmcore = bld.program(source = [], features = 'c cprogram', includes = [bld.path.get_bld()])
397 jmcore.target = 'jmcore'
398 jmcore.uselib = 'DBUS-1 JACK'
399 jmcore.defines = ['LOG_OUTPUT_STDOUT']
400 jmcore.source = ['jmcore.c']
402 for source in [
403 #'signal.c',
404 'method.c',
405 'error.c',
406 'object_path.c',
407 'interface.c',
408 'helpers.c',
410 jmcore.source.append(os.path.join("dbus", source))
412 create_service_taskgen(bld, DBUS_NAME_BASE + '.jmcore.service', DBUS_NAME_BASE + ".jmcore", jmcore.target)
414 #####################################################
415 # conf
416 ladiconfd = bld.program(source = [], features = 'c cprogram', includes = [bld.path.get_bld()])
417 ladiconfd.target = 'ladiconfd'
418 ladiconfd.uselib = 'DBUS-1'
419 ladiconfd.defines = ['LOG_OUTPUT_STDOUT']
420 ladiconfd.source = ['conf.c']
422 for source in [
423 'dirhelpers.c',
424 'catdup.c',
426 ladiconfd.source.append(os.path.join("common", source))
428 for source in [
429 'signal.c',
430 'method.c',
431 'error.c',
432 'object_path.c',
433 'interface.c',
434 'helpers.c',
436 ladiconfd.source.append(os.path.join("dbus", source))
438 create_service_taskgen(bld, DBUS_NAME_BASE + '.conf.service', DBUS_NAME_BASE + ".conf", ladiconfd.target)
440 #####################################################
441 # alsapid
442 bld.shlib(source = [os.path.join("alsapid", 'lib.c'), os.path.join("alsapid", "helper.c")], target = 'alsapid', uselib = 'DL')
444 #####################################################
445 # liblash
446 if bld.env['BUILD_LIBLASH']:
447 liblash = bld.shlib(source = [], features = 'c cshlib', includes = [bld.path.get_bld()])
448 liblash.uselib = 'DBUS-1'
449 liblash.target = 'lash'
450 liblash.vnum = "1.1.1"
451 liblash.defines = ['LOG_OUTPUT_STDOUT']
452 liblash.source = [os.path.join("lash_compat", "liblash", 'lash.c'), os.path.join("common", "catdup.c")]
454 bld.install_files('${PREFIX}/include/lash', bld.path.ant_glob('lash_compat/liblash/lash/*.h'))
456 # process lash-1.0.pc.in -> lash-1.0.pc
457 bld(
458 features = 'subst', # the feature 'subst' overrides the source/target processing
459 source = os.path.join("lash_compat", 'lash-1.0.pc.in'), # list of string or nodes
460 target = 'lash-1.0.pc', # list of strings or nodes
461 install_path = '${LIBDIR}/pkgconfig/',
462 # variables to use in the substitution
463 prefix = bld.env['PREFIX'],
464 exec_prefix = bld.env['PREFIX'],
465 libdir = bld.env['LIBDIR'],
466 includedir = os.path.normpath(bld.env['PREFIX'] + '/include'))
468 #####################################################
469 # pylash
470 if bld.env['BUILD_PYLASH']:
471 pylash = bld.shlib(features = 'c cshlib pyext', source = [])
472 pylash.target = '_lash'
473 pylash.use = 'lash'
474 pylash.install_path = '${PYTHONDIR}'
476 for source in [
477 'lash.c',
478 'lash_wrap.c',
480 pylash.source.append(os.path.join("lash_compat", "pylash", source))
482 bld.install_files('${PYTHONDIR}', os.path.join("lash_compat", "pylash", "lash.py"))
484 #####################################################
485 # gladish
486 if bld.env['BUILD_GLADISH']:
487 gladish = bld.program(source = [], features = 'c cxx cxxprogram', includes = [bld.path.get_bld()])
488 gladish.target = 'gladish'
489 gladish.defines = ['LOG_OUTPUT_STDOUT']
490 gladish.uselib = 'DBUS-1 DBUS-GLIB-1 FLOWCANVAS'
492 gladish.source = []
494 for source in [
495 'main.c',
496 'load_project_dialog.c',
497 'save_project_dialog.c',
498 'world_tree.c',
499 'graph_view.c',
500 'canvas.cpp',
501 'graph_canvas.c',
502 'gtk_builder.c',
503 'ask_dialog.c',
504 'create_room_dialog.c',
505 'menu.c',
506 'dynmenu.c',
507 'toolbar.c',
508 'about.c',
509 'dbus.c',
510 'studio.c',
511 'studio_list.c',
512 'dialogs.c',
513 'jack.c',
514 'control.c',
515 'pixbuf.c',
516 'room.c',
517 'statusbar.c',
518 'action.c',
519 'settings.c',
520 'zoom.c',
522 gladish.source.append(os.path.join("gui", source))
524 for source in [
525 'jack_proxy.c',
526 'graph_proxy.c',
527 'studio_proxy.c',
528 'control_proxy.c',
529 'app_supervisor_proxy.c',
530 "room_proxy.c",
531 "conf_proxy.c",
533 gladish.source.append(os.path.join("proxies", source))
535 for source in [
536 'method.c',
537 'helpers.c',
539 gladish.source.append(os.path.join("dbus", source))
541 for source in [
542 'catdup.c',
543 'file.c',
545 gladish.source.append(os.path.join("common", source))
547 # GtkBuilder UI definitions (XML)
548 bld.install_files('${DATA_DIR}', 'gui/gladish.ui')
550 # Help text
551 bld.install_files('${DATA_DIR}/help', 'gui/help/default.txt')
553 bld.install_files('${PREFIX}/bin', 'ladish_control', chmod=0755)
555 # 'Desktop' file (menu entry, icon, etc)
556 bld.install_files('${PREFIX}/share/applications/', 'gui/gladish.desktop', chmod=0644)
558 # Icons
559 icon_sizes = ['16x16', '22x22', '24x24', '32x32', '48x48', '256x256']
560 for icon_size in icon_sizes:
561 bld.path.ant_glob('art/' + icon_size + '/apps/*.png')
562 bld.install_files('${PREFIX}/share/icons/hicolor/' + icon_size + '/apps/', 'art/' + icon_size + '/apps/gladish.png')
564 status_images = []
565 for status in ["down", "unloaded", "started", "stopped", "warning", "error"]:
566 status_images.append("art/status_" + status + ".png")
568 bld.install_files('${DATA_DIR}', status_images)
569 bld.install_files('${DATA_DIR}', "art/ladish-logo-128x128.png")
570 bld.install_files('${DATA_DIR}', ["COPYING", "AUTHORS", "README", "NEWS"])
572 if bld.env['BUILD_DOXYGEN_DOCS'] == True:
573 html_docs_source_dir = "build/default/html"
574 if bld.cmd == 'clean':
575 if os.access(html_docs_source_dir, os.R_OK):
576 pprint('CYAN', "Removing doxygen generated documentation...")
577 shutil.rmtree(html_docs_source_dir)
578 pprint('CYAN', "Removing doxygen generated documentation done.")
579 elif bld.cmd == 'build':
580 if not os.access(html_docs_source_dir, os.R_OK):
581 os.popen("doxygen").read()
582 else:
583 pprint('CYAN', "doxygen documentation already built.")
585 def get_tags_dirs():
586 source_root = os.path.dirname(Utils.g_module.root_path)
587 if 'relpath' in os.path.__all__:
588 source_root = os.path.relpath(source_root)
589 paths = source_root
590 paths += " " + os.path.join(source_root, "common")
591 paths += " " + os.path.join(source_root, "dbus")
592 paths += " " + os.path.join(source_root, "proxies")
593 paths += " " + os.path.join(source_root, "daemon")
594 paths += " " + os.path.join(source_root, "gui")
595 paths += " " + os.path.join(source_root, "example-apps")
596 paths += " " + os.path.join(source_root, "lib")
597 paths += " " + os.path.join(source_root, "lash_compat", "liblash")
598 paths += " " + os.path.join(source_root, "lash_compat", "liblash", "lash")
599 return paths
601 def gtags(ctx):
602 '''build tag files for GNU global'''
603 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | gtags --statistics -f -" % get_tags_dirs()
604 #print("Running: %s" % cmd)
605 os.system(cmd)
607 def etags(ctx):
608 '''build TAGS file using etags'''
609 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | etags -" % get_tags_dirs()
610 #print("Running: %s" % cmd)
611 os.system(cmd)
612 os.system("stat -c '%y' TAGS")
614 def dist_hook():
615 #print repr(Options.options)
616 if Options.options.distnodeps:
617 shutil.rmtree('laditools')
618 shutil.rmtree('flowcanvas')
619 shutil.rmtree('jack2')
620 shutil.rmtree('a2jmidid')
621 nodist_files = ['.gitmodules', 'GTAGS', 'GRTAGS', 'GPATH', 'GSYMS'] # waf does not ignore these file
622 for nodist_file in nodist_files:
623 if os.access(nodist_file, os.F_OK):
624 os.remove(nodist_file)
625 shutil.copy('../build/default/version.h', "./")