3 from __future__
import print_function
11 from waflib
import Logs
, Options
, Task
, Utils
12 from waflib
.Build
import BuildContext
, CleanContext
, InstallContext
, UninstallContext
16 JACK_API_VERSION
= '0.1.0'
18 # these variables are mandatory ('/' are converted automatically)
22 # lib32 variant name used when building in mixed mode
27 def display_feature(conf
, msg
, build
):
29 conf
.msg(msg
, 'yes', color
='GREEN')
31 conf
.msg(msg
, 'no', color
='YELLOW')
33 # This function prints an error without stopping waf. The reason waf should not
34 # be stopped is to be able to list all missing dependencies in one chunk.
36 print(Logs
.colors
.RED
+ msg
+ Logs
.colors
.NORMAL
)
40 This class is the foundation for the auto options. It adds an option
41 --foo=no|yes to the list of options and deals with all logic and checks for
44 Each option can have different dependencies that will be checked. If all
45 dependencies are available and the user has not done any request the option
46 will be enabled. If the user has requested to enable the option the class
47 ensures that all dependencies are available and prints an error message
48 otherwise. If the user disables the option, i.e. --foo=no, no checks are
51 For each option it is possible to add packages that are required for the
52 option using the add_package function. For dependency programs add_program
53 should be used. For libraries (without pkg-config support) the add_library
54 function should be used. For headers the add_header function exists. If
55 there is another type of requirement or dependency the check hook (an
56 external function called when configuring) can be used.
58 When all checks have been made and the class has made a decision the result
59 is saved in conf.env['NAME'] where 'NAME' by default is the uppercase of the
60 name argument to __init__, but it can be changed with the conf_dest argument
63 The class will define a preprocessor symbol with the result. The default
64 name is HAVE_NAME, but it can be changed using the define argument to
68 def __init__(self
, opt
, name
, help, conf_dest
=None, define
=None):
69 # check hook to call upon configuration
70 self
.check_hook
= None
71 self
.check_hook_error
= None
72 self
.check_hook_found
= True
75 self
.libs
= [] # elements on the form [lib,uselib_store]
76 self
.libs_not_found
= [] # elements on the form lib
80 self
.headers_not_found
= []
82 # required packages (checked with pkg-config)
83 self
.packages
= [] # elements on the form [package,uselib_store,atleast_version]
84 self
.packages_not_found
= [] # elements on the form [package,atleast_version]
87 self
.programs
= [] # elements on the form [program,var]
88 self
.programs_not_found
= [] # elements on the form program
90 # the result of the configuration (should the option be enabled or not?)
94 self
.option
= '--' + name
95 self
.dest
= 'auto_option_' + name
97 self
.conf_dest
= conf_dest
99 self
.conf_dest
= name
.upper()
101 self
.define
= 'HAVE_' + name
.upper()
104 opt
.add_option(self
.option
, type='string', default
='auto', dest
=self
.dest
, help=self
.help+' (enabled by default if possible)', metavar
='no|yes')
106 def add_library(self
, library
, uselib_store
=None):
108 Add a required library that should be checked during configuration. The
109 library will be checked using the conf.check function. If the
110 uselib_store arugment is not given it defaults to LIBRARY (the uppercase
111 of the library argument). The uselib_store argument will be passed to
112 check which means LIB_LIBRARY, CFLAGS_LIBRARY and DEFINES_LIBRARY, etc.
113 will be defined if the option is enabled.
116 uselib_store
= library
.upper().replace('-', '_')
117 self
.libs
.append([library
, uselib_store
])
119 def add_header(self
, header
):
121 Add a required header that should be checked during configuration. The
122 header will be checked using the conf.check function which means
123 HAVE_HEADER_H will be defined if found.
125 self
.headers
.append(header
)
127 def add_package(self
, package
, uselib_store
=None, atleast_version
=None):
129 Add a required package that should be checked using pkg-config during
130 configuration. The package will be checked using the conf.check_cfg
131 function and the uselib_store and atleast_version will be passed to
132 check_cfg. If uselib_store is None it defaults to PACKAGE (uppercase of
133 the package argument) with hyphens and dots replaced with underscores.
134 If atleast_version is None it defaults to '0'.
137 uselib_store
= package
.upper().replace('-', '_').replace('.', '_')
138 if not atleast_version
:
139 atleast_version
= '0'
140 self
.packages
.append([package
, uselib_store
, atleast_version
])
142 def add_program(self
, program
, var
=None):
144 Add a required program that should be checked during configuration. If
145 var is not given it defaults to PROGRAM (the uppercase of the program
146 argument). If the option is enabled the program is saved as a list (?!)
147 in conf.env['PROGRAM'].
150 var
= program
.upper().replace('-', '_')
151 self
.programs
.append([program
, var
])
153 def set_check_hook(self
, check_hook
, check_hook_error
):
155 Set the check hook and the corresponding error printing function to the
156 configure step. The check_hook argument is a function that should return
157 True if the extra prerequisites were found and False if not. The
158 check_hook_error argument is an error printing function that should
159 print an error message telling the user that --foo was explicitly
160 requested but cannot be built since the extra prerequisites were not
161 found. Both function should take a single argument that is the waf
162 configuration context.
164 self
.check_hook
= check_hook
165 self
.check_hook_error
= check_hook_error
167 def _check(self
, conf
):
169 This is an internal function that runs all necessary configure checks.
170 It checks all dependencies (even if some dependency was not found) so
171 that the user can install all missing dependencies in one go, instead
172 of playing the infamous hit-configure-hit-configure game.
174 This function returns True if all dependencies were found and False if
179 # Use-variables that should be used when checking libraries, headers and
180 # programs. The list will be populated when looking for packages.
184 for package
,uselib_store
,atleast_version
in self
.packages
:
186 conf
.check_cfg(package
=package
, uselib_store
=uselib_store
, atleast_version
=atleast_version
, args
='--cflags --libs')
187 use
.append(uselib_store
)
188 except conf
.errors
.ConfigurationError
:
190 self
.packages_not_found
.append([package
,atleast_version
])
192 # check for libraries
193 for lib
,uselib_store
in self
.libs
:
195 conf
.check(lib
=lib
, uselib_store
=uselib_store
, use
=use
)
196 except conf
.errors
.ConfigurationError
:
198 self
.libs_not_found
.append(lib
)
201 for header
in self
.headers
:
203 conf
.check(header_name
=header
, use
=use
)
204 except conf
.errors
.ConfigurationError
:
206 self
.headers_not_found
.append(header
)
209 for program
,var
in self
.programs
:
211 conf
.find_program(program
, var
=var
, use
=use
)
212 except conf
.errors
.ConfigurationError
:
214 self
.programs_not_found
.append(program
)
216 # call hook (if specified)
218 self
.check_hook_found
= self
.check_hook(conf
)
219 if not self
.check_hook_found
:
224 def _configure_error(self
, conf
):
226 This is an internal function that prints errors for each missing
227 dependency. The error messages tell the user that this option required
228 some dependency, but it cannot be found.
231 for lib
in self
.libs_not_found
:
232 print_error('%s requires the %s library, but it cannot be found.' % (self
.option
, lib
))
234 for header
in self
.headers_not_found
:
235 print_error('%s requires the %s header, but it cannot be found.' % (self
.option
, header
))
237 for package
,atleast_version
in self
.packages_not_found
:
240 string
+= ' >= ' + atleast_version
241 print_error('%s requires the package %s, but it cannot be found.' % (self
.option
, string
))
243 for program
in self
.programs_not_found
:
244 print_error('%s requires the %s program, but it cannot be found.' % (self
.option
, program
))
246 if not self
.check_hook_found
:
247 self
.check_hook_error(conf
)
249 def configure(self
, conf
):
251 This function configures the option examining the argument given too
252 --foo (where foo is this option). This function sets self.result to the
253 result of the configuration; True if the option should be enabled or
254 False if not. If not all dependencies were found self.result will shall
255 be False. conf.env['NAME'] will be set to the same value aswell as a
256 preprocessor symbol will be defined according to the result.
258 If --foo[=yes] was given, but some dependency was not found an error
259 message is printed (foreach missing dependency).
261 This function returns True on success and False on error.
263 argument
= getattr(Options
.options
, self
.dest
)
267 elif argument
== 'yes':
268 if self
._check
(conf
):
274 self
._configure
_error
(conf
)
275 elif argument
== 'auto':
276 self
.result
= self
._check
(conf
)
279 print_error('Invalid argument "' + argument
+ '" to ' + self
.option
)
283 conf
.env
[self
.conf_dest
] = self
.result
285 conf
.define(self
.define
, 1)
287 conf
.define(self
.define
, 0)
290 def display_message(self
, conf
):
292 This function displays a result message with the help text and the
293 result of the configuration.
295 display_feature(conf
, self
.help, self
.result
)
297 # This function adds an option to the list of auto options and returns the newly
299 def add_auto_option(opt
, name
, help, conf_dest
=None, define
=None):
300 option
= AutoOption(opt
, name
, help, conf_dest
=conf_dest
, define
=define
)
301 auto_options
.append(option
)
304 # This function applies a hack that for each auto option --foo=no|yes replaces
305 # any occurence --foo in argv with --foo=yes, in effect interpreting --foo as
306 # --foo=yes. The function has to be called before waf issues the option parser,
307 # i.e. before the configure phase.
308 def auto_options_argv_hack():
309 for option
in auto_options
:
310 for x
in range(1, len(sys
.argv
)):
311 if sys
.argv
[x
] == option
.option
:
312 sys
.argv
[x
] += '=yes'
314 # This function configures all auto options. It stops waf and prints an error
315 # message if there were unsatisfied requirements.
316 def configure_auto_options(conf
):
318 for option
in auto_options
:
319 if not option
.configure(conf
):
322 conf
.fatal('There were unsatisfied requirements.')
324 # This function displays all options and the configuration results.
325 def display_auto_options_messages(conf
):
326 for option
in auto_options
:
327 option
.display_message(conf
)
329 def check_for_celt(conf
):
331 for version
in ['11', '8', '7', '5']:
332 define
= 'HAVE_CELT_API_0_' + version
335 conf
.check_cfg(package
='celt', atleast_version
='0.' + version
+ '.0', args
='--cflags --libs')
337 conf
.define(define
, 1)
339 except conf
.errors
.ConfigurationError
:
341 conf
.define(define
, 0)
344 def check_for_celt_error(conf
):
345 print_error('--celt requires the package celt, but it could not be found.')
347 # The readline/readline.h header does not work if stdio.h is not included
348 # before. Thus a fragment with both stdio.h and readline/readline.h need to be
349 # test-compiled to find out whether readline is available.
350 def check_for_readline(conf
):
351 # FIXME: This check can be incorporated into the AutoOptions class by
352 # passing header_name=['stdio.h', 'readline/readline.h'] to check.
354 conf
.check(fragment
='''
356 #include <readline/readline.h>
357 int main(void) { return 0; }''',
359 msg
='Checking for header readline/readline.h',
362 except conf
.errors
.ConfigurationError
:
365 def check_for_readline_error(conf
):
366 print_error('--readline requires the readline/readline.h header, but it cannot be found.')
368 def check_for_mmsystem(conf
):
369 # FIXME: See comment in check_for_readline.
371 conf
.check(fragment
='''
373 #include <mmsystem.h>
374 int main(void) { return 0; }''',
376 msg
='Checking for header mmsystem.h',
379 except conf
.errors
.ConfigurationError
:
382 def check_for_mmsystem_error(conf
):
383 print_error('--winmme requires the mmsystem.h header, but it cannot be found.')
386 # options provided by the modules
387 opt
.load('compiler_cxx')
388 opt
.load('compiler_c')
393 # install directories
394 opt
.add_option('--htmldir', type='string', default
=None, help='HTML documentation directory [Default: <prefix>/share/jack-audio-connection-kit/reference/html/')
395 opt
.add_option('--libdir', type='string', help='Library directory [Default: <prefix>/lib]')
396 opt
.add_option('--libdir32', type='string', help='32bit Library directory [Default: <prefix>/lib32]')
397 opt
.add_option('--mandir', type='string', help='Manpage directory [Default: <prefix>/share/man/man1]')
399 # options affecting binaries
400 opt
.add_option('--platform', type='string', default
=sys
.platform
, help='Target platform for cross-compiling, e.g. cygwin or win32')
401 opt
.add_option('--mixed', action
='store_true', default
=False, help='Build with 32/64 bits mixed mode')
402 opt
.add_option('--debug', action
='store_true', default
=False, dest
='debug', help='Build debuggable binaries')
404 # options affecting general jack functionality
405 opt
.add_option('--classic', action
='store_true', default
=False, help='Force enable standard JACK (jackd) even if D-Bus JACK (jackdbus) is enabled too')
406 opt
.add_option('--dbus', action
='store_true', default
=False, help='Enable D-Bus JACK (jackdbus)')
407 opt
.add_option('--autostart', type='string', default
='default', help='Autostart method. Possible values: "default", "classic", "dbus", "none"')
408 opt
.add_option('--profile', action
='store_true', default
=False, help='Build with engine profiling')
409 opt
.add_option('--clients', default
=64, type='int', dest
='clients', help='Maximum number of JACK clients')
410 opt
.add_option('--ports-per-application', default
=768, type='int', dest
='application_ports', help='Maximum number of ports per application')
412 # options with third party dependencies
413 doxygen
= add_auto_option(opt
, 'doxygen', help='Build doxygen documentation', conf_dest
='BUILD_DOXYGEN_DOCS')
414 doxygen
.add_program('doxygen')
415 alsa
= add_auto_option(opt
, 'alsa', help='Enable ALSA driver', conf_dest
='BUILD_DRIVER_ALSA')
416 alsa
.add_package('alsa', atleast_version
='1.0.18')
417 firewire
= add_auto_option(opt
, 'firewire', help='Enable FireWire driver (FFADO)', conf_dest
='BUILD_DRIVER_FFADO')
418 firewire
.add_package('libffado', atleast_version
='1.999.17')
419 freebob
= add_auto_option(opt
, 'freebob', help='Enable FreeBob driver')
420 freebob
.add_package('libfreebob', atleast_version
='1.0.0')
421 iio
= add_auto_option(opt
, 'iio', help='Enable IIO driver', conf_dest
='BUILD_DRIVER_IIO')
422 iio
.add_package('gtkIOStream', atleast_version
='1.4.0')
423 iio
.add_package('eigen3', atleast_version
='3.1.2')
424 portaudio
= add_auto_option(opt
, 'portaudio', help='Enable Portaudio driver', conf_dest
='BUILD_DRIVER_PORTAUDIO')
425 portaudio
.add_header('windows.h') # only build portaudio on windows
426 portaudio
.add_package('portaudio-2.0', uselib_store
='PORTAUDIO', atleast_version
='19')
427 winmme
= add_auto_option(opt
, 'winmme', help='Enable WinMME driver', conf_dest
='BUILD_DRIVER_WINMME')
428 winmme
.set_check_hook(check_for_mmsystem
, check_for_mmsystem_error
)
430 celt
= add_auto_option(opt
, 'celt', help='Build with CELT')
431 celt
.set_check_hook(check_for_celt
, check_for_celt_error
)
432 opus
= add_auto_option(opt
, 'opus', help='Build Opus netjack2')
433 opus
.add_header('opus/opus_custom.h')
434 opus
.add_package('opus', atleast_version
='0.9.0')
435 samplerate
= add_auto_option(opt
, 'samplerate', help='Build with libsamplerate')
436 samplerate
.add_package('samplerate')
437 sndfile
= add_auto_option(opt
, 'sndfile', help='Build with libsndfile')
438 sndfile
.add_package('sndfile')
439 readline
= add_auto_option(opt
, 'readline', help='Build with readline')
440 readline
.add_library('readline')
441 readline
.set_check_hook(check_for_readline
, check_for_readline_error
)
442 sd
= add_auto_option(opt
, 'systemd', help='Use systemd notify')
443 sd
.add_header('systemd/sd-daemon.h')
444 sd
.add_library('systemd')
449 # this must be called before the configure phase
450 auto_options_argv_hack()
452 def detect_platform(conf
):
453 # GNU/kFreeBSD and GNU/Hurd are treated as Linux
455 # ('KEY, 'Human readable name', ['strings', 'to', 'check', 'for'])
456 ('IS_LINUX', 'Linux', ['gnu0', 'gnukfreebsd', 'linux', 'posix']),
457 ('IS_MACOSX', 'MacOS X', ['darwin']),
458 ('IS_SUN', 'SunOS', ['sunos']),
459 ('IS_WINDOWS', 'Windows', ['cygwin', 'msys', 'win32'])
462 for key
,name
,strings
in platforms
:
463 conf
.env
[key
] = False
465 conf
.start_msg('Checking platform')
466 platform
= Options
.options
.platform
467 for key
,name
,strings
in platforms
:
469 if platform
.startswith(s
):
471 conf
.end_msg(name
, color
='CYAN')
475 conf
.load('compiler_cxx')
476 conf
.load('compiler_c')
478 detect_platform(conf
)
480 if conf
.env
['IS_WINDOWS']:
481 conf
.env
.append_unique('CCDEFINES', '_POSIX')
482 conf
.env
.append_unique('CXXDEFINES', '_POSIX')
484 conf
.env
.append_unique('CXXFLAGS', '-Wall')
485 conf
.env
.append_unique('CFLAGS', '-Wall')
487 if conf
.env
['IS_MACOSX']:
488 conf
.check(lib
='aften', uselib
='AFTEN', define_name
='AFTEN')
490 # configure all auto options
491 configure_auto_options(conf
)
493 # Check for functions.
495 function_name
='ppoll',
496 header_name
=['poll.h', 'signal.h'],
497 defines
=['_GNU_SOURCE'],
500 # Check for backtrace support
502 header_name
='execinfo.h',
503 define_name
='HAVE_EXECINFO_H',
506 conf
.recurse('common')
507 if Options
.options
.dbus
:
509 if conf
.env
['BUILD_JACKDBUS'] != True:
510 conf
.fatal('jackdbus was explicitly requested but cannot be built')
512 conf
.recurse('example-clients')
514 # test for the availability of ucontext, and how it should be used
515 for t
in ['gp_regs', 'uc_regs', 'mc_gregs', 'gregs']:
516 fragment
= '#include <ucontext.h>\n'
517 fragment
+= 'int main() { ucontext_t *ucontext; return (int) ucontext->uc_mcontext.%s[0]; }' % t
518 confvar
= 'HAVE_UCONTEXT_%s' % t
.upper()
519 conf
.check_cc(fragment
=fragment
, define_name
=confvar
, mandatory
=False,
520 msg
='Checking for ucontext->uc_mcontext.%s' % t
)
521 if conf
.is_defined(confvar
):
522 conf
.define('HAVE_UCONTEXT', 1)
524 fragment
= '#include <ucontext.h>\n'
525 fragment
+= 'int main() { return NGREG; }'
526 conf
.check_cc(fragment
=fragment
, define_name
='HAVE_NGREG', mandatory
=False,
527 msg
='Checking for NGREG')
529 conf
.env
['LIB_PTHREAD'] = ['pthread']
530 conf
.env
['LIB_DL'] = ['dl']
531 conf
.env
['LIB_RT'] = ['rt']
532 conf
.env
['LIB_M'] = ['m']
533 conf
.env
['LIB_STDC++'] = ['stdc++']
534 conf
.env
['JACK_API_VERSION'] = JACK_API_VERSION
535 conf
.env
['JACK_VERSION'] = VERSION
537 conf
.env
['BUILD_WITH_PROFILE'] = Options
.options
.profile
538 conf
.env
['BUILD_WITH_32_64'] = Options
.options
.mixed
539 conf
.env
['BUILD_CLASSIC'] = Options
.options
.classic
540 conf
.env
['BUILD_DEBUG'] = Options
.options
.debug
542 if conf
.env
['BUILD_JACKDBUS']:
543 conf
.env
['BUILD_JACKD'] = conf
.env
['BUILD_CLASSIC']
545 conf
.env
['BUILD_JACKD'] = True
547 conf
.env
['BINDIR'] = conf
.env
['PREFIX'] + '/bin'
549 if Options
.options
.htmldir
:
550 conf
.env
['HTMLDIR'] = Options
.options
.htmldir
552 # set to None here so that the doxygen code can find out the highest
553 # directory to remove upon install
554 conf
.env
['HTMLDIR'] = None
556 if Options
.options
.libdir
:
557 conf
.env
['LIBDIR'] = Options
.options
.libdir
559 conf
.env
['LIBDIR'] = conf
.env
['PREFIX'] + '/lib'
561 if Options
.options
.mandir
:
562 conf
.env
['MANDIR'] = Options
.options
.mandir
564 conf
.env
['MANDIR'] = conf
.env
['PREFIX'] + '/share/man/man1'
566 if conf
.env
['BUILD_DEBUG']:
567 conf
.env
.append_unique('CXXFLAGS', '-g')
568 conf
.env
.append_unique('CFLAGS', '-g')
569 conf
.env
.append_unique('LINKFLAGS', '-g')
571 if not Options
.options
.autostart
in ['default', 'classic', 'dbus', 'none']:
572 conf
.fatal('Invalid autostart value "' + Options
.options
.autostart
+ '"')
574 if Options
.options
.autostart
== 'default':
575 if conf
.env
['BUILD_JACKD']:
576 conf
.env
['AUTOSTART_METHOD'] = 'classic'
578 conf
.env
['AUTOSTART_METHOD'] = 'dbus'
580 conf
.env
['AUTOSTART_METHOD'] = Options
.options
.autostart
582 if conf
.env
['AUTOSTART_METHOD'] == 'dbus' and not conf
.env
['BUILD_JACKDBUS']:
583 conf
.fatal('D-Bus autostart mode was specified but jackdbus will not be built')
584 if conf
.env
['AUTOSTART_METHOD'] == 'classic' and not conf
.env
['BUILD_JACKD']:
585 conf
.fatal('Classic autostart mode was specified but jackd will not be built')
587 if conf
.env
['AUTOSTART_METHOD'] == 'dbus':
588 conf
.define('USE_LIBDBUS_AUTOLAUNCH', 1)
589 elif conf
.env
['AUTOSTART_METHOD'] == 'classic':
590 conf
.define('USE_CLASSIC_AUTOLAUNCH', 1)
592 conf
.define('CLIENT_NUM', Options
.options
.clients
)
593 conf
.define('PORT_NUM_FOR_CLIENT', Options
.options
.application_ports
)
595 if conf
.env
['IS_WINDOWS']:
596 # we define this in the environment to maintain compatability with
597 # existing install paths that use ADDON_DIR rather than have to
598 # have special cases for windows each time.
599 conf
.env
['ADDON_DIR'] = conf
.env
['BINDIR'] + '/jack'
600 # don't define ADDON_DIR in config.h, use the default 'jack' defined in
601 # windows/JackPlatformPlug_os.h
603 conf
.env
['ADDON_DIR'] = os
.path
.normpath(os
.path
.join(conf
.env
['LIBDIR'], 'jack'))
604 conf
.define('ADDON_DIR', conf
.env
['ADDON_DIR'])
605 conf
.define('JACK_LOCATION', os
.path
.normpath(os
.path
.join(conf
.env
['PREFIX'], 'bin')))
607 if not conf
.env
['IS_WINDOWS']:
608 conf
.define('USE_POSIX_SHM', 1)
609 conf
.define('JACKMP', 1)
610 if conf
.env
['BUILD_JACKDBUS']:
611 conf
.define('JACK_DBUS', 1)
612 if conf
.env
['BUILD_WITH_PROFILE']:
613 conf
.define('JACK_MONITOR', 1)
614 conf
.write_config_header('config.h', remove
=False)
618 f
= open('svnversion.h')
620 m
= re
.match(r
'^#define SVN_VERSION "([^"]*)"$', data
)
627 if Options
.options
.mixed
:
628 conf
.setenv(lib32
, env
=conf
.env
.derive())
629 conf
.env
.append_unique('CXXFLAGS', '-m32')
630 conf
.env
.append_unique('CFLAGS', '-m32')
631 conf
.env
.append_unique('LINKFLAGS', '-m32')
632 if Options
.options
.libdir32
:
633 conf
.env
['LIBDIR'] = Options
.options
.libdir32
635 conf
.env
['LIBDIR'] = conf
.env
['PREFIX'] + '/lib32'
636 conf
.write_config_header('config.h')
639 print('==================')
640 version_msg
= 'JACK ' + VERSION
642 version_msg
+= ' exported from r' + svnrev
644 version_msg
+= ' svn revision will checked and eventually updated during build'
647 conf
.msg('Maximum JACK clients', Options
.options
.clients
, color
='NORMAL')
648 conf
.msg('Maximum ports per application', Options
.options
.application_ports
, color
='NORMAL')
650 conf
.msg('Install prefix', conf
.env
['PREFIX'], color
='CYAN')
651 conf
.msg('Library directory', conf
.all_envs
['']['LIBDIR'], color
='CYAN')
652 if conf
.env
['BUILD_WITH_32_64']:
653 conf
.msg('32-bit library directory', conf
.all_envs
[lib32
]['LIBDIR'], color
='CYAN')
654 conf
.msg('Drivers directory', conf
.env
['ADDON_DIR'], color
='CYAN')
655 display_feature(conf
, 'Build debuggable binaries', conf
.env
['BUILD_DEBUG'])
658 ('C compiler flags', ['CFLAGS', 'CPPFLAGS']),
659 ('C++ compiler flags', ['CXXFLAGS', 'CPPFLAGS']),
660 ('Linker flags', ['LINKFLAGS', 'LDFLAGS'])
662 for name
,vars in tool_flags
:
665 flags
+= conf
.all_envs
[''][var
]
666 conf
.msg(name
, repr(flags
), color
='NORMAL')
668 if conf
.env
['BUILD_WITH_32_64']:
669 conf
.msg('32-bit C compiler flags', repr(conf
.all_envs
[lib32
]['CFLAGS']))
670 conf
.msg('32-bit C++ compiler flags', repr(conf
.all_envs
[lib32
]['CXXFLAGS']))
671 conf
.msg('32-bit linker flags', repr(conf
.all_envs
[lib32
]['LINKFLAGS']))
672 display_feature(conf
, 'Build with engine profiling', conf
.env
['BUILD_WITH_PROFILE'])
673 display_feature(conf
, 'Build with 32/64 bits mixed mode', conf
.env
['BUILD_WITH_32_64'])
675 display_feature(conf
, 'Build standard JACK (jackd)', conf
.env
['BUILD_JACKD'])
676 display_feature(conf
, 'Build D-Bus JACK (jackdbus)', conf
.env
['BUILD_JACKDBUS'])
677 conf
.msg('Autostart method', conf
.env
['AUTOSTART_METHOD'])
679 if conf
.env
['BUILD_JACKDBUS'] and conf
.env
['BUILD_JACKD']:
680 print(Logs
.colors
.RED
+ 'WARNING !! mixing both jackd and jackdbus may cause issues:' + Logs
.colors
.NORMAL
)
681 print(Logs
.colors
.RED
+ 'WARNING !! jackdbus does not use .jackdrc nor qjackctl settings' + Logs
.colors
.NORMAL
)
683 # display configuration result messages for auto options
684 display_auto_options_messages(conf
)
686 if conf
.env
['BUILD_JACKDBUS']:
687 conf
.msg('D-Bus service install directory', conf
.env
['DBUS_SERVICES_DIR'], color
='CYAN')
689 if conf
.env
['DBUS_SERVICES_DIR'] != conf
.env
['DBUS_SERVICES_DIR_REAL']:
691 print(Logs
.colors
.RED
+ 'WARNING: D-Bus session services directory as reported by pkg-config is')
692 print(Logs
.colors
.RED
+ 'WARNING:', end
=' ')
693 print(Logs
.colors
.CYAN
+ conf
.env
['DBUS_SERVICES_DIR_REAL'])
694 print(Logs
.colors
.RED
+ 'WARNING: but service file will be installed in')
695 print(Logs
.colors
.RED
+ 'WARNING:', end
=' ')
696 print(Logs
.colors
.CYAN
+ conf
.env
['DBUS_SERVICES_DIR'])
697 print(Logs
.colors
.RED
+ 'WARNING: You may need to adjust your D-Bus configuration after installing jackdbus')
698 print('WARNING: You can override dbus service install directory')
699 print('WARNING: with --enable-pkg-config-dbus-service-dir option to this script')
700 print(Logs
.colors
.NORMAL
, end
=' ')
704 for y
in (BuildContext
, CleanContext
, InstallContext
, UninstallContext
):
705 name
= y
.__name
__.replace('Context','').lower()
707 cmd
= name
+ '_' + lib32
710 def obj_add_includes(bld
, obj
):
711 if bld
.env
['BUILD_JACKDBUS']:
712 obj
.includes
+= ['dbus']
714 if bld
.env
['IS_LINUX']:
715 obj
.includes
+= ['linux', 'posix']
717 if bld
.env
['IS_MACOSX']:
718 obj
.includes
+= ['macosx', 'posix']
720 if bld
.env
['IS_SUN']:
721 obj
.includes
+= ['posix', 'solaris']
723 if bld
.env
['IS_WINDOWS']:
724 obj
.includes
+= ['windows']
726 # FIXME: Is SERVER_SIDE needed?
727 def build_jackd(bld
):
729 features
= ['cxx', 'cxxprogram'],
730 defines
= ['HAVE_CONFIG_H','SERVER_SIDE'],
731 includes
= ['.', 'common', 'common/jack'],
733 source
= ['common/Jackdmp.cpp'],
734 use
= ['serverlib', 'SYSTEMD']
737 if bld
.env
['BUILD_JACKDBUS']:
738 jackd
.source
+= ['dbus/audio_reserve.c', 'dbus/reserve.c']
739 jackd
.use
+= ['DBUS-1']
741 if bld
.env
['IS_LINUX']:
742 jackd
.use
+= ['DL', 'M', 'PTHREAD', 'RT', 'STDC++']
744 if bld
.env
['IS_MACOSX']:
745 jackd
.use
+= ['DL', 'PTHREAD']
746 jackd
.framework
= ['CoreFoundation']
748 if bld
.env
['IS_SUN']:
749 jackd
.use
+= ['DL', 'PTHREAD']
751 obj_add_includes(bld
, jackd
)
755 # FIXME: Is SERVER_SIDE needed?
756 def create_driver_obj(bld
, **kw
):
757 if bld
.env
['IS_MACOSX'] or bld
.env
['IS_WINDOWS']:
758 # On MacOSX this is necessary.
759 # I do not know if this is necessary on Windows.
760 # Note added on 2015-12-13 by karllinden.
762 kw
['use'] += ['serverlib']
764 kw
['use'] = ['serverlib']
767 features
= ['c', 'cxx', 'cshlib', 'cxxshlib'],
768 defines
= ['HAVE_CONFIG_H', 'SERVER_SIDE'],
769 includes
= ['.', 'common', 'common/jack'],
770 install_path
= '${ADDON_DIR}/',
773 if bld
.env
['IS_WINDOWS']:
774 driver
.env
['cxxshlib_PATTERN'] = 'jack_%s.dll'
776 driver
.env
['cxxshlib_PATTERN'] = 'jack_%s.so'
778 obj_add_includes(bld
, driver
)
782 def build_drivers(bld
):
783 # Non-hardware driver sources. Lexically sorted.
785 'common/JackDummyDriver.cpp'
789 'common/JackLoopbackDriver.cpp'
793 'common/JackNetDriver.cpp'
797 'common/JackNetOneDriver.cpp',
799 'common/netjack_packet.c'
803 'common/JackProxyDriver.cpp'
806 # Hardware driver sources. Lexically sorted.
809 'linux/alsa/JackAlsaDriver.cpp',
810 'linux/alsa/alsa_rawmidi.c',
811 'linux/alsa/alsa_seqmidi.c',
812 'linux/alsa/alsa_midi_jackmp.cpp',
813 'linux/alsa/generic_hw.c',
815 'linux/alsa/alsa_driver.c',
816 'linux/alsa/hammerfall.c',
817 'linux/alsa/ice1712.c'
821 'linux/alsarawmidi/JackALSARawMidiDriver.cpp',
822 'linux/alsarawmidi/JackALSARawMidiInputPort.cpp',
823 'linux/alsarawmidi/JackALSARawMidiOutputPort.cpp',
824 'linux/alsarawmidi/JackALSARawMidiPort.cpp',
825 'linux/alsarawmidi/JackALSARawMidiReceiveQueue.cpp',
826 'linux/alsarawmidi/JackALSARawMidiSendQueue.cpp',
827 'linux/alsarawmidi/JackALSARawMidiUtil.cpp'
832 'solaris/oss/JackBoomerDriver.cpp'
836 'macosx/coreaudio/JackCoreAudioDriver.mm',
837 'common/JackAC3Encoder.cpp'
841 'macosx/coremidi/JackCoreMidiInputPort.mm',
842 'macosx/coremidi/JackCoreMidiOutputPort.mm',
843 'macosx/coremidi/JackCoreMidiPhysicalInputPort.mm',
844 'macosx/coremidi/JackCoreMidiPhysicalOutputPort.mm',
845 'macosx/coremidi/JackCoreMidiVirtualInputPort.mm',
846 'macosx/coremidi/JackCoreMidiVirtualOutputPort.mm',
847 'macosx/coremidi/JackCoreMidiPort.mm',
848 'macosx/coremidi/JackCoreMidiUtil.mm',
849 'macosx/coremidi/JackCoreMidiDriver.mm'
853 'linux/firewire/JackFFADODriver.cpp',
854 'linux/firewire/JackFFADOMidiInputPort.cpp',
855 'linux/firewire/JackFFADOMidiOutputPort.cpp',
856 'linux/firewire/JackFFADOMidiReceiveQueue.cpp',
857 'linux/firewire/JackFFADOMidiSendQueue.cpp'
861 'linux/freebob/JackFreebobDriver.cpp'
865 'linux/iio/JackIIODriver.cpp'
870 'solaris/oss/JackOSSDriver.cpp'
874 'windows/portaudio/JackPortAudioDevices.cpp',
875 'windows/portaudio/JackPortAudioDriver.cpp',
879 'windows/winmme/JackWinMMEDriver.cpp',
880 'windows/winmme/JackWinMMEInputPort.cpp',
881 'windows/winmme/JackWinMMEOutputPort.cpp',
882 'windows/winmme/JackWinMMEPort.cpp',
885 # Create non-hardware driver objects. Lexically sorted.
894 source
= loopback_src
)
905 use
= ['SAMPLERATE', 'CELT'])
912 # Create hardware driver objects. Lexically sorted after the conditional,
913 # e.g. BUILD_DRIVER_ALSA.
914 if bld
.env
['BUILD_DRIVER_ALSA']:
922 target
= 'alsarawmidi',
923 source
= alsarawmidi_src
,
926 if bld
.env
['BUILD_DRIVER_FREEBOB']:
930 source
= freebob_src
,
931 use
= ['LIBFREEBOB'])
933 if bld
.env
['BUILD_DRIVER_FFADO']:
940 if bld
.env
['BUILD_DRIVER_IIO']:
945 use
= ['GTKIOSTREAM', 'EIGEN3'])
947 if bld
.env
['BUILD_DRIVER_PORTAUDIO']:
950 target
= 'portaudio',
951 source
= portaudio_src
,
954 if bld
.env
['BUILD_DRIVER_WINMME']:
961 if bld
.env
['IS_MACOSX']:
964 target
= 'coreaudio',
965 source
= coreaudio_src
,
967 framework
= ['AudioUnit', 'CoreAudio', 'CoreServices'])
972 source
= coremidi_src
,
973 use
= ['serverlib'], # FIXME: Is this needed?
974 framework
= ['AudioUnit', 'CoreMIDI', 'CoreServices', 'Foundation'])
976 if bld
.env
['IS_SUN']:
987 if not bld
.variant
and bld
.env
['BUILD_WITH_32_64']:
988 Options
.commands
.append(bld
.cmd
+ '_' + lib32
)
990 # process subfolders from here
991 bld
.recurse('common')
994 # only the wscript in common/ knows how to handle variants
997 if not os
.access('svnversion.h', os
.R_OK
):
999 sg
= Utils
.h_file(self
.outputs
[0].abspath(self
.env
))
1000 #print sg.encode('hex')
1001 Build
.bld
.node_sigs
[self
.env
.variant()][self
.outputs
[0].id] = sg
1003 script
= bld
.path
.find_resource('svnversion_regenerate.sh')
1004 script
= script
.abspath()
1007 rule
= '%s ${TGT}' % script
,
1008 name
= 'svnversion',
1009 runnable_status
= Task
.RUN_ME
,
1012 post_run
= post_run
,
1013 source
= ['svnversion_regenerate.sh'],
1014 target
= [bld
.path
.find_or_declare('svnversion.h')]
1017 if bld
.env
['BUILD_JACKD']:
1022 bld
.recurse('example-clients')
1023 if bld
.env
['IS_LINUX']:
1025 if not bld
.env
['IS_WINDOWS']:
1026 bld
.recurse('tests')
1027 if bld
.env
['BUILD_JACKDBUS']:
1030 if bld
.env
['BUILD_DOXYGEN_DOCS']:
1031 html_build_dir
= bld
.path
.find_or_declare('html').abspath()
1035 source
= 'doxyfile.in',
1036 target
= 'doxyfile',
1037 HTML_BUILD_DIR
= html_build_dir
,
1038 SRCDIR
= bld
.srcnode
.abspath(),
1042 # There are two reasons for logging to doxygen.log and using it as
1043 # target in the build rule (rather than html_build_dir):
1044 # (1) reduce the noise when running the build
1045 # (2) waf has a regular file to check for a timestamp. If the directory
1046 # is used instead waf will rebuild the doxygen target (even upon
1049 doxyfile
= task
.inputs
[0].abspath()
1050 logfile
= task
.outputs
[0].abspath()
1051 cmd
= '%s %s &> %s' % (task
.env
['DOXYGEN'][0], doxyfile
, logfile
)
1052 return task
.exec_command(cmd
)
1056 source
= 'doxyfile',
1057 target
= 'doxygen.log'
1060 # Determine where to install HTML documentation. Since share_dir is the
1061 # highest directory the uninstall routine should remove, there is no
1062 # better candidate for share_dir, but the requested HTML directory if
1063 # --htmldir is given.
1064 if bld
.env
['HTMLDIR']:
1065 html_install_dir
= bld
.options
.destdir
+ bld
.env
['HTMLDIR']
1066 share_dir
= html_install_dir
1068 share_dir
= bld
.options
.destdir
+ bld
.env
['PREFIX'] + '/share/jack-audio-connection-kit'
1069 html_install_dir
= share_dir
+ '/reference/html/'
1071 if bld
.cmd
== 'install':
1072 if os
.path
.isdir(html_install_dir
):
1073 Logs
.pprint('CYAN', 'Removing old doxygen documentation installation...')
1074 shutil
.rmtree(html_install_dir
)
1075 Logs
.pprint('CYAN', 'Removing old doxygen documentation installation done.')
1076 Logs
.pprint('CYAN', 'Installing doxygen documentation...')
1077 shutil
.copytree(html_build_dir
, html_install_dir
)
1078 Logs
.pprint('CYAN', 'Installing doxygen documentation done.')
1079 elif bld
.cmd
=='uninstall':
1080 Logs
.pprint('CYAN', 'Uninstalling doxygen documentation...')
1081 if os
.path
.isdir(share_dir
):
1082 shutil
.rmtree(share_dir
)
1083 Logs
.pprint('CYAN', 'Uninstalling doxygen documentation done.')
1084 elif bld
.cmd
=='clean':
1085 if os
.access(html_build_dir
, os
.R_OK
):
1086 Logs
.pprint('CYAN', 'Removing doxygen generated documentation...')
1087 shutil
.rmtree(html_build_dir
)
1088 Logs
.pprint('CYAN', 'Removing doxygen generated documentation done.')
1091 # This code blindly assumes it is working in the toplevel source directory.
1092 if not os
.path
.exists('svnversion.h'):
1093 os
.system('./svnversion_regenerate.sh svnversion.h')
1095 from waflib
import TaskGen
1096 @TaskGen.extension('.mm')
1097 def mm_hook(self
, node
):
1098 """Alias .mm files to be compiled the same as .cpp files, gcc will do the right thing."""
1099 return self
.create_compiled_task('cxx', node
)