Audio plugin host https://kx.studio/carla
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.

471 lines
18KB

  1. #!/usr/bin/env python
  2. import os
  3. import shutil
  4. import subprocess
  5. import sys
  6. import waflib.Options as Options
  7. import waflib.extras.autowaf as autowaf
  8. import waflib.Build as Build
  9. import waflib.Logs as Logs
  10. # Library and package version (UNIX style major, minor, micro)
  11. # major increment <=> incompatible changes
  12. # minor increment <=> compatible changes (additions)
  13. # micro increment <=> no interface changes
  14. LILV_VERSION = '0.24.0'
  15. LILV_MAJOR_VERSION = '0'
  16. # Mandatory waf variables
  17. APPNAME = 'lilv' # Package name for waf dist
  18. VERSION = LILV_VERSION # Package version for waf dist
  19. top = '.' # Source directory
  20. out = 'build' # Build directory
  21. test_plugins = [
  22. 'bad_syntax',
  23. 'failed_instantiation',
  24. 'failed_lib_descriptor',
  25. 'lib_descriptor',
  26. 'missing_descriptor',
  27. 'missing_name',
  28. 'missing_plugin',
  29. 'missing_port',
  30. 'missing_port_name',
  31. 'new_version',
  32. 'old_version'
  33. ]
  34. def options(opt):
  35. opt.load('compiler_c')
  36. opt.load('compiler_cxx')
  37. opt.load('python')
  38. autowaf.set_options(opt, test=True)
  39. opt.add_option('--no-utils', action='store_true', dest='no_utils',
  40. help='Do not build command line utilities')
  41. opt.add_option('--bindings', action='store_true', dest='bindings',
  42. help='Build python bindings')
  43. opt.add_option('--dyn-manifest', action='store_true', dest='dyn_manifest',
  44. help='Build support for dynamic manifests')
  45. opt.add_option('--no-bash-completion', action='store_true',
  46. dest='no_bash_completion',
  47. help='Do not install bash completion script in CONFIGDIR')
  48. opt.add_option('--static', action='store_true', dest='static',
  49. help='Build static library')
  50. opt.add_option('--no-shared', action='store_true', dest='no_shared',
  51. help='Do not build shared library')
  52. opt.add_option('--static-progs', action='store_true', dest='static_progs',
  53. help='Build programs as static binaries')
  54. opt.add_option('--default-lv2-path', type='string', default='',
  55. dest='default_lv2_path',
  56. help='Default LV2 path to use if LV2_PATH is unset')
  57. def configure(conf):
  58. conf.load('compiler_c')
  59. if Options.options.bindings:
  60. try:
  61. conf.load('python')
  62. conf.load('compiler_cxx')
  63. conf.check_python_headers()
  64. autowaf.define(conf, 'LILV_PYTHON', 1);
  65. except:
  66. Logs.warn('Failed to configure Python (%s)\n' % sys.exc_info()[1])
  67. autowaf.configure(conf)
  68. autowaf.set_c99_mode(conf)
  69. autowaf.display_header('Lilv Configuration')
  70. conf.env.BASH_COMPLETION = not Options.options.no_bash_completion
  71. conf.env.BUILD_UTILS = not Options.options.no_utils
  72. conf.env.BUILD_SHARED = not Options.options.no_shared
  73. conf.env.STATIC_PROGS = Options.options.static_progs
  74. conf.env.BUILD_STATIC = (Options.options.static or
  75. Options.options.static_progs)
  76. if not conf.env.BUILD_SHARED and not conf.env.BUILD_STATIC:
  77. conf.fatal('Neither a shared nor a static build requested')
  78. autowaf.check_pkg(conf, 'lv2', uselib_store='LV2',
  79. atleast_version='1.14.0', mandatory=True)
  80. autowaf.check_pkg(conf, 'serd-0', uselib_store='SERD',
  81. atleast_version='0.14.0', mandatory=True)
  82. autowaf.check_pkg(conf, 'sord-0', uselib_store='SORD',
  83. atleast_version='0.13.0', mandatory=True)
  84. autowaf.check_pkg(conf, 'sratom-0', uselib_store='SRATOM',
  85. atleast_version='0.4.0', mandatory=True)
  86. autowaf.check_pkg(conf, 'sndfile', uselib_store='SNDFILE',
  87. atleast_version='1.0.0', mandatory=False)
  88. defines = ['_POSIX_C_SOURCE=200809L', '_BSD_SOURCE', '_DEFAULT_SOURCE']
  89. if conf.env.DEST_OS == 'darwin':
  90. defines += ['_DARWIN_C_SOURCE']
  91. conf.check_cc(function_name='flock',
  92. header_name='sys/file.h',
  93. defines=defines,
  94. define_name='HAVE_FLOCK',
  95. mandatory=False)
  96. conf.check_cc(function_name='fileno',
  97. header_name='stdio.h',
  98. defines=defines,
  99. define_name='HAVE_FILENO',
  100. mandatory=False)
  101. conf.check_cc(function_name='clock_gettime',
  102. header_name=['sys/time.h','time.h'],
  103. defines=['_POSIX_C_SOURCE=200809L'],
  104. define_name='HAVE_CLOCK_GETTIME',
  105. uselib_store='CLOCK_GETTIME',
  106. lib=['rt'],
  107. mandatory=False)
  108. conf.check_cc(define_name = 'HAVE_LIBDL',
  109. lib = 'dl',
  110. mandatory = False)
  111. autowaf.define(conf, 'LILV_VERSION', LILV_VERSION)
  112. if Options.options.dyn_manifest:
  113. autowaf.define(conf, 'LILV_DYN_MANIFEST', 1)
  114. lilv_path_sep = ':'
  115. lilv_dir_sep = '/'
  116. if conf.env.DEST_OS == 'win32':
  117. lilv_path_sep = ';'
  118. lilv_dir_sep = '\\\\'
  119. autowaf.define(conf, 'LILV_PATH_SEP', lilv_path_sep)
  120. autowaf.define(conf, 'LILV_DIR_SEP', lilv_dir_sep)
  121. # Set default LV2 path
  122. lv2_path = Options.options.default_lv2_path
  123. if lv2_path == '':
  124. if conf.env.DEST_OS == 'darwin':
  125. lv2_path = lilv_path_sep.join(['~/Library/Audio/Plug-Ins/LV2',
  126. '~/.lv2',
  127. '/usr/local/lib/lv2',
  128. '/usr/lib/lv2',
  129. '/Library/Audio/Plug-Ins/LV2'])
  130. elif conf.env.DEST_OS == 'haiku':
  131. lv2_path = lilv_path_sep.join(['~/.lv2',
  132. '/boot/common/add-ons/lv2'])
  133. elif conf.env.DEST_OS == 'win32':
  134. lv2_path = lilv_path_sep.join(['%APPDATA%\\\\LV2',
  135. '%COMMONPROGRAMFILES%\\\\LV2'])
  136. else:
  137. libdirname = os.path.basename(conf.env.LIBDIR)
  138. lv2_path = lilv_path_sep.join(['~/.lv2',
  139. '/usr/%s/lv2' % libdirname,
  140. '/usr/local/%s/lv2' % libdirname])
  141. autowaf.define(conf, 'LILV_DEFAULT_LV2_PATH', lv2_path)
  142. autowaf.set_lib_env(conf, 'lilv', LILV_VERSION)
  143. conf.write_config_header('lilv_config.h', remove=False)
  144. autowaf.display_msg(conf, 'Default LV2_PATH',
  145. conf.env.LILV_DEFAULT_LV2_PATH)
  146. autowaf.display_msg(conf, 'Utilities',
  147. bool(conf.env.BUILD_UTILS))
  148. autowaf.display_msg(conf, 'Unit tests',
  149. bool(conf.env.BUILD_TESTS))
  150. autowaf.display_msg(conf, 'Dynamic manifest support',
  151. bool(conf.env.LILV_DYN_MANIFEST))
  152. autowaf.display_msg(conf, 'Python bindings',
  153. conf.is_defined('LILV_PYTHON'))
  154. conf.undefine('LILV_DEFAULT_LV2_PATH') # Cmd line errors with VC++
  155. print('')
  156. def build_util(bld, name, defines, libs=''):
  157. obj = bld(features = 'c cprogram',
  158. source = name + '.c',
  159. includes = ['.', './src', './utils'],
  160. use = 'liblilv',
  161. target = name,
  162. defines = defines,
  163. install_path = '${BINDIR}')
  164. autowaf.use_lib(bld, obj, 'SERD SORD SRATOM LV2 ' + libs)
  165. if not bld.env.BUILD_SHARED or bld.env.STATIC_PROGS:
  166. obj.use = 'liblilv_static'
  167. if bld.env.STATIC_PROGS:
  168. if not bld.env.MSVC_COMPILER:
  169. obj.lib = ['m']
  170. obj.env.SHLIB_MARKER = obj.env.STLIB_MARKER
  171. obj.linkflags = ['-static', '-Wl,--start-group']
  172. return obj
  173. def build(bld):
  174. # C/C++ Headers
  175. includedir = '${INCLUDEDIR}/lilv-%s/lilv' % LILV_MAJOR_VERSION
  176. bld.install_files(includedir, bld.path.ant_glob('lilv/*.h'))
  177. bld.install_files(includedir, bld.path.ant_glob('lilv/*.hpp'))
  178. lib_source = '''
  179. src/collections.c
  180. src/instance.c
  181. src/lib.c
  182. src/node.c
  183. src/plugin.c
  184. src/pluginclass.c
  185. src/port.c
  186. src/query.c
  187. src/scalepoint.c
  188. src/state.c
  189. src/ui.c
  190. src/util.c
  191. src/world.c
  192. src/zix/tree.c
  193. '''.split()
  194. lib = []
  195. libflags = ['-fvisibility=hidden']
  196. defines = []
  197. if bld.is_defined('HAVE_LIBDL'):
  198. lib += ['dl']
  199. if bld.env.DEST_OS == 'win32':
  200. lib = []
  201. if bld.env.MSVC_COMPILER:
  202. libflags = []
  203. defines = ['snprintf=_snprintf']
  204. # Pkgconfig file
  205. autowaf.build_pc(bld, 'LILV', LILV_VERSION, LILV_MAJOR_VERSION, [],
  206. {'LILV_MAJOR_VERSION' : LILV_MAJOR_VERSION,
  207. 'LILV_PKG_DEPS' : 'lv2 serd-0 sord-0 sratom-0',
  208. 'LILV_PKG_LIBS' : ' -l'.join([''] + lib)})
  209. # Shared Library
  210. if bld.env.BUILD_SHARED:
  211. obj = bld(features = 'c cshlib',
  212. export_includes = ['.'],
  213. source = lib_source,
  214. includes = ['.', './src'],
  215. name = 'liblilv',
  216. target = 'lilv-%s' % LILV_MAJOR_VERSION,
  217. vnum = LILV_VERSION,
  218. install_path = '${LIBDIR}',
  219. defines = ['LILV_SHARED', 'LILV_INTERNAL'],
  220. cflags = libflags,
  221. lib = lib)
  222. autowaf.use_lib(bld, obj, 'SERD SORD SRATOM LV2')
  223. # Static library
  224. if bld.env.BUILD_STATIC:
  225. obj = bld(features = 'c cstlib',
  226. export_includes = ['.'],
  227. source = lib_source,
  228. includes = ['.', './src'],
  229. name = 'liblilv_static',
  230. target = 'lilv-%s' % LILV_MAJOR_VERSION,
  231. vnum = LILV_VERSION,
  232. install_path = '${LIBDIR}',
  233. defines = defines + ['LILV_INTERNAL'])
  234. autowaf.use_lib(bld, obj, 'SERD SORD SRATOM LV2')
  235. if bld.env.BUILD_TESTS:
  236. test_libs = lib
  237. test_cflags = ['']
  238. test_linkflags = ['']
  239. if not bld.env.NO_COVERAGE:
  240. test_cflags += ['--coverage']
  241. test_linkflags += ['--coverage']
  242. # Test plugin library
  243. penv = bld.env.derive()
  244. shlib_pattern = penv.cshlib_PATTERN
  245. if shlib_pattern.startswith('lib'):
  246. shlib_pattern = shlib_pattern[3:]
  247. penv.cshlib_PATTERN = shlib_pattern
  248. shlib_ext = shlib_pattern[shlib_pattern.rfind('.'):]
  249. for p in ['test'] + test_plugins:
  250. obj = bld(features = 'c cshlib',
  251. env = penv,
  252. source = 'test/%s.lv2/%s.c' % (p, p),
  253. name = p,
  254. target = 'test/%s.lv2/%s' % (p, p),
  255. install_path = None,
  256. defines = defines,
  257. cflags = test_cflags,
  258. linkflags = test_linkflags,
  259. lib = test_libs,
  260. uselib = 'LV2')
  261. for p in test_plugins:
  262. if not bld.path.find_node('test/%s.lv2/test_%s.c' % (p, p)):
  263. continue
  264. obj = bld(features = 'c cprogram',
  265. source = 'test/%s.lv2/test_%s.c' % (p, p),
  266. target = 'test/test_%s' % p,
  267. includes = ['.', './src'],
  268. use = 'liblilv_profiled',
  269. install_path = None,
  270. defines = defines,
  271. cflags = test_cflags,
  272. linkflags = test_linkflags,
  273. lib = test_libs,
  274. uselib = 'LV2')
  275. autowaf.use_lib(bld, obj, 'SERD SORD SRATOM LV2')
  276. # Test plugin data files
  277. for p in ['test'] + test_plugins:
  278. for i in [ 'manifest.ttl.in', p + '.ttl.in' ]:
  279. bundle = 'test/%s.lv2/' % p
  280. bld(features = 'subst',
  281. source = bundle + i,
  282. target = bundle + i.replace('.in', ''),
  283. install_path = None,
  284. SHLIB_EXT = shlib_ext)
  285. # Static profiled library (for unit test code coverage)
  286. obj = bld(features = 'c cstlib',
  287. source = lib_source,
  288. includes = ['.', './src'],
  289. name = 'liblilv_profiled',
  290. target = 'lilv_profiled',
  291. install_path = None,
  292. defines = defines + ['LILV_INTERNAL'],
  293. cflags = test_cflags,
  294. linkflags = test_linkflags,
  295. lib = test_libs)
  296. autowaf.use_lib(bld, obj, 'SERD SORD SRATOM LV2')
  297. # Unit test program
  298. testdir = os.path.abspath(autowaf.build_dir(APPNAME, 'test'))
  299. bpath = os.path.join(testdir, 'test.lv2')
  300. bpath = bpath.replace('\\', '/')
  301. testdir = testdir.replace('\\', '/')
  302. obj = bld(features = 'c cprogram',
  303. source = 'test/lilv_test.c',
  304. includes = ['.', './src'],
  305. use = 'liblilv_profiled',
  306. lib = test_libs,
  307. target = 'test/lilv_test',
  308. install_path = None,
  309. defines = (defines + ['LILV_TEST_BUNDLE=\"%s/\"' % bpath] +
  310. ['LILV_TEST_DIR=\"%s/\"' % testdir]),
  311. cflags = test_cflags,
  312. linkflags = test_linkflags)
  313. autowaf.use_lib(bld, obj, 'SERD SORD SRATOM LV2')
  314. if bld.is_defined('LILV_PYTHON'):
  315. # Copy Python bindings to build directory
  316. bld(features = 'subst',
  317. is_copy = True,
  318. source = 'bindings/python/lilv.py',
  319. target = 'lilv.py',
  320. install_path = '${PYTHONDIR}')
  321. # Copy Python unittest files
  322. for i in [ 'test_api.py' ]:
  323. bld(features = 'subst',
  324. is_copy = True,
  325. source = 'bindings/test/python/' + i,
  326. target = 'bindings/' + i,
  327. install_path = None)
  328. # Build bindings test plugin
  329. obj = bld(features = 'c cshlib',
  330. env = penv,
  331. source = 'bindings/test/bindings_test_plugin.c',
  332. name = 'bindings_test_plugin',
  333. target = 'bindings/bindings_test_plugin.lv2/bindings_test_plugin',
  334. install_path = None,
  335. defines = defines,
  336. cflags = test_cflags,
  337. linkflags = test_linkflags,
  338. lib = test_libs,
  339. uselib = 'LV2')
  340. # Bindings test plugin data files
  341. for i in [ 'manifest.ttl.in', 'bindings_test_plugin.ttl.in' ]:
  342. bld(features = 'subst',
  343. source = 'bindings/test/' + i,
  344. target = 'bindings/bindings_test_plugin.lv2/' + i.replace('.in', ''),
  345. install_path = None,
  346. SHLIB_EXT = shlib_ext)
  347. # Utilities
  348. if bld.env.BUILD_UTILS:
  349. utils = '''
  350. utils/lilv-bench
  351. utils/lv2info
  352. utils/lv2ls
  353. '''
  354. for i in utils.split():
  355. build_util(bld, i, defines)
  356. if bld.env.HAVE_SNDFILE:
  357. obj = build_util(bld, 'utils/lv2apply', defines, 'SNDFILE')
  358. # lv2bench (less portable than other utilities)
  359. if bld.is_defined('HAVE_CLOCK_GETTIME') and not bld.env.STATIC_PROGS:
  360. obj = build_util(bld, 'utils/lv2bench', defines)
  361. if not bld.env.MSVC_COMPILER:
  362. obj.lib = ['rt']
  363. # Documentation
  364. autowaf.build_dox(bld, 'LILV', LILV_VERSION, top, out)
  365. # Man pages
  366. bld.install_files('${MANDIR}/man1', bld.path.ant_glob('doc/*.1'))
  367. # Bash completion
  368. if bld.env.BASH_COMPLETION:
  369. bld.install_as(
  370. '${SYSCONFDIR}/bash_completion.d/lilv', 'utils/lilv.bash_completion')
  371. bld.add_post_fun(autowaf.run_ldconfig)
  372. if bld.env.DOCS:
  373. bld.add_post_fun(fix_docs)
  374. def fix_docs(ctx):
  375. if ctx.cmd == 'build':
  376. autowaf.make_simple_dox(APPNAME)
  377. def upload_docs(ctx):
  378. import glob
  379. os.system('rsync -ravz --delete -e ssh build/doc/html/ drobilla@drobilla.net:~/drobilla.net/docs/lilv/')
  380. for page in glob.glob('doc/*.[1-8]'):
  381. os.system('soelim %s | pre-grohtml troff -man -wall -Thtml | post-grohtml > build/%s.html' % (page, page))
  382. os.system('rsync -avz --delete -e ssh build/%s.html drobilla@drobilla.net:~/drobilla.net/man/' % page)
  383. def test(ctx):
  384. assert ctx.env.BUILD_TESTS, "You have run waf configure without the --test flag. No tests were run."
  385. autowaf.pre_test(ctx, APPNAME)
  386. if ctx.is_defined('LILV_PYTHON'):
  387. os.environ['LD_LIBRARY_PATH'] = os.getcwd()
  388. autowaf.run_tests(ctx, APPNAME, ['python -m unittest discover bindings/'])
  389. os.environ['PATH'] = 'test' + os.pathsep + os.getenv('PATH')
  390. Logs.pprint('GREEN', '')
  391. autowaf.run_test(ctx, APPNAME, 'lilv_test', dirs=['./src','./test'], name='lilv_test')
  392. for p in test_plugins:
  393. test_prog = 'test_' + p + ' ' + ('test/%s.lv2/' % p)
  394. if os.path.exists('test/test_' + p):
  395. autowaf.run_test(ctx, APPNAME, test_prog, 0,
  396. dirs=['./src','./test','./test/%s.lv2' % p])
  397. autowaf.post_test(ctx, APPNAME)
  398. try:
  399. shutil.rmtree('state')
  400. except:
  401. pass
  402. def lint(ctx):
  403. subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-readability/todo,-build/include,-runtime/sizeof src/* lilv/*', shell=True)
  404. def posts(ctx):
  405. path = str(ctx.path.abspath())
  406. autowaf.news_to_posts(
  407. os.path.join(path, 'NEWS'),
  408. {'title' : 'Lilv',
  409. 'description' : autowaf.get_blurb(os.path.join(path, 'README')),
  410. 'dist_pattern' : 'http://download.drobilla.net/lilv-%s.tar.bz2'},
  411. { 'Author' : 'drobilla',
  412. 'Tags' : 'Hacking, LAD, LV2, Lilv' },
  413. os.path.join(out, 'posts'))