Fix things on case-insensitive file systems.
[vapoursynth-svn.git] / wscript
blobb854ecda96a051c31ced616a7306c281f2abcb63
1 import glob, os, subprocess, sys
2 from waflib import Build, Task, TaskGen, Utils
4 APPNAME = 'VapourSynth'
5 VERSION = '19'
7 TOP = os.curdir
8 OUT = 'build'
10 class docs(Task.Task):
11     "Build Sphinx documentation"
13     ext_out = ['.html']
14     inst_to = None
15     color = 'PINK'
17     def run(self):
18         subprocess.Popen('make html BUILDDIR={0}'.format(os.path.join(os.pardir, OUT)),
19                          shell = True,
20                          cwd = 'doc',
21                          stdout = subprocess.PIPE).wait()
23 @TaskGen.feature('docs')
24 @TaskGen.before_method('process_source')
25 def apply_rst(self):
26     rst_nodes = []
27     no_nodes = []
29     for x in self.to_nodes(self.source):
30         if x.name.endswith('.rst'):
31             rst_nodes.append(x)
32         else:
33             no_nodes.append(x)
35     self.source = no_nodes
37     inst = getattr(self, 'install_path', '${DOCDIR}')
38     mod = getattr(self, 'chmod', Utils.O644)
40     bld_nodes = []
41     i = 0
43     for node in rst_nodes:
44         n = self.path.find_node(OUT).make_node('html')
46         cur = node.parent
47         dirs = []
49         while not cur is self.path.find_node('doc'):
50             dirs.append(cur)
51             cur = cur.parent
53         for dir in reversed(dirs):
54             n = n.make_node(dir.name)
56         n = n.make_node(node.name).change_ext('.html')
58         bld_nodes.append(n)
60         if inst:
61             path = inst
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))
68         i += 1
70     self.rst_task = self.create_task('docs', rst_nodes, bld_nodes)
72 def options(opt):
73     opt.load('compiler_c')
74     opt.load('compiler_cxx')
75     opt.load('qt4')
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)')
89 def configure(conf):
90     def add_options(flags, options):
91         for flag in flags:
92             conf.env.append_unique(flag, options)
94     conf.load('compiler_c')
95     conf.load('compiler_cxx')
96     conf.load('qt4')
97     conf.load('python')
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)
106         conf.load('nasm')
108     if conf.env.DEST_OS == 'darwin':
109         if conf.env.CXX_NAME == 'gcc':
110             add_options(['ASFLAGS'],
111                         ['-DPREFIX=1'])
113     if conf.env.CXX_NAME == 'gcc':
114         add_options(['CFLAGS', 'CXXFLAGS'],
115                     ['-DVSCORE_EXPORTS',
116                      '-fPIC'])
117     elif conf.env.CXX_NAME == 'msvc':
118         add_options(['CFLAGS', 'CXXFLAGS'],
119                     ['/DVSCORE_EXPORTS',
120                      '/EHsc',
121                      '/Zc:wchar_t-'])
123     add_options(['ASFLAGS'],
124                 ['-w',
125                  '-Worphan-labels',
126                  '-Wunrecognized-char',
127                  '-Dprogram_name=vs'])
129     if conf.env.DEST_CPU in ['x86_64', 'x64', 'amd64', 'x86_amd64']:
130         add_options(['ASFLAGS'],
131                     ['-DARCH_X86_64=1',
132                      '-DPIC=1'])
134         if conf.env.DEST_OS == 'darwin':
135             fmt = 'macho64'
136         elif conf.env.DEST_OS in ['win32', 'cygwin', 'msys', 'uwin']:
137             fmt = 'win64'
138         else:
139             fmt = 'elf64'
140     elif conf.env.DEST_CPU == 'x86':
141         add_options(['ASFLAGS'],
142                     ['-DARCH_X86_64=0'])
144         if conf.env.DEST_OS == 'darwin':
145             fmt = 'macho32'
146         elif conf.env.DEST_OS in ['win32', 'cygwin', 'msys', 'uwin']:
147             fmt = 'win32'
148         else:
149             fmt = 'elf32'
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'],
158                         ['-DVSCORE_DEBUG',
159                          '-g',
160                          '-ggdb',
161                          '-ftrapv'])
162         elif conf.env.CXX_NAME == 'msvc':
163             add_options(['CFLAGS', 'CXXFLAGS'],
164                         ['/DVSCORE_DEBUG',
165                          '/Z7'])
167         add_options(['ASFLAGS'],
168                     ['-DVSCORE_DEBUG'])
170         if conf.env.DEST_OS in ['win32', 'cygwin', 'msys', 'uwin']:
171             dbgfmt = 'cv8'
172         else:
173             dbgfmt = 'dwarf2'
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'],
180                         ['-O3'])
181         elif conf.env.CXX_NAME == 'msvc':
182             add_options(['CFLAGS', 'CXXFLAGS'],
183                         ['/Ox'])
184     else:
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'],
195                         ['-Wl,-Bsymbolic',
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))
207         else:
208             u = name.upper()
210             conf.env[u] = val
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']:
228         u = dir.upper()
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)
253     libs = '-lm '
255     if not conf.env.DEST_OS in ['darwin', 'freebsd', 'netbsd', 'openbsd']:
256         libs += '-ldl '
258     conf.env.LIBS = libs.strip()
260 def build(bld):
261     def search_paths(paths):
262         srcpaths = []
264         for path in paths:
265             srcpaths += [os.path.join(path, '*.c'),
266                          os.path.join(path, '*.cpp'),
267                          os.path.join(path, '*.asm')]
269         return srcpaths
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),
285         target = 'objs')
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',
301             use = ['objs'],
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'],
324         target = 'vspipe')
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')])),
330             target = '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')])),
336             target = 'vivtc',
337             install_path = '${PLUGINDIR}')
339         if bld.env.LIB_ASS:
340             bld(features = 'c cxxshlib',
341                 includes = 'include',
342                 use = ['ASS'],
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',
358             install_path = None)
360         bld(features = 'c cxxshlib',
361             includes = 'include',
362             source = os.path.join('sdk', 'invert_example.c'),
363             target = 'example_invert',
364             install_path = None)
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,
378         LIBS = bld.env.LIBS,
379         VERSION = VERSION)
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,
386         LIBS = bld.env.LIBS,
387         VERSION = VERSION)
389 def test(ctx):
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):
397     cmd = 'test'
398     fun = 'test'