on project load adjust canvas positions of capture/playback clients
[ladish.git] / wscript
blobb7f08a54d029234d0171615f9048ba4409b1013f
1 #! /usr/bin/env python
2 # encoding: utf-8
4 import os
5 import Options
6 import Utils
7 import shutil
8 import re
10 APPNAME='ladish'
11 VERSION='0.3'
12 DBUS_NAME_BASE = 'org.ladish'
13 RELEASE = False
15 # these variables are mandatory ('/' are converted automatically)
16 srcdir = '.'
17 blddir = 'build'
19 def display_msg(conf, msg="", status = None, color = None):
20 if status:
21 conf.check_message_1(msg)
22 conf.check_message_2(status, color)
23 else:
24 Utils.pprint('NORMAL', msg)
26 def display_raw_text(conf, text, color = 'NORMAL'):
27 Utils.pprint(color, text, sep = '')
29 def display_line(conf, text, color = 'NORMAL'):
30 Utils.pprint(color, text, sep = os.linesep)
32 def yesno(bool):
33 if bool:
34 return "yes"
35 else:
36 return "no"
38 def set_options(opt):
39 opt.tool_options('compiler_cc')
40 opt.tool_options('compiler_cxx')
41 opt.tool_options('boost')
42 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')
43 opt.add_option('--enable-liblash', action='store_true', default=False, help='Build LASH compatibility library')
44 if RELEASE:
45 opt.add_option('--debug', action='store_true', default=False, dest='debug', help="Build debuggable binaries")
46 opt.add_option('--doxygen', action='store_true', default=False, help='Enable build of doxygen documentation')
48 def add_cflag(conf, flag):
49 conf.env.append_unique('CXXFLAGS', flag)
50 conf.env.append_unique('CCFLAGS', flag)
52 def add_linkflag(conf, flag):
53 conf.env.append_unique('LINKFLAGS', flag)
55 def check_gcc_optimizations_enabled(flags):
56 gcc_optimizations_enabled = False
57 for flag in flags:
58 if len(flag) < 2 or flag[0] != '-' or flag[1] != 'O':
59 continue
60 if len(flag) == 2:
61 gcc_optimizations_enabled = True;
62 else:
63 gcc_optimizations_enabled = flag[2] != '0';
64 return gcc_optimizations_enabled
66 def configure(conf):
67 conf.check_tool('compiler_cc')
68 conf.check_tool('compiler_cxx')
69 conf.check_tool('boost')
71 conf.check_cfg(
72 package = 'jack',
73 mandatory = True,
74 errmsg = "not installed, see http://jackaudio.org/",
75 args = '--cflags --libs')
77 conf.check_cfg(
78 package = 'dbus-1',
79 atleast_version = '1.0.0',
80 mandatory = True,
81 errmsg = "not installed, see http://dbus.freedesktop.org/",
82 args = '--cflags --libs')
84 dbus_dir = conf.check_cfg(package='dbus-1', args='--variable=session_bus_services_dir', msg="Retrieving D-Bus services dir")
85 if not dbus_dir:
86 return
88 dbus_dir = dbus_dir.strip()
89 conf.env['DBUS_SERVICES_DIR_REAL'] = dbus_dir
91 if Options.options.enable_pkg_config_dbus_service_dir:
92 conf.env['DBUS_SERVICES_DIR'] = dbus_dir
93 else:
94 conf.env['DBUS_SERVICES_DIR'] = os.path.join(os.path.normpath(conf.env['PREFIX']), 'share', 'dbus-1', 'services')
96 conf.env['LIBDIR'] = os.path.join(os.path.normpath(conf.env['PREFIX']), 'lib')
98 conf.env['BUILD_LIBLASH'] = Options.options.enable_liblash
99 conf.env['BUILD_DOXYGEN_DOCS'] = Options.options.doxygen
101 conf.check_cfg(
102 package = 'uuid',
103 mandatory = True,
104 errmsg = "not installed, see http://e2fsprogs.sourceforge.net/",
105 args = '--cflags --libs')
107 conf.check(
108 header_name='expat.h',
109 mandatory = True,
110 errmsg = "not installed, see http://expat.sourceforge.net/")
112 conf.env['LIB_EXPAT'] = ['expat']
114 build_gui = True
116 if build_gui and not conf.check_cfg(
117 package = 'glib-2.0',
118 mandatory = False,
119 errmsg = "not installed, see http://www.gtk.org/",
120 args = '--cflags --libs'):
121 build_gui = False
123 if build_gui and not conf.check_cfg(
124 package = 'dbus-glib-1',
125 mandatory = False,
126 errmsg = "not installed, see http://dbus.freedesktop.org/",
127 args = '--cflags --libs'):
128 build_gui = False
130 if build_gui and not conf.check_cfg(
131 package = 'gtk+-2.0',
132 mandatory = False,
133 atleast_version = '2.16.0',
134 errmsg = "not installed, see http://www.gtk.org/",
135 args = '--cflags --libs'):
136 build_gui = False
138 if build_gui and not conf.check_cfg(
139 package = 'flowcanvas',
140 mandatory = False,
141 atleast_version = '0.6.0',
142 errmsg = "not installed, see http://drobilla.net/software/flowcanvas/",
143 args = '--cflags --libs'):
144 build_gui = False
146 if build_gui:
147 # We need the boost headers package (e.g. libboost-dev)
148 # shared_ptr.hpp and weak_ptr.hpp
149 build_gui = conf.check_boost(errmsg="not found, see http://boost.org/")
151 conf.env['BUILD_GLADISH'] = build_gui
153 conf.env['BUILD_WERROR'] = not RELEASE
154 if conf.env['BUILD_WERROR']:
155 add_cflag(conf, '-Wall')
156 add_cflag(conf, '-Werror')
157 # for pre gcc-4.4, enable optimizations so use of uninitialized variables gets detected
158 try:
159 is_gcc = conf.env['CC_NAME'] == 'gcc'
160 if is_gcc:
161 gcc_ver = []
162 for n in conf.env['CC_VERSION']:
163 gcc_ver.append(int(n))
164 if gcc_ver[0] < 4 or gcc_ver[1] < 4:
165 #print "optimize force enable is required"
166 if not check_gcc_optimizations_enabled(conf.env['CCFLAGS']):
167 print "C optimization forced in order to enable -Wuninitialized"
168 conf.env.append_unique('CCFLAGS', "-O")
169 except:
170 pass
172 conf.env['BUILD_DEBUG'] = not RELEASE or Options.options.debug
173 if conf.env['BUILD_DEBUG']:
174 add_cflag(conf, '-g')
175 add_linkflag(conf, '-g')
177 conf.define('DATA_DIR', os.path.normpath(os.path.join(conf.env['PREFIX'], 'share', APPNAME)))
178 conf.define('PACKAGE_VERSION', VERSION)
179 conf.define('DBUS_NAME_BASE', DBUS_NAME_BASE)
180 conf.define('DBUS_BASE_PATH', '/' + DBUS_NAME_BASE.replace('.', '/'))
181 conf.define('BASE_NAME', APPNAME)
182 conf.define('_GNU_SOURCE', 1)
183 conf.write_config_header('config.h')
185 display_msg(conf)
187 display_msg(conf, "==================")
188 version_msg = APPNAME + "-" + VERSION
190 if os.access('version.h', os.R_OK):
191 data = file('version.h').read()
192 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
193 if m != None:
194 version_msg += " exported from " + m.group(1)
195 elif os.access('.git', os.R_OK):
196 version_msg += " git revision will checked and eventually updated during build"
198 display_msg(conf, version_msg)
200 display_msg(conf)
201 display_msg(conf, "Install prefix", conf.env['PREFIX'], 'CYAN')
203 display_msg(conf, 'Build gladish', yesno(conf.env['BUILD_GLADISH']))
204 display_msg(conf, 'Build liblash', yesno(Options.options.enable_liblash))
205 display_msg(conf, 'Treat warnings as errors', yesno(conf.env['BUILD_WERROR']))
206 display_msg(conf, 'Debuggable binaries', yesno(conf.env['BUILD_DEBUG']))
207 display_msg(conf, 'Build doxygen documentation', yesno(conf.env['BUILD_DOXYGEN_DOCS']))
209 if conf.env['DBUS_SERVICES_DIR'] != conf.env['DBUS_SERVICES_DIR_REAL']:
210 display_msg(conf)
211 display_line(conf, "WARNING: D-Bus session services directory as reported by pkg-config is", 'RED')
212 display_raw_text(conf, "WARNING:", 'RED')
213 display_line(conf, conf.env['DBUS_SERVICES_DIR_REAL'], 'CYAN')
214 display_line(conf, 'WARNING: but service file will be installed in', 'RED')
215 display_raw_text(conf, "WARNING:", 'RED')
216 display_line(conf, conf.env['DBUS_SERVICES_DIR'], 'CYAN')
217 display_line(conf, 'WARNING: You may need to adjust your D-Bus configuration after installing ladish', 'RED')
218 display_line(conf, 'WARNING: You can override dbus service install directory', 'RED')
219 display_line(conf, 'WARNING: with --enable-pkg-config-dbus-service-dir option to this script', 'RED')
221 display_msg(conf, 'C compiler flags', conf.env['CCFLAGS'])
222 display_msg(conf, 'C++ compiler flags', conf.env['CXXFLAGS'])
224 display_msg(conf)
226 def build(bld):
227 daemon = bld.new_task_gen('cc', 'program')
228 daemon.target = 'ladishd'
229 daemon.includes = "build/default" # XXX config.h version.h and other generated files
230 daemon.uselib = 'DBUS-1 UUID EXPAT'
231 daemon.ver_header = 'version.h'
232 daemon.env.append_value("LINKFLAGS", ["-lutil", "-ldl", "-Wl,-E"])
234 daemon.source = [
235 'catdup.c',
238 for source in [
239 'main.c',
240 'loader.c',
241 'log.c',
242 'dirhelpers.c',
243 'sigsegv.c',
244 'proctitle.c',
245 'appdb.c',
246 'procfs.c',
247 'control.c',
248 'studio.c',
249 'graph.c',
250 'client.c',
251 'port.c',
252 'virtualizer.c',
253 'dict.c',
254 'graph_dict.c',
255 'escape.c',
256 'studio_jack_conf.c',
257 'save.c',
258 'load.c',
259 'cmd_load_studio.c',
260 'cmd_new_studio.c',
261 'cmd_rename_studio.c',
262 'cmd_save_studio.c',
263 'cmd_start_studio.c',
264 'cmd_stop_studio.c',
265 'cmd_unload_studio.c',
266 'cmd_new_app.c',
267 'cmd_change_app_state.c',
268 'cmd_remove_app.c',
269 'cmd_create_room.c',
270 'cmd_delete_room.c',
271 'cmd_save_project.c',
272 'cmd_unload_project.c',
273 'cmd_load_project.c',
274 'cmd_exit.c',
275 'cqueue.c',
276 'app_supervisor.c',
277 'room.c',
278 'room_save.c',
279 'room_load.c',
281 daemon.source.append(os.path.join("daemon", source))
283 for source in [
284 'jack_proxy.c',
285 'graph_proxy.c',
286 'a2j_proxy.c',
287 "jmcore_proxy.c",
288 "notify_proxy.c",
290 daemon.source.append(os.path.join("proxies", source))
292 for source in [
293 'signal.c',
294 'method.c',
295 'error.c',
296 'object_path.c',
297 'interface.c',
298 'helpers.c',
300 daemon.source.append(os.path.join("dbus", source))
302 for source in [
303 'time.c',
305 daemon.source.append(os.path.join("common", source))
307 # process dbus.service.in -> ladish.service
308 import misc
309 obj = bld.new_task_gen('subst')
310 obj.source = os.path.join('daemon', 'dbus.service.in')
311 obj.target = DBUS_NAME_BASE + '.service'
312 obj.dict = {'dbus_object_path': DBUS_NAME_BASE,
313 'daemon_bin_path': os.path.join(bld.env['PREFIX'], 'bin', daemon.target)}
314 obj.install_path = bld.env['DBUS_SERVICES_DIR'] + os.path.sep
315 obj.fun = misc.subst_func
317 #####################################################
318 # jmcore
319 jmcore = bld.new_task_gen('cc', 'program')
320 jmcore.target = 'jmcore'
321 jmcore.includes = "build/default" # XXX config.h version.h and other generated files
322 jmcore.uselib = 'DBUS-1 JACK'
323 jmcore.defines = ['LOG_OUTPUT_STDOUT']
324 jmcore.source = ['jmcore.c']
326 for source in [
327 #'signal.c',
328 'method.c',
329 'error.c',
330 'object_path.c',
331 'interface.c',
332 'helpers.c',
334 jmcore.source.append(os.path.join("dbus", source))
336 if bld.env['BUILD_LIBLASH']:
337 liblash = bld.new_task_gen('cc', 'shlib')
338 liblash.includes = "build/default" # XXX config.h version.h and other generated files
339 liblash.uselib = 'DBUS-1'
340 liblash.target = 'lash'
341 liblash.vnum = "1.1.1"
342 liblash.defines = ['LOG_OUTPUT_STDOUT']
343 liblash.source = [os.path.join("lash_compat", "liblash", 'lash.c')]
345 bld.install_files('${PREFIX}/include/lash', 'lash_compat/liblash/lash/*.h')
347 # process lash-1.0.pc.in -> lash-1.0.pc
348 obj = bld.new_task_gen('subst')
349 obj.source = [os.path.join("lash_compat", 'lash-1.0.pc.in')]
350 obj.target = 'lash-1.0.pc'
351 obj.dict = {'prefix': bld.env['PREFIX'],
352 'exec_prefix': bld.env['PREFIX'],
353 'libdir': bld.env['LIBDIR'],
354 'includedir': os.path.normpath(bld.env['PREFIX'] + '/include'),
356 obj.install_path = '${LIBDIR}/pkgconfig/'
357 obj.fun = misc.subst_func
359 obj = bld.new_task_gen('subst')
360 obj.source = os.path.join('daemon', 'dbus.service.in')
361 obj.target = DBUS_NAME_BASE + '.jmcore.service'
362 obj.dict = {'dbus_object_path': DBUS_NAME_BASE + ".jmcore",
363 'daemon_bin_path': os.path.join(bld.env['PREFIX'], 'bin', jmcore.target)}
364 obj.install_path = bld.env['DBUS_SERVICES_DIR'] + os.path.sep
365 obj.fun = misc.subst_func
367 #####################################################
368 # pylash
370 # pkgpyexec_LTLIBRARIES = _lash.la
371 # INCLUDES = $(PYTHON_INCLUDES)
372 # _lash_la_LDFLAGS = -module -avoid-version ../liblash/liblash.la
373 # _lash_la_SOURCES = lash.c lash.h lash_wrap.c
374 # pkgpyexec_SCRIPTS = lash.py
375 # CLEANFILES = lash_wrap.c lash.py lash.pyc zynjacku.defs
376 # EXTRA_DIST = test.py lash.i lash.py
377 # lash_wrap.c lash.py: lash.i lash.h
378 # swig -o lash_wrap.c -I$(top_srcdir) -python $(top_srcdir)/$(subdir)/lash.i
380 #####################################################
381 # gladish
382 if bld.env['BUILD_GLADISH']:
383 gladish = bld.new_task_gen('cxx', 'program')
384 gladish.features.append('cc')
385 gladish.target = 'gladish'
386 gladish.defines = ['LOG_OUTPUT_STDOUT']
387 gladish.includes = "build/default" # XXX config.h version.h and other generated files
388 gladish.uselib = 'DBUS-1 DBUS-GLIB-1 FLOWCANVAS'
390 gladish.source = [
391 'catdup.c',
394 for source in [
395 'main.c',
396 'load_project_dialog.c',
397 'save_project_dialog.c',
398 'world_tree.c',
399 'graph_view.c',
400 'canvas.cpp',
401 'graph_canvas.c',
402 'gtk_builder.c',
403 'ask_dialog.c',
404 'create_room_dialog.c',
405 'menu.c',
407 gladish.source.append(os.path.join("gui", source))
409 for source in [
410 'jack_proxy.c',
411 'graph_proxy.c',
412 'studio_proxy.c',
413 'control_proxy.c',
414 'app_supervisor_proxy.c',
415 "room_proxy.c",
417 gladish.source.append(os.path.join("proxies", source))
419 for source in [
420 'method.c',
421 'helpers.c',
423 gladish.source.append(os.path.join("dbus", source))
425 # GtkBuilder UI definitions (XML)
426 bld.install_files(bld.env['DATA_DIR'], 'gui/gladish.ui')
428 bld.install_files('${PREFIX}/bin', 'ladish_control', chmod=0755)
430 # 'Desktop' file (menu entry, icon, etc)
431 bld.install_files('${PREFIX}/share/applications/', 'gui/gladish.desktop', chmod=0644)
433 # Icons
434 icon_sizes = ['16x16', '22x22', '24x24', '32x32', '48x48', '256x256']
435 for icon_size in icon_sizes:
436 bld.install_files('${PREFIX}/share/icons/hicolor/' + icon_size + '/apps/', 'art/' + icon_size + '/apps/gladish.png')
438 status_images = []
439 for status in ["down", "unloaded", "started", "stopped", "warning", "error"]:
440 status_images.append("art/status_" + status + ".png")
442 bld.install_files(bld.env['DATA_DIR'], status_images)
443 bld.install_files(bld.env['DATA_DIR'], "art/ladish-logo-128x128.png")
444 bld.install_files(bld.env['DATA_DIR'], ["COPYING", "AUTHORS", "README", "NEWS"])
446 if bld.env['BUILD_DOXYGEN_DOCS'] == True:
447 html_docs_source_dir = "build/default/html"
448 if Options.commands['clean']:
449 if os.access(html_docs_source_dir, os.R_OK):
450 Utils.pprint('CYAN', "Removing doxygen generated documentation...")
451 shutil.rmtree(html_docs_source_dir)
452 Utils.pprint('CYAN', "Removing doxygen generated documentation done.")
453 elif Options.commands['build']:
454 if not os.access(html_docs_source_dir, os.R_OK):
455 os.popen("doxygen").read()
456 else:
457 Utils.pprint('CYAN', "doxygen documentation already built.")
459 def get_tags_dirs():
460 source_root = os.path.dirname(Utils.g_module.root_path)
461 if 'relpath' in os.path.__all__:
462 source_root = os.path.relpath(source_root)
463 paths = source_root
464 paths += " " + os.path.join(source_root, "common")
465 paths += " " + os.path.join(source_root, "dbus")
466 paths += " " + os.path.join(source_root, "proxies")
467 paths += " " + os.path.join(source_root, "daemon")
468 paths += " " + os.path.join(source_root, "gui")
469 paths += " " + os.path.join(source_root, "example-apps")
470 paths += " " + os.path.join(source_root, "lib")
471 paths += " " + os.path.join(source_root, "lash_compat", "liblash")
472 paths += " " + os.path.join(source_root, "lash_compat", "liblash", "lash")
473 return paths
475 def gtags(ctx):
476 '''build tag files for GNU global'''
477 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | gtags --statistics -f -" % get_tags_dirs()
478 #print("Running: %s" % cmd)
479 os.system(cmd)
481 def etags(ctx):
482 '''build TAGS file using etags'''
483 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | etags -" % get_tags_dirs()
484 #print("Running: %s" % cmd)
485 os.system(cmd)
486 os.system("stat -c '%y' TAGS")
488 def dist_hook():
489 shutil.copy('../build/default/version.h', "./")
491 import commands
492 from Constants import RUN_ME
493 from TaskGen import feature, after
494 import Task, Utils
496 @feature('cc')
497 @after('apply_core')
498 def process_git(self):
499 if getattr(self, 'ver_header', None):
500 tsk = self.create_task('git_ver')
501 tsk.set_outputs(self.path.find_or_declare(self.ver_header))
503 def git_ver(self):
504 header = self.outputs[0].abspath(self.env)
505 if os.access('../version.h', os.R_OK):
506 shutil.copy('../version.h', header)
507 data = file(header).read()
508 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
509 if m != None:
510 self.ver = m.group(1)
511 Utils.pprint('BLUE', "tarball from git revision " + self.ver)
512 else:
513 self.ver = "tarball"
514 return
516 if os.access('../.git', os.R_OK):
517 self.ver = commands.getoutput("LANG= git rev-parse HEAD").splitlines()[0]
518 if commands.getoutput("LANG= git diff-index --name-only HEAD").splitlines():
519 self.ver += "-dirty"
521 Utils.pprint('BLUE', "git revision " + self.ver)
522 else:
523 self.ver = "unknown"
525 fi = open(header, 'w')
526 fi.write('#define GIT_VERSION "%s"\n' % self.ver)
527 fi.close()
529 cls = Task.task_type_from_func('git_ver', vars=[], func=git_ver, color='BLUE', before='cc')
531 def always(self):
532 return RUN_ME
533 cls.runnable_status = always
535 def post_run(self):
536 sg = Utils.h_list(self.ver)
537 node = self.outputs[0]
538 variant = node.variant(self.env)
539 self.generator.bld.node_sigs[variant][node.id] = sg
540 cls.post_run = post_run