jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

903 lines
31KB

  1. #! /usr/bin/python3
  2. # encoding: utf-8
  3. from __future__ import print_function
  4. import os
  5. import subprocess
  6. import shutil
  7. import re
  8. import sys
  9. from waflib import Logs, Options, Task, Utils
  10. from waflib.Build import BuildContext, CleanContext, InstallContext, UninstallContext
  11. VERSION='1.9.20'
  12. APPNAME='jack'
  13. JACK_API_VERSION = '0.1.0'
  14. # these variables are mandatory ('/' are converted automatically)
  15. top = '.'
  16. out = 'build'
  17. # lib32 variant name used when building in mixed mode
  18. lib32 = 'lib32'
  19. def display_feature(conf, msg, build):
  20. if build:
  21. conf.msg(msg, 'yes', color='GREEN')
  22. else:
  23. conf.msg(msg, 'no', color='YELLOW')
  24. def check_for_celt(conf):
  25. found = False
  26. for version in ['11', '8', '7', '5']:
  27. define = 'HAVE_CELT_API_0_' + version
  28. if not found:
  29. try:
  30. conf.check_cfg(
  31. package='celt >= 0.%s.0' % version,
  32. args='--cflags --libs')
  33. found = True
  34. conf.define(define, 1)
  35. continue
  36. except conf.errors.ConfigurationError:
  37. pass
  38. conf.define(define, 0)
  39. if not found:
  40. raise conf.errors.ConfigurationError
  41. def options(opt):
  42. # options provided by the modules
  43. opt.load('compiler_cxx')
  44. opt.load('compiler_c')
  45. opt.load('autooptions');
  46. opt.load('xcode6')
  47. opt.recurse('compat')
  48. # install directories
  49. opt.add_option('--htmldir', type='string', default=None, help='HTML documentation directory [Default: <prefix>/share/jack-audio-connection-kit/reference/html/')
  50. opt.add_option('--libdir', type='string', help='Library directory [Default: <prefix>/lib]')
  51. opt.add_option('--libdir32', type='string', help='32bit Library directory [Default: <prefix>/lib32]')
  52. opt.add_option('--pkgconfigdir', type='string', help='pkg-config file directory [Default: <libdir>/pkgconfig]')
  53. opt.add_option('--mandir', type='string', help='Manpage directory [Default: <prefix>/share/man/man1]')
  54. # options affecting binaries
  55. opt.add_option('--platform', type='string', default=sys.platform, help='Target platform for cross-compiling, e.g. cygwin or win32')
  56. opt.add_option('--mixed', action='store_true', default=False, help='Build with 32/64 bits mixed mode')
  57. opt.add_option('--debug', action='store_true', default=False, dest='debug', help='Build debuggable binaries')
  58. opt.add_option('--static', action='store_true', default=False, dest='static', help='Build static binaries (Windows only)')
  59. # options affecting general jack functionality
  60. opt.add_option('--classic', action='store_true', default=False, help='Force enable standard JACK (jackd) even if D-Bus JACK (jackdbus) is enabled too')
  61. opt.add_option('--dbus', action='store_true', default=False, help='Enable D-Bus JACK (jackdbus)')
  62. opt.add_option('--autostart', type='string', default='default', help='Autostart method. Possible values: "default", "classic", "dbus", "none"')
  63. opt.add_option('--profile', action='store_true', default=False, help='Build with engine profiling')
  64. opt.add_option('--clients', default=256, type='int', dest='clients', help='Maximum number of JACK clients')
  65. opt.add_option('--ports-per-application', default=2048, type='int', dest='application_ports', help='Maximum number of ports per application')
  66. opt.add_option('--systemd-unit', action='store_true', default=False, help='Install systemd units.')
  67. opt.set_auto_options_define('HAVE_%s')
  68. opt.set_auto_options_style('yesno_and_hack')
  69. # options with third party dependencies
  70. doxygen = opt.add_auto_option(
  71. 'doxygen',
  72. help='Build doxygen documentation',
  73. conf_dest='BUILD_DOXYGEN_DOCS',
  74. default=False)
  75. doxygen.find_program('doxygen')
  76. alsa = opt.add_auto_option(
  77. 'alsa',
  78. help='Enable ALSA driver',
  79. conf_dest='BUILD_DRIVER_ALSA')
  80. alsa.check_cfg(
  81. package='alsa >= 1.0.18',
  82. args='--cflags --libs')
  83. firewire = opt.add_auto_option(
  84. 'firewire',
  85. help='Enable FireWire driver (FFADO)',
  86. conf_dest='BUILD_DRIVER_FFADO')
  87. firewire.check_cfg(
  88. package='libffado >= 1.999.17',
  89. args='--cflags --libs')
  90. iio = opt.add_auto_option(
  91. 'iio',
  92. help='Enable IIO driver',
  93. conf_dest='BUILD_DRIVER_IIO')
  94. iio.check_cfg(
  95. package='gtkIOStream >= 1.4.0',
  96. args='--cflags --libs')
  97. iio.check_cfg(
  98. package='eigen3 >= 3.1.2',
  99. args='--cflags --libs')
  100. portaudio = opt.add_auto_option(
  101. 'portaudio',
  102. help='Enable Portaudio driver',
  103. conf_dest='BUILD_DRIVER_PORTAUDIO')
  104. portaudio.check(header_name='windows.h') # only build portaudio on windows
  105. portaudio.check_cfg(
  106. package='portaudio-2.0 >= 19',
  107. uselib_store='PORTAUDIO',
  108. args='--cflags --libs')
  109. winmme = opt.add_auto_option(
  110. 'winmme',
  111. help='Enable WinMME driver',
  112. conf_dest='BUILD_DRIVER_WINMME')
  113. winmme.check(
  114. header_name=['windows.h', 'mmsystem.h'],
  115. msg='Checking for header mmsystem.h')
  116. celt = opt.add_auto_option(
  117. 'celt',
  118. help='Build with CELT')
  119. celt.add_function(check_for_celt)
  120. # Suffix _PKG to not collide with HAVE_OPUS defined by the option.
  121. opus = opt.add_auto_option(
  122. 'opus',
  123. help='Build Opus netjack2')
  124. opus.check(header_name='opus/opus_custom.h')
  125. opus.check_cfg(
  126. package='opus >= 0.9.0',
  127. args='--cflags --libs',
  128. define_name='HAVE_OPUS_PKG')
  129. samplerate = opt.add_auto_option(
  130. 'samplerate',
  131. help='Build with libsamplerate')
  132. samplerate.check_cfg(
  133. package='samplerate',
  134. args='--cflags --libs')
  135. sndfile = opt.add_auto_option(
  136. 'sndfile',
  137. help='Build with libsndfile')
  138. sndfile.check_cfg(
  139. package='sndfile',
  140. args='--cflags --libs')
  141. readline = opt.add_auto_option(
  142. 'readline',
  143. help='Build with readline')
  144. readline.check(lib='readline')
  145. readline.check(
  146. header_name=['stdio.h', 'readline/readline.h'],
  147. msg='Checking for header readline/readline.h')
  148. sd = opt.add_auto_option(
  149. 'systemd',
  150. help='Use systemd notify')
  151. sd.check(header_name='systemd/sd-daemon.h')
  152. sd.check(lib='systemd')
  153. db = opt.add_auto_option(
  154. 'db',
  155. help='Use Berkeley DB (metadata)')
  156. db.check(header_name='db.h')
  157. db.check(lib='db')
  158. zalsa = opt.add_auto_option(
  159. 'zalsa',
  160. help='Build internal zita-a2j/j2a client')
  161. zalsa.check(lib='zita-alsa-pcmi')
  162. zalsa.check(lib='zita-resampler')
  163. # dbus options
  164. opt.recurse('dbus')
  165. # this must be called before the configure phase
  166. opt.apply_auto_options_hack()
  167. def detect_platform(conf):
  168. # GNU/kFreeBSD and GNU/Hurd are treated as Linux
  169. platforms = [
  170. # ('KEY, 'Human readable name', ['strings', 'to', 'check', 'for'])
  171. ('IS_LINUX', 'Linux', ['gnu0', 'gnukfreebsd', 'linux', 'posix']),
  172. ('IS_MACOSX', 'MacOS X', ['darwin']),
  173. ('IS_SUN', 'SunOS', ['sunos']),
  174. ('IS_WINDOWS', 'Windows', ['cygwin', 'msys', 'win32'])
  175. ]
  176. for key,name,strings in platforms:
  177. conf.env[key] = False
  178. conf.start_msg('Checking platform')
  179. platform = Options.options.platform
  180. for key,name,strings in platforms:
  181. for s in strings:
  182. if platform.startswith(s):
  183. conf.env[key] = True
  184. conf.end_msg(name, color='CYAN')
  185. break
  186. def configure(conf):
  187. conf.load('compiler_cxx')
  188. conf.load('compiler_c')
  189. detect_platform(conf)
  190. if conf.env['IS_WINDOWS']:
  191. conf.env.append_unique('CCDEFINES', '_POSIX')
  192. conf.env.append_unique('CXXDEFINES', '_POSIX')
  193. if Options.options.platform in ('msys', 'win32'):
  194. conf.env.append_value('INCLUDES', ['/mingw64/include'])
  195. conf.check(
  196. header_name='pa_asio.h',
  197. msg='Checking for PortAudio ASIO support',
  198. define_name='HAVE_ASIO',
  199. mandatory=False)
  200. conf.env.append_unique('CFLAGS', '-Wall')
  201. conf.env.append_unique('CXXFLAGS', ['-Wall', '-Wno-invalid-offsetof'])
  202. conf.env.append_unique('CXXFLAGS', '-std=gnu++11')
  203. conf.env.append_unique('CFLAGS', '-DBUILDING_JACK')
  204. conf.env.append_unique('CXXFLAGS', '-DBUILDING_JACK')
  205. if not conf.env['IS_MACOSX']:
  206. conf.env.append_unique('LDFLAGS', '-Wl,--no-undefined')
  207. else:
  208. conf.check(lib='aften', uselib='AFTEN', define_name='AFTEN')
  209. conf.check_cxx(
  210. fragment=''
  211. + '#include <aften/aften.h>\n'
  212. + 'int\n'
  213. + 'main(void)\n'
  214. + '{\n'
  215. + 'AftenContext fAftenContext;\n'
  216. + 'aften_set_defaults(&fAftenContext);\n'
  217. + 'unsigned char *fb;\n'
  218. + 'float *buf=new float[10];\n'
  219. + 'int res = aften_encode_frame(&fAftenContext, fb, buf, 1);\n'
  220. + '}\n',
  221. lib='aften',
  222. msg='Checking for aften_encode_frame()',
  223. define_name='HAVE_AFTEN_NEW_API',
  224. mandatory=False)
  225. # TODO
  226. conf.env.append_unique('CXXFLAGS', '-Wno-deprecated-register')
  227. conf.load('autooptions')
  228. conf.recurse('compat')
  229. # Check for functions.
  230. conf.check(
  231. fragment=''
  232. + '#define _GNU_SOURCE\n'
  233. + '#include <poll.h>\n'
  234. + '#include <signal.h>\n'
  235. + '#include <stddef.h>\n'
  236. + 'int\n'
  237. + 'main(void)\n'
  238. + '{\n'
  239. + ' ppoll(NULL, 0, NULL, NULL);\n'
  240. + '}\n',
  241. msg='Checking for ppoll',
  242. define_name='HAVE_PPOLL',
  243. mandatory=False)
  244. # Check for backtrace support
  245. conf.check(
  246. header_name='execinfo.h',
  247. define_name='HAVE_EXECINFO_H',
  248. mandatory=False)
  249. conf.recurse('common')
  250. if Options.options.dbus:
  251. conf.recurse('dbus')
  252. if conf.env['BUILD_JACKDBUS'] != True:
  253. conf.fatal('jackdbus was explicitly requested but cannot be built')
  254. if conf.env['IS_LINUX']:
  255. if Options.options.systemd_unit:
  256. conf.recurse('systemd')
  257. else:
  258. conf.env['SYSTEMD_USER_UNIT_DIR'] = None
  259. conf.recurse('example-clients')
  260. conf.recurse('tools')
  261. # test for the availability of ucontext, and how it should be used
  262. for t in ['gp_regs', 'uc_regs', 'mc_gregs', 'gregs']:
  263. fragment = '#include <ucontext.h>\n'
  264. fragment += 'int main() { ucontext_t *ucontext; return (int) ucontext->uc_mcontext.%s[0]; }' % t
  265. confvar = 'HAVE_UCONTEXT_%s' % t.upper()
  266. conf.check_cc(fragment=fragment, define_name=confvar, mandatory=False,
  267. msg='Checking for ucontext->uc_mcontext.%s' % t)
  268. if conf.is_defined(confvar):
  269. conf.define('HAVE_UCONTEXT', 1)
  270. fragment = '#include <ucontext.h>\n'
  271. fragment += 'int main() { return NGREG; }'
  272. conf.check_cc(fragment=fragment, define_name='HAVE_NGREG', mandatory=False,
  273. msg='Checking for NGREG')
  274. conf.env['LIB_PTHREAD'] = ['pthread']
  275. conf.env['LIB_DL'] = ['dl']
  276. conf.env['LIB_RT'] = ['rt']
  277. conf.env['LIB_M'] = ['m']
  278. conf.env['LIB_STDC++'] = ['stdc++']
  279. conf.env['JACK_API_VERSION'] = JACK_API_VERSION
  280. conf.env['JACK_VERSION'] = VERSION
  281. conf.env['BUILD_WITH_PROFILE'] = Options.options.profile
  282. conf.env['BUILD_WITH_32_64'] = Options.options.mixed
  283. conf.env['BUILD_CLASSIC'] = Options.options.classic
  284. conf.env['BUILD_DEBUG'] = Options.options.debug
  285. conf.env['BUILD_STATIC'] = Options.options.static
  286. if conf.env['BUILD_JACKDBUS']:
  287. conf.env['BUILD_JACKD'] = conf.env['BUILD_CLASSIC']
  288. else:
  289. conf.env['BUILD_JACKD'] = True
  290. conf.env['BINDIR'] = conf.env['PREFIX'] + '/bin'
  291. if Options.options.htmldir:
  292. conf.env['HTMLDIR'] = Options.options.htmldir
  293. else:
  294. # set to None here so that the doxygen code can find out the highest
  295. # directory to remove upon install
  296. conf.env['HTMLDIR'] = None
  297. if Options.options.libdir:
  298. conf.env['LIBDIR'] = Options.options.libdir
  299. else:
  300. conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib'
  301. if Options.options.pkgconfigdir:
  302. conf.env['PKGCONFDIR'] = Options.options.pkgconfigdir
  303. else:
  304. conf.env['PKGCONFDIR'] = conf.env['LIBDIR'] + '/pkgconfig'
  305. if Options.options.mandir:
  306. conf.env['MANDIR'] = Options.options.mandir
  307. else:
  308. conf.env['MANDIR'] = conf.env['PREFIX'] + '/share/man/man1'
  309. if conf.env['BUILD_DEBUG']:
  310. conf.env.append_unique('CXXFLAGS', '-g')
  311. conf.env.append_unique('CFLAGS', '-g')
  312. conf.env.append_unique('LINKFLAGS', '-g')
  313. if not Options.options.autostart in ['default', 'classic', 'dbus', 'none']:
  314. conf.fatal('Invalid autostart value "' + Options.options.autostart + '"')
  315. if Options.options.autostart == 'default':
  316. if conf.env['BUILD_JACKD']:
  317. conf.env['AUTOSTART_METHOD'] = 'classic'
  318. else:
  319. conf.env['AUTOSTART_METHOD'] = 'dbus'
  320. else:
  321. conf.env['AUTOSTART_METHOD'] = Options.options.autostart
  322. if conf.env['AUTOSTART_METHOD'] == 'dbus' and not conf.env['BUILD_JACKDBUS']:
  323. conf.fatal('D-Bus autostart mode was specified but jackdbus will not be built')
  324. if conf.env['AUTOSTART_METHOD'] == 'classic' and not conf.env['BUILD_JACKD']:
  325. conf.fatal('Classic autostart mode was specified but jackd will not be built')
  326. if conf.env['AUTOSTART_METHOD'] == 'dbus':
  327. conf.define('USE_LIBDBUS_AUTOLAUNCH', 1)
  328. elif conf.env['AUTOSTART_METHOD'] == 'classic':
  329. conf.define('USE_CLASSIC_AUTOLAUNCH', 1)
  330. conf.define('CLIENT_NUM', Options.options.clients)
  331. conf.define('PORT_NUM_FOR_CLIENT', Options.options.application_ports)
  332. if conf.env['IS_WINDOWS']:
  333. # we define this in the environment to maintain compatibility with
  334. # existing install paths that use ADDON_DIR rather than have to
  335. # have special cases for windows each time.
  336. conf.env['ADDON_DIR'] = conf.env['LIBDIR'] + '/jack'
  337. if Options.options.platform in ('msys', 'win32'):
  338. conf.define('ADDON_DIR', 'jack')
  339. conf.define('__STDC_FORMAT_MACROS', 1) # for PRIu64
  340. else:
  341. # don't define ADDON_DIR in config.h, use the default 'jack' defined in
  342. # windows/JackPlatformPlug_os.h
  343. pass
  344. else:
  345. conf.env['ADDON_DIR'] = os.path.normpath(os.path.join(conf.env['LIBDIR'], 'jack'))
  346. conf.define('ADDON_DIR', conf.env['ADDON_DIR'])
  347. conf.define('JACK_LOCATION', os.path.normpath(os.path.join(conf.env['PREFIX'], 'bin')))
  348. if not conf.env['IS_WINDOWS']:
  349. conf.define('USE_POSIX_SHM', 1)
  350. conf.define('JACKMP', 1)
  351. if conf.env['BUILD_JACKDBUS']:
  352. conf.define('JACK_DBUS', 1)
  353. if conf.env['BUILD_WITH_PROFILE']:
  354. conf.define('JACK_MONITOR', 1)
  355. conf.write_config_header('config.h', remove=False)
  356. svnrev = None
  357. try:
  358. f = open('svnversion.h')
  359. data = f.read()
  360. m = re.match(r'^#define SVN_VERSION "([^"]*)"$', data)
  361. if m != None:
  362. svnrev = m.group(1)
  363. f.close()
  364. except IOError:
  365. pass
  366. if Options.options.mixed:
  367. conf.setenv(lib32, env=conf.env.derive())
  368. conf.env.append_unique('CFLAGS', '-m32')
  369. conf.env.append_unique('CXXFLAGS', '-m32')
  370. conf.env.append_unique('CXXFLAGS', '-DBUILD_WITH_32_64')
  371. conf.env.append_unique('LINKFLAGS', '-m32')
  372. if Options.options.libdir32:
  373. conf.env['LIBDIR'] = Options.options.libdir32
  374. else:
  375. conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib32'
  376. if conf.env['IS_WINDOWS'] and conf.env['BUILD_STATIC']:
  377. def replaceFor32bit(env):
  378. for e in env: yield e.replace('x86_64', 'i686', 1)
  379. for env in ('AR', 'CC', 'CXX', 'LINK_CC', 'LINK_CXX'):
  380. conf.all_envs[lib32][env] = list(replaceFor32bit(conf.all_envs[lib32][env]))
  381. conf.all_envs[lib32]['LIB_REGEX'] = ['tre32']
  382. # libdb does not work in mixed mode
  383. conf.all_envs[lib32]['HAVE_DB'] = 0
  384. conf.all_envs[lib32]['HAVE_DB_H'] = 0
  385. conf.all_envs[lib32]['LIB_DB'] = []
  386. # no need for opus in 32bit mixed mode clients
  387. conf.all_envs[lib32]['LIB_OPUS'] = []
  388. # someone tell me where this file gets written please..
  389. conf.write_config_header('config.h')
  390. print()
  391. print('==================')
  392. version_msg = 'JACK ' + VERSION
  393. if svnrev:
  394. version_msg += ' exported from r' + svnrev
  395. else:
  396. version_msg += ' svn revision will checked and eventually updated during build'
  397. print(version_msg)
  398. conf.msg('Maximum JACK clients', Options.options.clients, color='NORMAL')
  399. conf.msg('Maximum ports per application', Options.options.application_ports, color='NORMAL')
  400. conf.msg('Install prefix', conf.env['PREFIX'], color='CYAN')
  401. conf.msg('Library directory', conf.all_envs['']['LIBDIR'], color='CYAN')
  402. if conf.env['BUILD_WITH_32_64']:
  403. conf.msg('32-bit library directory', conf.all_envs[lib32]['LIBDIR'], color='CYAN')
  404. conf.msg('Drivers directory', conf.env['ADDON_DIR'], color='CYAN')
  405. display_feature(conf, 'Build debuggable binaries', conf.env['BUILD_DEBUG'])
  406. tool_flags = [
  407. ('C compiler flags', ['CFLAGS', 'CPPFLAGS']),
  408. ('C++ compiler flags', ['CXXFLAGS', 'CPPFLAGS']),
  409. ('Linker flags', ['LINKFLAGS', 'LDFLAGS'])
  410. ]
  411. for name,vars in tool_flags:
  412. flags = []
  413. for var in vars:
  414. flags += conf.all_envs[''][var]
  415. conf.msg(name, repr(flags), color='NORMAL')
  416. if conf.env['BUILD_WITH_32_64']:
  417. conf.msg('32-bit C compiler flags', repr(conf.all_envs[lib32]['CFLAGS']))
  418. conf.msg('32-bit C++ compiler flags', repr(conf.all_envs[lib32]['CXXFLAGS']))
  419. conf.msg('32-bit linker flags', repr(conf.all_envs[lib32]['LINKFLAGS']))
  420. display_feature(conf, 'Build with engine profiling', conf.env['BUILD_WITH_PROFILE'])
  421. display_feature(conf, 'Build with 32/64 bits mixed mode', conf.env['BUILD_WITH_32_64'])
  422. display_feature(conf, 'Build standard JACK (jackd)', conf.env['BUILD_JACKD'])
  423. display_feature(conf, 'Build D-Bus JACK (jackdbus)', conf.env['BUILD_JACKDBUS'])
  424. conf.msg('Autostart method', conf.env['AUTOSTART_METHOD'])
  425. if conf.env['BUILD_JACKDBUS'] and conf.env['BUILD_JACKD']:
  426. print(Logs.colors.RED + 'WARNING !! mixing both jackd and jackdbus may cause issues:' + Logs.colors.NORMAL)
  427. print(Logs.colors.RED + 'WARNING !! jackdbus does not use .jackdrc nor qjackctl settings' + Logs.colors.NORMAL)
  428. conf.summarize_auto_options()
  429. if conf.env['BUILD_JACKDBUS']:
  430. conf.msg('D-Bus service install directory', conf.env['DBUS_SERVICES_DIR'], color='CYAN')
  431. if conf.env['DBUS_SERVICES_DIR'] != conf.env['DBUS_SERVICES_DIR_REAL']:
  432. print()
  433. print(Logs.colors.RED + 'WARNING: D-Bus session services directory as reported by pkg-config is')
  434. print(Logs.colors.RED + 'WARNING:', end=' ')
  435. print(Logs.colors.CYAN + conf.env['DBUS_SERVICES_DIR_REAL'])
  436. print(Logs.colors.RED + 'WARNING: but service file will be installed in')
  437. print(Logs.colors.RED + 'WARNING:', end=' ')
  438. print(Logs.colors.CYAN + conf.env['DBUS_SERVICES_DIR'])
  439. print(Logs.colors.RED + 'WARNING: You may need to adjust your D-Bus configuration after installing jackdbus')
  440. print('WARNING: You can override dbus service install directory')
  441. print('WARNING: with --enable-pkg-config-dbus-service-dir option to this script')
  442. print(Logs.colors.NORMAL, end=' ')
  443. print()
  444. def init(ctx):
  445. for y in (BuildContext, CleanContext, InstallContext, UninstallContext):
  446. name = y.__name__.replace('Context','').lower()
  447. class tmp(y):
  448. cmd = name + '_' + lib32
  449. variant = lib32
  450. def obj_add_includes(bld, obj):
  451. if bld.env['BUILD_JACKDBUS']:
  452. obj.includes += ['dbus']
  453. if bld.env['IS_LINUX']:
  454. obj.includes += ['linux', 'posix']
  455. if bld.env['IS_MACOSX']:
  456. obj.includes += ['macosx', 'posix']
  457. if bld.env['IS_SUN']:
  458. obj.includes += ['posix', 'solaris']
  459. if bld.env['IS_WINDOWS']:
  460. obj.includes += ['windows']
  461. # FIXME: Is SERVER_SIDE needed?
  462. def build_jackd(bld):
  463. jackd = bld(
  464. features = ['cxx', 'cxxprogram'],
  465. defines = ['HAVE_CONFIG_H','SERVER_SIDE'],
  466. includes = ['.', 'common', 'common/jack'],
  467. target = 'jackd',
  468. source = ['common/Jackdmp.cpp'],
  469. use = ['serverlib', 'SYSTEMD']
  470. )
  471. if bld.env['BUILD_JACKDBUS']:
  472. jackd.source += ['dbus/audio_reserve.c', 'dbus/reserve.c']
  473. jackd.use += ['DBUS-1']
  474. if bld.env['IS_LINUX']:
  475. jackd.use += ['DL', 'M', 'PTHREAD', 'RT', 'STDC++']
  476. if bld.env['IS_MACOSX']:
  477. jackd.use += ['DL', 'PTHREAD']
  478. jackd.framework = ['CoreFoundation']
  479. if bld.env['IS_SUN']:
  480. jackd.use += ['DL', 'PTHREAD']
  481. obj_add_includes(bld, jackd)
  482. return jackd
  483. # FIXME: Is SERVER_SIDE needed?
  484. def create_driver_obj(bld, **kw):
  485. if 'use' in kw:
  486. kw['use'] += ['serverlib']
  487. else:
  488. kw['use'] = ['serverlib']
  489. driver = bld(
  490. features = ['c', 'cxx', 'cshlib', 'cxxshlib'],
  491. defines = ['HAVE_CONFIG_H', 'SERVER_SIDE'],
  492. includes = ['.', 'common', 'common/jack'],
  493. install_path = '${ADDON_DIR}/',
  494. **kw)
  495. if bld.env['IS_WINDOWS']:
  496. driver.env['cxxshlib_PATTERN'] = 'jack_%s.dll'
  497. else:
  498. driver.env['cxxshlib_PATTERN'] = 'jack_%s.so'
  499. obj_add_includes(bld, driver)
  500. return driver
  501. def build_drivers(bld):
  502. # Non-hardware driver sources. Lexically sorted.
  503. dummy_src = [
  504. 'common/JackDummyDriver.cpp'
  505. ]
  506. loopback_src = [
  507. 'common/JackLoopbackDriver.cpp'
  508. ]
  509. net_src = [
  510. 'common/JackNetDriver.cpp'
  511. ]
  512. netone_src = [
  513. 'common/JackNetOneDriver.cpp',
  514. 'common/netjack.c',
  515. 'common/netjack_packet.c'
  516. ]
  517. proxy_src = [
  518. 'common/JackProxyDriver.cpp'
  519. ]
  520. # Hardware driver sources. Lexically sorted.
  521. alsa_src = [
  522. 'common/memops.c',
  523. 'linux/alsa/JackAlsaDriver.cpp',
  524. 'linux/alsa/alsa_rawmidi.c',
  525. 'linux/alsa/alsa_seqmidi.c',
  526. 'linux/alsa/alsa_midi_jackmp.cpp',
  527. 'linux/alsa/generic_hw.c',
  528. 'linux/alsa/hdsp.c',
  529. 'linux/alsa/alsa_driver.c',
  530. 'linux/alsa/hammerfall.c',
  531. 'linux/alsa/ice1712.c'
  532. ]
  533. alsarawmidi_src = [
  534. 'linux/alsarawmidi/JackALSARawMidiDriver.cpp',
  535. 'linux/alsarawmidi/JackALSARawMidiInputPort.cpp',
  536. 'linux/alsarawmidi/JackALSARawMidiOutputPort.cpp',
  537. 'linux/alsarawmidi/JackALSARawMidiPort.cpp',
  538. 'linux/alsarawmidi/JackALSARawMidiReceiveQueue.cpp',
  539. 'linux/alsarawmidi/JackALSARawMidiSendQueue.cpp',
  540. 'linux/alsarawmidi/JackALSARawMidiUtil.cpp'
  541. ]
  542. boomer_src = [
  543. 'common/memops.c',
  544. 'solaris/oss/JackBoomerDriver.cpp'
  545. ]
  546. coreaudio_src = [
  547. 'macosx/coreaudio/JackCoreAudioDriver.mm',
  548. 'common/JackAC3Encoder.cpp'
  549. ]
  550. coremidi_src = [
  551. 'macosx/coremidi/JackCoreMidiInputPort.mm',
  552. 'macosx/coremidi/JackCoreMidiOutputPort.mm',
  553. 'macosx/coremidi/JackCoreMidiPhysicalInputPort.mm',
  554. 'macosx/coremidi/JackCoreMidiPhysicalOutputPort.mm',
  555. 'macosx/coremidi/JackCoreMidiVirtualInputPort.mm',
  556. 'macosx/coremidi/JackCoreMidiVirtualOutputPort.mm',
  557. 'macosx/coremidi/JackCoreMidiPort.mm',
  558. 'macosx/coremidi/JackCoreMidiUtil.mm',
  559. 'macosx/coremidi/JackCoreMidiDriver.mm'
  560. ]
  561. ffado_src = [
  562. 'linux/firewire/JackFFADODriver.cpp',
  563. 'linux/firewire/JackFFADOMidiInputPort.cpp',
  564. 'linux/firewire/JackFFADOMidiOutputPort.cpp',
  565. 'linux/firewire/JackFFADOMidiReceiveQueue.cpp',
  566. 'linux/firewire/JackFFADOMidiSendQueue.cpp'
  567. ]
  568. iio_driver_src = [
  569. 'linux/iio/JackIIODriver.cpp'
  570. ]
  571. oss_src = [
  572. 'common/memops.c',
  573. 'solaris/oss/JackOSSDriver.cpp'
  574. ]
  575. portaudio_src = [
  576. 'windows/portaudio/JackPortAudioDevices.cpp',
  577. 'windows/portaudio/JackPortAudioDriver.cpp',
  578. ]
  579. winmme_src = [
  580. 'windows/winmme/JackWinMMEDriver.cpp',
  581. 'windows/winmme/JackWinMMEInputPort.cpp',
  582. 'windows/winmme/JackWinMMEOutputPort.cpp',
  583. 'windows/winmme/JackWinMMEPort.cpp',
  584. ]
  585. # Create non-hardware driver objects. Lexically sorted.
  586. create_driver_obj(
  587. bld,
  588. target = 'dummy',
  589. source = dummy_src)
  590. create_driver_obj(
  591. bld,
  592. target = 'loopback',
  593. source = loopback_src)
  594. create_driver_obj(
  595. bld,
  596. target = 'net',
  597. source = net_src)
  598. create_driver_obj(
  599. bld,
  600. target = 'netone',
  601. source = netone_src,
  602. use = ['SAMPLERATE', 'CELT'])
  603. create_driver_obj(
  604. bld,
  605. target = 'proxy',
  606. source = proxy_src)
  607. # Create hardware driver objects. Lexically sorted after the conditional,
  608. # e.g. BUILD_DRIVER_ALSA.
  609. if bld.env['BUILD_DRIVER_ALSA']:
  610. create_driver_obj(
  611. bld,
  612. target = 'alsa',
  613. source = alsa_src,
  614. use = ['ALSA'])
  615. create_driver_obj(
  616. bld,
  617. target = 'alsarawmidi',
  618. source = alsarawmidi_src,
  619. use = ['ALSA'])
  620. if bld.env['BUILD_DRIVER_FFADO']:
  621. create_driver_obj(
  622. bld,
  623. target = 'firewire',
  624. source = ffado_src,
  625. use = ['LIBFFADO'])
  626. if bld.env['BUILD_DRIVER_IIO']:
  627. create_driver_obj(
  628. bld,
  629. target = 'iio',
  630. source = iio_src,
  631. use = ['GTKIOSTREAM', 'EIGEN3'])
  632. if bld.env['BUILD_DRIVER_PORTAUDIO']:
  633. create_driver_obj(
  634. bld,
  635. target = 'portaudio',
  636. source = portaudio_src,
  637. use = ['PORTAUDIO'])
  638. if bld.env['BUILD_DRIVER_WINMME']:
  639. create_driver_obj(
  640. bld,
  641. target = 'winmme',
  642. source = winmme_src,
  643. use = ['WINMME'])
  644. if bld.env['IS_MACOSX']:
  645. create_driver_obj(
  646. bld,
  647. target = 'coreaudio',
  648. source = coreaudio_src,
  649. use = ['AFTEN'],
  650. framework = ['AudioUnit', 'CoreAudio', 'CoreServices'])
  651. create_driver_obj(
  652. bld,
  653. target = 'coremidi',
  654. source = coremidi_src,
  655. use = ['serverlib'], # FIXME: Is this needed?
  656. framework = ['AudioUnit', 'CoreMIDI', 'CoreServices', 'Foundation'])
  657. if bld.env['IS_SUN']:
  658. create_driver_obj(
  659. bld,
  660. target = 'boomer',
  661. source = boomer_src)
  662. create_driver_obj(
  663. bld,
  664. target = 'oss',
  665. source = oss_src)
  666. def build(bld):
  667. if not bld.variant and bld.env['BUILD_WITH_32_64']:
  668. Options.commands.append(bld.cmd + '_' + lib32)
  669. # process subfolders from here
  670. bld.recurse('common')
  671. if bld.variant:
  672. # only the wscript in common/ knows how to handle variants
  673. return
  674. bld.recurse('compat')
  675. if not os.access('svnversion.h', os.R_OK):
  676. def post_run(self):
  677. sg = Utils.h_file(self.outputs[0].abspath(self.env))
  678. #print sg.encode('hex')
  679. Build.bld.node_sigs[self.env.variant()][self.outputs[0].id] = sg
  680. script = bld.path.find_resource('svnversion_regenerate.sh')
  681. script = script.abspath()
  682. bld(
  683. rule = '%s ${TGT}' % script,
  684. name = 'svnversion',
  685. runnable_status = Task.RUN_ME,
  686. before = 'c cxx',
  687. color = 'BLUE',
  688. post_run = post_run,
  689. source = ['svnversion_regenerate.sh'],
  690. target = [bld.path.find_or_declare('svnversion.h')]
  691. )
  692. if bld.env['BUILD_JACKD']:
  693. build_jackd(bld)
  694. build_drivers(bld)
  695. bld.recurse('example-clients')
  696. bld.recurse('tools')
  697. if bld.env['IS_LINUX']:
  698. bld.recurse('man')
  699. bld.recurse('systemd')
  700. if not bld.env['IS_WINDOWS']:
  701. bld.recurse('tests')
  702. if bld.env['BUILD_JACKDBUS']:
  703. bld.recurse('dbus')
  704. if bld.env['BUILD_DOXYGEN_DOCS']:
  705. html_build_dir = bld.path.find_or_declare('html').abspath()
  706. bld(
  707. features = 'subst',
  708. source = 'doxyfile.in',
  709. target = 'doxyfile',
  710. HTML_BUILD_DIR = html_build_dir,
  711. SRCDIR = bld.srcnode.abspath(),
  712. VERSION = VERSION
  713. )
  714. # There are two reasons for logging to doxygen.log and using it as
  715. # target in the build rule (rather than html_build_dir):
  716. # (1) reduce the noise when running the build
  717. # (2) waf has a regular file to check for a timestamp. If the directory
  718. # is used instead waf will rebuild the doxygen target (even upon
  719. # install).
  720. def doxygen(task):
  721. doxyfile = task.inputs[0].abspath()
  722. logfile = task.outputs[0].abspath()
  723. cmd = '%s %s &> %s' % (task.env['DOXYGEN'][0], doxyfile, logfile)
  724. return task.exec_command(cmd)
  725. bld(
  726. rule = doxygen,
  727. source = 'doxyfile',
  728. target = 'doxygen.log'
  729. )
  730. # Determine where to install HTML documentation. Since share_dir is the
  731. # highest directory the uninstall routine should remove, there is no
  732. # better candidate for share_dir, but the requested HTML directory if
  733. # --htmldir is given.
  734. if bld.env['HTMLDIR']:
  735. html_install_dir = bld.options.destdir + bld.env['HTMLDIR']
  736. share_dir = html_install_dir
  737. else:
  738. share_dir = bld.options.destdir + bld.env['PREFIX'] + '/share/jack-audio-connection-kit'
  739. html_install_dir = share_dir + '/reference/html/'
  740. if bld.cmd == 'install':
  741. if os.path.isdir(html_install_dir):
  742. Logs.pprint('CYAN', 'Removing old doxygen documentation installation...')
  743. shutil.rmtree(html_install_dir)
  744. Logs.pprint('CYAN', 'Removing old doxygen documentation installation done.')
  745. Logs.pprint('CYAN', 'Installing doxygen documentation...')
  746. shutil.copytree(html_build_dir, html_install_dir)
  747. Logs.pprint('CYAN', 'Installing doxygen documentation done.')
  748. elif bld.cmd =='uninstall':
  749. Logs.pprint('CYAN', 'Uninstalling doxygen documentation...')
  750. if os.path.isdir(share_dir):
  751. shutil.rmtree(share_dir)
  752. Logs.pprint('CYAN', 'Uninstalling doxygen documentation done.')
  753. elif bld.cmd =='clean':
  754. if os.access(html_build_dir, os.R_OK):
  755. Logs.pprint('CYAN', 'Removing doxygen generated documentation...')
  756. shutil.rmtree(html_build_dir)
  757. Logs.pprint('CYAN', 'Removing doxygen generated documentation done.')
  758. def dist(ctx):
  759. # This code blindly assumes it is working in the toplevel source directory.
  760. if not os.path.exists('svnversion.h'):
  761. os.system('./svnversion_regenerate.sh svnversion.h')
  762. from waflib import TaskGen
  763. @TaskGen.extension('.mm')
  764. def mm_hook(self, node):
  765. """Alias .mm files to be compiled the same as .cpp files, gcc will do the right thing."""
  766. return self.create_compiled_task('cxx', node)