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.

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