1 import glob, os, subprocess, sys
2 from waflib import Build, Task, TaskGen, Utils
4 APPNAME = 'VapourSynth'
10 class docs(Task.Task):
11 "Build Sphinx documentation"
18 subprocess.Popen('make html BUILDDIR={0}'.format(os.path.join(os.pardir, OUT)),
21 stdout = subprocess.PIPE).wait()
23 @TaskGen.feature('docs')
24 @TaskGen.before_method('process_source')
29 for x in self.to_nodes(self.source):
30 if x.name.endswith('.rst'):
35 self.source = no_nodes
37 inst = getattr(self, 'install_path', '${DOCDIR}')
38 mod = getattr(self, 'chmod', Utils.O644)
43 for node in rst_nodes:
44 n = self.path.find_node(OUT).make_node('html')
49 while not cur is self.path.find_node('doc'):
53 for dir in reversed(dirs):
54 n = n.make_node(dir.name)
56 n = n.make_node(node.name).change_ext('.html')
63 for dir in reversed(dirs):
64 path = os.path.join(path, dir.name)
66 setattr(self, 'install_task_{0}'.format(i), self.bld.install_files(path, n, env = self.env, chmod = mod))
70 self.rst_task = self.create_task('docs', rst_nodes, bld_nodes)
73 opt.load('compiler_c')
74 opt.load('compiler_cxx')
77 opt.add_option('--libdir', action = 'store', default = '${PREFIX}/lib', help = 'library installation directory')
78 opt.add_option('--plugindir', action = 'store', default = '${LIBDIR}/vapoursynth', help = 'plugin installation directory')
79 opt.add_option('--docdir', action = 'store', default = '${PREFIX}/share/doc/vapoursynth', help = 'documentation installation directory')
80 opt.add_option('--includedir', action = 'store', default = '${PREFIX}/include/vapoursynth', help = 'header installation directory')
81 opt.add_option('--mode', action = 'store', default = 'release', help = 'the mode to compile in (debug/release)')
82 opt.add_option('--shared', action = 'store', default = 'true', help = 'build a shared library (true/false)')
83 opt.add_option('--static', action = 'store', default = 'false', help = 'build a static library (true/false)')
84 opt.add_option('--filters', action = 'store', default = 'true', help = 'build included filters (true/false)')
85 opt.add_option('--avisynth', action = 'store', default = 'true', help = 'build Avisynth compatibility layer (true/false)')
86 opt.add_option('--docs', action = 'store', default = 'false', help = 'build the documentation (true/false)')
87 opt.add_option('--examples', action = 'store', default = 'false', help = 'install SDK examples (true/false)')
90 def add_options(flags, options):
92 conf.env.append_unique(flag, options)
94 conf.load('compiler_c')
95 conf.load('compiler_cxx')
99 conf.check_python_version((3, 0, 0))
100 conf.check_python_headers()
102 if conf.env.DEST_CPU in ['x86', 'x86_64', 'x64', 'amd64', 'x86_amd64']:
103 # Load Yasm explicitly, then the Nasm module which
104 # supports both Nasm and Yasm.
105 conf.find_program('yasm', var = 'AS', mandatory = True)
108 if conf.env.DEST_OS == 'darwin':
109 if conf.env.CXX_NAME == 'gcc':
110 add_options(['ASFLAGS'],
113 if conf.env.CXX_NAME == 'gcc':
114 add_options(['CFLAGS', 'CXXFLAGS'],
117 elif conf.env.CXX_NAME == 'msvc':
118 add_options(['CFLAGS', 'CXXFLAGS'],
123 add_options(['ASFLAGS'],
126 '-Wunrecognized-char',
127 '-Dprogram_name=vs'])
129 if conf.env.DEST_CPU in ['x86_64', 'x64', 'amd64', 'x86_amd64']:
130 add_options(['ASFLAGS'],
134 if conf.env.DEST_OS == 'darwin':
136 elif conf.env.DEST_OS in ['win32', 'cygwin', 'msys', 'uwin']:
140 elif conf.env.DEST_CPU == 'x86':
141 add_options(['ASFLAGS'],
144 if conf.env.DEST_OS == 'darwin':
146 elif conf.env.DEST_OS in ['win32', 'cygwin', 'msys', 'uwin']:
151 if conf.env.DEST_CPU in ['x86', 'x86_64', 'x64']:
152 add_options(['ASFLAGS'],
153 ['-f{0}'.format(fmt)])
155 if conf.options.mode == 'debug':
156 if conf.env.CXX_NAME == 'gcc':
157 add_options(['CFLAGS', 'CXXFLAGS'],
162 elif conf.env.CXX_NAME == 'msvc':
163 add_options(['CFLAGS', 'CXXFLAGS'],
167 add_options(['ASFLAGS'],
170 if conf.env.DEST_OS in ['win32', 'cygwin', 'msys', 'uwin']:
175 add_options(['ASFLAGS'],
176 ['-g{0}'.format(dbgfmt)])
177 elif conf.options.mode == 'release':
178 if conf.env.CXX_NAME == 'gcc':
179 add_options(['CFLAGS', 'CXXFLAGS'],
181 elif conf.env.CXX_NAME == 'msvc':
182 add_options(['CFLAGS', 'CXXFLAGS'],
185 conf.fatal('--mode must be either debug or release.')
187 # Waf always uses gcc/g++ for linking when using a GCC
188 # compatible C/C++ compiler.
189 if conf.env.CXX_NAME == 'gcc':
190 if not conf.env.DEST_OS in ['darwin', 'win32', 'cygwin', 'msys', 'uwin']:
191 add_options(['LINKFLAGS_cshlib',
192 'LINKFLAGS_cprogram',
193 'LINKFLAGS_cxxshlib',
194 'LINKFLAGS_cxxprogram'],
196 '-Wl,-z,noexecstack'])
198 conf.msg("Setting DEST_OS to", conf.env.DEST_OS)
199 conf.msg("Setting DEST_CPU to", conf.env.DEST_CPU)
200 conf.msg("Setting DEST_BINFMT to", conf.env.DEST_BINFMT)
202 def check_feature(name, desc):
203 val = conf.options.__dict__[name]
205 if not val in ['true', 'false']:
206 conf.fatal('--{0} must be either true or false.'.format(name))
211 conf.define('FEATURE_' + u, 1 if val == 'true' else 0)
212 conf.msg("Enabling {0}?".format(desc), 'yes' if conf.env[u] == 'true' else 'no')
214 check_feature('shared', 'shared library')
215 check_feature('static', 'static library')
216 check_feature('filters', 'included filters')
217 check_feature('avisynth', 'Avisynth compatibility')
218 check_feature('docs', 'documentation')
219 check_feature('examples', 'SDK examples')
221 if (conf.env.SHARED, conf.env.STATIC) == ('false', 'false'):
222 conf.fatal('--static and --shared cannot both be false.')
224 conf.define('PATH_PREFIX', conf.env.PREFIX)
225 conf.msg("Setting PREFIX to", conf.env.PREFIX)
227 for dir in ['libdir', 'plugindir', 'docdir', 'includedir']:
230 conf.env[u] = Utils.subst_vars(conf.options.__dict__[dir], conf.env)
231 conf.define('PATH_' + u, conf.env[u])
232 conf.msg("Setting {0} to".format(u), conf.env[u])
234 conf.check_cxx(use = ['QTCORE'], header_name = 'QtCore/QtCore')
235 conf.check_cxx(use = ['QTCORE'], header_name = 'QtCore/QtCore', type_name = 'QAtomicInt')
237 conf.check_cc(lib = 'swscale')
238 conf.check_cc(use = ['SWSCALE'], header_name = 'libswscale/swscale.h')
239 conf.check_cc(use = ['SWSCALE'], header_name = 'libswscale/swscale.h', function_name = 'swscale_license')
241 conf.check_cc(lib = 'avutil')
242 conf.check_cc(use = ['AVUTIL'], header_name = 'libavutil/avutil.h')
243 conf.check_cc(use = ['AVUTIL'], header_name = 'libavutil/avutil.h', function_name = 'avutil_license')
245 conf.check_cc(lib = 'avcodec')
246 conf.check_cc(use = ['AVCODEC'], header_name = 'libavcodec/avcodec.h')
247 conf.check_cc(use = ['AVCODEC'], header_name = 'libavcodec/avcodec.h', function_name = 'avcodec_license')
249 conf.check_cc(lib = 'ass', mandatory = False)
250 conf.check_cc(use = ['ASS'], header_name = 'ass/ass.h', mandatory = False)
251 conf.check_cc(use = ['ASS'], header_name = 'ass/ass.h', function_name = 'ass_library_init', mandatory = False)
255 if not conf.env.DEST_OS in ['darwin', 'freebsd', 'netbsd', 'openbsd']:
258 conf.env.LIBS = libs.strip()
261 def search_paths(paths):
265 srcpaths += [os.path.join(path, '*.c'),
266 os.path.join(path, '*.cpp'),
267 os.path.join(path, '*.asm')]
271 sources = search_paths([os.path.join('src', 'core'),
272 os.path.join('src', 'core', 'asm')])
274 script_sources = search_paths([os.path.join('src', 'vsscript')])
276 pipe_sources = search_paths([os.path.join('src', 'vspipe')])
278 if bld.env.DEST_OS in ['win32', 'cygwin', 'msys', 'uwin'] and bld.env.AVISYNTH == 'true':
279 sources += search_paths([os.path.join('src', 'avisynth')])
281 bld(features = 'c qxx asm',
282 includes = 'include',
283 use = ['QTCORE', 'SWSCALE', 'AVUTIL', 'AVCODEC'],
284 source = bld.path.ant_glob(sources),
287 bld(features = 'c qxx asm pyembed',
288 includes = 'include',
289 use = ['QTCORE', 'SWSCALE', 'AVUTIL', 'AVCODEC'],
290 source = bld.path.ant_glob(script_sources),
291 target = 'script_objs')
293 bld(features = 'c qxx asm',
294 includes = 'include',
295 use = ['QTCORE', 'SWSCALE', 'AVUTIL', 'AVCODEC'],
296 source = bld.path.ant_glob(pipe_sources),
297 target = 'pipe_objs')
299 if bld.env.SHARED == 'true':
300 bld(features = 'c qxx asm cxxshlib',
302 target = 'vapoursynth',
303 install_path = '${LIBDIR}')
305 bld(features = 'c qxx asm cxxshlib pyembed',
306 use = ['script_objs'],
307 target = 'vapoursynth-script',
308 install_path = '${LIBDIR}')
310 if bld.env.STATIC == 'true':
311 bld(features = 'c qxx asm cxxstlib',
312 use = ['objs', 'QTCORE', 'SWSCALE', 'AVUTIL', 'AVCODEC'],
313 target = 'vapoursynth',
314 install_path = '${LIBDIR}')
316 bld(features = 'c qxx asm cxxstlib pyembed',
317 use = ['script_objs', 'QTCORE', 'SWSCALE', 'AVUTIL', 'AVCODEC'],
318 target = 'vapoursynth-script',
319 install_path = '${LIBDIR}')
321 bld(features = 'c qxx asm cxxprogram',
322 includes = 'include',
323 use = ['pipe_objs', 'vapoursynth', 'vapoursynth-script', 'QTCORE', 'SWSCALE', 'AVUTIL', 'AVCODEC'],
326 if bld.env.FILTERS == 'true':
327 bld(features = 'c qxx asm cxxshlib',
328 includes = 'include',
329 source = bld.path.ant_glob(search_paths([os.path.join('src', 'filters', 'eedi3')])),
331 install_path = '${PLUGINDIR}')
333 bld(features = 'c qxx asm cxxshlib',
334 includes = 'include',
335 source = bld.path.ant_glob(search_paths([os.path.join('src', 'filters', 'vivtc')])),
337 install_path = '${PLUGINDIR}')
340 bld(features = 'c cxxshlib',
341 includes = 'include',
343 source = bld.path.ant_glob(search_paths([os.path.join('src', 'filters', 'assvapour')])),
344 target = 'assvapour',
345 install_path = '${PLUGINDIR}')
347 if bld.env.DOCS == 'true':
348 bld(features = 'docs',
349 source = bld.path.ant_glob([os.path.join('doc', '*.rst'),
350 os.path.join('doc', '**', '*.rst')]),
351 install_path = '${DOCDIR}')
353 if bld.env.EXAMPLES == 'true':
354 bld(features = 'c cxxshlib',
355 includes = 'include',
356 source = os.path.join('sdk', 'filter_skeleton.c'),
357 target = 'example_skeleton',
360 bld(features = 'c cxxshlib',
361 includes = 'include',
362 source = os.path.join('sdk', 'invert_example.c'),
363 target = 'example_invert',
366 bld.install_files('${DOCDIR}/examples',
367 bld.path.ant_glob([os.path.join('sdk', '*')]))
369 bld.install_files('${INCLUDEDIR}', [os.path.join('include', 'VapourSynth.h'),
370 os.path.join('include', 'VSHelper.h'),
371 os.path.join('include', 'VSScript.h')])
373 bld(source = 'vapoursynth.pc.in',
374 install_path = '${LIBDIR}/pkgconfig',
375 PREFIX = bld.env.PREFIX,
376 LIBDIR = bld.env.LIBDIR,
377 INCLUDEDIR = bld.env.INCLUDEDIR,
381 bld(source = 'vapoursynth-script.pc.in',
382 install_path = '${LIBDIR}/pkgconfig',
383 PREFIX = bld.env.PREFIX,
384 LIBDIR = bld.env.LIBDIR,
385 INCLUDEDIR = bld.env.INCLUDEDIR,
390 '''runs the Cython tests'''
392 for name in glob.glob(os.path.join('test', '*.py')):
393 if subprocess.Popen([ctx.env.PYTHON, name]).wait() != 0:
394 ctx.fatal('Test {0} failed'.format(name))
396 class TestContext(Build.BuildContext):