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.

422 lines
17KB

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