waf: option for creating distribution tarballs without git submodules
[ladish.git] / wscript
blob539bd8224ae2d590c6c603a6ba9e0b18c2fd2bd1
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-rc'
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 opt.add_option('--debug', action='store_true', default=False, dest='debug', help="Build debuggable binaries")
45 opt.add_option('--doxygen', action='store_true', default=False, help='Enable build of doxygen documentation')
46 opt.add_option('--distnodeps', action='store_true', default=False, help="When creating distribution tarball, don't package git submodules")
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.4',
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 if Options.options.debug:
168 print "C optimization must be forced in order to enable -Wuninitialized"
169 print "However this will not be made because debug compilation is enabled"
170 else:
171 print "C optimization forced in order to enable -Wuninitialized"
172 conf.env.append_unique('CCFLAGS', "-O")
173 except:
174 pass
176 conf.env['BUILD_DEBUG'] = Options.options.debug
177 if conf.env['BUILD_DEBUG']:
178 add_cflag(conf, '-g')
179 add_cflag(conf, '-O0')
180 add_linkflag(conf, '-g')
182 conf.define('DATA_DIR', os.path.normpath(os.path.join(conf.env['PREFIX'], 'share', APPNAME)))
183 conf.define('PACKAGE_VERSION', VERSION)
184 conf.define('DBUS_NAME_BASE', DBUS_NAME_BASE)
185 conf.define('DBUS_BASE_PATH', '/' + DBUS_NAME_BASE.replace('.', '/'))
186 conf.define('BASE_NAME', APPNAME)
187 conf.define('_GNU_SOURCE', 1)
188 conf.write_config_header('config.h')
190 display_msg(conf)
192 display_msg(conf, "==================")
193 version_msg = APPNAME + "-" + VERSION
195 if os.access('version.h', os.R_OK):
196 data = file('version.h').read()
197 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
198 if m != None:
199 version_msg += " exported from " + m.group(1)
200 elif os.access('.git', os.R_OK):
201 version_msg += " git revision will checked and eventually updated during build"
203 display_msg(conf, version_msg)
205 display_msg(conf)
206 display_msg(conf, "Install prefix", conf.env['PREFIX'], 'CYAN')
208 display_msg(conf, 'Build gladish', yesno(conf.env['BUILD_GLADISH']))
209 display_msg(conf, 'Build liblash', yesno(Options.options.enable_liblash))
210 display_msg(conf, 'Treat warnings as errors', yesno(conf.env['BUILD_WERROR']))
211 display_msg(conf, 'Debuggable binaries', yesno(conf.env['BUILD_DEBUG']))
212 display_msg(conf, 'Build doxygen documentation', yesno(conf.env['BUILD_DOXYGEN_DOCS']))
214 if conf.env['DBUS_SERVICES_DIR'] != conf.env['DBUS_SERVICES_DIR_REAL']:
215 display_msg(conf)
216 display_line(conf, "WARNING: D-Bus session services directory as reported by pkg-config is", 'RED')
217 display_raw_text(conf, "WARNING:", 'RED')
218 display_line(conf, conf.env['DBUS_SERVICES_DIR_REAL'], 'CYAN')
219 display_line(conf, 'WARNING: but service file will be installed in', 'RED')
220 display_raw_text(conf, "WARNING:", 'RED')
221 display_line(conf, conf.env['DBUS_SERVICES_DIR'], 'CYAN')
222 display_line(conf, 'WARNING: You may need to adjust your D-Bus configuration after installing ladish', 'RED')
223 display_line(conf, 'WARNING: You can override dbus service install directory', 'RED')
224 display_line(conf, 'WARNING: with --enable-pkg-config-dbus-service-dir option to this script', 'RED')
226 display_msg(conf, 'C compiler flags', conf.env['CCFLAGS'])
227 display_msg(conf, 'C++ compiler flags', conf.env['CXXFLAGS'])
229 display_msg(conf)
231 def build(bld):
232 daemon = bld.new_task_gen('cc', 'program')
233 daemon.target = 'ladishd'
234 daemon.includes = "build/default" # XXX config.h version.h and other generated files
235 daemon.uselib = 'DBUS-1 UUID EXPAT'
236 daemon.ver_header = 'version.h'
237 daemon.env.append_value("LINKFLAGS", ["-lutil", "-ldl", "-Wl,-E"])
239 daemon.source = [
240 'catdup.c',
243 for source in [
244 'main.c',
245 'loader.c',
246 'log.c',
247 'dirhelpers.c',
248 'sigsegv.c',
249 'proctitle.c',
250 'appdb.c',
251 'procfs.c',
252 'control.c',
253 'studio.c',
254 'graph.c',
255 'client.c',
256 'port.c',
257 'virtualizer.c',
258 'dict.c',
259 'graph_dict.c',
260 'escape.c',
261 'studio_jack_conf.c',
262 'save.c',
263 'load.c',
264 'cmd_load_studio.c',
265 'cmd_new_studio.c',
266 'cmd_rename_studio.c',
267 'cmd_save_studio.c',
268 'cmd_start_studio.c',
269 'cmd_stop_studio.c',
270 'cmd_unload_studio.c',
271 'cmd_new_app.c',
272 'cmd_change_app_state.c',
273 'cmd_remove_app.c',
274 'cmd_create_room.c',
275 'cmd_delete_room.c',
276 'cmd_save_project.c',
277 'cmd_unload_project.c',
278 'cmd_load_project.c',
279 'cmd_exit.c',
280 'cqueue.c',
281 'app_supervisor.c',
282 'room.c',
283 'room_save.c',
284 'room_load.c',
286 daemon.source.append(os.path.join("daemon", source))
288 for source in [
289 'jack_proxy.c',
290 'graph_proxy.c',
291 'a2j_proxy.c',
292 "jmcore_proxy.c",
293 "notify_proxy.c",
295 daemon.source.append(os.path.join("proxies", source))
297 for source in [
298 'signal.c',
299 'method.c',
300 'error.c',
301 'object_path.c',
302 'interface.c',
303 'helpers.c',
305 daemon.source.append(os.path.join("dbus", source))
307 for source in [
308 'time.c',
310 daemon.source.append(os.path.join("common", source))
312 # process dbus.service.in -> ladish.service
313 import misc
314 obj = bld.new_task_gen('subst')
315 obj.source = os.path.join('daemon', 'dbus.service.in')
316 obj.target = DBUS_NAME_BASE + '.service'
317 obj.dict = {'dbus_object_path': DBUS_NAME_BASE,
318 'daemon_bin_path': os.path.join(bld.env['PREFIX'], 'bin', daemon.target)}
319 obj.install_path = bld.env['DBUS_SERVICES_DIR'] + os.path.sep
320 obj.fun = misc.subst_func
322 #####################################################
323 # jmcore
324 jmcore = bld.new_task_gen('cc', 'program')
325 jmcore.target = 'jmcore'
326 jmcore.includes = "build/default" # XXX config.h version.h and other generated files
327 jmcore.uselib = 'DBUS-1 JACK'
328 jmcore.defines = ['LOG_OUTPUT_STDOUT']
329 jmcore.source = ['jmcore.c']
331 for source in [
332 #'signal.c',
333 'method.c',
334 'error.c',
335 'object_path.c',
336 'interface.c',
337 'helpers.c',
339 jmcore.source.append(os.path.join("dbus", source))
341 if bld.env['BUILD_LIBLASH']:
342 liblash = bld.new_task_gen('cc', 'shlib')
343 liblash.includes = "build/default" # XXX config.h version.h and other generated files
344 liblash.uselib = 'DBUS-1'
345 liblash.target = 'lash'
346 liblash.vnum = "1.1.1"
347 liblash.defines = ['LOG_OUTPUT_STDOUT']
348 liblash.source = [os.path.join("lash_compat", "liblash", 'lash.c')]
350 bld.install_files('${PREFIX}/include/lash', 'lash_compat/liblash/lash/*.h')
352 # process lash-1.0.pc.in -> lash-1.0.pc
353 obj = bld.new_task_gen('subst')
354 obj.source = [os.path.join("lash_compat", 'lash-1.0.pc.in')]
355 obj.target = 'lash-1.0.pc'
356 obj.dict = {'prefix': bld.env['PREFIX'],
357 'exec_prefix': bld.env['PREFIX'],
358 'libdir': bld.env['LIBDIR'],
359 'includedir': os.path.normpath(bld.env['PREFIX'] + '/include'),
361 obj.install_path = '${LIBDIR}/pkgconfig/'
362 obj.fun = misc.subst_func
364 obj = bld.new_task_gen('subst')
365 obj.source = os.path.join('daemon', 'dbus.service.in')
366 obj.target = DBUS_NAME_BASE + '.jmcore.service'
367 obj.dict = {'dbus_object_path': DBUS_NAME_BASE + ".jmcore",
368 'daemon_bin_path': os.path.join(bld.env['PREFIX'], 'bin', jmcore.target)}
369 obj.install_path = bld.env['DBUS_SERVICES_DIR'] + os.path.sep
370 obj.fun = misc.subst_func
372 #####################################################
373 # pylash
375 # pkgpyexec_LTLIBRARIES = _lash.la
376 # INCLUDES = $(PYTHON_INCLUDES)
377 # _lash_la_LDFLAGS = -module -avoid-version ../liblash/liblash.la
378 # _lash_la_SOURCES = lash.c lash.h lash_wrap.c
379 # pkgpyexec_SCRIPTS = lash.py
380 # CLEANFILES = lash_wrap.c lash.py lash.pyc zynjacku.defs
381 # EXTRA_DIST = test.py lash.i lash.py
382 # lash_wrap.c lash.py: lash.i lash.h
383 # swig -o lash_wrap.c -I$(top_srcdir) -python $(top_srcdir)/$(subdir)/lash.i
385 #####################################################
386 # gladish
387 if bld.env['BUILD_GLADISH']:
388 gladish = bld.new_task_gen('cxx', 'program')
389 gladish.features.append('cc')
390 gladish.target = 'gladish'
391 gladish.defines = ['LOG_OUTPUT_STDOUT']
392 gladish.includes = "build/default" # XXX config.h version.h and other generated files
393 gladish.uselib = 'DBUS-1 DBUS-GLIB-1 FLOWCANVAS'
395 gladish.source = [
396 'catdup.c',
399 for source in [
400 'main.c',
401 'load_project_dialog.c',
402 'save_project_dialog.c',
403 'world_tree.c',
404 'graph_view.c',
405 'canvas.cpp',
406 'graph_canvas.c',
407 'gtk_builder.c',
408 'ask_dialog.c',
409 'create_room_dialog.c',
410 'menu.c',
412 gladish.source.append(os.path.join("gui", source))
414 for source in [
415 'jack_proxy.c',
416 'graph_proxy.c',
417 'studio_proxy.c',
418 'control_proxy.c',
419 'app_supervisor_proxy.c',
420 "room_proxy.c",
422 gladish.source.append(os.path.join("proxies", source))
424 for source in [
425 'method.c',
426 'helpers.c',
428 gladish.source.append(os.path.join("dbus", source))
430 # GtkBuilder UI definitions (XML)
431 bld.install_files(bld.env['DATA_DIR'], 'gui/gladish.ui')
433 bld.install_files('${PREFIX}/bin', 'ladish_control', chmod=0755)
435 # 'Desktop' file (menu entry, icon, etc)
436 bld.install_files('${PREFIX}/share/applications/', 'gui/gladish.desktop', chmod=0644)
438 # Icons
439 icon_sizes = ['16x16', '22x22', '24x24', '32x32', '48x48', '256x256']
440 for icon_size in icon_sizes:
441 bld.install_files('${PREFIX}/share/icons/hicolor/' + icon_size + '/apps/', 'art/' + icon_size + '/apps/gladish.png')
443 status_images = []
444 for status in ["down", "unloaded", "started", "stopped", "warning", "error"]:
445 status_images.append("art/status_" + status + ".png")
447 bld.install_files(bld.env['DATA_DIR'], status_images)
448 bld.install_files(bld.env['DATA_DIR'], "art/ladish-logo-128x128.png")
449 bld.install_files(bld.env['DATA_DIR'], ["COPYING", "AUTHORS", "README", "NEWS"])
451 if bld.env['BUILD_DOXYGEN_DOCS'] == True:
452 html_docs_source_dir = "build/default/html"
453 if Options.commands['clean']:
454 if os.access(html_docs_source_dir, os.R_OK):
455 Utils.pprint('CYAN', "Removing doxygen generated documentation...")
456 shutil.rmtree(html_docs_source_dir)
457 Utils.pprint('CYAN', "Removing doxygen generated documentation done.")
458 elif Options.commands['build']:
459 if not os.access(html_docs_source_dir, os.R_OK):
460 os.popen("doxygen").read()
461 else:
462 Utils.pprint('CYAN', "doxygen documentation already built.")
464 def get_tags_dirs():
465 source_root = os.path.dirname(Utils.g_module.root_path)
466 if 'relpath' in os.path.__all__:
467 source_root = os.path.relpath(source_root)
468 paths = source_root
469 paths += " " + os.path.join(source_root, "common")
470 paths += " " + os.path.join(source_root, "dbus")
471 paths += " " + os.path.join(source_root, "proxies")
472 paths += " " + os.path.join(source_root, "daemon")
473 paths += " " + os.path.join(source_root, "gui")
474 paths += " " + os.path.join(source_root, "example-apps")
475 paths += " " + os.path.join(source_root, "lib")
476 paths += " " + os.path.join(source_root, "lash_compat", "liblash")
477 paths += " " + os.path.join(source_root, "lash_compat", "liblash", "lash")
478 return paths
480 def gtags(ctx):
481 '''build tag files for GNU global'''
482 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | gtags --statistics -f -" % get_tags_dirs()
483 #print("Running: %s" % cmd)
484 os.system(cmd)
486 def etags(ctx):
487 '''build TAGS file using etags'''
488 cmd = "find %s -mindepth 1 -maxdepth 1 -name '*.[ch]' -print | etags -" % get_tags_dirs()
489 #print("Running: %s" % cmd)
490 os.system(cmd)
491 os.system("stat -c '%y' TAGS")
493 def dist_hook():
494 #print repr(Options.options)
495 if Options.options.distnodeps:
496 shutil.rmtree('laditools')
497 shutil.rmtree('flowcanvas')
498 shutil.rmtree('jack2')
499 shutil.rmtree('a2jmidid')
500 nodist_files = ['.gitmodules', 'GTAGS', 'GRTAGS', 'GPATH', 'GSYMS'] # waf does not ignore these file
501 for nodist_file in nodist_files:
502 os.remove(nodist_file)
503 shutil.copy('../build/default/version.h', "./")
505 import commands
506 from Constants import RUN_ME
507 from TaskGen import feature, after
508 import Task, Utils
510 @feature('cc')
511 @after('apply_core')
512 def process_git(self):
513 if getattr(self, 'ver_header', None):
514 tsk = self.create_task('git_ver')
515 tsk.set_outputs(self.path.find_or_declare(self.ver_header))
517 def git_ver(self):
518 header = self.outputs[0].abspath(self.env)
519 if os.access('../version.h', os.R_OK):
520 shutil.copy('../version.h', header)
521 data = file(header).read()
522 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
523 if m != None:
524 self.ver = m.group(1)
525 Utils.pprint('BLUE', "tarball from git revision " + self.ver)
526 else:
527 self.ver = "tarball"
528 return
530 if os.access('../.git', os.R_OK):
531 self.ver = commands.getoutput("LANG= git rev-parse HEAD").splitlines()[0]
532 if commands.getoutput("LANG= git diff-index --name-only HEAD").splitlines():
533 self.ver += "-dirty"
535 Utils.pprint('BLUE', "git revision " + self.ver)
536 else:
537 self.ver = "unknown"
539 fi = open(header, 'w')
540 fi.write('#define GIT_VERSION "%s"\n' % self.ver)
541 fi.close()
543 cls = Task.task_type_from_func('git_ver', vars=[], func=git_ver, color='BLUE', before='cc')
545 def always(self):
546 return RUN_ME
547 cls.runnable_status = always
549 def post_run(self):
550 sg = Utils.h_list(self.ver)
551 node = self.outputs[0]
552 variant = node.variant(self.env)
553 self.generator.bld.node_sigs[variant][node.id] = sg
554 cls.post_run = post_run