From 202873cf9bfdeb669365a6d76e54ad657c550fe2 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 21 Apr 2019 23:05:06 +0200 Subject: Switch to using a submodule for autowaf --- waflib | 1 + waflib/Tools/__init__.py | 3 - waflib/Tools/ar.py | 24 - waflib/Tools/asm.py | 73 --- waflib/Tools/bison.py | 49 -- waflib/Tools/c.py | 39 -- waflib/Tools/c_aliases.py | 144 ----- waflib/Tools/c_config.py | 1351 ----------------------------------------- waflib/Tools/c_osx.py | 193 ------ waflib/Tools/c_preproc.py | 1091 --------------------------------- waflib/Tools/c_tests.py | 229 ------- waflib/Tools/ccroot.py | 791 ------------------------ waflib/Tools/clang.py | 29 - waflib/Tools/clangxx.py | 30 - waflib/Tools/compiler_c.py | 110 ---- waflib/Tools/compiler_cxx.py | 111 ---- waflib/Tools/compiler_d.py | 85 --- waflib/Tools/compiler_fc.py | 73 --- waflib/Tools/cs.py | 211 ------- waflib/Tools/cxx.py | 40 -- waflib/Tools/d.py | 97 --- waflib/Tools/d_config.py | 64 -- waflib/Tools/d_scan.py | 211 ------- waflib/Tools/dbus.py | 70 --- waflib/Tools/dmd.py | 80 --- waflib/Tools/errcheck.py | 237 -------- waflib/Tools/fc.py | 203 ------- waflib/Tools/fc_config.py | 488 --------------- waflib/Tools/fc_scan.py | 120 ---- waflib/Tools/flex.py | 62 -- waflib/Tools/g95.py | 66 -- waflib/Tools/gas.py | 18 - waflib/Tools/gcc.py | 156 ----- waflib/Tools/gdc.py | 55 -- waflib/Tools/gfortran.py | 93 --- waflib/Tools/glib2.py | 489 --------------- waflib/Tools/gnu_dirs.py | 131 ---- waflib/Tools/gxx.py | 157 ----- waflib/Tools/icc.py | 30 - waflib/Tools/icpc.py | 30 - waflib/Tools/ifort.py | 413 ------------- waflib/Tools/intltool.py | 231 ------- waflib/Tools/irixcc.py | 66 -- waflib/Tools/javaw.py | 579 ------------------ waflib/Tools/ldc2.py | 56 -- waflib/Tools/lua.py | 38 -- waflib/Tools/md5_tstamp.py | 38 -- waflib/Tools/msvc.py | 1020 ------------------------------- waflib/Tools/nasm.py | 26 - waflib/Tools/nobuild.py | 24 - waflib/Tools/perl.py | 156 ----- waflib/Tools/python.py | 631 ------------------- waflib/Tools/qt5.py | 796 ------------------------ waflib/Tools/ruby.py | 186 ------ waflib/Tools/suncc.py | 67 -- waflib/Tools/suncxx.py | 67 -- waflib/Tools/tex.py | 543 ----------------- waflib/Tools/vala.py | 355 ----------- waflib/Tools/waf_unit_test.py | 296 --------- waflib/Tools/winres.py | 78 --- waflib/Tools/xlc.py | 65 -- waflib/Tools/xlcxx.py | 65 -- 62 files changed, 1 insertion(+), 13329 deletions(-) create mode 160000 waflib delete mode 100644 waflib/Tools/__init__.py delete mode 100644 waflib/Tools/ar.py delete mode 100644 waflib/Tools/asm.py delete mode 100644 waflib/Tools/bison.py delete mode 100644 waflib/Tools/c.py delete mode 100644 waflib/Tools/c_aliases.py delete mode 100644 waflib/Tools/c_config.py delete mode 100644 waflib/Tools/c_osx.py delete mode 100644 waflib/Tools/c_preproc.py delete mode 100644 waflib/Tools/c_tests.py delete mode 100644 waflib/Tools/ccroot.py delete mode 100644 waflib/Tools/clang.py delete mode 100644 waflib/Tools/clangxx.py delete mode 100644 waflib/Tools/compiler_c.py delete mode 100644 waflib/Tools/compiler_cxx.py delete mode 100644 waflib/Tools/compiler_d.py delete mode 100644 waflib/Tools/compiler_fc.py delete mode 100644 waflib/Tools/cs.py delete mode 100644 waflib/Tools/cxx.py delete mode 100644 waflib/Tools/d.py delete mode 100644 waflib/Tools/d_config.py delete mode 100644 waflib/Tools/d_scan.py delete mode 100644 waflib/Tools/dbus.py delete mode 100644 waflib/Tools/dmd.py delete mode 100644 waflib/Tools/errcheck.py delete mode 100644 waflib/Tools/fc.py delete mode 100644 waflib/Tools/fc_config.py delete mode 100644 waflib/Tools/fc_scan.py delete mode 100644 waflib/Tools/flex.py delete mode 100644 waflib/Tools/g95.py delete mode 100644 waflib/Tools/gas.py delete mode 100644 waflib/Tools/gcc.py delete mode 100644 waflib/Tools/gdc.py delete mode 100644 waflib/Tools/gfortran.py delete mode 100644 waflib/Tools/glib2.py delete mode 100644 waflib/Tools/gnu_dirs.py delete mode 100644 waflib/Tools/gxx.py delete mode 100644 waflib/Tools/icc.py delete mode 100644 waflib/Tools/icpc.py delete mode 100644 waflib/Tools/ifort.py delete mode 100644 waflib/Tools/intltool.py delete mode 100644 waflib/Tools/irixcc.py delete mode 100644 waflib/Tools/javaw.py delete mode 100644 waflib/Tools/ldc2.py delete mode 100644 waflib/Tools/lua.py delete mode 100644 waflib/Tools/md5_tstamp.py delete mode 100644 waflib/Tools/msvc.py delete mode 100644 waflib/Tools/nasm.py delete mode 100644 waflib/Tools/nobuild.py delete mode 100644 waflib/Tools/perl.py delete mode 100644 waflib/Tools/python.py delete mode 100644 waflib/Tools/qt5.py delete mode 100644 waflib/Tools/ruby.py delete mode 100644 waflib/Tools/suncc.py delete mode 100644 waflib/Tools/suncxx.py delete mode 100644 waflib/Tools/tex.py delete mode 100644 waflib/Tools/vala.py delete mode 100644 waflib/Tools/waf_unit_test.py delete mode 100644 waflib/Tools/winres.py delete mode 100644 waflib/Tools/xlc.py delete mode 100644 waflib/Tools/xlcxx.py (limited to 'waflib/Tools') diff --git a/waflib b/waflib new file mode 160000 index 0000000..2314e23 --- /dev/null +++ b/waflib @@ -0,0 +1 @@ +Subproject commit 2314e236ca6e7d94a26c3c17091da0f25f5867f3 diff --git a/waflib/Tools/__init__.py b/waflib/Tools/__init__.py deleted file mode 100644 index 079df35..0000000 --- a/waflib/Tools/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2005-2018 (ita) diff --git a/waflib/Tools/ar.py b/waflib/Tools/ar.py deleted file mode 100644 index b39b645..0000000 --- a/waflib/Tools/ar.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) -# Ralf Habacker, 2006 (rh) - -""" -The **ar** program creates static libraries. This tool is almost always loaded -from others (C, C++, D, etc) for static library support. -""" - -from waflib.Configure import conf - -@conf -def find_ar(conf): - """Configuration helper used by C/C++ tools to enable the support for static libraries""" - conf.load('ar') - -def configure(conf): - """Finds the ar program and sets the default flags in ``conf.env.ARFLAGS``""" - conf.find_program('ar', var='AR') - conf.add_os_flags('ARFLAGS') - if not conf.env.ARFLAGS: - conf.env.ARFLAGS = ['rcs'] - diff --git a/waflib/Tools/asm.py b/waflib/Tools/asm.py deleted file mode 100644 index b6f26fb..0000000 --- a/waflib/Tools/asm.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2008-2018 (ita) - -""" -Assembly support, used by tools such as gas and nasm - -To declare targets using assembly:: - - def configure(conf): - conf.load('gcc gas') - - def build(bld): - bld( - features='c cstlib asm', - source = 'test.S', - target = 'asmtest') - - bld( - features='asm asmprogram', - source = 'test.S', - target = 'asmtest') - -Support for pure asm programs and libraries should also work:: - - def configure(conf): - conf.load('nasm') - conf.find_program('ld', 'ASLINK') - - def build(bld): - bld( - features='asm asmprogram', - source = 'test.S', - target = 'asmtest') -""" - -from waflib import Task -from waflib.Tools.ccroot import link_task, stlink_task -from waflib.TaskGen import extension - -class asm(Task.Task): - """ - Compiles asm files by gas/nasm/yasm/... - """ - color = 'BLUE' - run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' - -@extension('.s', '.S', '.asm', '.ASM', '.spp', '.SPP') -def asm_hook(self, node): - """ - Binds the asm extension to the asm task - - :param node: input file - :type node: :py:class:`waflib.Node.Node` - """ - return self.create_compiled_task('asm', node) - -class asmprogram(link_task): - "Links object files into a c program" - run_str = '${ASLINK} ${ASLINKFLAGS} ${ASLNK_TGT_F}${TGT} ${ASLNK_SRC_F}${SRC}' - ext_out = ['.bin'] - inst_to = '${BINDIR}' - -class asmshlib(asmprogram): - "Links object files into a c shared library" - inst_to = '${LIBDIR}' - -class asmstlib(stlink_task): - "Links object files into a c static library" - pass # do not remove - -def configure(conf): - conf.env.ASMPATH_ST = '-I%s' diff --git a/waflib/Tools/bison.py b/waflib/Tools/bison.py deleted file mode 100644 index eef56dc..0000000 --- a/waflib/Tools/bison.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# John O'Meara, 2006 -# Thomas Nagy 2009-2018 (ita) - -""" -The **bison** program is a code generator which creates C or C++ files. -The generated files are compiled into object files. -""" - -from waflib import Task -from waflib.TaskGen import extension - -class bison(Task.Task): - """Compiles bison files""" - color = 'BLUE' - run_str = '${BISON} ${BISONFLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}' - ext_out = ['.h'] # just to make sure - -@extension('.y', '.yc', '.yy') -def big_bison(self, node): - """ - Creates a bison task, which must be executed from the directory of the output file. - """ - has_h = '-d' in self.env.BISONFLAGS - - outs = [] - if node.name.endswith('.yc'): - outs.append(node.change_ext('.tab.cc')) - if has_h: - outs.append(node.change_ext('.tab.hh')) - else: - outs.append(node.change_ext('.tab.c')) - if has_h: - outs.append(node.change_ext('.tab.h')) - - tsk = self.create_task('bison', node, outs) - tsk.cwd = node.parent.get_bld() - - # and the c/cxx file must be compiled too - self.source.append(outs[0]) - -def configure(conf): - """ - Detects the *bison* program - """ - conf.find_program('bison', var='BISON') - conf.env.BISONFLAGS = ['-d'] - diff --git a/waflib/Tools/c.py b/waflib/Tools/c.py deleted file mode 100644 index effd6b6..0000000 --- a/waflib/Tools/c.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -"Base for c programs/libraries" - -from waflib import TaskGen, Task -from waflib.Tools import c_preproc -from waflib.Tools.ccroot import link_task, stlink_task - -@TaskGen.extension('.c') -def c_hook(self, node): - "Binds the c file extensions create :py:class:`waflib.Tools.c.c` instances" - if not self.env.CC and self.env.CXX: - return self.create_compiled_task('cxx', node) - return self.create_compiled_task('c', node) - -class c(Task.Task): - "Compiles C files into object files" - run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' - vars = ['CCDEPS'] # unused variable to depend on, just in case - ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] - scan = c_preproc.scan - -class cprogram(link_task): - "Links object files into c programs" - run_str = '${LINK_CC} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' - ext_out = ['.bin'] - vars = ['LINKDEPS'] - inst_to = '${BINDIR}' - -class cshlib(cprogram): - "Links object files into c shared libraries" - inst_to = '${LIBDIR}' - -class cstlib(stlink_task): - "Links object files into a c static libraries" - pass # do not remove - diff --git a/waflib/Tools/c_aliases.py b/waflib/Tools/c_aliases.py deleted file mode 100644 index c9d5369..0000000 --- a/waflib/Tools/c_aliases.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2005-2015 (ita) - -"base for all c/c++ programs and libraries" - -from waflib import Utils, Errors -from waflib.Configure import conf - -def get_extensions(lst): - """ - Returns the file extensions for the list of files given as input - - :param lst: files to process - :list lst: list of string or :py:class:`waflib.Node.Node` - :return: list of file extensions - :rtype: list of string - """ - ret = [] - for x in Utils.to_list(lst): - if not isinstance(x, str): - x = x.name - ret.append(x[x.rfind('.') + 1:]) - return ret - -def sniff_features(**kw): - """ - Computes and returns the features required for a task generator by - looking at the file extensions. This aimed for C/C++ mainly:: - - snif_features(source=['foo.c', 'foo.cxx'], type='shlib') - # returns ['cxx', 'c', 'cxxshlib', 'cshlib'] - - :param source: source files to process - :type source: list of string or :py:class:`waflib.Node.Node` - :param type: object type in *program*, *shlib* or *stlib* - :type type: string - :return: the list of features for a task generator processing the source files - :rtype: list of string - """ - exts = get_extensions(kw['source']) - typ = kw['typ'] - feats = [] - - # watch the order, cxx will have the precedence - for x in 'cxx cpp c++ cc C'.split(): - if x in exts: - feats.append('cxx') - break - - if 'c' in exts or 'vala' in exts or 'gs' in exts: - feats.append('c') - - for x in 'f f90 F F90 for FOR'.split(): - if x in exts: - feats.append('fc') - break - - if 'd' in exts: - feats.append('d') - - if 'java' in exts: - feats.append('java') - return 'java' - - if typ in ('program', 'shlib', 'stlib'): - will_link = False - for x in feats: - if x in ('cxx', 'd', 'fc', 'c'): - feats.append(x + typ) - will_link = True - if not will_link and not kw.get('features', []): - raise Errors.WafError('Cannot link from %r, try passing eg: features="c cprogram"?' % kw) - return feats - -def set_features(kw, typ): - """ - Inserts data in the input dict *kw* based on existing data and on the type of target - required (typ). - - :param kw: task generator parameters - :type kw: dict - :param typ: type of target - :type typ: string - """ - kw['typ'] = typ - kw['features'] = Utils.to_list(kw.get('features', [])) + Utils.to_list(sniff_features(**kw)) - -@conf -def program(bld, *k, **kw): - """ - Alias for creating programs by looking at the file extensions:: - - def build(bld): - bld.program(source='foo.c', target='app') - # equivalent to: - # bld(features='c cprogram', source='foo.c', target='app') - - """ - set_features(kw, 'program') - return bld(*k, **kw) - -@conf -def shlib(bld, *k, **kw): - """ - Alias for creating shared libraries by looking at the file extensions:: - - def build(bld): - bld.shlib(source='foo.c', target='app') - # equivalent to: - # bld(features='c cshlib', source='foo.c', target='app') - - """ - set_features(kw, 'shlib') - return bld(*k, **kw) - -@conf -def stlib(bld, *k, **kw): - """ - Alias for creating static libraries by looking at the file extensions:: - - def build(bld): - bld.stlib(source='foo.cpp', target='app') - # equivalent to: - # bld(features='cxx cxxstlib', source='foo.cpp', target='app') - - """ - set_features(kw, 'stlib') - return bld(*k, **kw) - -@conf -def objects(bld, *k, **kw): - """ - Alias for creating object files by looking at the file extensions:: - - def build(bld): - bld.objects(source='foo.c', target='app') - # equivalent to: - # bld(features='c', source='foo.c', target='app') - - """ - set_features(kw, 'objects') - return bld(*k, **kw) - diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py deleted file mode 100644 index d546be9..0000000 --- a/waflib/Tools/c_config.py +++ /dev/null @@ -1,1351 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2005-2018 (ita) - -""" -C/C++/D configuration helpers -""" - -from __future__ import with_statement - -import os, re, shlex -from waflib import Build, Utils, Task, Options, Logs, Errors, Runner -from waflib.TaskGen import after_method, feature -from waflib.Configure import conf - -WAF_CONFIG_H = 'config.h' -"""default name for the config.h file""" - -DEFKEYS = 'define_key' -INCKEYS = 'include_key' - -SNIP_EMPTY_PROGRAM = ''' -int main(int argc, char **argv) { - (void)argc; (void)argv; - return 0; -} -''' - -MACRO_TO_DESTOS = { -'__linux__' : 'linux', -'__GNU__' : 'gnu', # hurd -'__FreeBSD__' : 'freebsd', -'__NetBSD__' : 'netbsd', -'__OpenBSD__' : 'openbsd', -'__sun' : 'sunos', -'__hpux' : 'hpux', -'__sgi' : 'irix', -'_AIX' : 'aix', -'__CYGWIN__' : 'cygwin', -'__MSYS__' : 'cygwin', -'_UWIN' : 'uwin', -'_WIN64' : 'win32', -'_WIN32' : 'win32', -# Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file. -'__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin', -'__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone -'__QNX__' : 'qnx', -'__native_client__' : 'nacl' # google native client platform -} - -MACRO_TO_DEST_CPU = { -'__x86_64__' : 'x86_64', -'__amd64__' : 'x86_64', -'__i386__' : 'x86', -'__ia64__' : 'ia', -'__mips__' : 'mips', -'__sparc__' : 'sparc', -'__alpha__' : 'alpha', -'__aarch64__' : 'aarch64', -'__thumb__' : 'thumb', -'__arm__' : 'arm', -'__hppa__' : 'hppa', -'__powerpc__' : 'powerpc', -'__ppc__' : 'powerpc', -'__convex__' : 'convex', -'__m68k__' : 'm68k', -'__s390x__' : 's390x', -'__s390__' : 's390', -'__sh__' : 'sh', -'__xtensa__' : 'xtensa', -} - -@conf -def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=None): - """ - Parses flags from the input lines, and adds them to the relevant use variables:: - - def configure(conf): - conf.parse_flags('-O3', 'FOO') - # conf.env.CXXFLAGS_FOO = ['-O3'] - # conf.env.CFLAGS_FOO = ['-O3'] - - :param line: flags - :type line: string - :param uselib_store: where to add the flags - :type uselib_store: string - :param env: config set or conf.env by default - :type env: :py:class:`waflib.ConfigSet.ConfigSet` - """ - - assert(isinstance(line, str)) - - env = env or self.env - - # Issue 811 and 1371 - if posix is None: - posix = True - if '\\' in line: - posix = ('\\ ' in line) or ('\\\\' in line) - - lex = shlex.shlex(line, posix=posix) - lex.whitespace_split = True - lex.commenters = '' - lst = list(lex) - - # append_unique is not always possible - # for example, apple flags may require both -arch i386 and -arch ppc - uselib = uselib_store - def app(var, val): - env.append_value('%s_%s' % (var, uselib), val) - def appu(var, val): - env.append_unique('%s_%s' % (var, uselib), val) - static = False - while lst: - x = lst.pop(0) - st = x[:2] - ot = x[2:] - - if st == '-I' or st == '/I': - if not ot: - ot = lst.pop(0) - appu('INCLUDES', ot) - elif st == '-i': - tmp = [x, lst.pop(0)] - app('CFLAGS', tmp) - app('CXXFLAGS', tmp) - elif st == '-D' or (env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but.. - if not ot: - ot = lst.pop(0) - app('DEFINES', ot) - elif st == '-l': - if not ot: - ot = lst.pop(0) - prefix = 'STLIB' if (force_static or static) else 'LIB' - app(prefix, ot) - elif st == '-L': - if not ot: - ot = lst.pop(0) - prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH' - appu(prefix, ot) - elif x.startswith('/LIBPATH:'): - prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH' - appu(prefix, x.replace('/LIBPATH:', '')) - elif x.startswith('-std='): - prefix = 'CXXFLAGS' if '++' in x else 'CFLAGS' - app(prefix, x) - elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie'): - app('CFLAGS', x) - app('CXXFLAGS', x) - app('LINKFLAGS', x) - elif x == '-framework': - appu('FRAMEWORK', lst.pop(0)) - elif x.startswith('-F'): - appu('FRAMEWORKPATH', x[2:]) - elif x == '-Wl,-rpath' or x == '-Wl,-R': - app('RPATH', lst.pop(0).lstrip('-Wl,')) - elif x.startswith('-Wl,-R,'): - app('RPATH', x[7:]) - elif x.startswith('-Wl,-R'): - app('RPATH', x[6:]) - elif x.startswith('-Wl,-rpath,'): - app('RPATH', x[11:]) - elif x == '-Wl,-Bstatic' or x == '-Bstatic': - static = True - elif x == '-Wl,-Bdynamic' or x == '-Bdynamic': - static = False - elif x.startswith('-Wl') or x in ('-rdynamic', '-pie'): - app('LINKFLAGS', x) - elif x.startswith(('-m', '-f', '-dynamic', '-O', '-g')): - # Adding the -W option breaks python builds on Openindiana - app('CFLAGS', x) - app('CXXFLAGS', x) - elif x.startswith('-bundle'): - app('LINKFLAGS', x) - elif x.startswith(('-undefined', '-Xlinker')): - arg = lst.pop(0) - app('LINKFLAGS', [x, arg]) - elif x.startswith(('-arch', '-isysroot')): - tmp = [x, lst.pop(0)] - app('CFLAGS', tmp) - app('CXXFLAGS', tmp) - app('LINKFLAGS', tmp) - elif x.endswith(('.a', '.so', '.dylib', '.lib')): - appu('LINKFLAGS', x) # not cool, #762 - else: - self.to_log('Unhandled flag %r' % x) - -@conf -def validate_cfg(self, kw): - """ - Searches for the program *pkg-config* if missing, and validates the - parameters to pass to :py:func:`waflib.Tools.c_config.exec_cfg`. - - :param path: the **-config program to use** (default is *pkg-config*) - :type path: list of string - :param msg: message to display to describe the test executed - :type msg: string - :param okmsg: message to display when the test is successful - :type okmsg: string - :param errmsg: message to display in case of error - :type errmsg: string - """ - if not 'path' in kw: - if not self.env.PKGCONFIG: - self.find_program('pkg-config', var='PKGCONFIG') - kw['path'] = self.env.PKGCONFIG - - # verify that exactly one action is requested - s = ('atleast_pkgconfig_version' in kw) + ('modversion' in kw) + ('package' in kw) - if s != 1: - raise ValueError('exactly one of atleast_pkgconfig_version, modversion and package must be set') - if not 'msg' in kw: - if 'atleast_pkgconfig_version' in kw: - kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version'] - elif 'modversion' in kw: - kw['msg'] = 'Checking for %r version' % kw['modversion'] - else: - kw['msg'] = 'Checking for %r' %(kw['package']) - - # let the modversion check set the okmsg to the detected version - if not 'okmsg' in kw and not 'modversion' in kw: - kw['okmsg'] = 'yes' - if not 'errmsg' in kw: - kw['errmsg'] = 'not found' - - # pkg-config version - if 'atleast_pkgconfig_version' in kw: - pass - elif 'modversion' in kw: - if not 'uselib_store' in kw: - kw['uselib_store'] = kw['modversion'] - if not 'define_name' in kw: - kw['define_name'] = '%s_VERSION' % Utils.quote_define_name(kw['uselib_store']) - else: - if not 'uselib_store' in kw: - kw['uselib_store'] = Utils.to_list(kw['package'])[0].upper() - if not 'define_name' in kw: - kw['define_name'] = self.have_define(kw['uselib_store']) - -@conf -def exec_cfg(self, kw): - """ - Executes ``pkg-config`` or other ``-config`` applications to collect configuration flags: - - * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return - * if modversion is given, then return the module version - * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable - - :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests) - :type atleast_pkgconfig_version: string - :param package: package name, for example *gtk+-2.0* - :type package: string - :param uselib_store: if the test is successful, define HAVE\\_*name*. It is also used to define *conf.env.FLAGS_name* variables. - :type uselib_store: string - :param modversion: if provided, return the version of the given module and define *name*\\_VERSION - :type modversion: string - :param args: arguments to give to *package* when retrieving flags - :type args: list of string - :param variables: return the values of particular variables - :type variables: list of string - :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES) - :type define_variable: dict(string: string) - """ - - path = Utils.to_list(kw['path']) - env = self.env.env or None - if kw.get('pkg_config_path'): - if not env: - env = dict(self.environ) - env['PKG_CONFIG_PATH'] = kw['pkg_config_path'] - - def define_it(): - define_name = kw['define_name'] - # by default, add HAVE_X to the config.h, else provide DEFINES_X for use=X - if kw.get('global_define', 1): - self.define(define_name, 1, False) - else: - self.env.append_unique('DEFINES_%s' % kw['uselib_store'], "%s=1" % define_name) - - if kw.get('add_have_to_env', 1): - self.env[define_name] = 1 - - # pkg-config version - if 'atleast_pkgconfig_version' in kw: - cmd = path + ['--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']] - self.cmd_and_log(cmd, env=env) - return - - # single version for a module - if 'modversion' in kw: - version = self.cmd_and_log(path + ['--modversion', kw['modversion']], env=env).strip() - if not 'okmsg' in kw: - kw['okmsg'] = version - self.define(kw['define_name'], version) - return version - - lst = [] + path - - defi = kw.get('define_variable') - if not defi: - defi = self.env.PKG_CONFIG_DEFINES or {} - for key, val in defi.items(): - lst.append('--define-variable=%s=%s' % (key, val)) - - static = kw.get('force_static', False) - if 'args' in kw: - args = Utils.to_list(kw['args']) - if '--static' in args or '--static-libs' in args: - static = True - lst += args - - # tools like pkgconf expect the package argument after the -- ones -_- - lst.extend(Utils.to_list(kw['package'])) - - # retrieving variables of a module - if 'variables' in kw: - v_env = kw.get('env', self.env) - vars = Utils.to_list(kw['variables']) - for v in vars: - val = self.cmd_and_log(lst + ['--variable=' + v], env=env).strip() - var = '%s_%s' % (kw['uselib_store'], v) - v_env[var] = val - return - - # so we assume the command-line will output flags to be parsed afterwards - ret = self.cmd_and_log(lst, env=env) - - define_it() - self.parse_flags(ret, kw['uselib_store'], kw.get('env', self.env), force_static=static, posix=kw.get('posix')) - return ret - -@conf -def check_cfg(self, *k, **kw): - """ - Checks for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc). - This wraps internal calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg` - - A few examples:: - - def configure(conf): - conf.load('compiler_c') - conf.check_cfg(package='glib-2.0', args='--libs --cflags') - conf.check_cfg(package='pango') - conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs']) - conf.check_cfg(package='pango', - args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'], - msg="Checking for 'pango 0.1.0'") - conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL') - conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', - package='', uselib_store='OPEN_MPI', mandatory=False) - # variables - conf.check_cfg(package='gtk+-2.0', variables=['includedir', 'prefix'], uselib_store='FOO') - print(conf.env.FOO_includedir) - """ - self.validate_cfg(kw) - if 'msg' in kw: - self.start_msg(kw['msg'], **kw) - ret = None - try: - ret = self.exec_cfg(kw) - except self.errors.WafError as e: - if 'errmsg' in kw: - self.end_msg(kw['errmsg'], 'YELLOW', **kw) - if Logs.verbose > 1: - self.to_log('Command failure: %s' % e) - self.fatal('The configuration failed') - else: - if not ret: - ret = True - kw['success'] = ret - if 'okmsg' in kw: - self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) - - return ret - -def build_fun(bld): - """ - Build function that is used for running configuration tests with ``conf.check()`` - """ - if bld.kw['compile_filename']: - node = bld.srcnode.make_node(bld.kw['compile_filename']) - node.write(bld.kw['code']) - - o = bld(features=bld.kw['features'], source=bld.kw['compile_filename'], target='testprog') - - for k, v in bld.kw.items(): - setattr(o, k, v) - - if not bld.kw.get('quiet'): - bld.conf.to_log("==>\n%s\n<==" % bld.kw['code']) - -@conf -def validate_c(self, kw): - """ - Pre-checks the parameters that will be given to :py:func:`waflib.Configure.run_build` - - :param compiler: c or cxx (tries to guess what is best) - :type compiler: string - :param type: cprogram, cshlib, cstlib - not required if *features are given directly* - :type type: binary to create - :param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib`` - :type feature: list of string - :param fragment: provide a piece of code for the test (default is to let the system create one) - :type fragment: string - :param uselib_store: define variables after the test is executed (IMPORTANT!) - :type uselib_store: string - :param use: parameters to use for building (just like the normal *use* keyword) - :type use: list of string - :param define_name: define to set when the check is over - :type define_name: string - :param execute: execute the resulting binary - :type execute: bool - :param define_ret: if execute is set to True, use the execution output in both the define and the return value - :type define_ret: bool - :param header_name: check for a particular header - :type header_name: string - :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers - :type auto_add_header_name: bool - """ - for x in ('type_name', 'field_name', 'function_name'): - if x in kw: - Logs.warn('Invalid argument %r in test' % x) - - if not 'build_fun' in kw: - kw['build_fun'] = build_fun - - if not 'env' in kw: - kw['env'] = self.env.derive() - env = kw['env'] - - if not 'compiler' in kw and not 'features' in kw: - kw['compiler'] = 'c' - if env.CXX_NAME and Task.classes.get('cxx'): - kw['compiler'] = 'cxx' - if not self.env.CXX: - self.fatal('a c++ compiler is required') - else: - if not self.env.CC: - self.fatal('a c compiler is required') - - if not 'compile_mode' in kw: - kw['compile_mode'] = 'c' - if 'cxx' in Utils.to_list(kw.get('features', [])) or kw.get('compiler') == 'cxx': - kw['compile_mode'] = 'cxx' - - if not 'type' in kw: - kw['type'] = 'cprogram' - - if not 'features' in kw: - if not 'header_name' in kw or kw.get('link_header_test', True): - kw['features'] = [kw['compile_mode'], kw['type']] # "c ccprogram" - else: - kw['features'] = [kw['compile_mode']] - else: - kw['features'] = Utils.to_list(kw['features']) - - if not 'compile_filename' in kw: - kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '') - - def to_header(dct): - if 'header_name' in dct: - dct = Utils.to_list(dct['header_name']) - return ''.join(['#include <%s>\n' % x for x in dct]) - return '' - - if 'framework_name' in kw: - # OSX, not sure this is used anywhere - fwkname = kw['framework_name'] - if not 'uselib_store' in kw: - kw['uselib_store'] = fwkname.upper() - if not kw.get('no_header'): - fwk = '%s/%s.h' % (fwkname, fwkname) - if kw.get('remove_dot_h'): - fwk = fwk[:-2] - val = kw.get('header_name', []) - kw['header_name'] = Utils.to_list(val) + [fwk] - kw['msg'] = 'Checking for framework %s' % fwkname - kw['framework'] = fwkname - - elif 'header_name' in kw: - if not 'msg' in kw: - kw['msg'] = 'Checking for header %s' % kw['header_name'] - - l = Utils.to_list(kw['header_name']) - assert len(l), 'list of headers in header_name is empty' - - kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM - if not 'uselib_store' in kw: - kw['uselib_store'] = l[0].upper() - if not 'define_name' in kw: - kw['define_name'] = self.have_define(l[0]) - - if 'lib' in kw: - if not 'msg' in kw: - kw['msg'] = 'Checking for library %s' % kw['lib'] - if not 'uselib_store' in kw: - kw['uselib_store'] = kw['lib'].upper() - - if 'stlib' in kw: - if not 'msg' in kw: - kw['msg'] = 'Checking for static library %s' % kw['stlib'] - if not 'uselib_store' in kw: - kw['uselib_store'] = kw['stlib'].upper() - - if 'fragment' in kw: - # an additional code fragment may be provided to replace the predefined code - # in custom headers - kw['code'] = kw['fragment'] - if not 'msg' in kw: - kw['msg'] = 'Checking for code snippet' - if not 'errmsg' in kw: - kw['errmsg'] = 'no' - - for (flagsname,flagstype) in (('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')): - if flagsname in kw: - if not 'msg' in kw: - kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname]) - if not 'errmsg' in kw: - kw['errmsg'] = 'no' - - if not 'execute' in kw: - kw['execute'] = False - if kw['execute']: - kw['features'].append('test_exec') - kw['chmod'] = Utils.O755 - - if not 'errmsg' in kw: - kw['errmsg'] = 'not found' - - if not 'okmsg' in kw: - kw['okmsg'] = 'yes' - - if not 'code' in kw: - kw['code'] = SNIP_EMPTY_PROGRAM - - # if there are headers to append automatically to the next tests - if self.env[INCKEYS]: - kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code'] - - # in case defines lead to very long command-lines - if kw.get('merge_config_header') or env.merge_config_header: - kw['code'] = '%s\n\n%s' % (self.get_config_header(), kw['code']) - env.DEFINES = [] # modify the copy - - if not kw.get('success'): - kw['success'] = None - - if 'define_name' in kw: - self.undefine(kw['define_name']) - if not 'msg' in kw: - self.fatal('missing "msg" in conf.check(...)') - -@conf -def post_check(self, *k, **kw): - """ - Sets the variables after a test executed in - :py:func:`waflib.Tools.c_config.check` was run successfully - """ - is_success = 0 - if kw['execute']: - if kw['success'] is not None: - if kw.get('define_ret'): - is_success = kw['success'] - else: - is_success = (kw['success'] == 0) - else: - is_success = (kw['success'] == 0) - - if kw.get('define_name'): - comment = kw.get('comment', '') - define_name = kw['define_name'] - if kw['execute'] and kw.get('define_ret') and isinstance(is_success, str): - if kw.get('global_define', 1): - self.define(define_name, is_success, quote=kw.get('quote', 1), comment=comment) - else: - if kw.get('quote', 1): - succ = '"%s"' % is_success - else: - succ = int(is_success) - val = '%s=%s' % (define_name, succ) - var = 'DEFINES_%s' % kw['uselib_store'] - self.env.append_value(var, val) - else: - if kw.get('global_define', 1): - self.define_cond(define_name, is_success, comment=comment) - else: - var = 'DEFINES_%s' % kw['uselib_store'] - self.env.append_value(var, '%s=%s' % (define_name, int(is_success))) - - # define conf.env.HAVE_X to 1 - if kw.get('add_have_to_env', 1): - if kw.get('uselib_store'): - self.env[self.have_define(kw['uselib_store'])] = 1 - elif kw['execute'] and kw.get('define_ret'): - self.env[define_name] = is_success - else: - self.env[define_name] = int(is_success) - - if 'header_name' in kw: - if kw.get('auto_add_header_name'): - self.env.append_value(INCKEYS, Utils.to_list(kw['header_name'])) - - if is_success and 'uselib_store' in kw: - from waflib.Tools import ccroot - # See get_uselib_vars in ccroot.py - _vars = set() - for x in kw['features']: - if x in ccroot.USELIB_VARS: - _vars |= ccroot.USELIB_VARS[x] - - for k in _vars: - x = k.lower() - if x in kw: - self.env.append_value(k + '_' + kw['uselib_store'], kw[x]) - return is_success - -@conf -def check(self, *k, **kw): - """ - Performs a configuration test by calling :py:func:`waflib.Configure.run_build`. - For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`. - To force a specific compiler, pass ``compiler='c'`` or ``compiler='cxx'`` to the list of arguments - - Besides build targets, complete builds can be given through a build function. All files will - be written to a temporary directory:: - - def build(bld): - lib_node = bld.srcnode.make_node('libdir/liblc1.c') - lib_node.parent.mkdir() - lib_node.write('#include \\nint lib_func(void) { FILE *f = fopen("foo", "r");}\\n', 'w') - bld(features='c cshlib', source=[lib_node], linkflags=conf.env.EXTRA_LDFLAGS, target='liblc') - conf.check(build_fun=build, msg=msg) - """ - self.validate_c(kw) - self.start_msg(kw['msg'], **kw) - ret = None - try: - ret = self.run_build(*k, **kw) - except self.errors.ConfigurationError: - self.end_msg(kw['errmsg'], 'YELLOW', **kw) - if Logs.verbose > 1: - raise - else: - self.fatal('The configuration failed') - else: - kw['success'] = ret - - ret = self.post_check(*k, **kw) - if not ret: - self.end_msg(kw['errmsg'], 'YELLOW', **kw) - self.fatal('The configuration failed %r' % ret) - else: - self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) - return ret - -class test_exec(Task.Task): - """ - A task that runs programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`. - """ - color = 'PINK' - def run(self): - if getattr(self.generator, 'rpath', None): - if getattr(self.generator, 'define_ret', False): - self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()]) - else: - self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()]) - else: - env = self.env.env or {} - env.update(dict(os.environ)) - for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'): - env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '') - if getattr(self.generator, 'define_ret', False): - self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env) - else: - self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env) - -@feature('test_exec') -@after_method('apply_link') -def test_exec_fun(self): - """ - The feature **test_exec** is used to create a task that will to execute the binary - created (link task output) during the build. The exit status will be set - on the build context, so only one program may have the feature *test_exec*. - This is used by configuration tests:: - - def configure(conf): - conf.check(execute=True) - """ - self.create_task('test_exec', self.link_task.outputs[0]) - -@conf -def check_cxx(self, *k, **kw): - """ - Runs a test with a task generator of the form:: - - conf.check(features='cxx cxxprogram', ...) - """ - kw['compiler'] = 'cxx' - return self.check(*k, **kw) - -@conf -def check_cc(self, *k, **kw): - """ - Runs a test with a task generator of the form:: - - conf.check(features='c cprogram', ...) - """ - kw['compiler'] = 'c' - return self.check(*k, **kw) - -@conf -def set_define_comment(self, key, comment): - """ - Sets a comment that will appear in the configuration header - - :type key: string - :type comment: string - """ - coms = self.env.DEFINE_COMMENTS - if not coms: - coms = self.env.DEFINE_COMMENTS = {} - coms[key] = comment or '' - -@conf -def get_define_comment(self, key): - """ - Returns the comment associated to a define - - :type key: string - """ - coms = self.env.DEFINE_COMMENTS or {} - return coms.get(key, '') - -@conf -def define(self, key, val, quote=True, comment=''): - """ - Stores a single define and its state into ``conf.env.DEFINES``. The value is cast to an integer (0/1). - - :param key: define name - :type key: string - :param val: value - :type val: int or string - :param quote: enclose strings in quotes (yes by default) - :type quote: bool - """ - assert isinstance(key, str) - if not key: - return - if val is True: - val = 1 - elif val in (False, None): - val = 0 - - if isinstance(val, int) or isinstance(val, float): - s = '%s=%s' - else: - s = quote and '%s="%s"' or '%s=%s' - app = s % (key, str(val)) - - ban = key + '=' - lst = self.env.DEFINES - for x in lst: - if x.startswith(ban): - lst[lst.index(x)] = app - break - else: - self.env.append_value('DEFINES', app) - - self.env.append_unique(DEFKEYS, key) - self.set_define_comment(key, comment) - -@conf -def undefine(self, key, comment=''): - """ - Removes a global define from ``conf.env.DEFINES`` - - :param key: define name - :type key: string - """ - assert isinstance(key, str) - if not key: - return - ban = key + '=' - lst = [x for x in self.env.DEFINES if not x.startswith(ban)] - self.env.DEFINES = lst - self.env.append_unique(DEFKEYS, key) - self.set_define_comment(key, comment) - -@conf -def define_cond(self, key, val, comment=''): - """ - Conditionally defines a name:: - - def configure(conf): - conf.define_cond('A', True) - # equivalent to: - # if val: conf.define('A', 1) - # else: conf.undefine('A') - - :param key: define name - :type key: string - :param val: value - :type val: int or string - """ - assert isinstance(key, str) - if not key: - return - if val: - self.define(key, 1, comment=comment) - else: - self.undefine(key, comment=comment) - -@conf -def is_defined(self, key): - """ - Indicates whether a particular define is globally set in ``conf.env.DEFINES``. - - :param key: define name - :type key: string - :return: True if the define is set - :rtype: bool - """ - assert key and isinstance(key, str) - - ban = key + '=' - for x in self.env.DEFINES: - if x.startswith(ban): - return True - return False - -@conf -def get_define(self, key): - """ - Returns the value of an existing define, or None if not found - - :param key: define name - :type key: string - :rtype: string - """ - assert key and isinstance(key, str) - - ban = key + '=' - for x in self.env.DEFINES: - if x.startswith(ban): - return x[len(ban):] - return None - -@conf -def have_define(self, key): - """ - Returns a variable suitable for command-line or header use by removing invalid characters - and prefixing it with ``HAVE_`` - - :param key: define name - :type key: string - :return: the input key prefixed by *HAVE_* and substitute any invalid characters. - :rtype: string - """ - return (self.env.HAVE_PAT or 'HAVE_%s') % Utils.quote_define_name(key) - -@conf -def write_config_header(self, configfile='', guard='', top=False, defines=True, headers=False, remove=True, define_prefix=''): - """ - Writes a configuration header containing defines and includes:: - - def configure(cnf): - cnf.define('A', 1) - cnf.write_config_header('config.h') - - This function only adds include guards (if necessary), consult - :py:func:`waflib.Tools.c_config.get_config_header` for details on the body. - - :param configfile: path to the file to create (relative or absolute) - :type configfile: string - :param guard: include guard name to add, by default it is computed from the file name - :type guard: string - :param top: write the configuration header from the build directory (default is from the current path) - :type top: bool - :param defines: add the defines (yes by default) - :type defines: bool - :param headers: add #include in the file - :type headers: bool - :param remove: remove the defines after they are added (yes by default, works like in autoconf) - :type remove: bool - :type define_prefix: string - :param define_prefix: prefix all the defines in the file with a particular prefix - """ - if not configfile: - configfile = WAF_CONFIG_H - waf_guard = guard or 'W_%s_WAF' % Utils.quote_define_name(configfile) - - node = top and self.bldnode or self.path.get_bld() - node = node.make_node(configfile) - node.parent.mkdir() - - lst = ['/* WARNING! All changes made to this file will be lost! */\n'] - lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard)) - lst.append(self.get_config_header(defines, headers, define_prefix=define_prefix)) - lst.append('\n#endif /* %s */\n' % waf_guard) - - node.write('\n'.join(lst)) - - # config files must not be removed on "waf clean" - self.env.append_unique(Build.CFG_FILES, [node.abspath()]) - - if remove: - for key in self.env[DEFKEYS]: - self.undefine(key) - self.env[DEFKEYS] = [] - -@conf -def get_config_header(self, defines=True, headers=False, define_prefix=''): - """ - Creates the contents of a ``config.h`` file from the defines and includes - set in conf.env.define_key / conf.env.include_key. No include guards are added. - - A prelude will be added from the variable env.WAF_CONFIG_H_PRELUDE if provided. This - can be used to insert complex macros or include guards:: - - def configure(conf): - conf.env.WAF_CONFIG_H_PRELUDE = '#include \\n' - conf.write_config_header('config.h') - - :param defines: write the defines values - :type defines: bool - :param headers: write include entries for each element in self.env.INCKEYS - :type headers: bool - :type define_prefix: string - :param define_prefix: prefix all the defines with a particular prefix - :return: the contents of a ``config.h`` file - :rtype: string - """ - lst = [] - - if self.env.WAF_CONFIG_H_PRELUDE: - lst.append(self.env.WAF_CONFIG_H_PRELUDE) - - if headers: - for x in self.env[INCKEYS]: - lst.append('#include <%s>' % x) - - if defines: - tbl = {} - for k in self.env.DEFINES: - a, _, b = k.partition('=') - tbl[a] = b - - for k in self.env[DEFKEYS]: - caption = self.get_define_comment(k) - if caption: - caption = ' /* %s */' % caption - try: - txt = '#define %s%s %s%s' % (define_prefix, k, tbl[k], caption) - except KeyError: - txt = '/* #undef %s%s */%s' % (define_prefix, k, caption) - lst.append(txt) - return "\n".join(lst) - -@conf -def cc_add_flags(conf): - """ - Adds CFLAGS / CPPFLAGS from os.environ to conf.env - """ - conf.add_os_flags('CPPFLAGS', dup=False) - conf.add_os_flags('CFLAGS', dup=False) - -@conf -def cxx_add_flags(conf): - """ - Adds CXXFLAGS / CPPFLAGS from os.environ to conf.env - """ - conf.add_os_flags('CPPFLAGS', dup=False) - conf.add_os_flags('CXXFLAGS', dup=False) - -@conf -def link_add_flags(conf): - """ - Adds LINKFLAGS / LDFLAGS from os.environ to conf.env - """ - conf.add_os_flags('LINKFLAGS', dup=False) - conf.add_os_flags('LDFLAGS', dup=False) - -@conf -def cc_load_tools(conf): - """ - Loads the Waf c extensions - """ - if not conf.env.DEST_OS: - conf.env.DEST_OS = Utils.unversioned_sys_platform() - conf.load('c') - -@conf -def cxx_load_tools(conf): - """ - Loads the Waf c++ extensions - """ - if not conf.env.DEST_OS: - conf.env.DEST_OS = Utils.unversioned_sys_platform() - conf.load('cxx') - -@conf -def get_cc_version(conf, cc, gcc=False, icc=False, clang=False): - """ - Runs the preprocessor to determine the gcc/icc/clang version - - The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env* - - :raise: :py:class:`waflib.Errors.ConfigurationError` - """ - cmd = cc + ['-dM', '-E', '-'] - env = conf.env.env or None - try: - out, err = conf.cmd_and_log(cmd, output=0, input='\n'.encode(), env=env) - except Errors.WafError: - conf.fatal('Could not determine the compiler version %r' % cmd) - - if gcc: - if out.find('__INTEL_COMPILER') >= 0: - conf.fatal('The intel compiler pretends to be gcc') - if out.find('__GNUC__') < 0 and out.find('__clang__') < 0: - conf.fatal('Could not determine the compiler type') - - if icc and out.find('__INTEL_COMPILER') < 0: - conf.fatal('Not icc/icpc') - - if clang and out.find('__clang__') < 0: - conf.fatal('Not clang/clang++') - if not clang and out.find('__clang__') >= 0: - conf.fatal('Could not find gcc/g++ (only Clang), if renamed try eg: CC=gcc48 CXX=g++48 waf configure') - - k = {} - if icc or gcc or clang: - out = out.splitlines() - for line in out: - lst = shlex.split(line) - if len(lst)>2: - key = lst[1] - val = lst[2] - k[key] = val - - def isD(var): - return var in k - - # Some documentation is available at http://predef.sourceforge.net - # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns. - if not conf.env.DEST_OS: - conf.env.DEST_OS = '' - for i in MACRO_TO_DESTOS: - if isD(i): - conf.env.DEST_OS = MACRO_TO_DESTOS[i] - break - else: - if isD('__APPLE__') and isD('__MACH__'): - conf.env.DEST_OS = 'darwin' - elif isD('__unix__'): # unix must be tested last as it's a generic fallback - conf.env.DEST_OS = 'generic' - - if isD('__ELF__'): - conf.env.DEST_BINFMT = 'elf' - elif isD('__WINNT__') or isD('__CYGWIN__') or isD('_WIN32'): - conf.env.DEST_BINFMT = 'pe' - if not conf.env.IMPLIBDIR: - conf.env.IMPLIBDIR = conf.env.LIBDIR # for .lib or .dll.a files - conf.env.LIBDIR = conf.env.BINDIR - elif isD('__APPLE__'): - conf.env.DEST_BINFMT = 'mac-o' - - if not conf.env.DEST_BINFMT: - # Infer the binary format from the os name. - conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS) - - for i in MACRO_TO_DEST_CPU: - if isD(i): - conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i] - break - - Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')])) - if icc: - ver = k['__INTEL_COMPILER'] - conf.env.CC_VERSION = (ver[:-2], ver[-2], ver[-1]) - else: - if isD('__clang__') and isD('__clang_major__'): - conf.env.CC_VERSION = (k['__clang_major__'], k['__clang_minor__'], k['__clang_patchlevel__']) - else: - # older clang versions and gcc - conf.env.CC_VERSION = (k['__GNUC__'], k['__GNUC_MINOR__'], k.get('__GNUC_PATCHLEVEL__', '0')) - return k - -@conf -def get_xlc_version(conf, cc): - """ - Returns the Aix compiler version - - :raise: :py:class:`waflib.Errors.ConfigurationError` - """ - cmd = cc + ['-qversion'] - try: - out, err = conf.cmd_and_log(cmd, output=0) - except Errors.WafError: - conf.fatal('Could not find xlc %r' % cmd) - - # the intention is to catch the 8.0 in "IBM XL C/C++ Enterprise Edition V8.0 for AIX..." - for v in (r"IBM XL C/C\+\+.* V(?P\d*)\.(?P\d*)",): - version_re = re.compile(v, re.I).search - match = version_re(out or err) - if match: - k = match.groupdict() - conf.env.CC_VERSION = (k['major'], k['minor']) - break - else: - conf.fatal('Could not determine the XLC version.') - -@conf -def get_suncc_version(conf, cc): - """ - Returns the Sun compiler version - - :raise: :py:class:`waflib.Errors.ConfigurationError` - """ - cmd = cc + ['-V'] - try: - out, err = conf.cmd_and_log(cmd, output=0) - except Errors.WafError as e: - # Older versions of the compiler exit with non-zero status when reporting their version - if not (hasattr(e, 'returncode') and hasattr(e, 'stdout') and hasattr(e, 'stderr')): - conf.fatal('Could not find suncc %r' % cmd) - out = e.stdout - err = e.stderr - - version = (out or err) - version = version.splitlines()[0] - - # cc: Sun C 5.10 SunOS_i386 2009/06/03 - # cc: Studio 12.5 Sun C++ 5.14 SunOS_sparc Beta 2015/11/17 - # cc: WorkShop Compilers 5.0 98/12/15 C 5.0 - version_re = re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P\d*)\.(?P\d*)', re.I).search - match = version_re(version) - if match: - k = match.groupdict() - conf.env.CC_VERSION = (k['major'], k['minor']) - else: - conf.fatal('Could not determine the suncc version.') - -# ============ the --as-needed flag should added during the configuration, not at runtime ========= - -@conf -def add_as_needed(self): - """ - Adds ``--as-needed`` to the *LINKFLAGS* - On some platforms, it is a default flag. In some cases (e.g., in NS-3) it is necessary to explicitly disable this feature with `-Wl,--no-as-needed` flag. - """ - if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME): - self.env.append_unique('LINKFLAGS', '-Wl,--as-needed') - -# ============ parallel configuration - -class cfgtask(Task.Task): - """ - A task that executes build configuration tests (calls conf.check) - - Make sure to use locks if concurrent access to the same conf.env data is necessary. - """ - def __init__(self, *k, **kw): - Task.Task.__init__(self, *k, **kw) - self.run_after = set() - - def display(self): - return '' - - def runnable_status(self): - for x in self.run_after: - if not x.hasrun: - return Task.ASK_LATER - return Task.RUN_ME - - def uid(self): - return Utils.SIG_NIL - - def signature(self): - return Utils.SIG_NIL - - def run(self): - conf = self.conf - bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath()) - bld.env = conf.env - bld.init_dirs() - bld.in_msg = 1 # suppress top-level start_msg - bld.logger = self.logger - bld.multicheck_task = self - args = self.args - try: - if 'func' in args: - bld.test(build_fun=args['func'], - msg=args.get('msg', ''), - okmsg=args.get('okmsg', ''), - errmsg=args.get('errmsg', ''), - ) - else: - args['multicheck_mandatory'] = args.get('mandatory', True) - args['mandatory'] = True - try: - bld.check(**args) - finally: - args['mandatory'] = args['multicheck_mandatory'] - except Exception: - return 1 - - def process(self): - Task.Task.process(self) - if 'msg' in self.args: - with self.generator.bld.multicheck_lock: - self.conf.start_msg(self.args['msg']) - if self.hasrun == Task.NOT_RUN: - self.conf.end_msg('test cancelled', 'YELLOW') - elif self.hasrun != Task.SUCCESS: - self.conf.end_msg(self.args.get('errmsg', 'no'), 'YELLOW') - else: - self.conf.end_msg(self.args.get('okmsg', 'yes'), 'GREEN') - -@conf -def multicheck(self, *k, **kw): - """ - Runs configuration tests in parallel; results are printed sequentially at the end of the build - but each test must provide its own msg value to display a line:: - - def test_build(ctx): - ctx.in_msg = True # suppress console outputs - ctx.check_large_file(mandatory=False) - - conf.multicheck( - {'header_name':'stdio.h', 'msg':'... stdio', 'uselib_store':'STDIO', 'global_define':False}, - {'header_name':'xyztabcd.h', 'msg':'... optional xyztabcd.h', 'mandatory': False}, - {'header_name':'stdlib.h', 'msg':'... stdlib', 'okmsg': 'aye', 'errmsg': 'nope'}, - {'func': test_build, 'msg':'... testing an arbitrary build function', 'okmsg':'ok'}, - msg = 'Checking for headers in parallel', - mandatory = True, # mandatory tests raise an error at the end - run_all_tests = True, # try running all tests - ) - - The configuration tests may modify the values in conf.env in any order, and the define - values can affect configuration tests being executed. It is hence recommended - to provide `uselib_store` values with `global_define=False` to prevent such issues. - """ - self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k)), **kw) - - # Force a copy so that threads append to the same list at least - # no order is guaranteed, but the values should not disappear at least - for var in ('DEFINES', DEFKEYS): - self.env.append_value(var, []) - self.env.DEFINE_COMMENTS = self.env.DEFINE_COMMENTS or {} - - # define a task object that will execute our tests - class par(object): - def __init__(self): - self.keep = False - self.task_sigs = {} - self.progress_bar = 0 - def total(self): - return len(tasks) - def to_log(self, *k, **kw): - return - - bld = par() - bld.keep = kw.get('run_all_tests', True) - bld.imp_sigs = {} - tasks = [] - - id_to_task = {} - for dct in k: - x = Task.classes['cfgtask'](bld=bld, env=None) - tasks.append(x) - x.args = dct - x.bld = bld - x.conf = self - x.args = dct - - # bind a logger that will keep the info in memory - x.logger = Logs.make_mem_logger(str(id(x)), self.logger) - - if 'id' in dct: - id_to_task[dct['id']] = x - - # second pass to set dependencies with after_test/before_test - for x in tasks: - for key in Utils.to_list(x.args.get('before_tests', [])): - tsk = id_to_task[key] - if not tsk: - raise ValueError('No test named %r' % key) - tsk.run_after.add(x) - for key in Utils.to_list(x.args.get('after_tests', [])): - tsk = id_to_task[key] - if not tsk: - raise ValueError('No test named %r' % key) - x.run_after.add(tsk) - - def it(): - yield tasks - while 1: - yield [] - bld.producer = p = Runner.Parallel(bld, Options.options.jobs) - bld.multicheck_lock = Utils.threading.Lock() - p.biter = it() - - self.end_msg('started') - p.start() - - # flush the logs in order into the config.log - for x in tasks: - x.logger.memhandler.flush() - - self.start_msg('-> processing test results') - if p.error: - for x in p.error: - if getattr(x, 'err_msg', None): - self.to_log(x.err_msg) - self.end_msg('fail', color='RED') - raise Errors.WafError('There is an error in the library, read config.log for more information') - - failure_count = 0 - for x in tasks: - if x.hasrun not in (Task.SUCCESS, Task.NOT_RUN): - failure_count += 1 - - if failure_count: - self.end_msg(kw.get('errmsg', '%s test failed' % failure_count), color='YELLOW', **kw) - else: - self.end_msg('all ok', **kw) - - for x in tasks: - if x.hasrun != Task.SUCCESS: - if x.args.get('mandatory', True): - self.fatal(kw.get('fatalmsg') or 'One of the tests has failed, read config.log for more information') - -@conf -def check_gcc_o_space(self, mode='c'): - if int(self.env.CC_VERSION[0]) > 4: - # this is for old compilers - return - self.env.stash() - if mode == 'c': - self.env.CCLNK_TGT_F = ['-o', ''] - elif mode == 'cxx': - self.env.CXXLNK_TGT_F = ['-o', ''] - features = '%s %sshlib' % (mode, mode) - try: - self.check(msg='Checking if the -o link must be split from arguments', fragment=SNIP_EMPTY_PROGRAM, features=features) - except self.errors.ConfigurationError: - self.env.revert() - else: - self.env.commit() - diff --git a/waflib/Tools/c_osx.py b/waflib/Tools/c_osx.py deleted file mode 100644 index f70b128..0000000 --- a/waflib/Tools/c_osx.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy 2008-2018 (ita) - -""" -MacOSX related tools -""" - -import os, shutil, platform -from waflib import Task, Utils -from waflib.TaskGen import taskgen_method, feature, after_method, before_method - -app_info = ''' - - - - - CFBundlePackageType - APPL - CFBundleGetInfoString - Created by Waf - CFBundleSignature - ???? - NOTE - THIS IS A GENERATED FILE, DO NOT MODIFY - CFBundleExecutable - {app_name} - - -''' -""" -plist template -""" - -@feature('c', 'cxx') -def set_macosx_deployment_target(self): - """ - see WAF issue 285 and also and also http://trac.macports.org/ticket/17059 - """ - if self.env.MACOSX_DEPLOYMENT_TARGET: - os.environ['MACOSX_DEPLOYMENT_TARGET'] = self.env.MACOSX_DEPLOYMENT_TARGET - elif 'MACOSX_DEPLOYMENT_TARGET' not in os.environ: - if Utils.unversioned_sys_platform() == 'darwin': - os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2]) - -@taskgen_method -def create_bundle_dirs(self, name, out): - """ - Creates bundle folders, used by :py:func:`create_task_macplist` and :py:func:`create_task_macapp` - """ - dir = out.parent.find_or_declare(name) - dir.mkdir() - macos = dir.find_or_declare(['Contents', 'MacOS']) - macos.mkdir() - return dir - -def bundle_name_for_output(out): - name = out.name - k = name.rfind('.') - if k >= 0: - name = name[:k] + '.app' - else: - name = name + '.app' - return name - -@feature('cprogram', 'cxxprogram') -@after_method('apply_link') -def create_task_macapp(self): - """ - To compile an executable into a Mac application (a .app), set its *mac_app* attribute:: - - def build(bld): - bld.shlib(source='a.c', target='foo', mac_app=True) - - To force *all* executables to be transformed into Mac applications:: - - def build(bld): - bld.env.MACAPP = True - bld.shlib(source='a.c', target='foo') - """ - if self.env.MACAPP or getattr(self, 'mac_app', False): - out = self.link_task.outputs[0] - - name = bundle_name_for_output(out) - dir = self.create_bundle_dirs(name, out) - - n1 = dir.find_or_declare(['Contents', 'MacOS', out.name]) - - self.apptask = self.create_task('macapp', self.link_task.outputs, n1) - inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/MacOS/' % name - self.add_install_files(install_to=inst_to, install_from=n1, chmod=Utils.O755) - - if getattr(self, 'mac_files', None): - # this only accepts files; they will be installed as seen from mac_files_root - mac_files_root = getattr(self, 'mac_files_root', None) - if isinstance(mac_files_root, str): - mac_files_root = self.path.find_node(mac_files_root) - if not mac_files_root: - self.bld.fatal('Invalid mac_files_root %r' % self.mac_files_root) - res_dir = n1.parent.parent.make_node('Resources') - inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Resources' % name - for node in self.to_nodes(self.mac_files): - relpath = node.path_from(mac_files_root or node.parent) - self.create_task('macapp', node, res_dir.make_node(relpath)) - self.add_install_as(install_to=os.path.join(inst_to, relpath), install_from=node) - - if getattr(self.bld, 'is_install', None): - # disable regular binary installation - self.install_task.hasrun = Task.SKIP_ME - -@feature('cprogram', 'cxxprogram') -@after_method('apply_link') -def create_task_macplist(self): - """ - Creates a :py:class:`waflib.Tools.c_osx.macplist` instance. - """ - if self.env.MACAPP or getattr(self, 'mac_app', False): - out = self.link_task.outputs[0] - - name = bundle_name_for_output(out) - - dir = self.create_bundle_dirs(name, out) - n1 = dir.find_or_declare(['Contents', 'Info.plist']) - self.plisttask = plisttask = self.create_task('macplist', [], n1) - plisttask.context = { - 'app_name': self.link_task.outputs[0].name, - 'env': self.env - } - - plist_ctx = getattr(self, 'plist_context', None) - if (plist_ctx): - plisttask.context.update(plist_ctx) - - if getattr(self, 'mac_plist', False): - node = self.path.find_resource(self.mac_plist) - if node: - plisttask.inputs.append(node) - else: - plisttask.code = self.mac_plist - else: - plisttask.code = app_info - - inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/' % name - self.add_install_files(install_to=inst_to, install_from=n1) - -@feature('cshlib', 'cxxshlib') -@before_method('apply_link', 'propagate_uselib_vars') -def apply_bundle(self): - """ - To make a bundled shared library (a ``.bundle``), set the *mac_bundle* attribute:: - - def build(bld): - bld.shlib(source='a.c', target='foo', mac_bundle = True) - - To force *all* executables to be transformed into bundles:: - - def build(bld): - bld.env.MACBUNDLE = True - bld.shlib(source='a.c', target='foo') - """ - if self.env.MACBUNDLE or getattr(self, 'mac_bundle', False): - self.env.LINKFLAGS_cshlib = self.env.LINKFLAGS_cxxshlib = [] # disable the '-dynamiclib' flag - self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN - use = self.use = self.to_list(getattr(self, 'use', [])) - if not 'MACBUNDLE' in use: - use.append('MACBUNDLE') - -app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources'] - -class macapp(Task.Task): - """ - Creates mac applications - """ - color = 'PINK' - def run(self): - self.outputs[0].parent.mkdir() - shutil.copy2(self.inputs[0].srcpath(), self.outputs[0].abspath()) - -class macplist(Task.Task): - """ - Creates plist files - """ - color = 'PINK' - ext_in = ['.bin'] - def run(self): - if getattr(self, 'code', None): - txt = self.code - else: - txt = self.inputs[0].read() - context = getattr(self, 'context', {}) - txt = txt.format(**context) - self.outputs[0].write(txt) - diff --git a/waflib/Tools/c_preproc.py b/waflib/Tools/c_preproc.py deleted file mode 100644 index 68e5f5a..0000000 --- a/waflib/Tools/c_preproc.py +++ /dev/null @@ -1,1091 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -""" -C/C++ preprocessor for finding dependencies - -Reasons for using the Waf preprocessor by default - -#. Some c/c++ extensions (Qt) require a custom preprocessor for obtaining the dependencies (.moc files) -#. Not all compilers provide .d files for obtaining the dependencies (portability) -#. A naive file scanner will not catch the constructs such as "#include foo()" -#. A naive file scanner will catch unnecessary dependencies (change an unused header -> recompile everything) - -Regarding the speed concerns: - -* the preprocessing is performed only when files must be compiled -* the macros are evaluated only for #if/#elif/#include -* system headers are not scanned by default - -Now if you do not want the Waf preprocessor, the tool +gccdeps* uses the .d files produced -during the compilation to track the dependencies (useful when used with the boost libraries). -It only works with gcc >= 4.4 though. - -A dumb preprocessor is also available in the tool *c_dumbpreproc* -""" -# TODO: more varargs, pragma once - -import re, string, traceback -from waflib import Logs, Utils, Errors - -class PreprocError(Errors.WafError): - pass - -FILE_CACHE_SIZE = 100000 -LINE_CACHE_SIZE = 100000 - -POPFILE = '-' -"Constant representing a special token used in :py:meth:`waflib.Tools.c_preproc.c_parser.start` iteration to switch to a header read previously" - -recursion_limit = 150 -"Limit on the amount of files to read in the dependency scanner" - -go_absolute = False -"Set to True to track headers on files in /usr/include, else absolute paths are ignored (but it becomes very slow)" - -standard_includes = ['/usr/local/include', '/usr/include'] -if Utils.is_win32: - standard_includes = [] - -use_trigraphs = 0 -"""Apply trigraph rules (False by default)""" - -# obsolete, do not use -strict_quotes = 0 - -g_optrans = { -'not':'!', -'not_eq':'!', -'and':'&&', -'and_eq':'&=', -'or':'||', -'or_eq':'|=', -'xor':'^', -'xor_eq':'^=', -'bitand':'&', -'bitor':'|', -'compl':'~', -} -"""Operators such as and/or/xor for c++. Set an empty dict to disable.""" - -# ignore #warning and #error -re_lines = re.compile( - '^[ \t]*(?:#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$', - re.IGNORECASE | re.MULTILINE) -"""Match #include lines""" - -re_mac = re.compile(r"^[a-zA-Z_]\w*") -"""Match macro definitions""" - -re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') -"""Match macro functions""" - -re_pragma_once = re.compile(r'^\s*once\s*', re.IGNORECASE) -"""Match #pragma once statements""" - -re_nl = re.compile('\\\\\r*\n', re.MULTILINE) -"""Match newlines""" - -re_cpp = re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) -"""Filter C/C++ comments""" - -trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')] -"""Trigraph definitions""" - -chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39} -"""Escape characters""" - -NUM = 'i' -"""Number token""" - -OP = 'O' -"""Operator token""" - -IDENT = 'T' -"""Identifier token""" - -STR = 's' -"""String token""" - -CHAR = 'c' -"""Character token""" - -tok_types = [NUM, STR, IDENT, OP] -"""Token types""" - -exp_types = [ - r"""0[xX](?P[a-fA-F0-9]+)(?P[uUlL]*)|L*?'(?P(\\.|[^\\'])+)'|(?P\d+)[Ee](?P[+-]*?\d+)(?P[fFlL]*)|(?P\d*\.\d+)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P\d+\.\d*)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P0*)(?P\d+)(?P[uUlL]*)""", - r'L?"([^"\\]|\\.)*"', - r'[a-zA-Z_]\w*', - r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]', -] -"""Expression types""" - -re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M) -"""Match expressions into tokens""" - -accepted = 'a' -"""Parser state is *accepted*""" - -ignored = 'i' -"""Parser state is *ignored*, for example preprocessor lines in an #if 0 block""" - -undefined = 'u' -"""Parser state is *undefined* at the moment""" - -skipped = 's' -"""Parser state is *skipped*, for example preprocessor lines in a #elif 0 block""" - -def repl(m): - """Replace function used with :py:attr:`waflib.Tools.c_preproc.re_cpp`""" - s = m.group() - if s[0] == '/': - return ' ' - return s - -prec = {} -""" -Operator precedence rules required for parsing expressions of the form:: - - #if 1 && 2 != 0 -""" -ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ','] -for x, syms in enumerate(ops): - for u in syms.split(): - prec[u] = x - -def reduce_nums(val_1, val_2, val_op): - """ - Apply arithmetic rules to compute a result - - :param val1: input parameter - :type val1: int or string - :param val2: input parameter - :type val2: int or string - :param val_op: C operator in *+*, */*, *-*, etc - :type val_op: string - :rtype: int - """ - #print val_1, val_2, val_op - - # now perform the operation, make certain a and b are numeric - try: - a = 0 + val_1 - except TypeError: - a = int(val_1) - try: - b = 0 + val_2 - except TypeError: - b = int(val_2) - - d = val_op - if d == '%': - c = a % b - elif d=='+': - c = a + b - elif d=='-': - c = a - b - elif d=='*': - c = a * b - elif d=='/': - c = a / b - elif d=='^': - c = a ^ b - elif d=='==': - c = int(a == b) - elif d=='|' or d == 'bitor': - c = a | b - elif d=='||' or d == 'or' : - c = int(a or b) - elif d=='&' or d == 'bitand': - c = a & b - elif d=='&&' or d == 'and': - c = int(a and b) - elif d=='!=' or d == 'not_eq': - c = int(a != b) - elif d=='^' or d == 'xor': - c = int(a^b) - elif d=='<=': - c = int(a <= b) - elif d=='<': - c = int(a < b) - elif d=='>': - c = int(a > b) - elif d=='>=': - c = int(a >= b) - elif d=='<<': - c = a << b - elif d=='>>': - c = a >> b - else: - c = 0 - return c - -def get_num(lst): - """ - Try to obtain a number from a list of tokens. The token types are defined in :py:attr:`waflib.Tools.ccroot.tok_types`. - - :param lst: list of preprocessor tokens - :type lst: list of tuple (tokentype, value) - :return: a pair containing the number and the rest of the list - :rtype: tuple(value, list) - """ - if not lst: - raise PreprocError('empty list for get_num') - (p, v) = lst[0] - if p == OP: - if v == '(': - count_par = 1 - i = 1 - while i < len(lst): - (p, v) = lst[i] - - if p == OP: - if v == ')': - count_par -= 1 - if count_par == 0: - break - elif v == '(': - count_par += 1 - i += 1 - else: - raise PreprocError('rparen expected %r' % lst) - - (num, _) = get_term(lst[1:i]) - return (num, lst[i+1:]) - - elif v == '+': - return get_num(lst[1:]) - elif v == '-': - num, lst = get_num(lst[1:]) - return (reduce_nums('-1', num, '*'), lst) - elif v == '!': - num, lst = get_num(lst[1:]) - return (int(not int(num)), lst) - elif v == '~': - num, lst = get_num(lst[1:]) - return (~ int(num), lst) - else: - raise PreprocError('Invalid op token %r for get_num' % lst) - elif p == NUM: - return v, lst[1:] - elif p == IDENT: - # all macros should have been replaced, remaining identifiers eval to 0 - return 0, lst[1:] - else: - raise PreprocError('Invalid token %r for get_num' % lst) - -def get_term(lst): - """ - Evaluate an expression recursively, for example:: - - 1+1+1 -> 2+1 -> 3 - - :param lst: list of tokens - :type lst: list of tuple(token, value) - :return: the value and the remaining tokens - :rtype: value, list - """ - - if not lst: - raise PreprocError('empty list for get_term') - num, lst = get_num(lst) - if not lst: - return (num, []) - (p, v) = lst[0] - if p == OP: - if v == ',': - # skip - return get_term(lst[1:]) - elif v == '?': - count_par = 0 - i = 1 - while i < len(lst): - (p, v) = lst[i] - - if p == OP: - if v == ')': - count_par -= 1 - elif v == '(': - count_par += 1 - elif v == ':': - if count_par == 0: - break - i += 1 - else: - raise PreprocError('rparen expected %r' % lst) - - if int(num): - return get_term(lst[1:i]) - else: - return get_term(lst[i+1:]) - - else: - num2, lst = get_num(lst[1:]) - - if not lst: - # no more tokens to process - num2 = reduce_nums(num, num2, v) - return get_term([(NUM, num2)] + lst) - - # operator precedence - p2, v2 = lst[0] - if p2 != OP: - raise PreprocError('op expected %r' % lst) - - if prec[v2] >= prec[v]: - num2 = reduce_nums(num, num2, v) - return get_term([(NUM, num2)] + lst) - else: - num3, lst = get_num(lst[1:]) - num3 = reduce_nums(num2, num3, v2) - return get_term([(NUM, num), (p, v), (NUM, num3)] + lst) - - - raise PreprocError('cannot reduce %r' % lst) - -def reduce_eval(lst): - """ - Take a list of tokens and output true or false for #if/#elif conditions. - - :param lst: a list of tokens - :type lst: list of tuple(token, value) - :return: a token - :rtype: tuple(NUM, int) - """ - num, lst = get_term(lst) - return (NUM, num) - -def stringize(lst): - """ - Merge a list of tokens into a string - - :param lst: a list of tokens - :type lst: list of tuple(token, value) - :rtype: string - """ - lst = [str(v2) for (p2, v2) in lst] - return "".join(lst) - -def paste_tokens(t1, t2): - """ - Token pasting works between identifiers, particular operators, and identifiers and numbers:: - - a ## b -> ab - > ## = -> >= - a ## 2 -> a2 - - :param t1: token - :type t1: tuple(type, value) - :param t2: token - :type t2: tuple(type, value) - """ - p1 = None - if t1[0] == OP and t2[0] == OP: - p1 = OP - elif t1[0] == IDENT and (t2[0] == IDENT or t2[0] == NUM): - p1 = IDENT - elif t1[0] == NUM and t2[0] == NUM: - p1 = NUM - if not p1: - raise PreprocError('tokens do not make a valid paste %r and %r' % (t1, t2)) - return (p1, t1[1] + t2[1]) - -def reduce_tokens(lst, defs, ban=[]): - """ - Replace the tokens in lst, using the macros provided in defs, and a list of macros that cannot be re-applied - - :param lst: list of tokens - :type lst: list of tuple(token, value) - :param defs: macro definitions - :type defs: dict - :param ban: macros that cannot be substituted (recursion is not allowed) - :type ban: list of string - :return: the new list of tokens - :rtype: value, list - """ - - i = 0 - while i < len(lst): - (p, v) = lst[i] - - if p == IDENT and v == "defined": - del lst[i] - if i < len(lst): - (p2, v2) = lst[i] - if p2 == IDENT: - if v2 in defs: - lst[i] = (NUM, 1) - else: - lst[i] = (NUM, 0) - elif p2 == OP and v2 == '(': - del lst[i] - (p2, v2) = lst[i] - del lst[i] # remove the ident, and change the ) for the value - if v2 in defs: - lst[i] = (NUM, 1) - else: - lst[i] = (NUM, 0) - else: - raise PreprocError('Invalid define expression %r' % lst) - - elif p == IDENT and v in defs: - - if isinstance(defs[v], str): - a, b = extract_macro(defs[v]) - defs[v] = b - macro_def = defs[v] - to_add = macro_def[1] - - if isinstance(macro_def[0], list): - # macro without arguments - del lst[i] - accu = to_add[:] - reduce_tokens(accu, defs, ban+[v]) - for tmp in accu: - lst.insert(i, tmp) - i += 1 - else: - # collect the arguments for the funcall - - args = [] - del lst[i] - - if i >= len(lst): - raise PreprocError('expected ( after %r (got nothing)' % v) - - (p2, v2) = lst[i] - if p2 != OP or v2 != '(': - raise PreprocError('expected ( after %r' % v) - - del lst[i] - - one_param = [] - count_paren = 0 - while i < len(lst): - p2, v2 = lst[i] - - del lst[i] - if p2 == OP and count_paren == 0: - if v2 == '(': - one_param.append((p2, v2)) - count_paren += 1 - elif v2 == ')': - if one_param: - args.append(one_param) - break - elif v2 == ',': - if not one_param: - raise PreprocError('empty param in funcall %r' % v) - args.append(one_param) - one_param = [] - else: - one_param.append((p2, v2)) - else: - one_param.append((p2, v2)) - if v2 == '(': - count_paren += 1 - elif v2 == ')': - count_paren -= 1 - else: - raise PreprocError('malformed macro') - - # substitute the arguments within the define expression - accu = [] - arg_table = macro_def[0] - j = 0 - while j < len(to_add): - (p2, v2) = to_add[j] - - if p2 == OP and v2 == '#': - # stringize is for arguments only - if j+1 < len(to_add) and to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: - toks = args[arg_table[to_add[j+1][1]]] - accu.append((STR, stringize(toks))) - j += 1 - else: - accu.append((p2, v2)) - elif p2 == OP and v2 == '##': - # token pasting, how can man invent such a complicated system? - if accu and j+1 < len(to_add): - # we have at least two tokens - - t1 = accu[-1] - - if to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: - toks = args[arg_table[to_add[j+1][1]]] - - if toks: - accu[-1] = paste_tokens(t1, toks[0]) #(IDENT, accu[-1][1] + toks[0][1]) - accu.extend(toks[1:]) - else: - # error, case "a##" - accu.append((p2, v2)) - accu.extend(toks) - elif to_add[j+1][0] == IDENT and to_add[j+1][1] == '__VA_ARGS__': - # first collect the tokens - va_toks = [] - st = len(macro_def[0]) - pt = len(args) - for x in args[pt-st+1:]: - va_toks.extend(x) - va_toks.append((OP, ',')) - if va_toks: - va_toks.pop() # extra comma - if len(accu)>1: - (p3, v3) = accu[-1] - (p4, v4) = accu[-2] - if v3 == '##': - # remove the token paste - accu.pop() - if v4 == ',' and pt < st: - # remove the comma - accu.pop() - accu += va_toks - else: - accu[-1] = paste_tokens(t1, to_add[j+1]) - - j += 1 - else: - # Invalid paste, case "##a" or "b##" - accu.append((p2, v2)) - - elif p2 == IDENT and v2 in arg_table: - toks = args[arg_table[v2]] - reduce_tokens(toks, defs, ban+[v]) - accu.extend(toks) - else: - accu.append((p2, v2)) - - j += 1 - - - reduce_tokens(accu, defs, ban+[v]) - - for x in range(len(accu)-1, -1, -1): - lst.insert(i, accu[x]) - - i += 1 - - -def eval_macro(lst, defs): - """ - Reduce the tokens by :py:func:`waflib.Tools.c_preproc.reduce_tokens` and try to return a 0/1 result by :py:func:`waflib.Tools.c_preproc.reduce_eval`. - - :param lst: list of tokens - :type lst: list of tuple(token, value) - :param defs: macro definitions - :type defs: dict - :rtype: int - """ - reduce_tokens(lst, defs, []) - if not lst: - raise PreprocError('missing tokens to evaluate') - - if lst: - p, v = lst[0] - if p == IDENT and v not in defs: - raise PreprocError('missing macro %r' % lst) - - p, v = reduce_eval(lst) - return int(v) != 0 - -def extract_macro(txt): - """ - Process a macro definition of the form:: - #define f(x, y) x * y - - into a function or a simple macro without arguments - - :param txt: expression to exact a macro definition from - :type txt: string - :return: a tuple containing the name, the list of arguments and the replacement - :rtype: tuple(string, [list, list]) - """ - t = tokenize(txt) - if re_fun.search(txt): - p, name = t[0] - - p, v = t[1] - if p != OP: - raise PreprocError('expected (') - - i = 1 - pindex = 0 - params = {} - prev = '(' - - while 1: - i += 1 - p, v = t[i] - - if prev == '(': - if p == IDENT: - params[v] = pindex - pindex += 1 - prev = p - elif p == OP and v == ')': - break - else: - raise PreprocError('unexpected token (3)') - elif prev == IDENT: - if p == OP and v == ',': - prev = v - elif p == OP and v == ')': - break - else: - raise PreprocError('comma or ... expected') - elif prev == ',': - if p == IDENT: - params[v] = pindex - pindex += 1 - prev = p - elif p == OP and v == '...': - raise PreprocError('not implemented (1)') - else: - raise PreprocError('comma or ... expected (2)') - elif prev == '...': - raise PreprocError('not implemented (2)') - else: - raise PreprocError('unexpected else') - - #~ print (name, [params, t[i+1:]]) - return (name, [params, t[i+1:]]) - else: - (p, v) = t[0] - if len(t) > 1: - return (v, [[], t[1:]]) - else: - # empty define, assign an empty token - return (v, [[], [('T','')]]) - -re_include = re.compile(r'^\s*(<(?:.*)>|"(?:.*)")') -def extract_include(txt, defs): - """ - Process a line in the form:: - - #include foo - - :param txt: include line to process - :type txt: string - :param defs: macro definitions - :type defs: dict - :return: the file name - :rtype: string - """ - m = re_include.search(txt) - if m: - txt = m.group(1) - return txt[0], txt[1:-1] - - # perform preprocessing and look at the result, it must match an include - toks = tokenize(txt) - reduce_tokens(toks, defs, ['waf_include']) - - if not toks: - raise PreprocError('could not parse include %r' % txt) - - if len(toks) == 1: - if toks[0][0] == STR: - return '"', toks[0][1] - else: - if toks[0][1] == '<' and toks[-1][1] == '>': - ret = '<', stringize(toks).lstrip('<').rstrip('>') - return ret - - raise PreprocError('could not parse include %r' % txt) - -def parse_char(txt): - """ - Parse a c character - - :param txt: character to parse - :type txt: string - :return: a character literal - :rtype: string - """ - - if not txt: - raise PreprocError('attempted to parse a null char') - if txt[0] != '\\': - return ord(txt) - c = txt[1] - if c == 'x': - if len(txt) == 4 and txt[3] in string.hexdigits: - return int(txt[2:], 16) - return int(txt[2:], 16) - elif c.isdigit(): - if c == '0' and len(txt)==2: - return 0 - for i in 3, 2, 1: - if len(txt) > i and txt[1:1+i].isdigit(): - return (1+i, int(txt[1:1+i], 8)) - else: - try: - return chr_esc[c] - except KeyError: - raise PreprocError('could not parse char literal %r' % txt) - -def tokenize(s): - """ - Convert a string into a list of tokens (shlex.split does not apply to c/c++/d) - - :param s: input to tokenize - :type s: string - :return: a list of tokens - :rtype: list of tuple(token, value) - """ - return tokenize_private(s)[:] # force a copy of the results - -def tokenize_private(s): - ret = [] - for match in re_clexer.finditer(s): - m = match.group - for name in tok_types: - v = m(name) - if v: - if name == IDENT: - if v in g_optrans: - name = OP - elif v.lower() == "true": - v = 1 - name = NUM - elif v.lower() == "false": - v = 0 - name = NUM - elif name == NUM: - if m('oct'): - v = int(v, 8) - elif m('hex'): - v = int(m('hex'), 16) - elif m('n0'): - v = m('n0') - else: - v = m('char') - if v: - v = parse_char(v) - else: - v = m('n2') or m('n4') - elif name == OP: - if v == '%:': - v = '#' - elif v == '%:%:': - v = '##' - elif name == STR: - # remove the quotes around the string - v = v[1:-1] - ret.append((name, v)) - break - return ret - -def format_defines(lst): - ret = [] - for y in lst: - if y: - pos = y.find('=') - if pos == -1: - # "-DFOO" should give "#define FOO 1" - ret.append(y) - elif pos > 0: - # all others are assumed to be -DX=Y - ret.append('%s %s' % (y[:pos], y[pos+1:])) - else: - raise ValueError('Invalid define expression %r' % y) - return ret - -class c_parser(object): - """ - Used by :py:func:`waflib.Tools.c_preproc.scan` to parse c/h files. Note that by default, - only project headers are parsed. - """ - def __init__(self, nodepaths=None, defines=None): - self.lines = [] - """list of lines read""" - - if defines is None: - self.defs = {} - else: - self.defs = dict(defines) # make a copy - self.state = [] - - self.count_files = 0 - self.currentnode_stack = [] - - self.nodepaths = nodepaths or [] - """Include paths""" - - self.nodes = [] - """List of :py:class:`waflib.Node.Node` found so far""" - - self.names = [] - """List of file names that could not be matched by any file""" - - self.curfile = '' - """Current file""" - - self.ban_includes = set() - """Includes that must not be read (#pragma once)""" - - self.listed = set() - """Include nodes/names already listed to avoid duplicates in self.nodes/self.names""" - - def cached_find_resource(self, node, filename): - """ - Find a file from the input directory - - :param node: directory - :type node: :py:class:`waflib.Node.Node` - :param filename: header to find - :type filename: string - :return: the node if found, or None - :rtype: :py:class:`waflib.Node.Node` - """ - try: - cache = node.ctx.preproc_cache_node - except AttributeError: - cache = node.ctx.preproc_cache_node = Utils.lru_cache(FILE_CACHE_SIZE) - - key = (node, filename) - try: - return cache[key] - except KeyError: - ret = node.find_resource(filename) - if ret: - if getattr(ret, 'children', None): - ret = None - elif ret.is_child_of(node.ctx.bldnode): - tmp = node.ctx.srcnode.search_node(ret.path_from(node.ctx.bldnode)) - if tmp and getattr(tmp, 'children', None): - ret = None - cache[key] = ret - return ret - - def tryfind(self, filename, kind='"', env=None): - """ - Try to obtain a node from the filename based from the include paths. Will add - the node found to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` or the file name to - :py:attr:`waflib.Tools.c_preproc.c_parser.names` if no corresponding file is found. Called by - :py:attr:`waflib.Tools.c_preproc.c_parser.start`. - - :param filename: header to find - :type filename: string - :return: the node if found - :rtype: :py:class:`waflib.Node.Node` - """ - if filename.endswith('.moc'): - # we could let the qt4 module use a subclass, but then the function "scan" below must be duplicated - # in the qt4 and in the qt5 classes. So we have two lines here and it is sufficient. - self.names.append(filename) - return None - - self.curfile = filename - - found = None - if kind == '"': - if env.MSVC_VERSION: - for n in reversed(self.currentnode_stack): - found = self.cached_find_resource(n, filename) - if found: - break - else: - found = self.cached_find_resource(self.currentnode_stack[-1], filename) - - if not found: - for n in self.nodepaths: - found = self.cached_find_resource(n, filename) - if found: - break - - listed = self.listed - if found and not found in self.ban_includes: - if found not in listed: - listed.add(found) - self.nodes.append(found) - self.addlines(found) - else: - if filename not in listed: - listed.add(filename) - self.names.append(filename) - return found - - def filter_comments(self, node): - """ - Filter the comments from a c/h file, and return the preprocessor lines. - The regexps :py:attr:`waflib.Tools.c_preproc.re_cpp`, :py:attr:`waflib.Tools.c_preproc.re_nl` and :py:attr:`waflib.Tools.c_preproc.re_lines` are used internally. - - :return: the preprocessor directives as a list of (keyword, line) - :rtype: a list of string pairs - """ - # return a list of tuples : keyword, line - code = node.read() - if use_trigraphs: - for (a, b) in trig_def: - code = code.split(a).join(b) - code = re_nl.sub('', code) - code = re_cpp.sub(repl, code) - return re_lines.findall(code) - - def parse_lines(self, node): - try: - cache = node.ctx.preproc_cache_lines - except AttributeError: - cache = node.ctx.preproc_cache_lines = Utils.lru_cache(LINE_CACHE_SIZE) - try: - return cache[node] - except KeyError: - cache[node] = lines = self.filter_comments(node) - lines.append((POPFILE, '')) - lines.reverse() - return lines - - def addlines(self, node): - """ - Add the lines from a header in the list of preprocessor lines to parse - - :param node: header - :type node: :py:class:`waflib.Node.Node` - """ - - self.currentnode_stack.append(node.parent) - - self.count_files += 1 - if self.count_files > recursion_limit: - # issue #812 - raise PreprocError('recursion limit exceeded') - - if Logs.verbose: - Logs.debug('preproc: reading file %r', node) - try: - lines = self.parse_lines(node) - except EnvironmentError: - raise PreprocError('could not read the file %r' % node) - except Exception: - if Logs.verbose > 0: - Logs.error('parsing %r failed %s', node, traceback.format_exc()) - else: - self.lines.extend(lines) - - def start(self, node, env): - """ - Preprocess a source file to obtain the dependencies, which are accumulated to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` - and :py:attr:`waflib.Tools.c_preproc.c_parser.names`. - - :param node: source file - :type node: :py:class:`waflib.Node.Node` - :param env: config set containing additional defines to take into account - :type env: :py:class:`waflib.ConfigSet.ConfigSet` - """ - Logs.debug('preproc: scanning %s (in %s)', node.name, node.parent.name) - - self.current_file = node - self.addlines(node) - - # macros may be defined on the command-line, so they must be parsed as if they were part of the file - if env.DEFINES: - lst = format_defines(env.DEFINES) - lst.reverse() - self.lines.extend([('define', x) for x in lst]) - - while self.lines: - (token, line) = self.lines.pop() - if token == POPFILE: - self.count_files -= 1 - self.currentnode_stack.pop() - continue - - try: - state = self.state - - # make certain we define the state if we are about to enter in an if block - if token[:2] == 'if': - state.append(undefined) - elif token == 'endif': - state.pop() - - # skip lines when in a dead 'if' branch, wait for the endif - if token[0] != 'e': - if skipped in self.state or ignored in self.state: - continue - - if token == 'if': - ret = eval_macro(tokenize(line), self.defs) - if ret: - state[-1] = accepted - else: - state[-1] = ignored - elif token == 'ifdef': - m = re_mac.match(line) - if m and m.group() in self.defs: - state[-1] = accepted - else: - state[-1] = ignored - elif token == 'ifndef': - m = re_mac.match(line) - if m and m.group() in self.defs: - state[-1] = ignored - else: - state[-1] = accepted - elif token == 'include' or token == 'import': - (kind, inc) = extract_include(line, self.defs) - self.current_file = self.tryfind(inc, kind, env) - if token == 'import': - self.ban_includes.add(self.current_file) - elif token == 'elif': - if state[-1] == accepted: - state[-1] = skipped - elif state[-1] == ignored: - if eval_macro(tokenize(line), self.defs): - state[-1] = accepted - elif token == 'else': - if state[-1] == accepted: - state[-1] = skipped - elif state[-1] == ignored: - state[-1] = accepted - elif token == 'define': - try: - self.defs[self.define_name(line)] = line - except AttributeError: - raise PreprocError('Invalid define line %r' % line) - elif token == 'undef': - m = re_mac.match(line) - if m and m.group() in self.defs: - self.defs.__delitem__(m.group()) - #print "undef %s" % name - elif token == 'pragma': - if re_pragma_once.match(line.lower()): - self.ban_includes.add(self.current_file) - except Exception as e: - if Logs.verbose: - Logs.debug('preproc: line parsing failed (%s): %s %s', e, line, traceback.format_exc()) - - def define_name(self, line): - """ - :param line: define line - :type line: string - :rtype: string - :return: the define name - """ - return re_mac.match(line).group() - -def scan(task): - """ - Get the dependencies using a c/c++ preprocessor, this is required for finding dependencies of the kind:: - - #include some_macro() - - This function is bound as a task method on :py:class:`waflib.Tools.c.c` and :py:class:`waflib.Tools.cxx.cxx` for example - """ - try: - incn = task.generator.includes_nodes - except AttributeError: - raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": ' % task.generator) - - if go_absolute: - nodepaths = incn + [task.generator.bld.root.find_dir(x) for x in standard_includes] - else: - nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] - - tmp = c_parser(nodepaths) - tmp.start(task.inputs[0], task.env) - return (tmp.nodes, tmp.names) diff --git a/waflib/Tools/c_tests.py b/waflib/Tools/c_tests.py deleted file mode 100644 index f858df5..0000000 --- a/waflib/Tools/c_tests.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2016-2018 (ita) - -""" -Various configuration tests. -""" - -from waflib import Task -from waflib.Configure import conf -from waflib.TaskGen import feature, before_method, after_method - -LIB_CODE = ''' -#ifdef _MSC_VER -#define testEXPORT __declspec(dllexport) -#else -#define testEXPORT -#endif -testEXPORT int lib_func(void) { return 9; } -''' - -MAIN_CODE = ''' -#ifdef _MSC_VER -#define testEXPORT __declspec(dllimport) -#else -#define testEXPORT -#endif -testEXPORT int lib_func(void); -int main(int argc, char **argv) { - (void)argc; (void)argv; - return !(lib_func() == 9); -} -''' - -@feature('link_lib_test') -@before_method('process_source') -def link_lib_test_fun(self): - """ - The configuration test :py:func:`waflib.Configure.run_build` declares a unique task generator, - so we need to create other task generators from here to check if the linker is able to link libraries. - """ - def write_test_file(task): - task.outputs[0].write(task.generator.code) - - rpath = [] - if getattr(self, 'add_rpath', False): - rpath = [self.bld.path.get_bld().abspath()] - - mode = self.mode - m = '%s %s' % (mode, mode) - ex = self.test_exec and 'test_exec' or '' - bld = self.bld - bld(rule=write_test_file, target='test.' + mode, code=LIB_CODE) - bld(rule=write_test_file, target='main.' + mode, code=MAIN_CODE) - bld(features='%sshlib' % m, source='test.' + mode, target='test') - bld(features='%sprogram %s' % (m, ex), source='main.' + mode, target='app', use='test', rpath=rpath) - -@conf -def check_library(self, mode=None, test_exec=True): - """ - Checks if libraries can be linked with the current linker. Uses :py:func:`waflib.Tools.c_tests.link_lib_test_fun`. - - :param mode: c or cxx or d - :type mode: string - """ - if not mode: - mode = 'c' - if self.env.CXX: - mode = 'cxx' - self.check( - compile_filename = [], - features = 'link_lib_test', - msg = 'Checking for libraries', - mode = mode, - test_exec = test_exec) - -######################################################################################## - -INLINE_CODE = ''' -typedef int foo_t; -static %s foo_t static_foo () {return 0; } -%s foo_t foo () { - return 0; -} -''' -INLINE_VALUES = ['inline', '__inline__', '__inline'] - -@conf -def check_inline(self, **kw): - """ - Checks for the right value for inline macro. - Define INLINE_MACRO to 1 if the define is found. - If the inline macro is not 'inline', add a define to the ``config.h`` (#define inline __inline__) - - :param define_name: define INLINE_MACRO by default to 1 if the macro is defined - :type define_name: string - :param features: by default *c* or *cxx* depending on the compiler present - :type features: list of string - """ - self.start_msg('Checking for inline') - - if not 'define_name' in kw: - kw['define_name'] = 'INLINE_MACRO' - if not 'features' in kw: - if self.env.CXX: - kw['features'] = ['cxx'] - else: - kw['features'] = ['c'] - - for x in INLINE_VALUES: - kw['fragment'] = INLINE_CODE % (x, x) - - try: - self.check(**kw) - except self.errors.ConfigurationError: - continue - else: - self.end_msg(x) - if x != 'inline': - self.define('inline', x, quote=False) - return x - self.fatal('could not use inline functions') - -######################################################################################## - -LARGE_FRAGMENT = '''#include -int main(int argc, char **argv) { - (void)argc; (void)argv; - return !(sizeof(off_t) >= 8); -} -''' - -@conf -def check_large_file(self, **kw): - """ - Checks for large file support and define the macro HAVE_LARGEFILE - The test is skipped on win32 systems (DEST_BINFMT == pe). - - :param define_name: define to set, by default *HAVE_LARGEFILE* - :type define_name: string - :param execute: execute the test (yes by default) - :type execute: bool - """ - if not 'define_name' in kw: - kw['define_name'] = 'HAVE_LARGEFILE' - if not 'execute' in kw: - kw['execute'] = True - - if not 'features' in kw: - if self.env.CXX: - kw['features'] = ['cxx', 'cxxprogram'] - else: - kw['features'] = ['c', 'cprogram'] - - kw['fragment'] = LARGE_FRAGMENT - - kw['msg'] = 'Checking for large file support' - ret = True - try: - if self.env.DEST_BINFMT != 'pe': - ret = self.check(**kw) - except self.errors.ConfigurationError: - pass - else: - if ret: - return True - - kw['msg'] = 'Checking for -D_FILE_OFFSET_BITS=64' - kw['defines'] = ['_FILE_OFFSET_BITS=64'] - try: - ret = self.check(**kw) - except self.errors.ConfigurationError: - pass - else: - self.define('_FILE_OFFSET_BITS', 64) - return ret - - self.fatal('There is no support for large files') - -######################################################################################## - -ENDIAN_FRAGMENT = ''' -short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; -short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; -int use_ascii (int i) { - return ascii_mm[i] + ascii_ii[i]; -} -short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; -short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; -int use_ebcdic (int i) { - return ebcdic_mm[i] + ebcdic_ii[i]; -} -extern int foo; -''' - -class grep_for_endianness(Task.Task): - """ - Task that reads a binary and tries to determine the endianness - """ - color = 'PINK' - def run(self): - txt = self.inputs[0].read(flags='rb').decode('latin-1') - if txt.find('LiTTleEnDian') > -1: - self.generator.tmp.append('little') - elif txt.find('BIGenDianSyS') > -1: - self.generator.tmp.append('big') - else: - return -1 - -@feature('grep_for_endianness') -@after_method('process_source') -def grep_for_endianness_fun(self): - """ - Used by the endianness configuration test - """ - self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0]) - -@conf -def check_endianness(self): - """ - Executes a configuration test to determine the endianness - """ - tmp = [] - def check_msg(self): - return tmp[0] - self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', - msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, okmsg=check_msg) - return tmp[0] - diff --git a/waflib/Tools/ccroot.py b/waflib/Tools/ccroot.py deleted file mode 100644 index 579d5b2..0000000 --- a/waflib/Tools/ccroot.py +++ /dev/null @@ -1,791 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2005-2018 (ita) - -""" -Classes and methods shared by tools providing support for C-like language such -as C/C++/D/Assembly/Go (this support module is almost never used alone). -""" - -import os, re -from waflib import Task, Utils, Node, Errors, Logs -from waflib.TaskGen import after_method, before_method, feature, taskgen_method, extension -from waflib.Tools import c_aliases, c_preproc, c_config, c_osx, c_tests -from waflib.Configure import conf - -SYSTEM_LIB_PATHS = ['/usr/lib64', '/usr/lib', '/usr/local/lib64', '/usr/local/lib'] - -USELIB_VARS = Utils.defaultdict(set) -""" -Mapping for features to :py:class:`waflib.ConfigSet.ConfigSet` variables. See :py:func:`waflib.Tools.ccroot.propagate_uselib_vars`. -""" - -USELIB_VARS['c'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CCDEPS', 'CFLAGS', 'ARCH']) -USELIB_VARS['cxx'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CXXDEPS', 'CXXFLAGS', 'ARCH']) -USELIB_VARS['d'] = set(['INCLUDES', 'DFLAGS']) -USELIB_VARS['includes'] = set(['INCLUDES', 'FRAMEWORKPATH', 'ARCH']) - -USELIB_VARS['cprogram'] = USELIB_VARS['cxxprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH', 'LDFLAGS']) -USELIB_VARS['cshlib'] = USELIB_VARS['cxxshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH', 'LDFLAGS']) -USELIB_VARS['cstlib'] = USELIB_VARS['cxxstlib'] = set(['ARFLAGS', 'LINKDEPS']) - -USELIB_VARS['dprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) -USELIB_VARS['dshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) -USELIB_VARS['dstlib'] = set(['ARFLAGS', 'LINKDEPS']) - -USELIB_VARS['asm'] = set(['ASFLAGS']) - -# ================================================================================================= - -@taskgen_method -def create_compiled_task(self, name, node): - """ - Create the compilation task: c, cxx, asm, etc. The output node is created automatically (object file with a typical **.o** extension). - The task is appended to the list *compiled_tasks* which is then used by :py:func:`waflib.Tools.ccroot.apply_link` - - :param name: name of the task class - :type name: string - :param node: the file to compile - :type node: :py:class:`waflib.Node.Node` - :return: The task created - :rtype: :py:class:`waflib.Task.Task` - """ - out = '%s.%d.o' % (node.name, self.idx) - task = self.create_task(name, node, node.parent.find_or_declare(out)) - try: - self.compiled_tasks.append(task) - except AttributeError: - self.compiled_tasks = [task] - return task - -@taskgen_method -def to_incnodes(self, inlst): - """ - Task generator method provided to convert a list of string/nodes into a list of includes folders. - - The paths are assumed to be relative to the task generator path, except if they begin by **#** - in which case they are searched from the top-level directory (``bld.srcnode``). - The folders are simply assumed to be existing. - - The node objects in the list are returned in the output list. The strings are converted - into node objects if possible. The node is searched from the source directory, and if a match is found, - the equivalent build directory is created and added to the returned list too. When a folder cannot be found, it is ignored. - - :param inlst: list of folders - :type inlst: space-delimited string or a list of string/nodes - :rtype: list of :py:class:`waflib.Node.Node` - :return: list of include folders as nodes - """ - lst = [] - seen = set() - for x in self.to_list(inlst): - if x in seen or not x: - continue - seen.add(x) - - # with a real lot of targets, it is sometimes interesting to cache the results below - if isinstance(x, Node.Node): - lst.append(x) - else: - if os.path.isabs(x): - lst.append(self.bld.root.make_node(x) or x) - else: - if x[0] == '#': - p = self.bld.bldnode.make_node(x[1:]) - v = self.bld.srcnode.make_node(x[1:]) - else: - p = self.path.get_bld().make_node(x) - v = self.path.make_node(x) - if p.is_child_of(self.bld.bldnode): - p.mkdir() - lst.append(p) - lst.append(v) - return lst - -@feature('c', 'cxx', 'd', 'asm', 'fc', 'includes') -@after_method('propagate_uselib_vars', 'process_source') -def apply_incpaths(self): - """ - Task generator method that processes the attribute *includes*:: - - tg = bld(features='includes', includes='.') - - The folders only need to be relative to the current directory, the equivalent build directory is - added automatically (for headers created in the build directory). This enables using a build directory - or not (``top == out``). - - This method will add a list of nodes read by :py:func:`waflib.Tools.ccroot.to_incnodes` in ``tg.env.INCPATHS``, - and the list of include paths in ``tg.env.INCLUDES``. - """ - - lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env.INCLUDES) - self.includes_nodes = lst - cwd = self.get_cwd() - self.env.INCPATHS = [x.path_from(cwd) for x in lst] - -class link_task(Task.Task): - """ - Base class for all link tasks. A task generator is supposed to have at most one link task bound in the attribute *link_task*. See :py:func:`waflib.Tools.ccroot.apply_link`. - - .. inheritance-diagram:: waflib.Tools.ccroot.stlink_task waflib.Tools.c.cprogram waflib.Tools.c.cshlib waflib.Tools.cxx.cxxstlib waflib.Tools.cxx.cxxprogram waflib.Tools.cxx.cxxshlib waflib.Tools.d.dprogram waflib.Tools.d.dshlib waflib.Tools.d.dstlib waflib.Tools.ccroot.fake_shlib waflib.Tools.ccroot.fake_stlib waflib.Tools.asm.asmprogram waflib.Tools.asm.asmshlib waflib.Tools.asm.asmstlib - """ - color = 'YELLOW' - - weight = 3 - """Try to process link tasks as early as possible""" - - inst_to = None - """Default installation path for the link task outputs, or None to disable""" - - chmod = Utils.O755 - """Default installation mode for the link task outputs""" - - def add_target(self, target): - """ - Process the *target* attribute to add the platform-specific prefix/suffix such as *.so* or *.exe*. - The settings are retrieved from ``env.clsname_PATTERN`` - """ - if isinstance(target, str): - base = self.generator.path - if target.startswith('#'): - # for those who like flat structures - target = target[1:] - base = self.generator.bld.bldnode - - pattern = self.env[self.__class__.__name__ + '_PATTERN'] - if not pattern: - pattern = '%s' - folder, name = os.path.split(target) - - if self.__class__.__name__.find('shlib') > 0 and getattr(self.generator, 'vnum', None): - nums = self.generator.vnum.split('.') - if self.env.DEST_BINFMT == 'pe': - # include the version in the dll file name, - # the import lib file name stays unversioned. - name = name + '-' + nums[0] - elif self.env.DEST_OS == 'openbsd': - pattern = '%s.%s' % (pattern, nums[0]) - if len(nums) >= 2: - pattern += '.%s' % nums[1] - - if folder: - tmp = folder + os.sep + pattern % name - else: - tmp = pattern % name - target = base.find_or_declare(tmp) - self.set_outputs(target) - - def exec_command(self, *k, **kw): - ret = super(link_task, self).exec_command(*k, **kw) - if not ret and self.env.DO_MANIFEST: - ret = self.exec_mf() - return ret - - def exec_mf(self): - """ - Create manifest files for VS-like compilers (msvc, ifort, ...) - """ - if not self.env.MT: - return 0 - - manifest = None - for out_node in self.outputs: - if out_node.name.endswith('.manifest'): - manifest = out_node.abspath() - break - else: - # Should never get here. If we do, it means the manifest file was - # never added to the outputs list, thus we don't have a manifest file - # to embed, so we just return. - return 0 - - # embedding mode. Different for EXE's and DLL's. - # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx - mode = '' - for x in Utils.to_list(self.generator.features): - if x in ('cprogram', 'cxxprogram', 'fcprogram', 'fcprogram_test'): - mode = 1 - elif x in ('cshlib', 'cxxshlib', 'fcshlib'): - mode = 2 - - Logs.debug('msvc: embedding manifest in mode %r', mode) - - lst = [] + self.env.MT - lst.extend(Utils.to_list(self.env.MTFLAGS)) - lst.extend(['-manifest', manifest]) - lst.append('-outputresource:%s;%s' % (self.outputs[0].abspath(), mode)) - - return super(link_task, self).exec_command(lst) - -class stlink_task(link_task): - """ - Base for static link tasks, which use *ar* most of the time. - The target is always removed before being written. - """ - run_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' - - chmod = Utils.O644 - """Default installation mode for the static libraries""" - -def rm_tgt(cls): - old = cls.run - def wrap(self): - try: - os.remove(self.outputs[0].abspath()) - except OSError: - pass - return old(self) - setattr(cls, 'run', wrap) -rm_tgt(stlink_task) - -@feature('skip_stlib_link_deps') -@before_method('process_use') -def apply_skip_stlib_link_deps(self): - """ - This enables an optimization in the :py:func:wafilb.Tools.ccroot.processes_use: method that skips dependency and - link flag optimizations for targets that generate static libraries (via the :py:class:Tools.ccroot.stlink_task task). - The actual behavior is implemented in :py:func:wafilb.Tools.ccroot.processes_use: method so this feature only tells waf - to enable the new behavior. - """ - self.env.SKIP_STLIB_LINK_DEPS = True - -@feature('c', 'cxx', 'd', 'fc', 'asm') -@after_method('process_source') -def apply_link(self): - """ - Collect the tasks stored in ``compiled_tasks`` (created by :py:func:`waflib.Tools.ccroot.create_compiled_task`), and - use the outputs for a new instance of :py:class:`waflib.Tools.ccroot.link_task`. The class to use is the first link task - matching a name from the attribute *features*, for example:: - - def build(bld): - tg = bld(features='cxx cxxprogram cprogram', source='main.c', target='app') - - will create the task ``tg.link_task`` as a new instance of :py:class:`waflib.Tools.cxx.cxxprogram` - """ - - for x in self.features: - if x == 'cprogram' and 'cxx' in self.features: # limited compat - x = 'cxxprogram' - elif x == 'cshlib' and 'cxx' in self.features: - x = 'cxxshlib' - - if x in Task.classes: - if issubclass(Task.classes[x], link_task): - link = x - break - else: - return - - objs = [t.outputs[0] for t in getattr(self, 'compiled_tasks', [])] - self.link_task = self.create_task(link, objs) - self.link_task.add_target(self.target) - - # remember that the install paths are given by the task generators - try: - inst_to = self.install_path - except AttributeError: - inst_to = self.link_task.inst_to - if inst_to: - # install a copy of the node list we have at this moment (implib not added) - self.install_task = self.add_install_files( - install_to=inst_to, install_from=self.link_task.outputs[:], - chmod=self.link_task.chmod, task=self.link_task) - -@taskgen_method -def use_rec(self, name, **kw): - """ - Processes the ``use`` keyword recursively. This method is kind of private and only meant to be used from ``process_use`` - """ - - if name in self.tmp_use_not or name in self.tmp_use_seen: - return - - try: - y = self.bld.get_tgen_by_name(name) - except Errors.WafError: - self.uselib.append(name) - self.tmp_use_not.add(name) - return - - self.tmp_use_seen.append(name) - y.post() - - # bind temporary attributes on the task generator - y.tmp_use_objects = objects = kw.get('objects', True) - y.tmp_use_stlib = stlib = kw.get('stlib', True) - try: - link_task = y.link_task - except AttributeError: - y.tmp_use_var = '' - else: - objects = False - if not isinstance(link_task, stlink_task): - stlib = False - y.tmp_use_var = 'LIB' - else: - y.tmp_use_var = 'STLIB' - - p = self.tmp_use_prec - for x in self.to_list(getattr(y, 'use', [])): - if self.env["STLIB_" + x]: - continue - try: - p[x].append(name) - except KeyError: - p[x] = [name] - self.use_rec(x, objects=objects, stlib=stlib) - -@feature('c', 'cxx', 'd', 'use', 'fc') -@before_method('apply_incpaths', 'propagate_uselib_vars') -@after_method('apply_link', 'process_source') -def process_use(self): - """ - Process the ``use`` attribute which contains a list of task generator names:: - - def build(bld): - bld.shlib(source='a.c', target='lib1') - bld.program(source='main.c', target='app', use='lib1') - - See :py:func:`waflib.Tools.ccroot.use_rec`. - """ - - use_not = self.tmp_use_not = set() - self.tmp_use_seen = [] # we would like an ordered set - use_prec = self.tmp_use_prec = {} - self.uselib = self.to_list(getattr(self, 'uselib', [])) - self.includes = self.to_list(getattr(self, 'includes', [])) - names = self.to_list(getattr(self, 'use', [])) - - for x in names: - self.use_rec(x) - - for x in use_not: - if x in use_prec: - del use_prec[x] - - # topological sort - out = self.tmp_use_sorted = [] - tmp = [] - for x in self.tmp_use_seen: - for k in use_prec.values(): - if x in k: - break - else: - tmp.append(x) - - while tmp: - e = tmp.pop() - out.append(e) - try: - nlst = use_prec[e] - except KeyError: - pass - else: - del use_prec[e] - for x in nlst: - for y in use_prec: - if x in use_prec[y]: - break - else: - tmp.append(x) - if use_prec: - raise Errors.WafError('Cycle detected in the use processing %r' % use_prec) - out.reverse() - - link_task = getattr(self, 'link_task', None) - for x in out: - y = self.bld.get_tgen_by_name(x) - var = y.tmp_use_var - if var and link_task: - if self.env.SKIP_STLIB_LINK_DEPS and isinstance(link_task, stlink_task): - # If the skip_stlib_link_deps feature is enabled then we should - # avoid adding lib deps to the stlink_task instance. - pass - elif var == 'LIB' or y.tmp_use_stlib or x in names: - self.env.append_value(var, [y.target[y.target.rfind(os.sep) + 1:]]) - self.link_task.dep_nodes.extend(y.link_task.outputs) - tmp_path = y.link_task.outputs[0].parent.path_from(self.get_cwd()) - self.env.append_unique(var + 'PATH', [tmp_path]) - else: - if y.tmp_use_objects: - self.add_objects_from_tgen(y) - - if getattr(y, 'export_includes', None): - # self.includes may come from a global variable #2035 - self.includes = self.includes + y.to_incnodes(y.export_includes) - - if getattr(y, 'export_defines', None): - self.env.append_value('DEFINES', self.to_list(y.export_defines)) - - - # and finally, add the use variables (no recursion needed) - for x in names: - try: - y = self.bld.get_tgen_by_name(x) - except Errors.WafError: - if not self.env['STLIB_' + x] and not x in self.uselib: - self.uselib.append(x) - else: - for k in self.to_list(getattr(y, 'use', [])): - if not self.env['STLIB_' + k] and not k in self.uselib: - self.uselib.append(k) - -@taskgen_method -def accept_node_to_link(self, node): - """ - PRIVATE INTERNAL USE ONLY - """ - return not node.name.endswith('.pdb') - -@taskgen_method -def add_objects_from_tgen(self, tg): - """ - Add the objects from the depending compiled tasks as link task inputs. - - Some objects are filtered: for instance, .pdb files are added - to the compiled tasks but not to the link tasks (to avoid errors) - PRIVATE INTERNAL USE ONLY - """ - try: - link_task = self.link_task - except AttributeError: - pass - else: - for tsk in getattr(tg, 'compiled_tasks', []): - for x in tsk.outputs: - if self.accept_node_to_link(x): - link_task.inputs.append(x) - -@taskgen_method -def get_uselib_vars(self): - """ - :return: the *uselib* variables associated to the *features* attribute (see :py:attr:`waflib.Tools.ccroot.USELIB_VARS`) - :rtype: list of string - """ - _vars = set() - for x in self.features: - if x in USELIB_VARS: - _vars |= USELIB_VARS[x] - return _vars - -@feature('c', 'cxx', 'd', 'fc', 'javac', 'cs', 'uselib', 'asm') -@after_method('process_use') -def propagate_uselib_vars(self): - """ - Process uselib variables for adding flags. For example, the following target:: - - def build(bld): - bld.env.AFLAGS_aaa = ['bar'] - from waflib.Tools.ccroot import USELIB_VARS - USELIB_VARS['aaa'] = ['AFLAGS'] - - tg = bld(features='aaa', aflags='test') - - The *aflags* attribute will be processed and this method will set:: - - tg.env.AFLAGS = ['bar', 'test'] - """ - _vars = self.get_uselib_vars() - env = self.env - app = env.append_value - feature_uselib = self.features + self.to_list(getattr(self, 'uselib', [])) - for var in _vars: - y = var.lower() - val = getattr(self, y, []) - if val: - app(var, self.to_list(val)) - - for x in feature_uselib: - val = env['%s_%s' % (var, x)] - if val: - app(var, val) - -# ============ the code above must not know anything about import libs ========== - -@feature('cshlib', 'cxxshlib', 'fcshlib') -@after_method('apply_link') -def apply_implib(self): - """ - Handle dlls and their import libs on Windows-like systems. - - A ``.dll.a`` file called *import library* is generated. - It must be installed as it is required for linking the library. - """ - if not self.env.DEST_BINFMT == 'pe': - return - - dll = self.link_task.outputs[0] - if isinstance(self.target, Node.Node): - name = self.target.name - else: - name = os.path.split(self.target)[1] - implib = self.env.implib_PATTERN % name - implib = dll.parent.find_or_declare(implib) - self.env.append_value('LINKFLAGS', self.env.IMPLIB_ST % implib.bldpath()) - self.link_task.outputs.append(implib) - - if getattr(self, 'defs', None) and self.env.DEST_BINFMT == 'pe': - node = self.path.find_resource(self.defs) - if not node: - raise Errors.WafError('invalid def file %r' % self.defs) - if self.env.def_PATTERN: - self.env.append_value('LINKFLAGS', self.env.def_PATTERN % node.path_from(self.get_cwd())) - self.link_task.dep_nodes.append(node) - else: - # gcc for windows takes *.def file as input without any special flag - self.link_task.inputs.append(node) - - # where to put the import library - if getattr(self, 'install_task', None): - try: - # user has given a specific installation path for the import library - inst_to = self.install_path_implib - except AttributeError: - try: - # user has given an installation path for the main library, put the import library in it - inst_to = self.install_path - except AttributeError: - # else, put the library in BINDIR and the import library in LIBDIR - inst_to = '${IMPLIBDIR}' - self.install_task.install_to = '${BINDIR}' - if not self.env.IMPLIBDIR: - self.env.IMPLIBDIR = self.env.LIBDIR - self.implib_install_task = self.add_install_files(install_to=inst_to, install_from=implib, - chmod=self.link_task.chmod, task=self.link_task) - -# ============ the code above must not know anything about vnum processing on unix platforms ========= - -re_vnum = re.compile('^([1-9]\\d*|0)([.]([1-9]\\d*|0)){0,2}?$') -@feature('cshlib', 'cxxshlib', 'dshlib', 'fcshlib', 'vnum') -@after_method('apply_link', 'propagate_uselib_vars') -def apply_vnum(self): - """ - Enforce version numbering on shared libraries. The valid version numbers must have either zero or two dots:: - - def build(bld): - bld.shlib(source='a.c', target='foo', vnum='14.15.16') - - In this example on Linux platform, ``libfoo.so`` is installed as ``libfoo.so.14.15.16``, and the following symbolic links are created: - - * ``libfoo.so → libfoo.so.14.15.16`` - * ``libfoo.so.14 → libfoo.so.14.15.16`` - - By default, the library will be assigned SONAME ``libfoo.so.14``, effectively declaring ABI compatibility between all minor and patch releases for the major version of the library. When necessary, the compatibility can be explicitly defined using `cnum` parameter: - - def build(bld): - bld.shlib(source='a.c', target='foo', vnum='14.15.16', cnum='14.15') - - In this case, the assigned SONAME will be ``libfoo.so.14.15`` with ABI compatibility only between path releases for a specific major and minor version of the library. - - On OS X platform, install-name parameter will follow the above logic for SONAME with exception that it also specifies an absolute path (based on install_path) of the library. - """ - if not getattr(self, 'vnum', '') or os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'): - return - - link = self.link_task - if not re_vnum.match(self.vnum): - raise Errors.WafError('Invalid vnum %r for target %r' % (self.vnum, getattr(self, 'name', self))) - nums = self.vnum.split('.') - node = link.outputs[0] - - cnum = getattr(self, 'cnum', str(nums[0])) - cnums = cnum.split('.') - if len(cnums)>len(nums) or nums[0:len(cnums)] != cnums: - raise Errors.WafError('invalid compatibility version %s' % cnum) - - libname = node.name - if libname.endswith('.dylib'): - name3 = libname.replace('.dylib', '.%s.dylib' % self.vnum) - name2 = libname.replace('.dylib', '.%s.dylib' % cnum) - else: - name3 = libname + '.' + self.vnum - name2 = libname + '.' + cnum - - # add the so name for the ld linker - to disable, just unset env.SONAME_ST - if self.env.SONAME_ST: - v = self.env.SONAME_ST % name2 - self.env.append_value('LINKFLAGS', v.split()) - - # the following task is just to enable execution from the build dir :-/ - if self.env.DEST_OS != 'openbsd': - outs = [node.parent.make_node(name3)] - if name2 != name3: - outs.append(node.parent.make_node(name2)) - self.create_task('vnum', node, outs) - - if getattr(self, 'install_task', None): - self.install_task.hasrun = Task.SKIPPED - self.install_task.no_errcheck_out = True - path = self.install_task.install_to - if self.env.DEST_OS == 'openbsd': - libname = self.link_task.outputs[0].name - t1 = self.add_install_as(install_to='%s/%s' % (path, libname), install_from=node, chmod=self.link_task.chmod) - self.vnum_install_task = (t1,) - else: - t1 = self.add_install_as(install_to=path + os.sep + name3, install_from=node, chmod=self.link_task.chmod) - t3 = self.add_symlink_as(install_to=path + os.sep + libname, install_from=name3) - if name2 != name3: - t2 = self.add_symlink_as(install_to=path + os.sep + name2, install_from=name3) - self.vnum_install_task = (t1, t2, t3) - else: - self.vnum_install_task = (t1, t3) - - if '-dynamiclib' in self.env.LINKFLAGS: - # this requires after(propagate_uselib_vars) - try: - inst_to = self.install_path - except AttributeError: - inst_to = self.link_task.inst_to - if inst_to: - p = Utils.subst_vars(inst_to, self.env) - path = os.path.join(p, name2) - self.env.append_value('LINKFLAGS', ['-install_name', path]) - self.env.append_value('LINKFLAGS', '-Wl,-compatibility_version,%s' % cnum) - self.env.append_value('LINKFLAGS', '-Wl,-current_version,%s' % self.vnum) - -class vnum(Task.Task): - """ - Create the symbolic links for a versioned shared library. Instances are created by :py:func:`waflib.Tools.ccroot.apply_vnum` - """ - color = 'CYAN' - ext_in = ['.bin'] - def keyword(self): - return 'Symlinking' - def run(self): - for x in self.outputs: - path = x.abspath() - try: - os.remove(path) - except OSError: - pass - - try: - os.symlink(self.inputs[0].name, path) - except OSError: - return 1 - -class fake_shlib(link_task): - """ - Task used for reading a system library and adding the dependency on it - """ - def runnable_status(self): - for t in self.run_after: - if not t.hasrun: - return Task.ASK_LATER - return Task.SKIP_ME - -class fake_stlib(stlink_task): - """ - Task used for reading a system library and adding the dependency on it - """ - def runnable_status(self): - for t in self.run_after: - if not t.hasrun: - return Task.ASK_LATER - return Task.SKIP_ME - -@conf -def read_shlib(self, name, paths=[], export_includes=[], export_defines=[]): - """ - Read a system shared library, enabling its use as a local library. Will trigger a rebuild if the file changes:: - - def build(bld): - bld.read_shlib('m') - bld.program(source='main.c', use='m') - """ - return self(name=name, features='fake_lib', lib_paths=paths, lib_type='shlib', export_includes=export_includes, export_defines=export_defines) - -@conf -def read_stlib(self, name, paths=[], export_includes=[], export_defines=[]): - """ - Read a system static library, enabling a use as a local library. Will trigger a rebuild if the file changes. - """ - return self(name=name, features='fake_lib', lib_paths=paths, lib_type='stlib', export_includes=export_includes, export_defines=export_defines) - -lib_patterns = { - 'shlib' : ['lib%s.so', '%s.so', 'lib%s.dylib', 'lib%s.dll', '%s.dll'], - 'stlib' : ['lib%s.a', '%s.a', 'lib%s.dll', '%s.dll', 'lib%s.lib', '%s.lib'], -} - -@feature('fake_lib') -def process_lib(self): - """ - Find the location of a foreign library. Used by :py:class:`waflib.Tools.ccroot.read_shlib` and :py:class:`waflib.Tools.ccroot.read_stlib`. - """ - node = None - - names = [x % self.name for x in lib_patterns[self.lib_type]] - for x in self.lib_paths + [self.path] + SYSTEM_LIB_PATHS: - if not isinstance(x, Node.Node): - x = self.bld.root.find_node(x) or self.path.find_node(x) - if not x: - continue - - for y in names: - node = x.find_node(y) - if node: - try: - Utils.h_file(node.abspath()) - except EnvironmentError: - raise ValueError('Could not read %r' % y) - break - else: - continue - break - else: - raise Errors.WafError('could not find library %r' % self.name) - self.link_task = self.create_task('fake_%s' % self.lib_type, [], [node]) - self.target = self.name - - -class fake_o(Task.Task): - def runnable_status(self): - return Task.SKIP_ME - -@extension('.o', '.obj') -def add_those_o_files(self, node): - tsk = self.create_task('fake_o', [], node) - try: - self.compiled_tasks.append(tsk) - except AttributeError: - self.compiled_tasks = [tsk] - -@feature('fake_obj') -@before_method('process_source') -def process_objs(self): - """ - Puts object files in the task generator outputs - """ - for node in self.to_nodes(self.source): - self.add_those_o_files(node) - self.source = [] - -@conf -def read_object(self, obj): - """ - Read an object file, enabling injection in libs/programs. Will trigger a rebuild if the file changes. - - :param obj: object file path, as string or Node - """ - if not isinstance(obj, self.path.__class__): - obj = self.path.find_resource(obj) - return self(features='fake_obj', source=obj, name=obj.name) - -@feature('cxxprogram', 'cprogram') -@after_method('apply_link', 'process_use') -def set_full_paths_hpux(self): - """ - On hp-ux, extend the libpaths and static library paths to absolute paths - """ - if self.env.DEST_OS != 'hp-ux': - return - base = self.bld.bldnode.abspath() - for var in ['LIBPATH', 'STLIBPATH']: - lst = [] - for x in self.env[var]: - if x.startswith('/'): - lst.append(x) - else: - lst.append(os.path.normpath(os.path.join(base, x))) - self.env[var] = lst - diff --git a/waflib/Tools/clang.py b/waflib/Tools/clang.py deleted file mode 100644 index 3828e39..0000000 --- a/waflib/Tools/clang.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Krzysztof Kosiński 2014 - -""" -Detect the Clang C compiler -""" - -from waflib.Tools import ccroot, ar, gcc -from waflib.Configure import conf - -@conf -def find_clang(conf): - """ - Finds the program clang and executes it to ensure it really is clang - """ - cc = conf.find_program('clang', var='CC') - conf.get_cc_version(cc, clang=True) - conf.env.CC_NAME = 'clang' - -def configure(conf): - conf.find_clang() - conf.find_program(['llvm-ar', 'ar'], var='AR') - conf.find_ar() - conf.gcc_common_flags() - conf.gcc_modifier_platform() - conf.cc_load_tools() - conf.cc_add_flags() - conf.link_add_flags() diff --git a/waflib/Tools/clangxx.py b/waflib/Tools/clangxx.py deleted file mode 100644 index 152013c..0000000 --- a/waflib/Tools/clangxx.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy 2009-2018 (ita) - -""" -Detect the Clang++ C++ compiler -""" - -from waflib.Tools import ccroot, ar, gxx -from waflib.Configure import conf - -@conf -def find_clangxx(conf): - """ - Finds the program clang++, and executes it to ensure it really is clang++ - """ - cxx = conf.find_program('clang++', var='CXX') - conf.get_cc_version(cxx, clang=True) - conf.env.CXX_NAME = 'clang' - -def configure(conf): - conf.find_clangxx() - conf.find_program(['llvm-ar', 'ar'], var='AR') - conf.find_ar() - conf.gxx_common_flags() - conf.gxx_modifier_platform() - conf.cxx_load_tools() - conf.cxx_add_flags() - conf.link_add_flags() - diff --git a/waflib/Tools/compiler_c.py b/waflib/Tools/compiler_c.py deleted file mode 100644 index 2dba3f8..0000000 --- a/waflib/Tools/compiler_c.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Matthias Jahn jahn dôt matthias ât freenet dôt de, 2007 (pmarat) - -""" -Try to detect a C compiler from the list of supported compilers (gcc, msvc, etc):: - - def options(opt): - opt.load('compiler_c') - def configure(cnf): - cnf.load('compiler_c') - def build(bld): - bld.program(source='main.c', target='app') - -The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_c.c_compiler`. To register -a new C compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: - - from waflib.Tools.compiler_c import c_compiler - c_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] - - def options(opt): - opt.load('compiler_c') - def configure(cnf): - cnf.load('compiler_c') - def build(bld): - bld.program(source='main.c', target='app') - -Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: - - $ CC=clang waf configure -""" - -import re -from waflib.Tools import ccroot -from waflib import Utils -from waflib.Logs import debug - -c_compiler = { -'win32': ['msvc', 'gcc', 'clang'], -'cygwin': ['gcc'], -'darwin': ['clang', 'gcc'], -'aix': ['xlc', 'gcc', 'clang'], -'linux': ['gcc', 'clang', 'icc'], -'sunos': ['suncc', 'gcc'], -'irix': ['gcc', 'irixcc'], -'hpux': ['gcc'], -'osf1V': ['gcc'], -'gnu': ['gcc', 'clang'], -'java': ['gcc', 'msvc', 'clang', 'icc'], -'default':['clang', 'gcc'], -} -""" -Dict mapping platform names to Waf tools finding specific C compilers:: - - from waflib.Tools.compiler_c import c_compiler - c_compiler['linux'] = ['gcc', 'icc', 'suncc'] -""" - -def default_compilers(): - build_platform = Utils.unversioned_sys_platform() - possible_compiler_list = c_compiler.get(build_platform, c_compiler['default']) - return ' '.join(possible_compiler_list) - -def configure(conf): - """ - Detects a suitable C compiler - - :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found - """ - try: - test_for_compiler = conf.options.check_c_compiler or default_compilers() - except AttributeError: - conf.fatal("Add options(opt): opt.load('compiler_c')") - - for compiler in re.split('[ ,]+', test_for_compiler): - conf.env.stash() - conf.start_msg('Checking for %r (C compiler)' % compiler) - try: - conf.load(compiler) - except conf.errors.ConfigurationError as e: - conf.env.revert() - conf.end_msg(False) - debug('compiler_c: %r', e) - else: - if conf.env.CC: - conf.end_msg(conf.env.get_flat('CC')) - conf.env.COMPILER_CC = compiler - conf.env.commit() - break - conf.env.revert() - conf.end_msg(False) - else: - conf.fatal('could not configure a C compiler!') - -def options(opt): - """ - This is how to provide compiler preferences on the command-line:: - - $ waf configure --check-c-compiler=gcc - """ - test_for_compiler = default_compilers() - opt.load_special_tools('c_*.py', ban=['c_dumbpreproc.py']) - cc_compiler_opts = opt.add_option_group('Configuration options') - cc_compiler_opts.add_option('--check-c-compiler', default=None, - help='list of C compilers to try [%s]' % test_for_compiler, - dest="check_c_compiler") - - for x in test_for_compiler.split(): - opt.load('%s' % x) - diff --git a/waflib/Tools/compiler_cxx.py b/waflib/Tools/compiler_cxx.py deleted file mode 100644 index 1af65a2..0000000 --- a/waflib/Tools/compiler_cxx.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Matthias Jahn jahn dôt matthias ât freenet dôt de 2007 (pmarat) - -""" -Try to detect a C++ compiler from the list of supported compilers (g++, msvc, etc):: - - def options(opt): - opt.load('compiler_cxx') - def configure(cnf): - cnf.load('compiler_cxx') - def build(bld): - bld.program(source='main.cpp', target='app') - -The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_cxx.cxx_compiler`. To register -a new C++ compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: - - from waflib.Tools.compiler_cxx import cxx_compiler - cxx_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] - - def options(opt): - opt.load('compiler_cxx') - def configure(cnf): - cnf.load('compiler_cxx') - def build(bld): - bld.program(source='main.c', target='app') - -Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: - - $ CXX=clang waf configure -""" - - -import re -from waflib.Tools import ccroot -from waflib import Utils -from waflib.Logs import debug - -cxx_compiler = { -'win32': ['msvc', 'g++', 'clang++'], -'cygwin': ['g++'], -'darwin': ['clang++', 'g++'], -'aix': ['xlc++', 'g++', 'clang++'], -'linux': ['g++', 'clang++', 'icpc'], -'sunos': ['sunc++', 'g++'], -'irix': ['g++'], -'hpux': ['g++'], -'osf1V': ['g++'], -'gnu': ['g++', 'clang++'], -'java': ['g++', 'msvc', 'clang++', 'icpc'], -'default': ['clang++', 'g++'] -} -""" -Dict mapping the platform names to Waf tools finding specific C++ compilers:: - - from waflib.Tools.compiler_cxx import cxx_compiler - cxx_compiler['linux'] = ['gxx', 'icpc', 'suncxx'] -""" - -def default_compilers(): - build_platform = Utils.unversioned_sys_platform() - possible_compiler_list = cxx_compiler.get(build_platform, cxx_compiler['default']) - return ' '.join(possible_compiler_list) - -def configure(conf): - """ - Detects a suitable C++ compiler - - :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found - """ - try: - test_for_compiler = conf.options.check_cxx_compiler or default_compilers() - except AttributeError: - conf.fatal("Add options(opt): opt.load('compiler_cxx')") - - for compiler in re.split('[ ,]+', test_for_compiler): - conf.env.stash() - conf.start_msg('Checking for %r (C++ compiler)' % compiler) - try: - conf.load(compiler) - except conf.errors.ConfigurationError as e: - conf.env.revert() - conf.end_msg(False) - debug('compiler_cxx: %r', e) - else: - if conf.env.CXX: - conf.end_msg(conf.env.get_flat('CXX')) - conf.env.COMPILER_CXX = compiler - conf.env.commit() - break - conf.env.revert() - conf.end_msg(False) - else: - conf.fatal('could not configure a C++ compiler!') - -def options(opt): - """ - This is how to provide compiler preferences on the command-line:: - - $ waf configure --check-cxx-compiler=gxx - """ - test_for_compiler = default_compilers() - opt.load_special_tools('cxx_*.py') - cxx_compiler_opts = opt.add_option_group('Configuration options') - cxx_compiler_opts.add_option('--check-cxx-compiler', default=None, - help='list of C++ compilers to try [%s]' % test_for_compiler, - dest="check_cxx_compiler") - - for x in test_for_compiler.split(): - opt.load('%s' % x) - diff --git a/waflib/Tools/compiler_d.py b/waflib/Tools/compiler_d.py deleted file mode 100644 index 43bb1f6..0000000 --- a/waflib/Tools/compiler_d.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Carlos Rafael Giani, 2007 (dv) -# Thomas Nagy, 2016-2018 (ita) - -""" -Try to detect a D compiler from the list of supported compilers:: - - def options(opt): - opt.load('compiler_d') - def configure(cnf): - cnf.load('compiler_d') - def build(bld): - bld.program(source='main.d', target='app') - -Only three D compilers are really present at the moment: - -* gdc -* dmd, the ldc compiler having a very similar command-line interface -* ldc2 -""" - -import re -from waflib import Utils, Logs - -d_compiler = { -'default' : ['gdc', 'dmd', 'ldc2'] -} -""" -Dict mapping the platform names to lists of names of D compilers to try, in order of preference:: - - from waflib.Tools.compiler_d import d_compiler - d_compiler['default'] = ['gdc', 'dmd', 'ldc2'] -""" - -def default_compilers(): - build_platform = Utils.unversioned_sys_platform() - possible_compiler_list = d_compiler.get(build_platform, d_compiler['default']) - return ' '.join(possible_compiler_list) - -def configure(conf): - """ - Detects a suitable D compiler - - :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found - """ - try: - test_for_compiler = conf.options.check_d_compiler or default_compilers() - except AttributeError: - conf.fatal("Add options(opt): opt.load('compiler_d')") - - for compiler in re.split('[ ,]+', test_for_compiler): - conf.env.stash() - conf.start_msg('Checking for %r (D compiler)' % compiler) - try: - conf.load(compiler) - except conf.errors.ConfigurationError as e: - conf.env.revert() - conf.end_msg(False) - Logs.debug('compiler_d: %r', e) - else: - if conf.env.D: - conf.end_msg(conf.env.get_flat('D')) - conf.env.COMPILER_D = compiler - conf.env.commit() - break - conf.env.revert() - conf.end_msg(False) - else: - conf.fatal('could not configure a D compiler!') - -def options(opt): - """ - This is how to provide compiler preferences on the command-line:: - - $ waf configure --check-d-compiler=dmd - """ - test_for_compiler = default_compilers() - d_compiler_opts = opt.add_option_group('Configuration options') - d_compiler_opts.add_option('--check-d-compiler', default=None, - help='list of D compilers to try [%s]' % test_for_compiler, dest='check_d_compiler') - - for x in test_for_compiler.split(): - opt.load('%s' % x) - diff --git a/waflib/Tools/compiler_fc.py b/waflib/Tools/compiler_fc.py deleted file mode 100644 index 96b58e7..0000000 --- a/waflib/Tools/compiler_fc.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -import re -from waflib import Utils, Logs -from waflib.Tools import fc - -fc_compiler = { - 'win32' : ['gfortran','ifort'], - 'darwin' : ['gfortran', 'g95', 'ifort'], - 'linux' : ['gfortran', 'g95', 'ifort'], - 'java' : ['gfortran', 'g95', 'ifort'], - 'default': ['gfortran'], - 'aix' : ['gfortran'] -} -""" -Dict mapping the platform names to lists of names of Fortran compilers to try, in order of preference:: - - from waflib.Tools.compiler_c import c_compiler - c_compiler['linux'] = ['gfortran', 'g95', 'ifort'] -""" - -def default_compilers(): - build_platform = Utils.unversioned_sys_platform() - possible_compiler_list = fc_compiler.get(build_platform, fc_compiler['default']) - return ' '.join(possible_compiler_list) - -def configure(conf): - """ - Detects a suitable Fortran compiler - - :raises: :py:class:`waflib.Errors.ConfigurationError` when no suitable compiler is found - """ - try: - test_for_compiler = conf.options.check_fortran_compiler or default_compilers() - except AttributeError: - conf.fatal("Add options(opt): opt.load('compiler_fc')") - for compiler in re.split('[ ,]+', test_for_compiler): - conf.env.stash() - conf.start_msg('Checking for %r (Fortran compiler)' % compiler) - try: - conf.load(compiler) - except conf.errors.ConfigurationError as e: - conf.env.revert() - conf.end_msg(False) - Logs.debug('compiler_fortran: %r', e) - else: - if conf.env.FC: - conf.end_msg(conf.env.get_flat('FC')) - conf.env.COMPILER_FORTRAN = compiler - conf.env.commit() - break - conf.env.revert() - conf.end_msg(False) - else: - conf.fatal('could not configure a Fortran compiler!') - -def options(opt): - """ - This is how to provide compiler preferences on the command-line:: - - $ waf configure --check-fortran-compiler=ifort - """ - test_for_compiler = default_compilers() - opt.load_special_tools('fc_*.py') - fortran_compiler_opts = opt.add_option_group('Configuration options') - fortran_compiler_opts.add_option('--check-fortran-compiler', default=None, - help='list of Fortran compiler to try [%s]' % test_for_compiler, - dest="check_fortran_compiler") - - for x in test_for_compiler.split(): - opt.load('%s' % x) - diff --git a/waflib/Tools/cs.py b/waflib/Tools/cs.py deleted file mode 100644 index aecca6d..0000000 --- a/waflib/Tools/cs.py +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -""" -C# support. A simple example:: - - def configure(conf): - conf.load('cs') - def build(bld): - bld(features='cs', source='main.cs', gen='foo') - -Note that the configuration may compile C# snippets:: - - FRAG = ''' - namespace Moo { - public class Test { public static int Main(string[] args) { return 0; } } - }''' - def configure(conf): - conf.check(features='cs', fragment=FRAG, compile_filename='test.cs', gen='test.exe', - bintype='exe', csflags=['-pkg:gtk-sharp-2.0'], msg='Checking for Gtksharp support') -""" - -from waflib import Utils, Task, Options, Errors -from waflib.TaskGen import before_method, after_method, feature -from waflib.Tools import ccroot -from waflib.Configure import conf - -ccroot.USELIB_VARS['cs'] = set(['CSFLAGS', 'ASSEMBLIES', 'RESOURCES']) -ccroot.lib_patterns['csshlib'] = ['%s'] - -@feature('cs') -@before_method('process_source') -def apply_cs(self): - """ - Create a C# task bound to the attribute *cs_task*. There can be only one C# task by task generator. - """ - cs_nodes = [] - no_nodes = [] - for x in self.to_nodes(self.source): - if x.name.endswith('.cs'): - cs_nodes.append(x) - else: - no_nodes.append(x) - self.source = no_nodes - - bintype = getattr(self, 'bintype', self.gen.endswith('.dll') and 'library' or 'exe') - self.cs_task = tsk = self.create_task('mcs', cs_nodes, self.path.find_or_declare(self.gen)) - tsk.env.CSTYPE = '/target:%s' % bintype - tsk.env.OUT = '/out:%s' % tsk.outputs[0].abspath() - self.env.append_value('CSFLAGS', '/platform:%s' % getattr(self, 'platform', 'anycpu')) - - inst_to = getattr(self, 'install_path', bintype=='exe' and '${BINDIR}' or '${LIBDIR}') - if inst_to: - # note: we are making a copy, so the files added to cs_task.outputs won't be installed automatically - mod = getattr(self, 'chmod', bintype=='exe' and Utils.O755 or Utils.O644) - self.install_task = self.add_install_files(install_to=inst_to, install_from=self.cs_task.outputs[:], chmod=mod) - -@feature('cs') -@after_method('apply_cs') -def use_cs(self): - """ - C# applications honor the **use** keyword:: - - def build(bld): - bld(features='cs', source='My.cs', bintype='library', gen='my.dll', name='mylib') - bld(features='cs', source='Hi.cs', includes='.', bintype='exe', gen='hi.exe', use='mylib', name='hi') - """ - names = self.to_list(getattr(self, 'use', [])) - get = self.bld.get_tgen_by_name - for x in names: - try: - y = get(x) - except Errors.WafError: - self.env.append_value('CSFLAGS', '/reference:%s' % x) - continue - y.post() - - tsk = getattr(y, 'cs_task', None) or getattr(y, 'link_task', None) - if not tsk: - self.bld.fatal('cs task has no link task for use %r' % self) - self.cs_task.dep_nodes.extend(tsk.outputs) # dependency - self.cs_task.set_run_after(tsk) # order (redundant, the order is inferred from the nodes inputs/outputs) - self.env.append_value('CSFLAGS', '/reference:%s' % tsk.outputs[0].abspath()) - -@feature('cs') -@after_method('apply_cs', 'use_cs') -def debug_cs(self): - """ - The C# targets may create .mdb or .pdb files:: - - def build(bld): - bld(features='cs', source='My.cs', bintype='library', gen='my.dll', csdebug='full') - # csdebug is a value in (True, 'full', 'pdbonly') - """ - csdebug = getattr(self, 'csdebug', self.env.CSDEBUG) - if not csdebug: - return - - node = self.cs_task.outputs[0] - if self.env.CS_NAME == 'mono': - out = node.parent.find_or_declare(node.name + '.mdb') - else: - out = node.change_ext('.pdb') - self.cs_task.outputs.append(out) - - if getattr(self, 'install_task', None): - self.pdb_install_task = self.add_install_files( - install_to=self.install_task.install_to, install_from=out) - - if csdebug == 'pdbonly': - val = ['/debug+', '/debug:pdbonly'] - elif csdebug == 'full': - val = ['/debug+', '/debug:full'] - else: - val = ['/debug-'] - self.env.append_value('CSFLAGS', val) - -@feature('cs') -@after_method('debug_cs') -def doc_cs(self): - """ - The C# targets may create .xml documentation files:: - - def build(bld): - bld(features='cs', source='My.cs', bintype='library', gen='my.dll', csdoc=True) - # csdoc is a boolean value - """ - csdoc = getattr(self, 'csdoc', self.env.CSDOC) - if not csdoc: - return - - node = self.cs_task.outputs[0] - out = node.change_ext('.xml') - self.cs_task.outputs.append(out) - - if getattr(self, 'install_task', None): - self.doc_install_task = self.add_install_files( - install_to=self.install_task.install_to, install_from=out) - - self.env.append_value('CSFLAGS', '/doc:%s' % out.abspath()) - -class mcs(Task.Task): - """ - Compile C# files - """ - color = 'YELLOW' - run_str = '${MCS} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' - - def split_argfile(self, cmd): - inline = [cmd[0]] - infile = [] - for x in cmd[1:]: - # csc doesn't want /noconfig in @file - if x.lower() == '/noconfig': - inline.append(x) - else: - infile.append(self.quote_flag(x)) - return (inline, infile) - -def configure(conf): - """ - Find a C# compiler, set the variable MCS for the compiler and CS_NAME (mono or csc) - """ - csc = getattr(Options.options, 'cscbinary', None) - if csc: - conf.env.MCS = csc - conf.find_program(['csc', 'mcs', 'gmcs'], var='MCS') - conf.env.ASS_ST = '/r:%s' - conf.env.RES_ST = '/resource:%s' - - conf.env.CS_NAME = 'csc' - if str(conf.env.MCS).lower().find('mcs') > -1: - conf.env.CS_NAME = 'mono' - -def options(opt): - """ - Add a command-line option for the configuration:: - - $ waf configure --with-csc-binary=/foo/bar/mcs - """ - opt.add_option('--with-csc-binary', type='string', dest='cscbinary') - -class fake_csshlib(Task.Task): - """ - Task used for reading a foreign .net assembly and adding the dependency on it - """ - color = 'YELLOW' - inst_to = None - - def runnable_status(self): - return Task.SKIP_ME - -@conf -def read_csshlib(self, name, paths=[]): - """ - Read a foreign .net assembly for the *use* system:: - - def build(bld): - bld.read_csshlib('ManagedLibrary.dll', paths=[bld.env.mylibrarypath]) - bld(features='cs', source='Hi.cs', bintype='exe', gen='hi.exe', use='ManagedLibrary.dll') - - :param name: Name of the library - :type name: string - :param paths: Folders in which the library may be found - :type paths: list of string - :return: A task generator having the feature *fake_lib* which will call :py:func:`waflib.Tools.ccroot.process_lib` - :rtype: :py:class:`waflib.TaskGen.task_gen` - """ - return self(name=name, features='fake_lib', lib_paths=paths, lib_type='csshlib') - diff --git a/waflib/Tools/cxx.py b/waflib/Tools/cxx.py deleted file mode 100644 index 194fad7..0000000 --- a/waflib/Tools/cxx.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2005-2018 (ita) - -"Base for c++ programs and libraries" - -from waflib import TaskGen, Task -from waflib.Tools import c_preproc -from waflib.Tools.ccroot import link_task, stlink_task - -@TaskGen.extension('.cpp','.cc','.cxx','.C','.c++') -def cxx_hook(self, node): - "Binds c++ file extensions to create :py:class:`waflib.Tools.cxx.cxx` instances" - return self.create_compiled_task('cxx', node) - -if not '.c' in TaskGen.task_gen.mappings: - TaskGen.task_gen.mappings['.c'] = TaskGen.task_gen.mappings['.cpp'] - -class cxx(Task.Task): - "Compiles C++ files into object files" - run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' - vars = ['CXXDEPS'] # unused variable to depend on, just in case - ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] - scan = c_preproc.scan - -class cxxprogram(link_task): - "Links object files into c++ programs" - run_str = '${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' - vars = ['LINKDEPS'] - ext_out = ['.bin'] - inst_to = '${BINDIR}' - -class cxxshlib(cxxprogram): - "Links object files into c++ shared libraries" - inst_to = '${LIBDIR}' - -class cxxstlib(stlink_task): - "Links object files into c++ static libraries" - pass # do not remove - diff --git a/waflib/Tools/d.py b/waflib/Tools/d.py deleted file mode 100644 index e4cf73b..0000000 --- a/waflib/Tools/d.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Carlos Rafael Giani, 2007 (dv) -# Thomas Nagy, 2007-2018 (ita) - -from waflib import Utils, Task, Errors -from waflib.TaskGen import taskgen_method, feature, extension -from waflib.Tools import d_scan, d_config -from waflib.Tools.ccroot import link_task, stlink_task - -class d(Task.Task): - "Compile a d file into an object file" - color = 'GREEN' - run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_SRC_F:SRC} ${D_TGT_F:TGT}' - scan = d_scan.scan - -class d_with_header(d): - "Compile a d file and generate a header" - run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_HDR_F:tgt.outputs[1].bldpath()} ${D_SRC_F:SRC} ${D_TGT_F:tgt.outputs[0].bldpath()}' - -class d_header(Task.Task): - "Compile d headers" - color = 'BLUE' - run_str = '${D} ${D_HEADER} ${SRC}' - -class dprogram(link_task): - "Link object files into a d program" - run_str = '${D_LINKER} ${LINKFLAGS} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F:TGT} ${RPATH_ST:RPATH} ${DSTLIB_MARKER} ${DSTLIBPATH_ST:STLIBPATH} ${DSTLIB_ST:STLIB} ${DSHLIB_MARKER} ${DLIBPATH_ST:LIBPATH} ${DSHLIB_ST:LIB}' - inst_to = '${BINDIR}' - -class dshlib(dprogram): - "Link object files into a d shared library" - inst_to = '${LIBDIR}' - -class dstlib(stlink_task): - "Link object files into a d static library" - pass # do not remove - -@extension('.d', '.di', '.D') -def d_hook(self, node): - """ - Compile *D* files. To get .di files as well as .o files, set the following:: - - def build(bld): - bld.program(source='foo.d', target='app', generate_headers=True) - - """ - ext = Utils.destos_to_binfmt(self.env.DEST_OS) == 'pe' and 'obj' or 'o' - out = '%s.%d.%s' % (node.name, self.idx, ext) - def create_compiled_task(self, name, node): - task = self.create_task(name, node, node.parent.find_or_declare(out)) - try: - self.compiled_tasks.append(task) - except AttributeError: - self.compiled_tasks = [task] - return task - - if getattr(self, 'generate_headers', None): - tsk = create_compiled_task(self, 'd_with_header', node) - tsk.outputs.append(node.change_ext(self.env.DHEADER_ext)) - else: - tsk = create_compiled_task(self, 'd', node) - return tsk - -@taskgen_method -def generate_header(self, filename): - """ - See feature request #104:: - - def build(bld): - tg = bld.program(source='foo.d', target='app') - tg.generate_header('blah.d') - # is equivalent to: - #tg = bld.program(source='foo.d', target='app', header_lst='blah.d') - - :param filename: header to create - :type filename: string - """ - try: - self.header_lst.append([filename, self.install_path]) - except AttributeError: - self.header_lst = [[filename, self.install_path]] - -@feature('d') -def process_header(self): - """ - Process the attribute 'header_lst' to create the d header compilation tasks:: - - def build(bld): - bld.program(source='foo.d', target='app', header_lst='blah.d') - """ - for i in getattr(self, 'header_lst', []): - node = self.path.find_resource(i[0]) - if not node: - raise Errors.WafError('file %r not found on d obj' % i[0]) - self.create_task('d_header', node, node.change_ext('.di')) - diff --git a/waflib/Tools/d_config.py b/waflib/Tools/d_config.py deleted file mode 100644 index 6637556..0000000 --- a/waflib/Tools/d_config.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2016-2018 (ita) - -from waflib import Utils -from waflib.Configure import conf - -@conf -def d_platform_flags(self): - """ - Sets the extensions dll/so for d programs and libraries - """ - v = self.env - if not v.DEST_OS: - v.DEST_OS = Utils.unversioned_sys_platform() - binfmt = Utils.destos_to_binfmt(self.env.DEST_OS) - if binfmt == 'pe': - v.dprogram_PATTERN = '%s.exe' - v.dshlib_PATTERN = 'lib%s.dll' - v.dstlib_PATTERN = 'lib%s.a' - elif binfmt == 'mac-o': - v.dprogram_PATTERN = '%s' - v.dshlib_PATTERN = 'lib%s.dylib' - v.dstlib_PATTERN = 'lib%s.a' - else: - v.dprogram_PATTERN = '%s' - v.dshlib_PATTERN = 'lib%s.so' - v.dstlib_PATTERN = 'lib%s.a' - -DLIB = ''' -version(D_Version2) { - import std.stdio; - int main() { - writefln("phobos2"); - return 0; - } -} else { - version(Tango) { - import tango.stdc.stdio; - int main() { - printf("tango"); - return 0; - } - } else { - import std.stdio; - int main() { - writefln("phobos1"); - return 0; - } - } -} -''' -"""Detection string for the D standard library""" - -@conf -def check_dlibrary(self, execute=True): - """ - Detects the kind of standard library that comes with the compiler, - and sets conf.env.DLIBRARY to tango, phobos1 or phobos2 - """ - ret = self.check_cc(features='d dprogram', fragment=DLIB, compile_filename='test.d', execute=execute, define_ret=True) - if execute: - self.env.DLIBRARY = ret.strip() - diff --git a/waflib/Tools/d_scan.py b/waflib/Tools/d_scan.py deleted file mode 100644 index 4e807a6..0000000 --- a/waflib/Tools/d_scan.py +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2016-2018 (ita) - -""" -Provide a scanner for finding dependencies on d files -""" - -import re -from waflib import Utils - -def filter_comments(filename): - """ - :param filename: d file name - :type filename: string - :rtype: list - :return: a list of characters - """ - txt = Utils.readf(filename) - i = 0 - buf = [] - max = len(txt) - begin = 0 - while i < max: - c = txt[i] - if c == '"' or c == "'": # skip a string or character literal - buf.append(txt[begin:i]) - delim = c - i += 1 - while i < max: - c = txt[i] - if c == delim: - break - elif c == '\\': # skip the character following backslash - i += 1 - i += 1 - i += 1 - begin = i - elif c == '/': # try to replace a comment with whitespace - buf.append(txt[begin:i]) - i += 1 - if i == max: - break - c = txt[i] - if c == '+': # eat nesting /+ +/ comment - i += 1 - nesting = 1 - c = None - while i < max: - prev = c - c = txt[i] - if prev == '/' and c == '+': - nesting += 1 - c = None - elif prev == '+' and c == '/': - nesting -= 1 - if nesting == 0: - break - c = None - i += 1 - elif c == '*': # eat /* */ comment - i += 1 - c = None - while i < max: - prev = c - c = txt[i] - if prev == '*' and c == '/': - break - i += 1 - elif c == '/': # eat // comment - i += 1 - while i < max and txt[i] != '\n': - i += 1 - else: # no comment - begin = i - 1 - continue - i += 1 - begin = i - buf.append(' ') - else: - i += 1 - buf.append(txt[begin:]) - return buf - -class d_parser(object): - """ - Parser for d files - """ - def __init__(self, env, incpaths): - #self.code = '' - #self.module = '' - #self.imports = [] - - self.allnames = [] - - self.re_module = re.compile(r"module\s+([^;]+)") - self.re_import = re.compile(r"import\s+([^;]+)") - self.re_import_bindings = re.compile("([^:]+):(.*)") - self.re_import_alias = re.compile("[^=]+=(.+)") - - self.env = env - - self.nodes = [] - self.names = [] - - self.incpaths = incpaths - - def tryfind(self, filename): - """ - Search file a file matching an module/import directive - - :param filename: file to read - :type filename: string - """ - found = 0 - for n in self.incpaths: - found = n.find_resource(filename.replace('.', '/') + '.d') - if found: - self.nodes.append(found) - self.waiting.append(found) - break - if not found: - if not filename in self.names: - self.names.append(filename) - - def get_strings(self, code): - """ - :param code: d code to parse - :type code: string - :return: the modules that the code uses - :rtype: a list of match objects - """ - #self.imports = [] - self.module = '' - lst = [] - - # get the module name (if present) - - mod_name = self.re_module.search(code) - if mod_name: - self.module = re.sub(r'\s+', '', mod_name.group(1)) # strip all whitespaces - - # go through the code, have a look at all import occurrences - - # first, lets look at anything beginning with "import" and ending with ";" - import_iterator = self.re_import.finditer(code) - if import_iterator: - for import_match in import_iterator: - import_match_str = re.sub(r'\s+', '', import_match.group(1)) # strip all whitespaces - - # does this end with an import bindings declaration? - # (import bindings always terminate the list of imports) - bindings_match = self.re_import_bindings.match(import_match_str) - if bindings_match: - import_match_str = bindings_match.group(1) - # if so, extract the part before the ":" (since the module declaration(s) is/are located there) - - # split the matching string into a bunch of strings, separated by a comma - matches = import_match_str.split(',') - - for match in matches: - alias_match = self.re_import_alias.match(match) - if alias_match: - # is this an alias declaration? (alias = module name) if so, extract the module name - match = alias_match.group(1) - - lst.append(match) - return lst - - def start(self, node): - """ - The parsing starts here - - :param node: input file - :type node: :py:class:`waflib.Node.Node` - """ - self.waiting = [node] - # while the stack is not empty, add the dependencies - while self.waiting: - nd = self.waiting.pop(0) - self.iter(nd) - - def iter(self, node): - """ - Find all the modules that a file depends on, uses :py:meth:`waflib.Tools.d_scan.d_parser.tryfind` to process dependent files - - :param node: input file - :type node: :py:class:`waflib.Node.Node` - """ - path = node.abspath() # obtain the absolute path - code = "".join(filter_comments(path)) # read the file and filter the comments - names = self.get_strings(code) # obtain the import strings - for x in names: - # optimization - if x in self.allnames: - continue - self.allnames.append(x) - - # for each name, see if it is like a node or not - self.tryfind(x) - -def scan(self): - "look for .d/.di used by a d file" - env = self.env - gruik = d_parser(env, self.generator.includes_nodes) - node = self.inputs[0] - gruik.start(node) - nodes = gruik.nodes - names = gruik.names - return (nodes, names) - diff --git a/waflib/Tools/dbus.py b/waflib/Tools/dbus.py deleted file mode 100644 index d520f1c..0000000 --- a/waflib/Tools/dbus.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Ali Sabil, 2007 - -""" -Compiles dbus files with **dbus-binding-tool** - -Typical usage:: - - def options(opt): - opt.load('compiler_c dbus') - def configure(conf): - conf.load('compiler_c dbus') - def build(bld): - tg = bld.program( - includes = '.', - source = bld.path.ant_glob('*.c'), - target = 'gnome-hello') - tg.add_dbus_file('test.xml', 'test_prefix', 'glib-server') -""" - -from waflib import Task, Errors -from waflib.TaskGen import taskgen_method, before_method - -@taskgen_method -def add_dbus_file(self, filename, prefix, mode): - """ - Adds a dbus file to the list of dbus files to process. Store them in the attribute *dbus_lst*. - - :param filename: xml file to compile - :type filename: string - :param prefix: dbus binding tool prefix (--prefix=prefix) - :type prefix: string - :param mode: dbus binding tool mode (--mode=mode) - :type mode: string - """ - if not hasattr(self, 'dbus_lst'): - self.dbus_lst = [] - if not 'process_dbus' in self.meths: - self.meths.append('process_dbus') - self.dbus_lst.append([filename, prefix, mode]) - -@before_method('process_source') -def process_dbus(self): - """ - Processes the dbus files stored in the attribute *dbus_lst* to create :py:class:`waflib.Tools.dbus.dbus_binding_tool` instances. - """ - for filename, prefix, mode in getattr(self, 'dbus_lst', []): - node = self.path.find_resource(filename) - if not node: - raise Errors.WafError('file not found ' + filename) - tsk = self.create_task('dbus_binding_tool', node, node.change_ext('.h')) - tsk.env.DBUS_BINDING_TOOL_PREFIX = prefix - tsk.env.DBUS_BINDING_TOOL_MODE = mode - -class dbus_binding_tool(Task.Task): - """ - Compiles a dbus file - """ - color = 'BLUE' - ext_out = ['.h'] - run_str = '${DBUS_BINDING_TOOL} --prefix=${DBUS_BINDING_TOOL_PREFIX} --mode=${DBUS_BINDING_TOOL_MODE} --output=${TGT} ${SRC}' - shell = True # temporary workaround for #795 - -def configure(conf): - """ - Detects the program dbus-binding-tool and sets ``conf.env.DBUS_BINDING_TOOL`` - """ - conf.find_program('dbus-binding-tool', var='DBUS_BINDING_TOOL') - diff --git a/waflib/Tools/dmd.py b/waflib/Tools/dmd.py deleted file mode 100644 index 8917ca1..0000000 --- a/waflib/Tools/dmd.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Carlos Rafael Giani, 2007 (dv) -# Thomas Nagy, 2008-2018 (ita) - -import sys -from waflib.Tools import ar, d -from waflib.Configure import conf - -@conf -def find_dmd(conf): - """ - Finds the program *dmd*, *dmd2*, or *ldc* and set the variable *D* - """ - conf.find_program(['dmd', 'dmd2', 'ldc'], var='D') - - # make sure that we're dealing with dmd1, dmd2, or ldc(1) - out = conf.cmd_and_log(conf.env.D + ['--help']) - if out.find("D Compiler v") == -1: - out = conf.cmd_and_log(conf.env.D + ['-version']) - if out.find("based on DMD v1.") == -1: - conf.fatal("detected compiler is not dmd/ldc") - -@conf -def common_flags_ldc(conf): - """ - Sets the D flags required by *ldc* - """ - v = conf.env - v.DFLAGS = ['-d-version=Posix'] - v.LINKFLAGS = [] - v.DFLAGS_dshlib = ['-relocation-model=pic'] - -@conf -def common_flags_dmd(conf): - """ - Set the flags required by *dmd* or *dmd2* - """ - v = conf.env - - v.D_SRC_F = ['-c'] - v.D_TGT_F = '-of%s' - - v.D_LINKER = v.D - v.DLNK_SRC_F = '' - v.DLNK_TGT_F = '-of%s' - v.DINC_ST = '-I%s' - - v.DSHLIB_MARKER = v.DSTLIB_MARKER = '' - v.DSTLIB_ST = v.DSHLIB_ST = '-L-l%s' - v.DSTLIBPATH_ST = v.DLIBPATH_ST = '-L-L%s' - - v.LINKFLAGS_dprogram= ['-quiet'] - - v.DFLAGS_dshlib = ['-fPIC'] - v.LINKFLAGS_dshlib = ['-L-shared'] - - v.DHEADER_ext = '.di' - v.DFLAGS_d_with_header = ['-H', '-Hf'] - v.D_HDR_F = '%s' - -def configure(conf): - """ - Configuration for *dmd*, *dmd2*, and *ldc* - """ - conf.find_dmd() - - if sys.platform == 'win32': - out = conf.cmd_and_log(conf.env.D + ['--help']) - if out.find('D Compiler v2.') > -1: - conf.fatal('dmd2 on Windows is not supported, use gdc or ldc2 instead') - - conf.load('ar') - conf.load('d') - conf.common_flags_dmd() - conf.d_platform_flags() - - if str(conf.env.D).find('ldc') > -1: - conf.common_flags_ldc() - diff --git a/waflib/Tools/errcheck.py b/waflib/Tools/errcheck.py deleted file mode 100644 index de8d75a..0000000 --- a/waflib/Tools/errcheck.py +++ /dev/null @@ -1,237 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2011 (ita) - -""" -Common mistakes highlighting. - -There is a performance impact, so this tool is only loaded when running ``waf -v`` -""" - -typos = { -'feature':'features', -'sources':'source', -'targets':'target', -'include':'includes', -'export_include':'export_includes', -'define':'defines', -'importpath':'includes', -'installpath':'install_path', -'iscopy':'is_copy', -'uses':'use', -} - -meths_typos = ['__call__', 'program', 'shlib', 'stlib', 'objects'] - -import sys -from waflib import Logs, Build, Node, Task, TaskGen, ConfigSet, Errors, Utils -from waflib.Tools import ccroot - -def check_same_targets(self): - mp = Utils.defaultdict(list) - uids = {} - - def check_task(tsk): - if not isinstance(tsk, Task.Task): - return - if hasattr(tsk, 'no_errcheck_out'): - return - - for node in tsk.outputs: - mp[node].append(tsk) - try: - uids[tsk.uid()].append(tsk) - except KeyError: - uids[tsk.uid()] = [tsk] - - for g in self.groups: - for tg in g: - try: - for tsk in tg.tasks: - check_task(tsk) - except AttributeError: - # raised if not a task generator, which should be uncommon - check_task(tg) - - dupe = False - for (k, v) in mp.items(): - if len(v) > 1: - dupe = True - msg = '* Node %r is created more than once%s. The task generators are:' % (k, Logs.verbose == 1 and " (full message on 'waf -v -v')" or "") - Logs.error(msg) - for x in v: - if Logs.verbose > 1: - Logs.error(' %d. %r', 1 + v.index(x), x.generator) - else: - Logs.error(' %d. %r in %r', 1 + v.index(x), x.generator.name, getattr(x.generator, 'path', None)) - Logs.error('If you think that this is an error, set no_errcheck_out on the task instance') - - if not dupe: - for (k, v) in uids.items(): - if len(v) > 1: - Logs.error('* Several tasks use the same identifier. Please check the information on\n https://waf.io/apidocs/Task.html?highlight=uid#waflib.Task.Task.uid') - tg_details = tsk.generator.name - if Logs.verbose > 2: - tg_details = tsk.generator - for tsk in v: - Logs.error(' - object %r (%r) defined in %r', tsk.__class__.__name__, tsk, tg_details) - -def check_invalid_constraints(self): - feat = set() - for x in list(TaskGen.feats.values()): - feat.union(set(x)) - for (x, y) in TaskGen.task_gen.prec.items(): - feat.add(x) - feat.union(set(y)) - ext = set() - for x in TaskGen.task_gen.mappings.values(): - ext.add(x.__name__) - invalid = ext & feat - if invalid: - Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method', list(invalid)) - - # the build scripts have been read, so we can check for invalid after/before attributes on task classes - for cls in list(Task.classes.values()): - if sys.hexversion > 0x3000000 and issubclass(cls, Task.Task) and isinstance(cls.hcode, str): - raise Errors.WafError('Class %r has hcode value %r of type , expecting (use Utils.h_cmd() ?)' % (cls, cls.hcode)) - - for x in ('before', 'after'): - for y in Utils.to_list(getattr(cls, x, [])): - if not Task.classes.get(y): - Logs.error('Erroneous order constraint %r=%r on task class %r', x, y, cls.__name__) - if getattr(cls, 'rule', None): - Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")', cls.__name__) - -def replace(m): - """ - Replaces existing BuildContext methods to verify parameter names, - for example ``bld(source=)`` has no ending *s* - """ - oldcall = getattr(Build.BuildContext, m) - def call(self, *k, **kw): - ret = oldcall(self, *k, **kw) - for x in typos: - if x in kw: - if x == 'iscopy' and 'subst' in getattr(self, 'features', ''): - continue - Logs.error('Fix the typo %r -> %r on %r', x, typos[x], ret) - return ret - setattr(Build.BuildContext, m, call) - -def enhance_lib(): - """ - Modifies existing classes and methods to enable error verification - """ - for m in meths_typos: - replace(m) - - # catch '..' in ant_glob patterns - def ant_glob(self, *k, **kw): - if k: - lst = Utils.to_list(k[0]) - for pat in lst: - sp = pat.split('/') - if '..' in sp: - Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'", k[0]) - if '.' in sp: - Logs.error("In ant_glob pattern %r: '.' means 'one dot', not 'current directory'", k[0]) - return self.old_ant_glob(*k, **kw) - Node.Node.old_ant_glob = Node.Node.ant_glob - Node.Node.ant_glob = ant_glob - - # catch ant_glob on build folders - def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True, quiet=False): - if remove: - try: - if self.is_child_of(self.ctx.bldnode) and not quiet: - quiet = True - Logs.error('Calling ant_glob on build folders (%r) is dangerous: add quiet=True / remove=False', self) - except AttributeError: - pass - return self.old_ant_iter(accept, maxdepth, pats, dir, src, remove, quiet) - Node.Node.old_ant_iter = Node.Node.ant_iter - Node.Node.ant_iter = ant_iter - - # catch conflicting ext_in/ext_out/before/after declarations - old = Task.is_before - def is_before(t1, t2): - ret = old(t1, t2) - if ret and old(t2, t1): - Logs.error('Contradictory order constraints in classes %r %r', t1, t2) - return ret - Task.is_before = is_before - - # check for bld(feature='cshlib') where no 'c' is given - this can be either a mistake or on purpose - # so we only issue a warning - def check_err_features(self): - lst = self.to_list(self.features) - if 'shlib' in lst: - Logs.error('feature shlib -> cshlib, dshlib or cxxshlib') - for x in ('c', 'cxx', 'd', 'fc'): - if not x in lst and lst and lst[0] in [x+y for y in ('program', 'shlib', 'stlib')]: - Logs.error('%r features is probably missing %r', self, x) - TaskGen.feature('*')(check_err_features) - - # check for erroneous order constraints - def check_err_order(self): - if not hasattr(self, 'rule') and not 'subst' in Utils.to_list(self.features): - for x in ('before', 'after', 'ext_in', 'ext_out'): - if hasattr(self, x): - Logs.warn('Erroneous order constraint %r on non-rule based task generator %r', x, self) - else: - for x in ('before', 'after'): - for y in self.to_list(getattr(self, x, [])): - if not Task.classes.get(y): - Logs.error('Erroneous order constraint %s=%r on %r (no such class)', x, y, self) - TaskGen.feature('*')(check_err_order) - - # check for @extension used with @feature/@before_method/@after_method - def check_compile(self): - check_invalid_constraints(self) - try: - ret = self.orig_compile() - finally: - check_same_targets(self) - return ret - Build.BuildContext.orig_compile = Build.BuildContext.compile - Build.BuildContext.compile = check_compile - - # check for invalid build groups #914 - def use_rec(self, name, **kw): - try: - y = self.bld.get_tgen_by_name(name) - except Errors.WafError: - pass - else: - idx = self.bld.get_group_idx(self) - odx = self.bld.get_group_idx(y) - if odx > idx: - msg = "Invalid 'use' across build groups:" - if Logs.verbose > 1: - msg += '\n target %r\n uses:\n %r' % (self, y) - else: - msg += " %r uses %r (try 'waf -v -v' for the full error)" % (self.name, name) - raise Errors.WafError(msg) - self.orig_use_rec(name, **kw) - TaskGen.task_gen.orig_use_rec = TaskGen.task_gen.use_rec - TaskGen.task_gen.use_rec = use_rec - - # check for env.append - def _getattr(self, name, default=None): - if name == 'append' or name == 'add': - raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique') - elif name == 'prepend': - raise Errors.WafError('env.prepend does not exist: use env.prepend_value') - if name in self.__slots__: - return super(ConfigSet.ConfigSet, self).__getattr__(name, default) - else: - return self[name] - ConfigSet.ConfigSet.__getattr__ = _getattr - - -def options(opt): - """ - Error verification can be enabled by default (not just on ``waf -v``) by adding to the user script options - """ - enhance_lib() - diff --git a/waflib/Tools/fc.py b/waflib/Tools/fc.py deleted file mode 100644 index fd4d39c..0000000 --- a/waflib/Tools/fc.py +++ /dev/null @@ -1,203 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# DC 2008 -# Thomas Nagy 2016-2018 (ita) - -""" -Fortran support -""" - -from waflib import Utils, Task, Errors -from waflib.Tools import ccroot, fc_config, fc_scan -from waflib.TaskGen import extension -from waflib.Configure import conf - -ccroot.USELIB_VARS['fc'] = set(['FCFLAGS', 'DEFINES', 'INCLUDES', 'FCPPFLAGS']) -ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) -ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) -ccroot.USELIB_VARS['fcstlib'] = set(['ARFLAGS', 'LINKDEPS']) - -@extension('.f','.F','.f90','.F90','.for','.FOR','.f95','.F95','.f03','.F03','.f08','.F08') -def fc_hook(self, node): - "Binds the Fortran file extensions create :py:class:`waflib.Tools.fc.fc` instances" - return self.create_compiled_task('fc', node) - -@conf -def modfile(conf, name): - """ - Turns a module name into the right module file name. - Defaults to all lower case. - """ - if name.find(':') >= 0: - # Depending on a submodule! - separator = conf.env.FC_SUBMOD_SEPARATOR or '@' - # Ancestors of the submodule will be prefixed to the - # submodule name, separated by a colon. - modpath = name.split(':') - # Only the ancestor (actual) module and the submodule name - # will be used for the filename. - modname = modpath[0] + separator + modpath[-1] - suffix = conf.env.FC_SUBMOD_SUFFIX or '.smod' - else: - modname = name - suffix = '.mod' - - return {'lower' :modname.lower() + suffix.lower(), - 'lower.MOD' :modname.lower() + suffix.upper(), - 'UPPER.mod' :modname.upper() + suffix.lower(), - 'UPPER' :modname.upper() + suffix.upper()}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] - -def get_fortran_tasks(tsk): - """ - Obtains all fortran tasks from the same build group. Those tasks must not have - the attribute 'nomod' or 'mod_fortran_done' - - :return: a list of :py:class:`waflib.Tools.fc.fc` instances - """ - bld = tsk.generator.bld - tasks = bld.get_tasks_group(bld.get_group_idx(tsk.generator)) - return [x for x in tasks if isinstance(x, fc) and not getattr(x, 'nomod', None) and not getattr(x, 'mod_fortran_done', None)] - -class fc(Task.Task): - """ - Fortran tasks can only run when all fortran tasks in a current task group are ready to be executed - This may cause a deadlock if some fortran task is waiting for something that cannot happen (circular dependency) - Should this ever happen, set the 'nomod=True' on those tasks instances to break the loop - """ - color = 'GREEN' - run_str = '${FC} ${FCFLAGS} ${FCINCPATH_ST:INCPATHS} ${FCDEFINES_ST:DEFINES} ${_FCMODOUTFLAGS} ${FC_TGT_F}${TGT[0].abspath()} ${FC_SRC_F}${SRC[0].abspath()} ${FCPPFLAGS}' - vars = ["FORTRANMODPATHFLAG"] - - def scan(self): - """Fortran dependency scanner""" - tmp = fc_scan.fortran_parser(self.generator.includes_nodes) - tmp.task = self - tmp.start(self.inputs[0]) - return (tmp.nodes, tmp.names) - - def runnable_status(self): - """ - Sets the mod file outputs and the dependencies on the mod files over all Fortran tasks - executed by the main thread so there are no concurrency issues - """ - if getattr(self, 'mod_fortran_done', None): - return super(fc, self).runnable_status() - - # now, if we reach this part it is because this fortran task is the first in the list - bld = self.generator.bld - - # obtain the fortran tasks - lst = get_fortran_tasks(self) - - # disable this method for other tasks - for tsk in lst: - tsk.mod_fortran_done = True - - # wait for all the .f tasks to be ready for execution - # and ensure that the scanners are called at least once - for tsk in lst: - ret = tsk.runnable_status() - if ret == Task.ASK_LATER: - # we have to wait for one of the other fortran tasks to be ready - # this may deadlock if there are dependencies between fortran tasks - # but this should not happen (we are setting them here!) - for x in lst: - x.mod_fortran_done = None - - return Task.ASK_LATER - - ins = Utils.defaultdict(set) - outs = Utils.defaultdict(set) - - # the .mod files to create - for tsk in lst: - key = tsk.uid() - for x in bld.raw_deps[key]: - if x.startswith('MOD@'): - name = bld.modfile(x.replace('MOD@', '')) - node = bld.srcnode.find_or_declare(name) - tsk.set_outputs(node) - outs[node].add(tsk) - - # the .mod files to use - for tsk in lst: - key = tsk.uid() - for x in bld.raw_deps[key]: - if x.startswith('USE@'): - name = bld.modfile(x.replace('USE@', '')) - node = bld.srcnode.find_resource(name) - if node and node not in tsk.outputs: - if not node in bld.node_deps[key]: - bld.node_deps[key].append(node) - ins[node].add(tsk) - - # if the intersection matches, set the order - for k in ins.keys(): - for a in ins[k]: - a.run_after.update(outs[k]) - for x in outs[k]: - self.generator.bld.producer.revdeps[x].add(a) - - # the scanner cannot output nodes, so we have to set them - # ourselves as task.dep_nodes (additional input nodes) - tmp = [] - for t in outs[k]: - tmp.extend(t.outputs) - a.dep_nodes.extend(tmp) - a.dep_nodes.sort(key=lambda x: x.abspath()) - - # the task objects have changed: clear the signature cache - for tsk in lst: - try: - delattr(tsk, 'cache_sig') - except AttributeError: - pass - - return super(fc, self).runnable_status() - -class fcprogram(ccroot.link_task): - """Links Fortran programs""" - color = 'YELLOW' - run_str = '${FC} ${LINKFLAGS} ${FCLNK_SRC_F}${SRC} ${FCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FCSTLIB_MARKER} ${FCSTLIBPATH_ST:STLIBPATH} ${FCSTLIB_ST:STLIB} ${FCSHLIB_MARKER} ${FCLIBPATH_ST:LIBPATH} ${FCLIB_ST:LIB} ${LDFLAGS}' - inst_to = '${BINDIR}' - -class fcshlib(fcprogram): - """Links Fortran libraries""" - inst_to = '${LIBDIR}' - -class fcstlib(ccroot.stlink_task): - """Links Fortran static libraries (uses ar by default)""" - pass # do not remove the pass statement - -class fcprogram_test(fcprogram): - """Custom link task to obtain compiler outputs for Fortran configuration tests""" - - def runnable_status(self): - """This task is always executed""" - ret = super(fcprogram_test, self).runnable_status() - if ret == Task.SKIP_ME: - ret = Task.RUN_ME - return ret - - def exec_command(self, cmd, **kw): - """Stores the compiler std our/err onto the build context, to bld.out + bld.err""" - bld = self.generator.bld - - kw['shell'] = isinstance(cmd, str) - kw['stdout'] = kw['stderr'] = Utils.subprocess.PIPE - kw['cwd'] = self.get_cwd() - bld.out = bld.err = '' - - bld.to_log('command: %s\n' % cmd) - - kw['output'] = 0 - try: - (bld.out, bld.err) = bld.cmd_and_log(cmd, **kw) - except Errors.WafError: - return -1 - - if bld.out: - bld.to_log('out: %s\n' % bld.out) - if bld.err: - bld.to_log('err: %s\n' % bld.err) - diff --git a/waflib/Tools/fc_config.py b/waflib/Tools/fc_config.py deleted file mode 100644 index dc5e5c9..0000000 --- a/waflib/Tools/fc_config.py +++ /dev/null @@ -1,488 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# DC 2008 -# Thomas Nagy 2016-2018 (ita) - -""" -Fortran configuration helpers -""" - -import re, os, sys, shlex -from waflib.Configure import conf -from waflib.TaskGen import feature, before_method - -FC_FRAGMENT = ' program main\n end program main\n' -FC_FRAGMENT2 = ' PROGRAM MAIN\n END\n' # what's the actual difference between these? - -@conf -def fc_flags(conf): - """ - Defines common fortran configuration flags and file extensions - """ - v = conf.env - - v.FC_SRC_F = [] - v.FC_TGT_F = ['-c', '-o'] - v.FCINCPATH_ST = '-I%s' - v.FCDEFINES_ST = '-D%s' - - if not v.LINK_FC: - v.LINK_FC = v.FC - - v.FCLNK_SRC_F = [] - v.FCLNK_TGT_F = ['-o'] - - v.FCFLAGS_fcshlib = ['-fpic'] - v.LINKFLAGS_fcshlib = ['-shared'] - v.fcshlib_PATTERN = 'lib%s.so' - - v.fcstlib_PATTERN = 'lib%s.a' - - v.FCLIB_ST = '-l%s' - v.FCLIBPATH_ST = '-L%s' - v.FCSTLIB_ST = '-l%s' - v.FCSTLIBPATH_ST = '-L%s' - v.FCSTLIB_MARKER = '-Wl,-Bstatic' - v.FCSHLIB_MARKER = '-Wl,-Bdynamic' - - v.SONAME_ST = '-Wl,-h,%s' - -@conf -def fc_add_flags(conf): - """ - Adds FCFLAGS / LDFLAGS / LINKFLAGS from os.environ to conf.env - """ - conf.add_os_flags('FCPPFLAGS', dup=False) - conf.add_os_flags('FCFLAGS', dup=False) - conf.add_os_flags('LINKFLAGS', dup=False) - conf.add_os_flags('LDFLAGS', dup=False) - -@conf -def check_fortran(self, *k, **kw): - """ - Compiles a Fortran program to ensure that the settings are correct - """ - self.check_cc( - fragment = FC_FRAGMENT, - compile_filename = 'test.f', - features = 'fc fcprogram', - msg = 'Compiling a simple fortran app') - -@conf -def check_fc(self, *k, **kw): - """ - Same as :py:func:`waflib.Tools.c_config.check` but defaults to the *Fortran* programming language - (this overrides the C defaults in :py:func:`waflib.Tools.c_config.validate_c`) - """ - kw['compiler'] = 'fc' - if not 'compile_mode' in kw: - kw['compile_mode'] = 'fc' - if not 'type' in kw: - kw['type'] = 'fcprogram' - if not 'compile_filename' in kw: - kw['compile_filename'] = 'test.f90' - if not 'code' in kw: - kw['code'] = FC_FRAGMENT - return self.check(*k, **kw) - -# ------------------------------------------------------------------------ -# --- These are the default platform modifiers, refactored here for -# convenience. gfortran and g95 have much overlap. -# ------------------------------------------------------------------------ - -@conf -def fortran_modifier_darwin(conf): - """ - Defines Fortran flags and extensions for OSX systems - """ - v = conf.env - v.FCFLAGS_fcshlib = ['-fPIC'] - v.LINKFLAGS_fcshlib = ['-dynamiclib'] - v.fcshlib_PATTERN = 'lib%s.dylib' - v.FRAMEWORKPATH_ST = '-F%s' - v.FRAMEWORK_ST = ['-framework'] - - v.LINKFLAGS_fcstlib = [] - - v.FCSHLIB_MARKER = '' - v.FCSTLIB_MARKER = '' - v.SONAME_ST = '' - -@conf -def fortran_modifier_win32(conf): - """ - Defines Fortran flags for Windows platforms - """ - v = conf.env - v.fcprogram_PATTERN = v.fcprogram_test_PATTERN = '%s.exe' - - v.fcshlib_PATTERN = '%s.dll' - v.implib_PATTERN = '%s.dll.a' - v.IMPLIB_ST = '-Wl,--out-implib,%s' - - v.FCFLAGS_fcshlib = [] - - # Auto-import is enabled by default even without this option, - # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages - # that the linker emits otherwise. - v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) - -@conf -def fortran_modifier_cygwin(conf): - """ - Defines Fortran flags for use on cygwin - """ - fortran_modifier_win32(conf) - v = conf.env - v.fcshlib_PATTERN = 'cyg%s.dll' - v.append_value('LINKFLAGS_fcshlib', ['-Wl,--enable-auto-image-base']) - v.FCFLAGS_fcshlib = [] - -# ------------------------------------------------------------------------ - -@conf -def check_fortran_dummy_main(self, *k, **kw): - """ - Determines if a main function is needed by compiling a code snippet with - the C compiler and linking it with the Fortran compiler (useful on unix-like systems) - """ - if not self.env.CC: - self.fatal('A c compiler is required for check_fortran_dummy_main') - - lst = ['MAIN__', '__MAIN', '_MAIN', 'MAIN_', 'MAIN'] - lst.extend([m.lower() for m in lst]) - lst.append('') - - self.start_msg('Detecting whether we need a dummy main') - for main in lst: - kw['fortran_main'] = main - try: - self.check_cc( - fragment = 'int %s() { return 0; }\n' % (main or 'test'), - features = 'c fcprogram', - mandatory = True - ) - if not main: - self.env.FC_MAIN = -1 - self.end_msg('no') - else: - self.env.FC_MAIN = main - self.end_msg('yes %s' % main) - break - except self.errors.ConfigurationError: - pass - else: - self.end_msg('not found') - self.fatal('could not detect whether fortran requires a dummy main, see the config.log') - -# ------------------------------------------------------------------------ - -GCC_DRIVER_LINE = re.compile('^Driving:') -POSIX_STATIC_EXT = re.compile(r'\S+\.a') -POSIX_LIB_FLAGS = re.compile(r'-l\S+') - -@conf -def is_link_verbose(self, txt): - """Returns True if 'useful' link options can be found in txt""" - assert isinstance(txt, str) - for line in txt.splitlines(): - if not GCC_DRIVER_LINE.search(line): - if POSIX_STATIC_EXT.search(line) or POSIX_LIB_FLAGS.search(line): - return True - return False - -@conf -def check_fortran_verbose_flag(self, *k, **kw): - """ - Checks what kind of verbose (-v) flag works, then sets it to env.FC_VERBOSE_FLAG - """ - self.start_msg('fortran link verbose flag') - for x in ('-v', '--verbose', '-verbose', '-V'): - try: - self.check_cc( - features = 'fc fcprogram_test', - fragment = FC_FRAGMENT2, - compile_filename = 'test.f', - linkflags = [x], - mandatory=True) - except self.errors.ConfigurationError: - pass - else: - # output is on stderr or stdout (for xlf) - if self.is_link_verbose(self.test_bld.err) or self.is_link_verbose(self.test_bld.out): - self.end_msg(x) - break - else: - self.end_msg('failure') - self.fatal('Could not obtain the fortran link verbose flag (see config.log)') - - self.env.FC_VERBOSE_FLAG = x - return x - -# ------------------------------------------------------------------------ - -# linkflags which match those are ignored -LINKFLAGS_IGNORED = [r'-lang*', r'-lcrt[a-zA-Z0-9\.]*\.o', r'-lc$', r'-lSystem', r'-libmil', r'-LIST:*', r'-LNO:*'] -if os.name == 'nt': - LINKFLAGS_IGNORED.extend([r'-lfrt*', r'-luser32', r'-lkernel32', r'-ladvapi32', r'-lmsvcrt', r'-lshell32', r'-lmingw', r'-lmoldname']) -else: - LINKFLAGS_IGNORED.append(r'-lgcc*') -RLINKFLAGS_IGNORED = [re.compile(f) for f in LINKFLAGS_IGNORED] - -def _match_ignore(line): - """Returns True if the line should be ignored (Fortran verbose flag test)""" - for i in RLINKFLAGS_IGNORED: - if i.match(line): - return True - return False - -def parse_fortran_link(lines): - """Given the output of verbose link of Fortran compiler, this returns a - list of flags necessary for linking using the standard linker.""" - final_flags = [] - for line in lines: - if not GCC_DRIVER_LINE.match(line): - _parse_flink_line(line, final_flags) - return final_flags - -SPACE_OPTS = re.compile('^-[LRuYz]$') -NOSPACE_OPTS = re.compile('^-[RL]') - -def _parse_flink_token(lexer, token, tmp_flags): - # Here we go (convention for wildcard is shell, not regex !) - # 1 TODO: we first get some root .a libraries - # 2 TODO: take everything starting by -bI:* - # 3 Ignore the following flags: -lang* | -lcrt*.o | -lc | - # -lgcc* | -lSystem | -libmil | -LANG:=* | -LIST:* | -LNO:*) - # 4 take into account -lkernel32 - # 5 For options of the kind -[[LRuYz]], as they take one argument - # after, the actual option is the next token - # 6 For -YP,*: take and replace by -Larg where arg is the old - # argument - # 7 For -[lLR]*: take - - # step 3 - if _match_ignore(token): - pass - # step 4 - elif token.startswith('-lkernel32') and sys.platform == 'cygwin': - tmp_flags.append(token) - # step 5 - elif SPACE_OPTS.match(token): - t = lexer.get_token() - if t.startswith('P,'): - t = t[2:] - for opt in t.split(os.pathsep): - tmp_flags.append('-L%s' % opt) - # step 6 - elif NOSPACE_OPTS.match(token): - tmp_flags.append(token) - # step 7 - elif POSIX_LIB_FLAGS.match(token): - tmp_flags.append(token) - else: - # ignore anything not explicitly taken into account - pass - - t = lexer.get_token() - return t - -def _parse_flink_line(line, final_flags): - """private""" - lexer = shlex.shlex(line, posix = True) - lexer.whitespace_split = True - - t = lexer.get_token() - tmp_flags = [] - while t: - t = _parse_flink_token(lexer, t, tmp_flags) - - final_flags.extend(tmp_flags) - return final_flags - -@conf -def check_fortran_clib(self, autoadd=True, *k, **kw): - """ - Obtains the flags for linking with the C library - if this check works, add uselib='CLIB' to your task generators - """ - if not self.env.FC_VERBOSE_FLAG: - self.fatal('env.FC_VERBOSE_FLAG is not set: execute check_fortran_verbose_flag?') - - self.start_msg('Getting fortran runtime link flags') - try: - self.check_cc( - fragment = FC_FRAGMENT2, - compile_filename = 'test.f', - features = 'fc fcprogram_test', - linkflags = [self.env.FC_VERBOSE_FLAG] - ) - except Exception: - self.end_msg(False) - if kw.get('mandatory', True): - conf.fatal('Could not find the c library flags') - else: - out = self.test_bld.err - flags = parse_fortran_link(out.splitlines()) - self.end_msg('ok (%s)' % ' '.join(flags)) - self.env.LINKFLAGS_CLIB = flags - return flags - return [] - -def getoutput(conf, cmd, stdin=False): - """ - Obtains Fortran command outputs - """ - from waflib import Errors - if conf.env.env: - env = conf.env.env - else: - env = dict(os.environ) - env['LANG'] = 'C' - input = stdin and '\n'.encode() or None - try: - out, err = conf.cmd_and_log(cmd, env=env, output=0, input=input) - except Errors.WafError as e: - # An WafError might indicate an error code during the command - # execution, in this case we still obtain the stderr and stdout, - # which we can use to find the version string. - if not (hasattr(e, 'stderr') and hasattr(e, 'stdout')): - raise e - else: - # Ignore the return code and return the original - # stdout and stderr. - out = e.stdout - err = e.stderr - except Exception: - conf.fatal('could not determine the compiler version %r' % cmd) - return (out, err) - -# ------------------------------------------------------------------------ - -ROUTINES_CODE = """\ - subroutine foobar() - return - end - subroutine foo_bar() - return - end -""" - -MAIN_CODE = """ -void %(dummy_func_nounder)s(void); -void %(dummy_func_under)s(void); -int %(main_func_name)s() { - %(dummy_func_nounder)s(); - %(dummy_func_under)s(); - return 0; -} -""" - -@feature('link_main_routines_func') -@before_method('process_source') -def link_main_routines_tg_method(self): - """ - The configuration test declares a unique task generator, - so we create other task generators from there for fortran link tests - """ - def write_test_file(task): - task.outputs[0].write(task.generator.code) - bld = self.bld - bld(rule=write_test_file, target='main.c', code=MAIN_CODE % self.__dict__) - bld(rule=write_test_file, target='test.f', code=ROUTINES_CODE) - bld(features='fc fcstlib', source='test.f', target='test') - bld(features='c fcprogram', source='main.c', target='app', use='test') - -def mangling_schemes(): - """ - Generate triplets for use with mangle_name - (used in check_fortran_mangling) - the order is tuned for gfortan - """ - for u in ('_', ''): - for du in ('', '_'): - for c in ("lower", "upper"): - yield (u, du, c) - -def mangle_name(u, du, c, name): - """Mangle a name from a triplet (used in check_fortran_mangling)""" - return getattr(name, c)() + u + (name.find('_') != -1 and du or '') - -@conf -def check_fortran_mangling(self, *k, **kw): - """ - Detect the mangling scheme, sets FORTRAN_MANGLING to the triplet found - - This test will compile a fortran static library, then link a c app against it - """ - if not self.env.CC: - self.fatal('A c compiler is required for link_main_routines') - if not self.env.FC: - self.fatal('A fortran compiler is required for link_main_routines') - if not self.env.FC_MAIN: - self.fatal('Checking for mangling requires self.env.FC_MAIN (execute "check_fortran_dummy_main" first?)') - - self.start_msg('Getting fortran mangling scheme') - for (u, du, c) in mangling_schemes(): - try: - self.check_cc( - compile_filename = [], - features = 'link_main_routines_func', - msg = 'nomsg', - errmsg = 'nomsg', - dummy_func_nounder = mangle_name(u, du, c, 'foobar'), - dummy_func_under = mangle_name(u, du, c, 'foo_bar'), - main_func_name = self.env.FC_MAIN - ) - except self.errors.ConfigurationError: - pass - else: - self.end_msg("ok ('%s', '%s', '%s-case')" % (u, du, c)) - self.env.FORTRAN_MANGLING = (u, du, c) - break - else: - self.end_msg(False) - self.fatal('mangler not found') - return (u, du, c) - -@feature('pyext') -@before_method('propagate_uselib_vars', 'apply_link') -def set_lib_pat(self): - """Sets the Fortran flags for linking with Python""" - self.env.fcshlib_PATTERN = self.env.pyext_PATTERN - -@conf -def detect_openmp(self): - """ - Detects openmp flags and sets the OPENMP ``FCFLAGS``/``LINKFLAGS`` - """ - for x in ('-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp'): - try: - self.check_fc( - msg = 'Checking for OpenMP flag %s' % x, - fragment = 'program main\n call omp_get_num_threads()\nend program main', - fcflags = x, - linkflags = x, - uselib_store = 'OPENMP' - ) - except self.errors.ConfigurationError: - pass - else: - break - else: - self.fatal('Could not find OpenMP') - -@conf -def check_gfortran_o_space(self): - if self.env.FC_NAME != 'GFORTRAN' or int(self.env.FC_VERSION[0]) > 4: - # This is for old compilers and only for gfortran. - # No idea how other implementations handle this. Be safe and bail out. - return - self.env.stash() - self.env.FCLNK_TGT_F = ['-o', ''] - try: - self.check_fc(msg='Checking if the -o link must be split from arguments', fragment=FC_FRAGMENT, features='fc fcshlib') - except self.errors.ConfigurationError: - self.env.revert() - else: - self.env.commit() diff --git a/waflib/Tools/fc_scan.py b/waflib/Tools/fc_scan.py deleted file mode 100644 index 0824c92..0000000 --- a/waflib/Tools/fc_scan.py +++ /dev/null @@ -1,120 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# DC 2008 -# Thomas Nagy 2016-2018 (ita) - -import re - -INC_REGEX = r"""(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" -USE_REGEX = r"""(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" -MOD_REGEX = r"""(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)""" -SMD_REGEX = r"""(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)""" - -re_inc = re.compile(INC_REGEX, re.I) -re_use = re.compile(USE_REGEX, re.I) -re_mod = re.compile(MOD_REGEX, re.I) -re_smd = re.compile(SMD_REGEX, re.I) - -class fortran_parser(object): - """ - This parser returns: - - * the nodes corresponding to the module names to produce - * the nodes corresponding to the include files used - * the module names used by the fortran files - """ - def __init__(self, incpaths): - self.seen = [] - """Files already parsed""" - - self.nodes = [] - """List of :py:class:`waflib.Node.Node` representing the dependencies to return""" - - self.names = [] - """List of module names to return""" - - self.incpaths = incpaths - """List of :py:class:`waflib.Node.Node` representing the include paths""" - - def find_deps(self, node): - """ - Parses a Fortran file to obtain the dependencies used/provided - - :param node: fortran file to read - :type node: :py:class:`waflib.Node.Node` - :return: lists representing the includes, the modules used, and the modules created by a fortran file - :rtype: tuple of list of strings - """ - txt = node.read() - incs = [] - uses = [] - mods = [] - for line in txt.splitlines(): - # line by line regexp search? optimize? - m = re_inc.search(line) - if m: - incs.append(m.group(1)) - m = re_use.search(line) - if m: - uses.append(m.group(1)) - m = re_mod.search(line) - if m: - mods.append(m.group(1)) - m = re_smd.search(line) - if m: - uses.append(m.group(1)) - mods.append('{0}:{1}'.format(m.group(1),m.group(2))) - return (incs, uses, mods) - - def start(self, node): - """ - Start parsing. Use the stack ``self.waiting`` to hold nodes to iterate on - - :param node: fortran file - :type node: :py:class:`waflib.Node.Node` - """ - self.waiting = [node] - while self.waiting: - nd = self.waiting.pop(0) - self.iter(nd) - - def iter(self, node): - """ - Processes a single file during dependency parsing. Extracts files used - modules used and modules provided. - """ - incs, uses, mods = self.find_deps(node) - for x in incs: - if x in self.seen: - continue - self.seen.append(x) - self.tryfind_header(x) - - for x in uses: - name = "USE@%s" % x - if not name in self.names: - self.names.append(name) - - for x in mods: - name = "MOD@%s" % x - if not name in self.names: - self.names.append(name) - - def tryfind_header(self, filename): - """ - Adds an include file to the list of nodes to process - - :param filename: file name - :type filename: string - """ - found = None - for n in self.incpaths: - found = n.find_resource(filename) - if found: - self.nodes.append(found) - self.waiting.append(found) - break - if not found: - if not filename in self.names: - self.names.append(filename) - diff --git a/waflib/Tools/flex.py b/waflib/Tools/flex.py deleted file mode 100644 index 2256657..0000000 --- a/waflib/Tools/flex.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# John O'Meara, 2006 -# Thomas Nagy, 2006-2018 (ita) - -""" -The **flex** program is a code generator which creates C or C++ files. -The generated files are compiled into object files. -""" - -import os, re -from waflib import Task, TaskGen -from waflib.Tools import ccroot - -def decide_ext(self, node): - if 'cxx' in self.features: - return ['.lex.cc'] - return ['.lex.c'] - -def flexfun(tsk): - env = tsk.env - bld = tsk.generator.bld - wd = bld.variant_dir - def to_list(xx): - if isinstance(xx, str): - return [xx] - return xx - tsk.last_cmd = lst = [] - lst.extend(to_list(env.FLEX)) - lst.extend(to_list(env.FLEXFLAGS)) - inputs = [a.path_from(tsk.get_cwd()) for a in tsk.inputs] - if env.FLEX_MSYS: - inputs = [x.replace(os.sep, '/') for x in inputs] - lst.extend(inputs) - lst = [x for x in lst if x] - txt = bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) - tsk.outputs[0].write(txt.replace('\r\n', '\n').replace('\r', '\n')) # issue #1207 - -TaskGen.declare_chain( - name = 'flex', - rule = flexfun, # issue #854 - ext_in = '.l', - decider = decide_ext, -) - -# To support the following: -# bld(features='c', flexflags='-P/foo') -Task.classes['flex'].vars = ['FLEXFLAGS', 'FLEX'] -ccroot.USELIB_VARS['c'].add('FLEXFLAGS') -ccroot.USELIB_VARS['cxx'].add('FLEXFLAGS') - -def configure(conf): - """ - Detect the *flex* program - """ - conf.find_program('flex', var='FLEX') - conf.env.FLEXFLAGS = ['-t'] - - if re.search (r"\\msys\\[0-9.]+\\bin\\flex.exe$", conf.env.FLEX[0]): - # this is the flex shipped with MSYS - conf.env.FLEX_MSYS = True - diff --git a/waflib/Tools/g95.py b/waflib/Tools/g95.py deleted file mode 100644 index f69ba4f..0000000 --- a/waflib/Tools/g95.py +++ /dev/null @@ -1,66 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# KWS 2010 -# Thomas Nagy 2016-2018 (ita) - -import re -from waflib import Utils -from waflib.Tools import fc, fc_config, fc_scan, ar -from waflib.Configure import conf - -@conf -def find_g95(conf): - fc = conf.find_program('g95', var='FC') - conf.get_g95_version(fc) - conf.env.FC_NAME = 'G95' - -@conf -def g95_flags(conf): - v = conf.env - v.FCFLAGS_fcshlib = ['-fPIC'] - v.FORTRANMODFLAG = ['-fmod=', ''] # template for module path - v.FCFLAGS_DEBUG = ['-Werror'] # why not - -@conf -def g95_modifier_win32(conf): - fc_config.fortran_modifier_win32(conf) - -@conf -def g95_modifier_cygwin(conf): - fc_config.fortran_modifier_cygwin(conf) - -@conf -def g95_modifier_darwin(conf): - fc_config.fortran_modifier_darwin(conf) - -@conf -def g95_modifier_platform(conf): - dest_os = conf.env.DEST_OS or Utils.unversioned_sys_platform() - g95_modifier_func = getattr(conf, 'g95_modifier_' + dest_os, None) - if g95_modifier_func: - g95_modifier_func() - -@conf -def get_g95_version(conf, fc): - """get the compiler version""" - - version_re = re.compile(r"g95\s*(?P\d*)\.(?P\d*)").search - cmd = fc + ['--version'] - out, err = fc_config.getoutput(conf, cmd, stdin=False) - if out: - match = version_re(out) - else: - match = version_re(err) - if not match: - conf.fatal('cannot determine g95 version') - k = match.groupdict() - conf.env.FC_VERSION = (k['major'], k['minor']) - -def configure(conf): - conf.find_g95() - conf.find_ar() - conf.fc_flags() - conf.fc_add_flags() - conf.g95_flags() - conf.g95_modifier_platform() - diff --git a/waflib/Tools/gas.py b/waflib/Tools/gas.py deleted file mode 100644 index 77afed7..0000000 --- a/waflib/Tools/gas.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2008-2018 (ita) - -"Detect as/gas/gcc for compiling assembly files" - -import waflib.Tools.asm # - leave this -from waflib.Tools import ar - -def configure(conf): - """ - Find the programs gas/as/gcc and set the variable *AS* - """ - conf.find_program(['gas', 'gcc'], var='AS') - conf.env.AS_TGT_F = ['-c', '-o'] - conf.env.ASLNK_TGT_F = ['-o'] - conf.find_ar() - conf.load('asm') diff --git a/waflib/Tools/gcc.py b/waflib/Tools/gcc.py deleted file mode 100644 index acdd473..0000000 --- a/waflib/Tools/gcc.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) -# Ralf Habacker, 2006 (rh) -# Yinon Ehrlich, 2009 - -""" -gcc/llvm detection. -""" - -from waflib.Tools import ccroot, ar -from waflib.Configure import conf - -@conf -def find_gcc(conf): - """ - Find the program gcc, and if present, try to detect its version number - """ - cc = conf.find_program(['gcc', 'cc'], var='CC') - conf.get_cc_version(cc, gcc=True) - conf.env.CC_NAME = 'gcc' - -@conf -def gcc_common_flags(conf): - """ - Common flags for gcc on nearly all platforms - """ - v = conf.env - - v.CC_SRC_F = [] - v.CC_TGT_F = ['-c', '-o'] - - if not v.LINK_CC: - v.LINK_CC = v.CC - - v.CCLNK_SRC_F = [] - v.CCLNK_TGT_F = ['-o'] - v.CPPPATH_ST = '-I%s' - v.DEFINES_ST = '-D%s' - - v.LIB_ST = '-l%s' # template for adding libs - v.LIBPATH_ST = '-L%s' # template for adding libpaths - v.STLIB_ST = '-l%s' - v.STLIBPATH_ST = '-L%s' - v.RPATH_ST = '-Wl,-rpath,%s' - - v.SONAME_ST = '-Wl,-h,%s' - v.SHLIB_MARKER = '-Wl,-Bdynamic' - v.STLIB_MARKER = '-Wl,-Bstatic' - - v.cprogram_PATTERN = '%s' - - v.CFLAGS_cshlib = ['-fPIC'] - v.LINKFLAGS_cshlib = ['-shared'] - v.cshlib_PATTERN = 'lib%s.so' - - v.LINKFLAGS_cstlib = ['-Wl,-Bstatic'] - v.cstlib_PATTERN = 'lib%s.a' - - v.LINKFLAGS_MACBUNDLE = ['-bundle', '-undefined', 'dynamic_lookup'] - v.CFLAGS_MACBUNDLE = ['-fPIC'] - v.macbundle_PATTERN = '%s.bundle' - -@conf -def gcc_modifier_win32(conf): - """Configuration flags for executing gcc on Windows""" - v = conf.env - v.cprogram_PATTERN = '%s.exe' - - v.cshlib_PATTERN = '%s.dll' - v.implib_PATTERN = '%s.dll.a' - v.IMPLIB_ST = '-Wl,--out-implib,%s' - - v.CFLAGS_cshlib = [] - - # Auto-import is enabled by default even without this option, - # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages - # that the linker emits otherwise. - v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) - -@conf -def gcc_modifier_cygwin(conf): - """Configuration flags for executing gcc on Cygwin""" - gcc_modifier_win32(conf) - v = conf.env - v.cshlib_PATTERN = 'cyg%s.dll' - v.append_value('LINKFLAGS_cshlib', ['-Wl,--enable-auto-image-base']) - v.CFLAGS_cshlib = [] - -@conf -def gcc_modifier_darwin(conf): - """Configuration flags for executing gcc on MacOS""" - v = conf.env - v.CFLAGS_cshlib = ['-fPIC'] - v.LINKFLAGS_cshlib = ['-dynamiclib'] - v.cshlib_PATTERN = 'lib%s.dylib' - v.FRAMEWORKPATH_ST = '-F%s' - v.FRAMEWORK_ST = ['-framework'] - v.ARCH_ST = ['-arch'] - - v.LINKFLAGS_cstlib = [] - - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - v.SONAME_ST = [] - -@conf -def gcc_modifier_aix(conf): - """Configuration flags for executing gcc on AIX""" - v = conf.env - v.LINKFLAGS_cprogram = ['-Wl,-brtl'] - v.LINKFLAGS_cshlib = ['-shared','-Wl,-brtl,-bexpfull'] - v.SHLIB_MARKER = [] - -@conf -def gcc_modifier_hpux(conf): - v = conf.env - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - v.CFLAGS_cshlib = ['-fPIC','-DPIC'] - v.cshlib_PATTERN = 'lib%s.sl' - -@conf -def gcc_modifier_openbsd(conf): - conf.env.SONAME_ST = [] - -@conf -def gcc_modifier_osf1V(conf): - v = conf.env - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - v.SONAME_ST = [] - -@conf -def gcc_modifier_platform(conf): - """Execute platform-specific functions based on *gcc_modifier_+NAME*""" - # * set configurations specific for a platform. - # * the destination platform is detected automatically by looking at the macros the compiler predefines, - # and if it's not recognised, it fallbacks to sys.platform. - gcc_modifier_func = getattr(conf, 'gcc_modifier_' + conf.env.DEST_OS, None) - if gcc_modifier_func: - gcc_modifier_func() - -def configure(conf): - """ - Configuration for gcc - """ - conf.find_gcc() - conf.find_ar() - conf.gcc_common_flags() - conf.gcc_modifier_platform() - conf.cc_load_tools() - conf.cc_add_flags() - conf.link_add_flags() - conf.check_gcc_o_space() - diff --git a/waflib/Tools/gdc.py b/waflib/Tools/gdc.py deleted file mode 100644 index d89a66d..0000000 --- a/waflib/Tools/gdc.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Carlos Rafael Giani, 2007 (dv) - -from waflib.Tools import ar, d -from waflib.Configure import conf - -@conf -def find_gdc(conf): - """ - Finds the program gdc and set the variable *D* - """ - conf.find_program('gdc', var='D') - - out = conf.cmd_and_log(conf.env.D + ['--version']) - if out.find("gdc") == -1: - conf.fatal("detected compiler is not gdc") - -@conf -def common_flags_gdc(conf): - """ - Sets the flags required by *gdc* - """ - v = conf.env - - v.DFLAGS = [] - - v.D_SRC_F = ['-c'] - v.D_TGT_F = '-o%s' - - v.D_LINKER = v.D - v.DLNK_SRC_F = '' - v.DLNK_TGT_F = '-o%s' - v.DINC_ST = '-I%s' - - v.DSHLIB_MARKER = v.DSTLIB_MARKER = '' - v.DSTLIB_ST = v.DSHLIB_ST = '-l%s' - v.DSTLIBPATH_ST = v.DLIBPATH_ST = '-L%s' - - v.LINKFLAGS_dshlib = ['-shared'] - - v.DHEADER_ext = '.di' - v.DFLAGS_d_with_header = '-fintfc' - v.D_HDR_F = '-fintfc-file=%s' - -def configure(conf): - """ - Configuration for gdc - """ - conf.find_gdc() - conf.load('ar') - conf.load('d') - conf.common_flags_gdc() - conf.d_platform_flags() - diff --git a/waflib/Tools/gfortran.py b/waflib/Tools/gfortran.py deleted file mode 100644 index 1050667..0000000 --- a/waflib/Tools/gfortran.py +++ /dev/null @@ -1,93 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# DC 2008 -# Thomas Nagy 2016-2018 (ita) - -import re -from waflib import Utils -from waflib.Tools import fc, fc_config, fc_scan, ar -from waflib.Configure import conf - -@conf -def find_gfortran(conf): - """Find the gfortran program (will look in the environment variable 'FC')""" - fc = conf.find_program(['gfortran','g77'], var='FC') - # (fallback to g77 for systems, where no gfortran is available) - conf.get_gfortran_version(fc) - conf.env.FC_NAME = 'GFORTRAN' - -@conf -def gfortran_flags(conf): - v = conf.env - v.FCFLAGS_fcshlib = ['-fPIC'] - v.FORTRANMODFLAG = ['-J', ''] # template for module path - v.FCFLAGS_DEBUG = ['-Werror'] # why not - -@conf -def gfortran_modifier_win32(conf): - fc_config.fortran_modifier_win32(conf) - -@conf -def gfortran_modifier_cygwin(conf): - fc_config.fortran_modifier_cygwin(conf) - -@conf -def gfortran_modifier_darwin(conf): - fc_config.fortran_modifier_darwin(conf) - -@conf -def gfortran_modifier_platform(conf): - dest_os = conf.env.DEST_OS or Utils.unversioned_sys_platform() - gfortran_modifier_func = getattr(conf, 'gfortran_modifier_' + dest_os, None) - if gfortran_modifier_func: - gfortran_modifier_func() - -@conf -def get_gfortran_version(conf, fc): - """Get the compiler version""" - - # ensure this is actually gfortran, not an imposter. - version_re = re.compile(r"GNU\s*Fortran", re.I).search - cmd = fc + ['--version'] - out, err = fc_config.getoutput(conf, cmd, stdin=False) - if out: - match = version_re(out) - else: - match = version_re(err) - if not match: - conf.fatal('Could not determine the compiler type') - - # --- now get more detailed info -- see c_config.get_cc_version - cmd = fc + ['-dM', '-E', '-'] - out, err = fc_config.getoutput(conf, cmd, stdin=True) - - if out.find('__GNUC__') < 0: - conf.fatal('Could not determine the compiler type') - - k = {} - out = out.splitlines() - import shlex - - for line in out: - lst = shlex.split(line) - if len(lst)>2: - key = lst[1] - val = lst[2] - k[key] = val - - def isD(var): - return var in k - - def isT(var): - return var in k and k[var] != '0' - - conf.env.FC_VERSION = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) - -def configure(conf): - conf.find_gfortran() - conf.find_ar() - conf.fc_flags() - conf.fc_add_flags() - conf.gfortran_flags() - conf.gfortran_modifier_platform() - conf.check_gfortran_o_space() diff --git a/waflib/Tools/glib2.py b/waflib/Tools/glib2.py deleted file mode 100644 index 949fe37..0000000 --- a/waflib/Tools/glib2.py +++ /dev/null @@ -1,489 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -""" -Support for GLib2 tools: - -* marshal -* enums -* gsettings -* gresource -""" - -import os -import functools -from waflib import Context, Task, Utils, Options, Errors, Logs -from waflib.TaskGen import taskgen_method, before_method, feature, extension -from waflib.Configure import conf - -################## marshal files - -@taskgen_method -def add_marshal_file(self, filename, prefix): - """ - Adds a file to the list of marshal files to process. Store them in the attribute *marshal_list*. - - :param filename: xml file to compile - :type filename: string - :param prefix: marshal prefix (--prefix=prefix) - :type prefix: string - """ - if not hasattr(self, 'marshal_list'): - self.marshal_list = [] - self.meths.append('process_marshal') - self.marshal_list.append((filename, prefix)) - -@before_method('process_source') -def process_marshal(self): - """ - Processes the marshal files stored in the attribute *marshal_list* to create :py:class:`waflib.Tools.glib2.glib_genmarshal` instances. - Adds the c file created to the list of source to process. - """ - for f, prefix in getattr(self, 'marshal_list', []): - node = self.path.find_resource(f) - - if not node: - raise Errors.WafError('file not found %r' % f) - - h_node = node.change_ext('.h') - c_node = node.change_ext('.c') - - task = self.create_task('glib_genmarshal', node, [h_node, c_node]) - task.env.GLIB_GENMARSHAL_PREFIX = prefix - self.source = self.to_nodes(getattr(self, 'source', [])) - self.source.append(c_node) - -class glib_genmarshal(Task.Task): - vars = ['GLIB_GENMARSHAL_PREFIX', 'GLIB_GENMARSHAL'] - color = 'BLUE' - ext_out = ['.h'] - def run(self): - bld = self.generator.bld - - get = self.env.get_flat - cmd1 = "%s %s --prefix=%s --header > %s" % ( - get('GLIB_GENMARSHAL'), - self.inputs[0].srcpath(), - get('GLIB_GENMARSHAL_PREFIX'), - self.outputs[0].abspath() - ) - - ret = bld.exec_command(cmd1) - if ret: - return ret - - #print self.outputs[1].abspath() - c = '''#include "%s"\n''' % self.outputs[0].name - self.outputs[1].write(c) - - cmd2 = "%s %s --prefix=%s --body >> %s" % ( - get('GLIB_GENMARSHAL'), - self.inputs[0].srcpath(), - get('GLIB_GENMARSHAL_PREFIX'), - self.outputs[1].abspath() - ) - return bld.exec_command(cmd2) - -########################## glib-mkenums - -@taskgen_method -def add_enums_from_template(self, source='', target='', template='', comments=''): - """ - Adds a file to the list of enum files to process. Stores them in the attribute *enums_list*. - - :param source: enum file to process - :type source: string - :param target: target file - :type target: string - :param template: template file - :type template: string - :param comments: comments - :type comments: string - """ - if not hasattr(self, 'enums_list'): - self.enums_list = [] - self.meths.append('process_enums') - self.enums_list.append({'source': source, - 'target': target, - 'template': template, - 'file-head': '', - 'file-prod': '', - 'file-tail': '', - 'enum-prod': '', - 'value-head': '', - 'value-prod': '', - 'value-tail': '', - 'comments': comments}) - -@taskgen_method -def add_enums(self, source='', target='', - file_head='', file_prod='', file_tail='', enum_prod='', - value_head='', value_prod='', value_tail='', comments=''): - """ - Adds a file to the list of enum files to process. Stores them in the attribute *enums_list*. - - :param source: enum file to process - :type source: string - :param target: target file - :type target: string - :param file_head: unused - :param file_prod: unused - :param file_tail: unused - :param enum_prod: unused - :param value_head: unused - :param value_prod: unused - :param value_tail: unused - :param comments: comments - :type comments: string - """ - if not hasattr(self, 'enums_list'): - self.enums_list = [] - self.meths.append('process_enums') - self.enums_list.append({'source': source, - 'template': '', - 'target': target, - 'file-head': file_head, - 'file-prod': file_prod, - 'file-tail': file_tail, - 'enum-prod': enum_prod, - 'value-head': value_head, - 'value-prod': value_prod, - 'value-tail': value_tail, - 'comments': comments}) - -@before_method('process_source') -def process_enums(self): - """ - Processes the enum files stored in the attribute *enum_list* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. - """ - for enum in getattr(self, 'enums_list', []): - task = self.create_task('glib_mkenums') - env = task.env - - inputs = [] - - # process the source - source_list = self.to_list(enum['source']) - if not source_list: - raise Errors.WafError('missing source ' + str(enum)) - source_list = [self.path.find_resource(k) for k in source_list] - inputs += source_list - env.GLIB_MKENUMS_SOURCE = [k.abspath() for k in source_list] - - # find the target - if not enum['target']: - raise Errors.WafError('missing target ' + str(enum)) - tgt_node = self.path.find_or_declare(enum['target']) - if tgt_node.name.endswith('.c'): - self.source.append(tgt_node) - env.GLIB_MKENUMS_TARGET = tgt_node.abspath() - - - options = [] - - if enum['template']: # template, if provided - template_node = self.path.find_resource(enum['template']) - options.append('--template %s' % (template_node.abspath())) - inputs.append(template_node) - params = {'file-head' : '--fhead', - 'file-prod' : '--fprod', - 'file-tail' : '--ftail', - 'enum-prod' : '--eprod', - 'value-head' : '--vhead', - 'value-prod' : '--vprod', - 'value-tail' : '--vtail', - 'comments': '--comments'} - for param, option in params.items(): - if enum[param]: - options.append('%s %r' % (option, enum[param])) - - env.GLIB_MKENUMS_OPTIONS = ' '.join(options) - - # update the task instance - task.set_inputs(inputs) - task.set_outputs(tgt_node) - -class glib_mkenums(Task.Task): - """ - Processes enum files - """ - run_str = '${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}' - color = 'PINK' - ext_out = ['.h'] - -######################################### gsettings - -@taskgen_method -def add_settings_schemas(self, filename_list): - """ - Adds settings files to process to *settings_schema_files* - - :param filename_list: files - :type filename_list: list of string - """ - if not hasattr(self, 'settings_schema_files'): - self.settings_schema_files = [] - - if not isinstance(filename_list, list): - filename_list = [filename_list] - - self.settings_schema_files.extend(filename_list) - -@taskgen_method -def add_settings_enums(self, namespace, filename_list): - """ - Called only once by task generator to set the enums namespace. - - :param namespace: namespace - :type namespace: string - :param filename_list: enum files to process - :type filename_list: file list - """ - if hasattr(self, 'settings_enum_namespace'): - raise Errors.WafError("Tried to add gsettings enums to %r more than once" % self.name) - self.settings_enum_namespace = namespace - - if not isinstance(filename_list, list): - filename_list = [filename_list] - self.settings_enum_files = filename_list - -@feature('glib2') -def process_settings(self): - """ - Processes the schema files in *settings_schema_files* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. The - same files are validated through :py:class:`waflib.Tools.glib2.glib_validate_schema` tasks. - - """ - enums_tgt_node = [] - install_files = [] - - settings_schema_files = getattr(self, 'settings_schema_files', []) - if settings_schema_files and not self.env.GLIB_COMPILE_SCHEMAS: - raise Errors.WafError ("Unable to process GSettings schemas - glib-compile-schemas was not found during configure") - - # 1. process gsettings_enum_files (generate .enums.xml) - # - if hasattr(self, 'settings_enum_files'): - enums_task = self.create_task('glib_mkenums') - - source_list = self.settings_enum_files - source_list = [self.path.find_resource(k) for k in source_list] - enums_task.set_inputs(source_list) - enums_task.env.GLIB_MKENUMS_SOURCE = [k.abspath() for k in source_list] - - target = self.settings_enum_namespace + '.enums.xml' - tgt_node = self.path.find_or_declare(target) - enums_task.set_outputs(tgt_node) - enums_task.env.GLIB_MKENUMS_TARGET = tgt_node.abspath() - enums_tgt_node = [tgt_node] - - install_files.append(tgt_node) - - options = '--comments "" --fhead "" --vhead " <@type@ id=\\"%s.@EnumName@\\">" --vprod " " --vtail " " --ftail "" ' % (self.settings_enum_namespace) - enums_task.env.GLIB_MKENUMS_OPTIONS = options - - # 2. process gsettings_schema_files (validate .gschema.xml files) - # - for schema in settings_schema_files: - schema_task = self.create_task ('glib_validate_schema') - - schema_node = self.path.find_resource(schema) - if not schema_node: - raise Errors.WafError("Cannot find the schema file %r" % schema) - install_files.append(schema_node) - source_list = enums_tgt_node + [schema_node] - - schema_task.set_inputs (source_list) - schema_task.env.GLIB_COMPILE_SCHEMAS_OPTIONS = [("--schema-file=" + k.abspath()) for k in source_list] - - target_node = schema_node.change_ext('.xml.valid') - schema_task.set_outputs (target_node) - schema_task.env.GLIB_VALIDATE_SCHEMA_OUTPUT = target_node.abspath() - - # 3. schemas install task - def compile_schemas_callback(bld): - if not bld.is_install: - return - compile_schemas = Utils.to_list(bld.env.GLIB_COMPILE_SCHEMAS) - destdir = Options.options.destdir - paths = bld._compile_schemas_registered - if destdir: - paths = (os.path.join(destdir, path.lstrip(os.sep)) for path in paths) - for path in paths: - Logs.pprint('YELLOW', 'Updating GSettings schema cache %r' % path) - if self.bld.exec_command(compile_schemas + [path]): - Logs.warn('Could not update GSettings schema cache %r' % path) - - if self.bld.is_install: - schemadir = self.env.GSETTINGSSCHEMADIR - if not schemadir: - raise Errors.WafError ('GSETTINGSSCHEMADIR not defined (should have been set up automatically during configure)') - - if install_files: - self.add_install_files(install_to=schemadir, install_from=install_files) - registered_schemas = getattr(self.bld, '_compile_schemas_registered', None) - if not registered_schemas: - registered_schemas = self.bld._compile_schemas_registered = set() - self.bld.add_post_fun(compile_schemas_callback) - registered_schemas.add(schemadir) - -class glib_validate_schema(Task.Task): - """ - Validates schema files - """ - run_str = 'rm -f ${GLIB_VALIDATE_SCHEMA_OUTPUT} && ${GLIB_COMPILE_SCHEMAS} --dry-run ${GLIB_COMPILE_SCHEMAS_OPTIONS} && touch ${GLIB_VALIDATE_SCHEMA_OUTPUT}' - color = 'PINK' - -################## gresource - -@extension('.gresource.xml') -def process_gresource_source(self, node): - """ - Creates tasks that turn ``.gresource.xml`` files to C code - """ - if not self.env.GLIB_COMPILE_RESOURCES: - raise Errors.WafError ("Unable to process GResource file - glib-compile-resources was not found during configure") - - if 'gresource' in self.features: - return - - h_node = node.change_ext('_xml.h') - c_node = node.change_ext('_xml.c') - self.create_task('glib_gresource_source', node, [h_node, c_node]) - self.source.append(c_node) - -@feature('gresource') -def process_gresource_bundle(self): - """ - Creates tasks to turn ``.gresource`` files from ``.gresource.xml`` files:: - - def build(bld): - bld( - features='gresource', - source=['resources1.gresource.xml', 'resources2.gresource.xml'], - install_path='${LIBDIR}/${PACKAGE}' - ) - - :param source: XML files to process - :type source: list of string - :param install_path: installation path - :type install_path: string - """ - for i in self.to_list(self.source): - node = self.path.find_resource(i) - - task = self.create_task('glib_gresource_bundle', node, node.change_ext('')) - inst_to = getattr(self, 'install_path', None) - if inst_to: - self.add_install_files(install_to=inst_to, install_from=task.outputs) - -class glib_gresource_base(Task.Task): - """ - Base class for gresource based tasks - """ - color = 'BLUE' - base_cmd = '${GLIB_COMPILE_RESOURCES} --sourcedir=${SRC[0].parent.srcpath()} --sourcedir=${SRC[0].bld_dir()}' - - def scan(self): - """ - Scans gresource dependencies through ``glib-compile-resources --generate-dependencies command`` - """ - bld = self.generator.bld - kw = {} - kw['cwd'] = self.get_cwd() - kw['quiet'] = Context.BOTH - - cmd = Utils.subst_vars('${GLIB_COMPILE_RESOURCES} --sourcedir=%s --sourcedir=%s --generate-dependencies %s' % ( - self.inputs[0].parent.srcpath(), - self.inputs[0].bld_dir(), - self.inputs[0].bldpath() - ), self.env) - - output = bld.cmd_and_log(cmd, **kw) - - nodes = [] - names = [] - for dep in output.splitlines(): - if dep: - node = bld.bldnode.find_node(dep) - if node: - nodes.append(node) - else: - names.append(dep) - - return (nodes, names) - -class glib_gresource_source(glib_gresource_base): - """ - Task to generate C source code (.h and .c files) from a gresource.xml file - """ - vars = ['GLIB_COMPILE_RESOURCES'] - fun_h = Task.compile_fun_shell(glib_gresource_base.base_cmd + ' --target=${TGT[0].abspath()} --generate-header ${SRC}') - fun_c = Task.compile_fun_shell(glib_gresource_base.base_cmd + ' --target=${TGT[1].abspath()} --generate-source ${SRC}') - ext_out = ['.h'] - - def run(self): - return self.fun_h[0](self) or self.fun_c[0](self) - -class glib_gresource_bundle(glib_gresource_base): - """ - Task to generate a .gresource binary file from a gresource.xml file - """ - run_str = glib_gresource_base.base_cmd + ' --target=${TGT} ${SRC}' - shell = True # temporary workaround for #795 - -@conf -def find_glib_genmarshal(conf): - conf.find_program('glib-genmarshal', var='GLIB_GENMARSHAL') - -@conf -def find_glib_mkenums(conf): - if not conf.env.PERL: - conf.find_program('perl', var='PERL') - conf.find_program('glib-mkenums', interpreter='PERL', var='GLIB_MKENUMS') - -@conf -def find_glib_compile_schemas(conf): - # when cross-compiling, gsettings.m4 locates the program with the following: - # pkg-config --variable glib_compile_schemas gio-2.0 - conf.find_program('glib-compile-schemas', var='GLIB_COMPILE_SCHEMAS') - - def getstr(varname): - return getattr(Options.options, varname, getattr(conf.env,varname, '')) - - gsettingsschemadir = getstr('GSETTINGSSCHEMADIR') - if not gsettingsschemadir: - datadir = getstr('DATADIR') - if not datadir: - prefix = conf.env.PREFIX - datadir = os.path.join(prefix, 'share') - gsettingsschemadir = os.path.join(datadir, 'glib-2.0', 'schemas') - - conf.env.GSETTINGSSCHEMADIR = gsettingsschemadir - -@conf -def find_glib_compile_resources(conf): - conf.find_program('glib-compile-resources', var='GLIB_COMPILE_RESOURCES') - -def configure(conf): - """ - Finds the following programs: - - * *glib-genmarshal* and set *GLIB_GENMARSHAL* - * *glib-mkenums* and set *GLIB_MKENUMS* - * *glib-compile-schemas* and set *GLIB_COMPILE_SCHEMAS* (not mandatory) - * *glib-compile-resources* and set *GLIB_COMPILE_RESOURCES* (not mandatory) - """ - conf.find_glib_genmarshal() - conf.find_glib_mkenums() - conf.find_glib_compile_schemas(mandatory=False) - conf.find_glib_compile_resources(mandatory=False) - -def options(opt): - """ - Adds the ``--gsettingsschemadir`` command-line option - """ - gr = opt.add_option_group('Installation directories') - gr.add_option('--gsettingsschemadir', help='GSettings schema location [DATADIR/glib-2.0/schemas]', default='', dest='GSETTINGSSCHEMADIR') - diff --git a/waflib/Tools/gnu_dirs.py b/waflib/Tools/gnu_dirs.py deleted file mode 100644 index 2847071..0000000 --- a/waflib/Tools/gnu_dirs.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Ali Sabil, 2007 - -""" -Sets various standard variables such as INCLUDEDIR. SBINDIR and others. To use this module just call:: - - opt.load('gnu_dirs') - -and:: - - conf.load('gnu_dirs') - -Add options for the standard GNU directories, this tool will add the options -found in autotools, and will update the environment with the following -installation variables: - -============== ========================================= ======================= -Variable Description Default Value -============== ========================================= ======================= -PREFIX installation prefix /usr/local -EXEC_PREFIX installation prefix for binaries PREFIX -BINDIR user commands EXEC_PREFIX/bin -SBINDIR system binaries EXEC_PREFIX/sbin -LIBEXECDIR program-specific binaries EXEC_PREFIX/libexec -SYSCONFDIR host-specific configuration PREFIX/etc -SHAREDSTATEDIR architecture-independent variable data PREFIX/com -LOCALSTATEDIR variable data PREFIX/var -LIBDIR object code libraries EXEC_PREFIX/lib -INCLUDEDIR header files PREFIX/include -OLDINCLUDEDIR header files for non-GCC compilers /usr/include -DATAROOTDIR architecture-independent data root PREFIX/share -DATADIR architecture-independent data DATAROOTDIR -INFODIR GNU "info" documentation DATAROOTDIR/info -LOCALEDIR locale-dependent data DATAROOTDIR/locale -MANDIR manual pages DATAROOTDIR/man -DOCDIR documentation root DATAROOTDIR/doc/APPNAME -HTMLDIR HTML documentation DOCDIR -DVIDIR DVI documentation DOCDIR -PDFDIR PDF documentation DOCDIR -PSDIR PostScript documentation DOCDIR -============== ========================================= ======================= -""" - -import os, re -from waflib import Utils, Options, Context - -gnuopts = ''' -bindir, user commands, ${EXEC_PREFIX}/bin -sbindir, system binaries, ${EXEC_PREFIX}/sbin -libexecdir, program-specific binaries, ${EXEC_PREFIX}/libexec -sysconfdir, host-specific configuration, ${PREFIX}/etc -sharedstatedir, architecture-independent variable data, ${PREFIX}/com -localstatedir, variable data, ${PREFIX}/var -libdir, object code libraries, ${EXEC_PREFIX}/lib%s -includedir, header files, ${PREFIX}/include -oldincludedir, header files for non-GCC compilers, /usr/include -datarootdir, architecture-independent data root, ${PREFIX}/share -datadir, architecture-independent data, ${DATAROOTDIR} -infodir, GNU "info" documentation, ${DATAROOTDIR}/info -localedir, locale-dependent data, ${DATAROOTDIR}/locale -mandir, manual pages, ${DATAROOTDIR}/man -docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} -htmldir, HTML documentation, ${DOCDIR} -dvidir, DVI documentation, ${DOCDIR} -pdfdir, PDF documentation, ${DOCDIR} -psdir, PostScript documentation, ${DOCDIR} -''' % Utils.lib64() - -_options = [x.split(', ') for x in gnuopts.splitlines() if x] - -def configure(conf): - """ - Reads the command-line options to set lots of variables in *conf.env*. The variables - BINDIR and LIBDIR will be overwritten. - """ - def get_param(varname, default): - return getattr(Options.options, varname, '') or default - - env = conf.env - env.LIBDIR = env.BINDIR = [] - env.EXEC_PREFIX = get_param('EXEC_PREFIX', env.PREFIX) - env.PACKAGE = getattr(Context.g_module, 'APPNAME', None) or env.PACKAGE - - complete = False - iter = 0 - while not complete and iter < len(_options) + 1: - iter += 1 - complete = True - for name, help, default in _options: - name = name.upper() - if not env[name]: - try: - env[name] = Utils.subst_vars(get_param(name, default).replace('/', os.sep), env) - except TypeError: - complete = False - - if not complete: - lst = [x for x, _, _ in _options if not env[x.upper()]] - raise conf.errors.WafError('Variable substitution failure %r' % lst) - -def options(opt): - """ - Adds lots of command-line options, for example:: - - --exec-prefix: EXEC_PREFIX - """ - inst_dir = opt.add_option_group('Installation prefix', -'By default, "waf install" will put the files in\ - "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\ - than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"') - - for k in ('--prefix', '--destdir'): - option = opt.parser.get_option(k) - if option: - opt.parser.remove_option(k) - inst_dir.add_option(option) - - inst_dir.add_option('--exec-prefix', - help = 'installation prefix for binaries [PREFIX]', - default = '', - dest = 'EXEC_PREFIX') - - dirs_options = opt.add_option_group('Installation directories') - - for name, help, default in _options: - option_name = '--' + name - str_default = default - str_help = '%s [%s]' % (help, re.sub(r'\$\{([^}]+)\}', r'\1', str_default)) - dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) - diff --git a/waflib/Tools/gxx.py b/waflib/Tools/gxx.py deleted file mode 100644 index 22c5d26..0000000 --- a/waflib/Tools/gxx.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) -# Ralf Habacker, 2006 (rh) -# Yinon Ehrlich, 2009 - -""" -g++/llvm detection. -""" - -from waflib.Tools import ccroot, ar -from waflib.Configure import conf - -@conf -def find_gxx(conf): - """ - Finds the program g++, and if present, try to detect its version number - """ - cxx = conf.find_program(['g++', 'c++'], var='CXX') - conf.get_cc_version(cxx, gcc=True) - conf.env.CXX_NAME = 'gcc' - -@conf -def gxx_common_flags(conf): - """ - Common flags for g++ on nearly all platforms - """ - v = conf.env - - v.CXX_SRC_F = [] - v.CXX_TGT_F = ['-c', '-o'] - - if not v.LINK_CXX: - v.LINK_CXX = v.CXX - - v.CXXLNK_SRC_F = [] - v.CXXLNK_TGT_F = ['-o'] - v.CPPPATH_ST = '-I%s' - v.DEFINES_ST = '-D%s' - - v.LIB_ST = '-l%s' # template for adding libs - v.LIBPATH_ST = '-L%s' # template for adding libpaths - v.STLIB_ST = '-l%s' - v.STLIBPATH_ST = '-L%s' - v.RPATH_ST = '-Wl,-rpath,%s' - - v.SONAME_ST = '-Wl,-h,%s' - v.SHLIB_MARKER = '-Wl,-Bdynamic' - v.STLIB_MARKER = '-Wl,-Bstatic' - - v.cxxprogram_PATTERN = '%s' - - v.CXXFLAGS_cxxshlib = ['-fPIC'] - v.LINKFLAGS_cxxshlib = ['-shared'] - v.cxxshlib_PATTERN = 'lib%s.so' - - v.LINKFLAGS_cxxstlib = ['-Wl,-Bstatic'] - v.cxxstlib_PATTERN = 'lib%s.a' - - v.LINKFLAGS_MACBUNDLE = ['-bundle', '-undefined', 'dynamic_lookup'] - v.CXXFLAGS_MACBUNDLE = ['-fPIC'] - v.macbundle_PATTERN = '%s.bundle' - -@conf -def gxx_modifier_win32(conf): - """Configuration flags for executing gcc on Windows""" - v = conf.env - v.cxxprogram_PATTERN = '%s.exe' - - v.cxxshlib_PATTERN = '%s.dll' - v.implib_PATTERN = '%s.dll.a' - v.IMPLIB_ST = '-Wl,--out-implib,%s' - - v.CXXFLAGS_cxxshlib = [] - - # Auto-import is enabled by default even without this option, - # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages - # that the linker emits otherwise. - v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) - -@conf -def gxx_modifier_cygwin(conf): - """Configuration flags for executing g++ on Cygwin""" - gxx_modifier_win32(conf) - v = conf.env - v.cxxshlib_PATTERN = 'cyg%s.dll' - v.append_value('LINKFLAGS_cxxshlib', ['-Wl,--enable-auto-image-base']) - v.CXXFLAGS_cxxshlib = [] - -@conf -def gxx_modifier_darwin(conf): - """Configuration flags for executing g++ on MacOS""" - v = conf.env - v.CXXFLAGS_cxxshlib = ['-fPIC'] - v.LINKFLAGS_cxxshlib = ['-dynamiclib'] - v.cxxshlib_PATTERN = 'lib%s.dylib' - v.FRAMEWORKPATH_ST = '-F%s' - v.FRAMEWORK_ST = ['-framework'] - v.ARCH_ST = ['-arch'] - - v.LINKFLAGS_cxxstlib = [] - - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - v.SONAME_ST = [] - -@conf -def gxx_modifier_aix(conf): - """Configuration flags for executing g++ on AIX""" - v = conf.env - v.LINKFLAGS_cxxprogram= ['-Wl,-brtl'] - - v.LINKFLAGS_cxxshlib = ['-shared', '-Wl,-brtl,-bexpfull'] - v.SHLIB_MARKER = [] - -@conf -def gxx_modifier_hpux(conf): - v = conf.env - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - v.CFLAGS_cxxshlib = ['-fPIC','-DPIC'] - v.cxxshlib_PATTERN = 'lib%s.sl' - -@conf -def gxx_modifier_openbsd(conf): - conf.env.SONAME_ST = [] - -@conf -def gcc_modifier_osf1V(conf): - v = conf.env - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - v.SONAME_ST = [] - -@conf -def gxx_modifier_platform(conf): - """Execute platform-specific functions based on *gxx_modifier_+NAME*""" - # * set configurations specific for a platform. - # * the destination platform is detected automatically by looking at the macros the compiler predefines, - # and if it's not recognised, it fallbacks to sys.platform. - gxx_modifier_func = getattr(conf, 'gxx_modifier_' + conf.env.DEST_OS, None) - if gxx_modifier_func: - gxx_modifier_func() - -def configure(conf): - """ - Configuration for g++ - """ - conf.find_gxx() - conf.find_ar() - conf.gxx_common_flags() - conf.gxx_modifier_platform() - conf.cxx_load_tools() - conf.cxx_add_flags() - conf.link_add_flags() - conf.check_gcc_o_space('cxx') - diff --git a/waflib/Tools/icc.py b/waflib/Tools/icc.py deleted file mode 100644 index b6492c8..0000000 --- a/waflib/Tools/icc.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Stian Selnes 2008 -# Thomas Nagy 2009-2018 (ita) - -""" -Detects the Intel C compiler -""" - -import sys -from waflib.Tools import ccroot, ar, gcc -from waflib.Configure import conf - -@conf -def find_icc(conf): - """ - Finds the program icc and execute it to ensure it really is icc - """ - cc = conf.find_program(['icc', 'ICL'], var='CC') - conf.get_cc_version(cc, icc=True) - conf.env.CC_NAME = 'icc' - -def configure(conf): - conf.find_icc() - conf.find_ar() - conf.gcc_common_flags() - conf.gcc_modifier_platform() - conf.cc_load_tools() - conf.cc_add_flags() - conf.link_add_flags() diff --git a/waflib/Tools/icpc.py b/waflib/Tools/icpc.py deleted file mode 100644 index 8a6cc6c..0000000 --- a/waflib/Tools/icpc.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy 2009-2018 (ita) - -""" -Detects the Intel C++ compiler -""" - -import sys -from waflib.Tools import ccroot, ar, gxx -from waflib.Configure import conf - -@conf -def find_icpc(conf): - """ - Finds the program icpc, and execute it to ensure it really is icpc - """ - cxx = conf.find_program('icpc', var='CXX') - conf.get_cc_version(cxx, icc=True) - conf.env.CXX_NAME = 'icc' - -def configure(conf): - conf.find_icpc() - conf.find_ar() - conf.gxx_common_flags() - conf.gxx_modifier_platform() - conf.cxx_load_tools() - conf.cxx_add_flags() - conf.link_add_flags() - diff --git a/waflib/Tools/ifort.py b/waflib/Tools/ifort.py deleted file mode 100644 index 17d3052..0000000 --- a/waflib/Tools/ifort.py +++ /dev/null @@ -1,413 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# DC 2008 -# Thomas Nagy 2016-2018 (ita) - -import os, re, traceback -from waflib import Utils, Logs, Errors -from waflib.Tools import fc, fc_config, fc_scan, ar, ccroot -from waflib.Configure import conf -from waflib.TaskGen import after_method, feature - -@conf -def find_ifort(conf): - fc = conf.find_program('ifort', var='FC') - conf.get_ifort_version(fc) - conf.env.FC_NAME = 'IFORT' - -@conf -def ifort_modifier_win32(self): - v = self.env - v.IFORT_WIN32 = True - v.FCSTLIB_MARKER = '' - v.FCSHLIB_MARKER = '' - - v.FCLIB_ST = v.FCSTLIB_ST = '%s.lib' - v.FCLIBPATH_ST = v.STLIBPATH_ST = '/LIBPATH:%s' - v.FCINCPATH_ST = '/I%s' - v.FCDEFINES_ST = '/D%s' - - v.fcprogram_PATTERN = v.fcprogram_test_PATTERN = '%s.exe' - v.fcshlib_PATTERN = '%s.dll' - v.fcstlib_PATTERN = v.implib_PATTERN = '%s.lib' - - v.FCLNK_TGT_F = '/out:' - v.FC_TGT_F = ['/c', '/o', ''] - v.FCFLAGS_fcshlib = '' - v.LINKFLAGS_fcshlib = '/DLL' - v.AR_TGT_F = '/out:' - v.IMPLIB_ST = '/IMPLIB:%s' - - v.append_value('LINKFLAGS', '/subsystem:console') - if v.IFORT_MANIFEST: - v.append_value('LINKFLAGS', ['/MANIFEST']) - -@conf -def ifort_modifier_darwin(conf): - fc_config.fortran_modifier_darwin(conf) - -@conf -def ifort_modifier_platform(conf): - dest_os = conf.env.DEST_OS or Utils.unversioned_sys_platform() - ifort_modifier_func = getattr(conf, 'ifort_modifier_' + dest_os, None) - if ifort_modifier_func: - ifort_modifier_func() - -@conf -def get_ifort_version(conf, fc): - """ - Detects the compiler version and sets ``conf.env.FC_VERSION`` - """ - version_re = re.compile(r"\bIntel\b.*\bVersion\s*(?P\d*)\.(?P\d*)",re.I).search - if Utils.is_win32: - cmd = fc - else: - cmd = fc + ['-logo'] - - out, err = fc_config.getoutput(conf, cmd, stdin=False) - match = version_re(out) or version_re(err) - if not match: - conf.fatal('cannot determine ifort version.') - k = match.groupdict() - conf.env.FC_VERSION = (k['major'], k['minor']) - -def configure(conf): - """ - Detects the Intel Fortran compilers - """ - if Utils.is_win32: - compiler, version, path, includes, libdirs, arch = conf.detect_ifort() - v = conf.env - v.DEST_CPU = arch - v.PATH = path - v.INCLUDES = includes - v.LIBPATH = libdirs - v.MSVC_COMPILER = compiler - try: - v.MSVC_VERSION = float(version) - except ValueError: - v.MSVC_VERSION = float(version[:-3]) - - conf.find_ifort_win32() - conf.ifort_modifier_win32() - else: - conf.find_ifort() - conf.find_program('xiar', var='AR') - conf.find_ar() - conf.fc_flags() - conf.fc_add_flags() - conf.ifort_modifier_platform() - - -all_ifort_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] -"""List of icl platforms""" - -@conf -def gather_ifort_versions(conf, versions): - """ - List compiler versions by looking up registry keys - """ - version_pattern = re.compile(r'^...?.?\....?.?') - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\Fortran') - except OSError: - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\Fortran') - except OSError: - return - index = 0 - while 1: - try: - version = Utils.winreg.EnumKey(all_versions, index) - except OSError: - break - index += 1 - if not version_pattern.match(version): - continue - targets = {} - for target,arch in all_ifort_platforms: - if target=='intel64': - targetDir='EM64T_NATIVE' - else: - targetDir=target - try: - Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) - icl_version=Utils.winreg.OpenKey(all_versions,version) - path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except OSError: - pass - else: - batch_file=os.path.join(path,'bin','ifortvars.bat') - if os.path.isfile(batch_file): - targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) - - for target,arch in all_ifort_platforms: - try: - icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) - path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except OSError: - continue - else: - batch_file=os.path.join(path,'bin','ifortvars.bat') - if os.path.isfile(batch_file): - targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) - major = version[0:2] - versions['intel ' + major] = targets - -@conf -def setup_ifort(conf, versiondict): - """ - Checks installed compilers and targets and returns the first combination from the user's - options, env, or the global supported lists that checks. - - :param versiondict: dict(platform -> dict(architecture -> configuration)) - :type versiondict: dict(string -> dict(string -> target_compiler) - :return: the compiler, revision, path, include dirs, library paths and target architecture - :rtype: tuple of strings - """ - platforms = Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_ifort_platforms] - desired_versions = conf.env.MSVC_VERSIONS or list(reversed(list(versiondict.keys()))) - for version in desired_versions: - try: - targets = versiondict[version] - except KeyError: - continue - for arch in platforms: - try: - cfg = targets[arch] - except KeyError: - continue - cfg.evaluate() - if cfg.is_valid: - compiler,revision = version.rsplit(' ', 1) - return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu - conf.fatal('ifort: Impossible to find a valid architecture for building %r - %r' % (desired_versions, list(versiondict.keys()))) - -@conf -def get_ifort_version_win32(conf, compiler, version, target, vcvars): - # FIXME hack - try: - conf.msvc_cnt += 1 - except AttributeError: - conf.msvc_cnt = 1 - batfile = conf.bldnode.make_node('waf-print-msvc-%d.bat' % conf.msvc_cnt) - batfile.write("""@echo off -set INCLUDE= -set LIB= -call "%s" %s -echo PATH=%%PATH%% -echo INCLUDE=%%INCLUDE%% -echo LIB=%%LIB%%;%%LIBPATH%% -""" % (vcvars,target)) - sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()]) - batfile.delete() - lines = sout.splitlines() - - if not lines[0]: - lines.pop(0) - - MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None - for line in lines: - if line.startswith('PATH='): - path = line[5:] - MSVC_PATH = path.split(';') - elif line.startswith('INCLUDE='): - MSVC_INCDIR = [i for i in line[8:].split(';') if i] - elif line.startswith('LIB='): - MSVC_LIBDIR = [i for i in line[4:].split(';') if i] - if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR): - conf.fatal('ifort: Could not find a valid architecture for building (get_ifort_version_win32)') - - # Check if the compiler is usable at all. - # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run. - env = dict(os.environ) - env.update(PATH = path) - compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) - fc = conf.find_program(compiler_name, path_list=MSVC_PATH) - - # delete CL if exists. because it could contain parameters which can change cl's behaviour rather catastrophically. - if 'CL' in env: - del(env['CL']) - - try: - conf.cmd_and_log(fc + ['/help'], env=env) - except UnicodeError: - st = traceback.format_exc() - if conf.logger: - conf.logger.error(st) - conf.fatal('ifort: Unicode error - check the code page?') - except Exception as e: - Logs.debug('ifort: get_ifort_version: %r %r %r -> failure %s', compiler, version, target, str(e)) - conf.fatal('ifort: cannot run the compiler in get_ifort_version (run with -v to display errors)') - else: - Logs.debug('ifort: get_ifort_version: %r %r %r -> OK', compiler, version, target) - finally: - conf.env[compiler_name] = '' - - return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) - -class target_compiler(object): - """ - Wraps a compiler configuration; call evaluate() to determine - whether the configuration is usable. - """ - def __init__(self, ctx, compiler, cpu, version, bat_target, bat, callback=None): - """ - :param ctx: configuration context to use to eventually get the version environment - :param compiler: compiler name - :param cpu: target cpu - :param version: compiler version number - :param bat_target: ? - :param bat: path to the batch file to run - :param callback: optional function to take the realized environment variables tup and map it (e.g. to combine other constant paths) - """ - self.conf = ctx - self.name = None - self.is_valid = False - self.is_done = False - - self.compiler = compiler - self.cpu = cpu - self.version = version - self.bat_target = bat_target - self.bat = bat - self.callback = callback - - def evaluate(self): - if self.is_done: - return - self.is_done = True - try: - vs = self.conf.get_ifort_version_win32(self.compiler, self.version, self.bat_target, self.bat) - except Errors.ConfigurationError: - self.is_valid = False - return - if self.callback: - vs = self.callback(self, vs) - self.is_valid = True - (self.bindirs, self.incdirs, self.libdirs) = vs - - def __str__(self): - return str((self.bindirs, self.incdirs, self.libdirs)) - - def __repr__(self): - return repr((self.bindirs, self.incdirs, self.libdirs)) - -@conf -def detect_ifort(self): - return self.setup_ifort(self.get_ifort_versions(False)) - -@conf -def get_ifort_versions(self, eval_and_save=True): - """ - :return: platforms to compiler configurations - :rtype: dict - """ - dct = {} - self.gather_ifort_versions(dct) - return dct - -def _get_prog_names(self, compiler): - if compiler=='intel': - compiler_name = 'ifort' - linker_name = 'XILINK' - lib_name = 'XILIB' - else: - # assumes CL.exe - compiler_name = 'CL' - linker_name = 'LINK' - lib_name = 'LIB' - return compiler_name, linker_name, lib_name - -@conf -def find_ifort_win32(conf): - # the autodetection is supposed to be performed before entering in this method - v = conf.env - path = v.PATH - compiler = v.MSVC_COMPILER - version = v.MSVC_VERSION - - compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) - v.IFORT_MANIFEST = (compiler == 'intel' and version >= 11) - - # compiler - fc = conf.find_program(compiler_name, var='FC', path_list=path) - - # before setting anything, check if the compiler is really intel fortran - env = dict(conf.environ) - if path: - env.update(PATH = ';'.join(path)) - if not conf.cmd_and_log(fc + ['/nologo', '/help'], env=env): - conf.fatal('not intel fortran compiler could not be identified') - - v.FC_NAME = 'IFORT' - - if not v.LINK_FC: - conf.find_program(linker_name, var='LINK_FC', path_list=path, mandatory=True) - - if not v.AR: - conf.find_program(lib_name, path_list=path, var='AR', mandatory=True) - v.ARFLAGS = ['/nologo'] - - # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later - if v.IFORT_MANIFEST: - conf.find_program('MT', path_list=path, var='MT') - v.MTFLAGS = ['/nologo'] - - try: - conf.load('winres') - except Errors.WafError: - Logs.warn('Resource compiler not found. Compiling resource file is disabled') - -####################################################################################################### -##### conf above, build below - -@after_method('apply_link') -@feature('fc') -def apply_flags_ifort(self): - """ - Adds additional flags implied by msvc, such as subsystems and pdb files:: - - def build(bld): - bld.stlib(source='main.c', target='bar', subsystem='gruik') - """ - if not self.env.IFORT_WIN32 or not getattr(self, 'link_task', None): - return - - is_static = isinstance(self.link_task, ccroot.stlink_task) - - subsystem = getattr(self, 'subsystem', '') - if subsystem: - subsystem = '/subsystem:%s' % subsystem - flags = is_static and 'ARFLAGS' or 'LINKFLAGS' - self.env.append_value(flags, subsystem) - - if not is_static: - for f in self.env.LINKFLAGS: - d = f.lower() - if d[1:] == 'debug': - pdbnode = self.link_task.outputs[0].change_ext('.pdb') - self.link_task.outputs.append(pdbnode) - - if getattr(self, 'install_task', None): - self.pdb_install_task = self.add_install_files(install_to=self.install_task.install_to, install_from=pdbnode) - - break - -@feature('fcprogram', 'fcshlib', 'fcprogram_test') -@after_method('apply_link') -def apply_manifest_ifort(self): - """ - Enables manifest embedding in Fortran DLLs when using ifort on Windows - See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx - """ - if self.env.IFORT_WIN32 and getattr(self, 'link_task', None): - # it seems ifort.exe cannot be called for linking - self.link_task.env.FC = self.env.LINK_FC - - if self.env.IFORT_WIN32 and self.env.IFORT_MANIFEST and getattr(self, 'link_task', None): - out_node = self.link_task.outputs[0] - man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') - self.link_task.outputs.append(man_node) - self.env.DO_MANIFEST = True - diff --git a/waflib/Tools/intltool.py b/waflib/Tools/intltool.py deleted file mode 100644 index af95ba8..0000000 --- a/waflib/Tools/intltool.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -""" -Support for translation tools such as msgfmt and intltool - -Usage:: - - def configure(conf): - conf.load('gnu_dirs intltool') - - def build(bld): - # process the .po files into .gmo files, and install them in LOCALEDIR - bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") - - # process an input file, substituting the translations from the po dir - bld( - features = "intltool_in", - podir = "../po", - style = "desktop", - flags = ["-u"], - source = 'kupfer.desktop.in', - install_path = "${DATADIR}/applications", - ) - -Usage of the :py:mod:`waflib.Tools.gnu_dirs` is recommended, but not obligatory. -""" - -from __future__ import with_statement - -import os, re -from waflib import Context, Task, Utils, Logs -import waflib.Tools.ccroot -from waflib.TaskGen import feature, before_method, taskgen_method -from waflib.Logs import error -from waflib.Configure import conf - -_style_flags = { - 'ba': '-b', - 'desktop': '-d', - 'keys': '-k', - 'quoted': '--quoted-style', - 'quotedxml': '--quotedxml-style', - 'rfc822deb': '-r', - 'schemas': '-s', - 'xml': '-x', -} - -@taskgen_method -def ensure_localedir(self): - """ - Expands LOCALEDIR from DATAROOTDIR/locale if possible, or falls back to PREFIX/share/locale - """ - # use the tool gnu_dirs to provide options to define this - if not self.env.LOCALEDIR: - if self.env.DATAROOTDIR: - self.env.LOCALEDIR = os.path.join(self.env.DATAROOTDIR, 'locale') - else: - self.env.LOCALEDIR = os.path.join(self.env.PREFIX, 'share', 'locale') - -@before_method('process_source') -@feature('intltool_in') -def apply_intltool_in_f(self): - """ - Creates tasks to translate files by intltool-merge:: - - def build(bld): - bld( - features = "intltool_in", - podir = "../po", - style = "desktop", - flags = ["-u"], - source = 'kupfer.desktop.in', - install_path = "${DATADIR}/applications", - ) - - :param podir: location of the .po files - :type podir: string - :param source: source files to process - :type source: list of string - :param style: the intltool-merge mode of operation, can be one of the following values: - ``ba``, ``desktop``, ``keys``, ``quoted``, ``quotedxml``, ``rfc822deb``, ``schemas`` and ``xml``. - See the ``intltool-merge`` man page for more information about supported modes of operation. - :type style: string - :param flags: compilation flags ("-quc" by default) - :type flags: list of string - :param install_path: installation path - :type install_path: string - """ - try: - self.meths.remove('process_source') - except ValueError: - pass - - self.ensure_localedir() - - podir = getattr(self, 'podir', '.') - podirnode = self.path.find_dir(podir) - if not podirnode: - error("could not find the podir %r" % podir) - return - - cache = getattr(self, 'intlcache', '.intlcache') - self.env.INTLCACHE = [os.path.join(str(self.path.get_bld()), podir, cache)] - self.env.INTLPODIR = podirnode.bldpath() - self.env.append_value('INTLFLAGS', getattr(self, 'flags', self.env.INTLFLAGS_DEFAULT)) - - if '-c' in self.env.INTLFLAGS: - self.bld.fatal('Redundant -c flag in intltool task %r' % self) - - style = getattr(self, 'style', None) - if style: - try: - style_flag = _style_flags[style] - except KeyError: - self.bld.fatal('intltool_in style "%s" is not valid' % style) - - self.env.append_unique('INTLFLAGS', [style_flag]) - - for i in self.to_list(self.source): - node = self.path.find_resource(i) - - task = self.create_task('intltool', node, node.change_ext('')) - inst = getattr(self, 'install_path', None) - if inst: - self.add_install_files(install_to=inst, install_from=task.outputs) - -@feature('intltool_po') -def apply_intltool_po(self): - """ - Creates tasks to process po files:: - - def build(bld): - bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") - - The relevant task generator arguments are: - - :param podir: directory of the .po files - :type podir: string - :param appname: name of the application - :type appname: string - :param install_path: installation directory - :type install_path: string - - The file LINGUAS must be present in the directory pointed by *podir* and list the translation files to process. - """ - try: - self.meths.remove('process_source') - except ValueError: - pass - - self.ensure_localedir() - - appname = getattr(self, 'appname', getattr(Context.g_module, Context.APPNAME, 'set_your_app_name')) - podir = getattr(self, 'podir', '.') - inst = getattr(self, 'install_path', '${LOCALEDIR}') - - linguas = self.path.find_node(os.path.join(podir, 'LINGUAS')) - if linguas: - # scan LINGUAS file for locales to process - with open(linguas.abspath()) as f: - langs = [] - for line in f.readlines(): - # ignore lines containing comments - if not line.startswith('#'): - langs += line.split() - re_linguas = re.compile('[-a-zA-Z_@.]+') - for lang in langs: - # Make sure that we only process lines which contain locales - if re_linguas.match(lang): - node = self.path.find_resource(os.path.join(podir, re_linguas.match(lang).group() + '.po')) - task = self.create_task('po', node, node.change_ext('.mo')) - - if inst: - filename = task.outputs[0].name - (langname, ext) = os.path.splitext(filename) - inst_file = inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo' - self.add_install_as(install_to=inst_file, install_from=task.outputs[0], - chmod=getattr(self, 'chmod', Utils.O644)) - - else: - Logs.pprint('RED', "Error no LINGUAS file found in po directory") - -class po(Task.Task): - """ - Compiles .po files into .gmo files - """ - run_str = '${MSGFMT} -o ${TGT} ${SRC}' - color = 'BLUE' - -class intltool(Task.Task): - """ - Calls intltool-merge to update translation files - """ - run_str = '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE_ST:INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}' - color = 'BLUE' - -@conf -def find_msgfmt(conf): - """ - Detects msgfmt and sets the ``MSGFMT`` variable - """ - conf.find_program('msgfmt', var='MSGFMT') - -@conf -def find_intltool_merge(conf): - """ - Detects intltool-merge - """ - if not conf.env.PERL: - conf.find_program('perl', var='PERL') - conf.env.INTLCACHE_ST = '--cache=%s' - conf.env.INTLFLAGS_DEFAULT = ['-q', '-u'] - conf.find_program('intltool-merge', interpreter='PERL', var='INTLTOOL') - -def configure(conf): - """ - Detects the program *msgfmt* and set *conf.env.MSGFMT*. - Detects the program *intltool-merge* and set *conf.env.INTLTOOL*. - It is possible to set INTLTOOL in the environment, but it must not have spaces in it:: - - $ INTLTOOL="/path/to/the program/intltool" waf configure - - If a C/C++ compiler is present, execute a compilation test to find the header *locale.h*. - """ - conf.find_msgfmt() - conf.find_intltool_merge() - if conf.env.CC or conf.env.CXX: - conf.check(header_name='locale.h') - diff --git a/waflib/Tools/irixcc.py b/waflib/Tools/irixcc.py deleted file mode 100644 index c3ae1ac..0000000 --- a/waflib/Tools/irixcc.py +++ /dev/null @@ -1,66 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# imported from samba - -""" -Compiler definition for irix/MIPSpro cc compiler -""" - -from waflib import Errors -from waflib.Tools import ccroot, ar -from waflib.Configure import conf - -@conf -def find_irixcc(conf): - v = conf.env - cc = None - if v.CC: - cc = v.CC - elif 'CC' in conf.environ: - cc = conf.environ['CC'] - if not cc: - cc = conf.find_program('cc', var='CC') - if not cc: - conf.fatal('irixcc was not found') - - try: - conf.cmd_and_log(cc + ['-version']) - except Errors.WafError: - conf.fatal('%r -version could not be executed' % cc) - - v.CC = cc - v.CC_NAME = 'irix' - -@conf -def irixcc_common_flags(conf): - v = conf.env - - v.CC_SRC_F = '' - v.CC_TGT_F = ['-c', '-o'] - v.CPPPATH_ST = '-I%s' - v.DEFINES_ST = '-D%s' - - if not v.LINK_CC: - v.LINK_CC = v.CC - - v.CCLNK_SRC_F = '' - v.CCLNK_TGT_F = ['-o'] - - v.LIB_ST = '-l%s' # template for adding libs - v.LIBPATH_ST = '-L%s' # template for adding libpaths - v.STLIB_ST = '-l%s' - v.STLIBPATH_ST = '-L%s' - - v.cprogram_PATTERN = '%s' - v.cshlib_PATTERN = 'lib%s.so' - v.cstlib_PATTERN = 'lib%s.a' - -def configure(conf): - conf.find_irixcc() - conf.find_cpp() - conf.find_ar() - conf.irixcc_common_flags() - conf.cc_load_tools() - conf.cc_add_flags() - conf.link_add_flags() - diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py deleted file mode 100644 index 9daed39..0000000 --- a/waflib/Tools/javaw.py +++ /dev/null @@ -1,579 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -""" -Java support - -Javac is one of the few compilers that behaves very badly: - -#. it outputs files where it wants to (-d is only for the package root) - -#. it recompiles files silently behind your back - -#. it outputs an undefined amount of files (inner classes) - -Remember that the compilation can be performed using Jython[1] rather than regular Python. Instead of -running one of the following commands:: - - ./waf configure - python waf configure - -You would have to run:: - - java -jar /path/to/jython.jar waf configure - -[1] http://www.jython.org/ - -Usage -===== - -Load the "java" tool. - -def configure(conf): - conf.load('java') - -Java tools will be autodetected and eventually, if present, the quite -standard JAVA_HOME environment variable will be used. The also standard -CLASSPATH variable is used for library searching. - -In configuration phase checks can be done on the system environment, for -example to check if a class is known in the classpath:: - - conf.check_java_class('java.io.FileOutputStream') - -or if the system supports JNI applications building:: - - conf.check_jni_headers() - - -The java tool supports compiling java code, creating jar files and -creating javadoc documentation. This can be either done separately or -together in a single definition. For example to manage them separately:: - - bld(features = 'javac', - srcdir = 'src', - compat = '1.7', - use = 'animals', - name = 'cats-src', - ) - - bld(features = 'jar', - basedir = '.', - destfile = '../cats.jar', - name = 'cats', - use = 'cats-src' - ) - - -Or together by defining all the needed attributes:: - - bld(features = 'javac jar javadoc', - srcdir = 'src/', # folder containing the sources to compile - outdir = 'src', # folder where to output the classes (in the build directory) - compat = '1.6', # java compatibility version number - classpath = ['.', '..'], - - # jar - basedir = 'src', # folder containing the classes and other files to package (must match outdir) - destfile = 'foo.jar', # do not put the destfile in the folder of the java classes! - use = 'NNN', - jaropts = ['-C', 'default/src/', '.'], # can be used to give files - manifest = 'src/Manifest.mf', # Manifest file to include - - # javadoc - javadoc_package = ['com.meow' , 'com.meow.truc.bar', 'com.meow.truc.foo'], - javadoc_output = 'javadoc', - ) - -External jar dependencies can be mapped to a standard waf "use" dependency by -setting an environment variable with a CLASSPATH prefix in the configuration, -for example:: - - conf.env.CLASSPATH_NNN = ['aaaa.jar', 'bbbb.jar'] - -and then NNN can be freely used in rules as:: - - use = 'NNN', - -In the java tool the dependencies via use are not transitive by default, as -this necessity depends on the code. To enable recursive dependency scanning -use on a specific rule: - - recurse_use = True - -Or build-wise by setting RECURSE_JAVA: - - bld.env.RECURSE_JAVA = True - -Unit tests can be integrated in the waf unit test environment using the javatest extra. -""" - -import os, shutil -from waflib import Task, Utils, Errors, Node -from waflib.Configure import conf -from waflib.TaskGen import feature, before_method, after_method, taskgen_method - -from waflib.Tools import ccroot -ccroot.USELIB_VARS['javac'] = set(['CLASSPATH', 'JAVACFLAGS']) - -SOURCE_RE = '**/*.java' -JAR_RE = '**/*' - -class_check_source = ''' -public class Test { - public static void main(String[] argv) { - Class lib; - if (argv.length < 1) { - System.err.println("Missing argument"); - System.exit(77); - } - try { - lib = Class.forName(argv[0]); - } catch (ClassNotFoundException e) { - System.err.println("ClassNotFoundException"); - System.exit(1); - } - lib = null; - System.exit(0); - } -} -''' - -@feature('javac') -@before_method('process_source') -def apply_java(self): - """ - Create a javac task for compiling *.java files*. There can be - only one javac task by task generator. - """ - Utils.def_attrs(self, jarname='', classpath='', - sourcepath='.', srcdir='.', - jar_mf_attributes={}, jar_mf_classpath=[]) - - outdir = getattr(self, 'outdir', None) - if outdir: - if not isinstance(outdir, Node.Node): - outdir = self.path.get_bld().make_node(self.outdir) - else: - outdir = self.path.get_bld() - outdir.mkdir() - self.outdir = outdir - self.env.OUTDIR = outdir.abspath() - - self.javac_task = tsk = self.create_task('javac') - tmp = [] - - srcdir = getattr(self, 'srcdir', '') - if isinstance(srcdir, Node.Node): - srcdir = [srcdir] - for x in Utils.to_list(srcdir): - if isinstance(x, Node.Node): - y = x - else: - y = self.path.find_dir(x) - if not y: - self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) - tmp.append(y) - - tsk.srcdir = tmp - - if getattr(self, 'compat', None): - tsk.env.append_value('JAVACFLAGS', ['-source', str(self.compat)]) - - if hasattr(self, 'sourcepath'): - fold = [isinstance(x, Node.Node) and x or self.path.find_dir(x) for x in self.to_list(self.sourcepath)] - names = os.pathsep.join([x.srcpath() for x in fold]) - else: - names = [x.srcpath() for x in tsk.srcdir] - - if names: - tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) - - -@taskgen_method -def java_use_rec(self, name, **kw): - """ - Processes recursively the *use* attribute for each referred java compilation - """ - if name in self.tmp_use_seen: - return - - self.tmp_use_seen.append(name) - - try: - y = self.bld.get_tgen_by_name(name) - except Errors.WafError: - self.uselib.append(name) - return - else: - y.post() - # Add generated JAR name for CLASSPATH. Task ordering (set_run_after) - # is already guaranteed by ordering done between the single tasks - if hasattr(y, 'jar_task'): - self.use_lst.append(y.jar_task.outputs[0].abspath()) - - for x in self.to_list(getattr(y, 'use', [])): - self.java_use_rec(x) - -@feature('javac') -@before_method('propagate_uselib_vars') -@after_method('apply_java') -def use_javac_files(self): - """ - Processes the *use* attribute referring to other java compilations - """ - self.use_lst = [] - self.tmp_use_seen = [] - self.uselib = self.to_list(getattr(self, 'uselib', [])) - names = self.to_list(getattr(self, 'use', [])) - get = self.bld.get_tgen_by_name - for x in names: - try: - y = get(x) - except Errors.WafError: - self.uselib.append(x) - else: - y.post() - if hasattr(y, 'jar_task'): - self.use_lst.append(y.jar_task.outputs[0].abspath()) - self.javac_task.set_run_after(y.jar_task) - else: - for tsk in y.tasks: - self.javac_task.set_run_after(tsk) - - # If recurse use scan is enabled recursively add use attribute for each used one - if getattr(self, 'recurse_use', False) or self.bld.env.RECURSE_JAVA: - self.java_use_rec(x) - - self.env.append_value('CLASSPATH', self.use_lst) - -@feature('javac') -@after_method('apply_java', 'propagate_uselib_vars', 'use_javac_files') -def set_classpath(self): - """ - Sets the CLASSPATH value on the *javac* task previously created. - """ - if getattr(self, 'classpath', None): - self.env.append_unique('CLASSPATH', getattr(self, 'classpath', [])) - for x in self.tasks: - x.env.CLASSPATH = os.pathsep.join(self.env.CLASSPATH) + os.pathsep - -@feature('jar') -@after_method('apply_java', 'use_javac_files') -@before_method('process_source') -def jar_files(self): - """ - Creates a jar task (one maximum per task generator) - """ - destfile = getattr(self, 'destfile', 'test.jar') - jaropts = getattr(self, 'jaropts', []) - manifest = getattr(self, 'manifest', None) - - basedir = getattr(self, 'basedir', None) - if basedir: - if not isinstance(self.basedir, Node.Node): - basedir = self.path.get_bld().make_node(basedir) - else: - basedir = self.path.get_bld() - if not basedir: - self.bld.fatal('Could not find the basedir %r for %r' % (self.basedir, self)) - - self.jar_task = tsk = self.create_task('jar_create') - if manifest: - jarcreate = getattr(self, 'jarcreate', 'cfm') - if not isinstance(manifest,Node.Node): - node = self.path.find_resource(manifest) - else: - node = manifest - if not node: - self.bld.fatal('invalid manifest file %r for %r' % (manifest, self)) - tsk.dep_nodes.append(node) - jaropts.insert(0, node.abspath()) - else: - jarcreate = getattr(self, 'jarcreate', 'cf') - if not isinstance(destfile, Node.Node): - destfile = self.path.find_or_declare(destfile) - if not destfile: - self.bld.fatal('invalid destfile %r for %r' % (destfile, self)) - tsk.set_outputs(destfile) - tsk.basedir = basedir - - jaropts.append('-C') - jaropts.append(basedir.bldpath()) - jaropts.append('.') - - tsk.env.JAROPTS = jaropts - tsk.env.JARCREATE = jarcreate - - if getattr(self, 'javac_task', None): - tsk.set_run_after(self.javac_task) - -@feature('jar') -@after_method('jar_files') -def use_jar_files(self): - """ - Processes the *use* attribute to set the build order on the - tasks created by another task generator. - """ - self.uselib = self.to_list(getattr(self, 'uselib', [])) - names = self.to_list(getattr(self, 'use', [])) - get = self.bld.get_tgen_by_name - for x in names: - try: - y = get(x) - except Errors.WafError: - self.uselib.append(x) - else: - y.post() - self.jar_task.run_after.update(y.tasks) - -class JTask(Task.Task): - """ - Base class for java and jar tasks; provides functionality to run long commands - """ - def split_argfile(self, cmd): - inline = [cmd[0]] - infile = [] - for x in cmd[1:]: - # jar and javac do not want -J flags in @file - if x.startswith('-J'): - inline.append(x) - else: - infile.append(self.quote_flag(x)) - return (inline, infile) - -class jar_create(JTask): - """ - Creates a jar file - """ - color = 'GREEN' - run_str = '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}' - - def runnable_status(self): - """ - Wait for dependent tasks to be executed, then read the - files to update the list of inputs. - """ - for t in self.run_after: - if not t.hasrun: - return Task.ASK_LATER - if not self.inputs: - try: - self.inputs = [x for x in self.basedir.ant_glob(JAR_RE, remove=False, quiet=True) if id(x) != id(self.outputs[0])] - except Exception: - raise Errors.WafError('Could not find the basedir %r for %r' % (self.basedir, self)) - return super(jar_create, self).runnable_status() - -class javac(JTask): - """ - Compiles java files - """ - color = 'BLUE' - run_str = '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}' - vars = ['CLASSPATH', 'JAVACFLAGS', 'JAVAC', 'OUTDIR'] - """ - The javac task will be executed again if the variables CLASSPATH, JAVACFLAGS, JAVAC or OUTDIR change. - """ - def uid(self): - """Identify java tasks by input&output folder""" - lst = [self.__class__.__name__, self.generator.outdir.abspath()] - for x in self.srcdir: - lst.append(x.abspath()) - return Utils.h_list(lst) - - def runnable_status(self): - """ - Waits for dependent tasks to be complete, then read the file system to find the input nodes. - """ - for t in self.run_after: - if not t.hasrun: - return Task.ASK_LATER - - if not self.inputs: - self.inputs = [] - for x in self.srcdir: - if x.exists(): - self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False, quiet=True)) - return super(javac, self).runnable_status() - - def post_run(self): - """ - List class files created - """ - for node in self.generator.outdir.ant_glob('**/*.class', quiet=True): - self.generator.bld.node_sigs[node] = self.uid() - self.generator.bld.task_sigs[self.uid()] = self.cache_sig - -@feature('javadoc') -@after_method('process_rule') -def create_javadoc(self): - """ - Creates a javadoc task (feature 'javadoc') - """ - tsk = self.create_task('javadoc') - tsk.classpath = getattr(self, 'classpath', []) - self.javadoc_package = Utils.to_list(self.javadoc_package) - if not isinstance(self.javadoc_output, Node.Node): - self.javadoc_output = self.bld.path.find_or_declare(self.javadoc_output) - -class javadoc(Task.Task): - """ - Builds java documentation - """ - color = 'BLUE' - - def __str__(self): - return '%s: %s -> %s\n' % (self.__class__.__name__, self.generator.srcdir, self.generator.javadoc_output) - - def run(self): - env = self.env - bld = self.generator.bld - wd = bld.bldnode - - #add src node + bld node (for generated java code) - srcpath = self.generator.path.abspath() + os.sep + self.generator.srcdir - srcpath += os.pathsep - srcpath += self.generator.path.get_bld().abspath() + os.sep + self.generator.srcdir - - classpath = env.CLASSPATH - classpath += os.pathsep - classpath += os.pathsep.join(self.classpath) - classpath = "".join(classpath) - - self.last_cmd = lst = [] - lst.extend(Utils.to_list(env.JAVADOC)) - lst.extend(['-d', self.generator.javadoc_output.abspath()]) - lst.extend(['-sourcepath', srcpath]) - lst.extend(['-classpath', classpath]) - lst.extend(['-subpackages']) - lst.extend(self.generator.javadoc_package) - lst = [x for x in lst if x] - - self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) - - def post_run(self): - nodes = self.generator.javadoc_output.ant_glob('**', quiet=True) - for node in nodes: - self.generator.bld.node_sigs[node] = self.uid() - self.generator.bld.task_sigs[self.uid()] = self.cache_sig - -def configure(self): - """ - Detects the javac, java and jar programs - """ - # If JAVA_PATH is set, we prepend it to the path list - java_path = self.environ['PATH'].split(os.pathsep) - v = self.env - - if 'JAVA_HOME' in self.environ: - java_path = [os.path.join(self.environ['JAVA_HOME'], 'bin')] + java_path - self.env.JAVA_HOME = [self.environ['JAVA_HOME']] - - for x in 'javac java jar javadoc'.split(): - self.find_program(x, var=x.upper(), path_list=java_path) - - if 'CLASSPATH' in self.environ: - v.CLASSPATH = self.environ['CLASSPATH'] - - if not v.JAR: - self.fatal('jar is required for making java packages') - if not v.JAVAC: - self.fatal('javac is required for compiling java classes') - - v.JARCREATE = 'cf' # can use cvf - v.JAVACFLAGS = [] - -@conf -def check_java_class(self, classname, with_classpath=None): - """ - Checks if the specified java class exists - - :param classname: class to check, like java.util.HashMap - :type classname: string - :param with_classpath: additional classpath to give - :type with_classpath: string - """ - javatestdir = '.waf-javatest' - - classpath = javatestdir - if self.env.CLASSPATH: - classpath += os.pathsep + self.env.CLASSPATH - if isinstance(with_classpath, str): - classpath += os.pathsep + with_classpath - - shutil.rmtree(javatestdir, True) - os.mkdir(javatestdir) - - Utils.writef(os.path.join(javatestdir, 'Test.java'), class_check_source) - - # Compile the source - self.exec_command(self.env.JAVAC + [os.path.join(javatestdir, 'Test.java')], shell=False) - - # Try to run the app - cmd = self.env.JAVA + ['-cp', classpath, 'Test', classname] - self.to_log("%s\n" % str(cmd)) - found = self.exec_command(cmd, shell=False) - - self.msg('Checking for java class %s' % classname, not found) - - shutil.rmtree(javatestdir, True) - - return found - -@conf -def check_jni_headers(conf): - """ - Checks for jni headers and libraries. On success the conf.env variables xxx_JAVA are added for use in C/C++ targets:: - - def options(opt): - opt.load('compiler_c') - - def configure(conf): - conf.load('compiler_c java') - conf.check_jni_headers() - - def build(bld): - bld.shlib(source='a.c', target='app', use='JAVA') - """ - if not conf.env.CC_NAME and not conf.env.CXX_NAME: - conf.fatal('load a compiler first (gcc, g++, ..)') - - if not conf.env.JAVA_HOME: - conf.fatal('set JAVA_HOME in the system environment') - - # jni requires the jvm - javaHome = conf.env.JAVA_HOME[0] - - dir = conf.root.find_dir(conf.env.JAVA_HOME[0] + '/include') - if dir is None: - dir = conf.root.find_dir(conf.env.JAVA_HOME[0] + '/../Headers') # think different?! - if dir is None: - conf.fatal('JAVA_HOME does not seem to be set properly') - - f = dir.ant_glob('**/(jni|jni_md).h') - incDirs = [x.parent.abspath() for x in f] - - dir = conf.root.find_dir(conf.env.JAVA_HOME[0]) - f = dir.ant_glob('**/*jvm.(so|dll|dylib)') - libDirs = [x.parent.abspath() for x in f] or [javaHome] - - # On windows, we need both the .dll and .lib to link. On my JDK, they are - # in different directories... - f = dir.ant_glob('**/*jvm.(lib)') - if f: - libDirs = [[x, y.parent.abspath()] for x in libDirs for y in f] - - if conf.env.DEST_OS == 'freebsd': - conf.env.append_unique('LINKFLAGS_JAVA', '-pthread') - for d in libDirs: - try: - conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm', - libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA') - except Exception: - pass - else: - break - else: - conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) - diff --git a/waflib/Tools/ldc2.py b/waflib/Tools/ldc2.py deleted file mode 100644 index a51c344..0000000 --- a/waflib/Tools/ldc2.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Alex Rønne Petersen, 2012 (alexrp/Zor) - -from waflib.Tools import ar, d -from waflib.Configure import conf - -@conf -def find_ldc2(conf): - """ - Finds the program *ldc2* and set the variable *D* - """ - conf.find_program(['ldc2'], var='D') - - out = conf.cmd_and_log(conf.env.D + ['-version']) - if out.find("based on DMD v2.") == -1: - conf.fatal("detected compiler is not ldc2") - -@conf -def common_flags_ldc2(conf): - """ - Sets the D flags required by *ldc2* - """ - v = conf.env - - v.D_SRC_F = ['-c'] - v.D_TGT_F = '-of%s' - - v.D_LINKER = v.D - v.DLNK_SRC_F = '' - v.DLNK_TGT_F = '-of%s' - v.DINC_ST = '-I%s' - - v.DSHLIB_MARKER = v.DSTLIB_MARKER = '' - v.DSTLIB_ST = v.DSHLIB_ST = '-L-l%s' - v.DSTLIBPATH_ST = v.DLIBPATH_ST = '-L-L%s' - - v.LINKFLAGS_dshlib = ['-L-shared'] - - v.DHEADER_ext = '.di' - v.DFLAGS_d_with_header = ['-H', '-Hf'] - v.D_HDR_F = '%s' - - v.LINKFLAGS = [] - v.DFLAGS_dshlib = ['-relocation-model=pic'] - -def configure(conf): - """ - Configuration for *ldc2* - """ - conf.find_ldc2() - conf.load('ar') - conf.load('d') - conf.common_flags_ldc2() - conf.d_platform_flags() - diff --git a/waflib/Tools/lua.py b/waflib/Tools/lua.py deleted file mode 100644 index 15a333a..0000000 --- a/waflib/Tools/lua.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Sebastian Schlingmann, 2008 -# Thomas Nagy, 2008-2018 (ita) - -""" -Lua support. - -Compile *.lua* files into *.luac*:: - - def configure(conf): - conf.load('lua') - conf.env.LUADIR = '/usr/local/share/myapp/scripts/' - def build(bld): - bld(source='foo.lua') -""" - -from waflib.TaskGen import extension -from waflib import Task - -@extension('.lua') -def add_lua(self, node): - tsk = self.create_task('luac', node, node.change_ext('.luac')) - inst_to = getattr(self, 'install_path', self.env.LUADIR and '${LUADIR}' or None) - if inst_to: - self.add_install_files(install_to=inst_to, install_from=tsk.outputs) - return tsk - -class luac(Task.Task): - run_str = '${LUAC} -s -o ${TGT} ${SRC}' - color = 'PINK' - -def configure(conf): - """ - Detect the luac compiler and set *conf.env.LUAC* - """ - conf.find_program('luac', var='LUAC') - diff --git a/waflib/Tools/md5_tstamp.py b/waflib/Tools/md5_tstamp.py deleted file mode 100644 index 2a58792..0000000 --- a/waflib/Tools/md5_tstamp.py +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 - -""" -Re-calculate md5 hashes of files only when the file time have changed. - -The hashes can also reflect either the file contents (STRONGEST=True) or the -file time and file size. - -The performance benefits of this module are usually insignificant. -""" - -import os, stat -from waflib import Utils, Build, Node - -STRONGEST = True - -Build.SAVED_ATTRS.append('hashes_md5_tstamp') -def h_file(self): - filename = self.abspath() - st = os.stat(filename) - - cache = self.ctx.hashes_md5_tstamp - if filename in cache and cache[filename][0] == st.st_mtime: - return cache[filename][1] - - if STRONGEST: - ret = Utils.h_file(filename) - else: - if stat.S_ISDIR(st[stat.ST_MODE]): - raise IOError('Not a file') - ret = Utils.md5(str((st.st_mtime, st.st_size)).encode()).digest() - - cache[filename] = (st.st_mtime, ret) - return ret -h_file.__doc__ = Node.Node.h_file.__doc__ -Node.Node.h_file = h_file - diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py deleted file mode 100644 index ff58449..0000000 --- a/waflib/Tools/msvc.py +++ /dev/null @@ -1,1020 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Carlos Rafael Giani, 2006 (dv) -# Tamas Pal, 2007 (folti) -# Nicolas Mercier, 2009 -# Matt Clarkson, 2012 - -""" -Microsoft Visual C++/Intel C++ compiler support - -If you get detection problems, first try any of the following:: - - chcp 65001 - set PYTHONIOENCODING=... - set PYTHONLEGACYWINDOWSSTDIO=1 - -Usage:: - - $ waf configure --msvc_version="msvc 10.0,msvc 9.0" --msvc_target="x64" - -or:: - - def configure(conf): - conf.env.MSVC_VERSIONS = ['msvc 10.0', 'msvc 9.0', 'msvc 8.0', 'msvc 7.1', 'msvc 7.0', 'msvc 6.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0'] - conf.env.MSVC_TARGETS = ['x64'] - conf.load('msvc') - -or:: - - def configure(conf): - conf.load('msvc', funs='no_autodetect') - conf.check_lib_msvc('gdi32') - conf.check_libs_msvc('kernel32 user32') - def build(bld): - tg = bld.program(source='main.c', target='app', use='KERNEL32 USER32 GDI32') - -Platforms and targets will be tested in the order they appear; -the first good configuration will be used. - -To force testing all the configurations that are not used, use the ``--no-msvc-lazy`` option -or set ``conf.env.MSVC_LAZY_AUTODETECT=False``. - -Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64, x86_arm, amd64_x86, amd64_arm - -Compilers supported: - -* msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 15 (Visual Studio 2017) -* wsdk => Windows SDK, versions 6.0, 6.1, 7.0, 7.1, 8.0 -* icl => Intel compiler, versions 9, 10, 11, 13 -* winphone => Visual Studio to target Windows Phone 8 native (version 8.0 for now) -* Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i) -* PocketPC => Compiler/SDK for PocketPC devices (armv4/v4i) - -To use WAF in a VS2008 Make file project (see http://code.google.com/p/waf/issues/detail?id=894) -You may consider to set the environment variable "VS_UNICODE_OUTPUT" to nothing before calling waf. -So in your project settings use something like 'cmd.exe /C "set VS_UNICODE_OUTPUT=& set PYTHONUNBUFFERED=true & waf build"'. -cmd.exe /C "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf configure" -Setting PYTHONUNBUFFERED gives the unbuffered output. -""" - -import os, sys, re, traceback -from waflib import Utils, Logs, Options, Errors -from waflib.TaskGen import after_method, feature - -from waflib.Configure import conf -from waflib.Tools import ccroot, c, cxx, ar - -g_msvc_systemlibs = ''' -aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet -cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs -credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d -ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp -faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid -gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop -kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi -mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree -msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm -netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp -odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 -osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu -ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm -rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 -shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 -traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg -version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm -wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp -'''.split() -"""importlibs provided by MSVC/Platform SDK. Do NOT search them""" - -all_msvc_platforms = [ ('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'), - ('x86_amd64', 'amd64'), ('x86_ia64', 'ia64'), ('x86_arm', 'arm'), ('x86_arm64', 'arm64'), - ('amd64_x86', 'x86'), ('amd64_arm', 'arm'), ('amd64_arm64', 'arm64') ] -"""List of msvc platforms""" - -all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ] -"""List of wince platforms""" - -all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] -"""List of icl platforms""" - -def options(opt): - opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='') - opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') - opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy') - -@conf -def setup_msvc(conf, versiondict): - """ - Checks installed compilers and targets and returns the first combination from the user's - options, env, or the global supported lists that checks. - - :param versiondict: dict(platform -> dict(architecture -> configuration)) - :type versiondict: dict(string -> dict(string -> target_compiler) - :return: the compiler, revision, path, include dirs, library paths and target architecture - :rtype: tuple of strings - """ - platforms = getattr(Options.options, 'msvc_targets', '').split(',') - if platforms == ['']: - platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] - desired_versions = getattr(Options.options, 'msvc_version', '').split(',') - if desired_versions == ['']: - desired_versions = conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys()))) - - # Override lazy detection by evaluating after the fact. - lazy_detect = getattr(Options.options, 'msvc_lazy', True) - if conf.env.MSVC_LAZY_AUTODETECT is False: - lazy_detect = False - - if not lazy_detect: - for val in versiondict.values(): - for arch in list(val.keys()): - cfg = val[arch] - cfg.evaluate() - if not cfg.is_valid: - del val[arch] - conf.env.MSVC_INSTALLED_VERSIONS = versiondict - - for version in desired_versions: - Logs.debug('msvc: detecting %r - %r', version, desired_versions) - try: - targets = versiondict[version] - except KeyError: - continue - - seen = set() - for arch in platforms: - if arch in seen: - continue - else: - seen.add(arch) - try: - cfg = targets[arch] - except KeyError: - continue - - cfg.evaluate() - if cfg.is_valid: - compiler,revision = version.rsplit(' ', 1) - return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu - conf.fatal('msvc: Impossible to find a valid architecture for building %r - %r' % (desired_versions, list(versiondict.keys()))) - -@conf -def get_msvc_version(conf, compiler, version, target, vcvars): - """ - Checks that an installed compiler actually runs and uses vcvars to obtain the - environment needed by the compiler. - - :param compiler: compiler type, for looking up the executable name - :param version: compiler version, for debugging only - :param target: target architecture - :param vcvars: batch file to run to check the environment - :return: the location of the compiler executable, the location of include dirs, and the library paths - :rtype: tuple of strings - """ - Logs.debug('msvc: get_msvc_version: %r %r %r', compiler, version, target) - - try: - conf.msvc_cnt += 1 - except AttributeError: - conf.msvc_cnt = 1 - batfile = conf.bldnode.make_node('waf-print-msvc-%d.bat' % conf.msvc_cnt) - batfile.write("""@echo off -set INCLUDE= -set LIB= -call "%s" %s -echo PATH=%%PATH%% -echo INCLUDE=%%INCLUDE%% -echo LIB=%%LIB%%;%%LIBPATH%% -""" % (vcvars,target)) - sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()]) - lines = sout.splitlines() - - if not lines[0]: - lines.pop(0) - - MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None - for line in lines: - if line.startswith('PATH='): - path = line[5:] - MSVC_PATH = path.split(';') - elif line.startswith('INCLUDE='): - MSVC_INCDIR = [i for i in line[8:].split(';') if i] - elif line.startswith('LIB='): - MSVC_LIBDIR = [i for i in line[4:].split(';') if i] - if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR): - conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)') - - # Check if the compiler is usable at all. - # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run. - env = dict(os.environ) - env.update(PATH = path) - compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) - cxx = conf.find_program(compiler_name, path_list=MSVC_PATH) - - # delete CL if exists. because it could contain parameters which can change cl's behaviour rather catastrophically. - if 'CL' in env: - del(env['CL']) - - try: - conf.cmd_and_log(cxx + ['/help'], env=env) - except UnicodeError: - st = traceback.format_exc() - if conf.logger: - conf.logger.error(st) - conf.fatal('msvc: Unicode error - check the code page?') - except Exception as e: - Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s', compiler, version, target, str(e)) - conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)') - else: - Logs.debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target) - finally: - conf.env[compiler_name] = '' - - return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) - -def gather_wince_supported_platforms(): - """ - Checks SmartPhones SDKs - - :param versions: list to modify - :type versions: list - """ - supported_wince_platforms = [] - try: - ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') - except OSError: - try: - ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') - except OSError: - ce_sdk = '' - if not ce_sdk: - return supported_wince_platforms - - index = 0 - while 1: - try: - sdk_device = Utils.winreg.EnumKey(ce_sdk, index) - sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device) - except OSError: - break - index += 1 - try: - path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir') - except OSError: - try: - path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation') - except OSError: - continue - path,xml = os.path.split(path) - path = str(path) - path,device = os.path.split(path) - if not device: - path,device = os.path.split(path) - platforms = [] - for arch,compiler in all_wince_platforms: - if os.path.isdir(os.path.join(path, device, 'Lib', arch)): - platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch))) - if platforms: - supported_wince_platforms.append((device, platforms)) - return supported_wince_platforms - -def gather_msvc_detected_versions(): - #Detected MSVC versions! - version_pattern = re.compile(r'^(\d\d?\.\d\d?)(Exp)?$') - detected_versions = [] - for vcver,vcvar in (('VCExpress','Exp'), ('VisualStudio','')): - prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) - except OSError: - prefix = 'SOFTWARE\\Microsoft\\' + vcver - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) - except OSError: - continue - - index = 0 - while 1: - try: - version = Utils.winreg.EnumKey(all_versions, index) - except OSError: - break - index += 1 - match = version_pattern.match(version) - if match: - versionnumber = float(match.group(1)) - else: - continue - detected_versions.append((versionnumber, version+vcvar, prefix+'\\'+version)) - def fun(tup): - return tup[0] - - detected_versions.sort(key = fun) - return detected_versions - -class target_compiler(object): - """ - Wrap a compiler configuration; call evaluate() to determine - whether the configuration is usable. - """ - def __init__(self, ctx, compiler, cpu, version, bat_target, bat, callback=None): - """ - :param ctx: configuration context to use to eventually get the version environment - :param compiler: compiler name - :param cpu: target cpu - :param version: compiler version number - :param bat_target: ? - :param bat: path to the batch file to run - """ - self.conf = ctx - self.name = None - self.is_valid = False - self.is_done = False - - self.compiler = compiler - self.cpu = cpu - self.version = version - self.bat_target = bat_target - self.bat = bat - self.callback = callback - - def evaluate(self): - if self.is_done: - return - self.is_done = True - try: - vs = self.conf.get_msvc_version(self.compiler, self.version, self.bat_target, self.bat) - except Errors.ConfigurationError: - self.is_valid = False - return - if self.callback: - vs = self.callback(self, vs) - self.is_valid = True - (self.bindirs, self.incdirs, self.libdirs) = vs - - def __str__(self): - return str((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) - - def __repr__(self): - return repr((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) - -@conf -def gather_wsdk_versions(conf, versions): - """ - Use winreg to add the msvc versions to the input list - - :param versions: list to modify - :type versions: list - """ - version_pattern = re.compile(r'^v..?.?\...?.?') - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') - except OSError: - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') - except OSError: - return - index = 0 - while 1: - try: - version = Utils.winreg.EnumKey(all_versions, index) - except OSError: - break - index += 1 - if not version_pattern.match(version): - continue - try: - msvc_version = Utils.winreg.OpenKey(all_versions, version) - path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') - except OSError: - continue - if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): - targets = {} - for target,arch in all_msvc_platforms: - targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')) - versions['wsdk ' + version[1:]] = targets - -@conf -def gather_msvc_targets(conf, versions, version, vc_path): - #Looking for normal MSVC compilers! - targets = {} - - if os.path.isfile(os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat')): - for target,realtarget in all_msvc_platforms[::-1]: - targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat')) - elif os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')): - for target,realtarget in all_msvc_platforms[::-1]: - targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'vcvarsall.bat')) - elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')): - targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')) - elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')): - targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat')) - if targets: - versions['msvc %s' % version] = targets - -@conf -def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms): - #Looking for Win CE compilers! - for device,platforms in supported_platforms: - targets = {} - for platform,compiler,include,lib in platforms: - winCEpath = os.path.join(vc_path, 'ce') - if not os.path.isdir(winCEpath): - continue - - if os.path.isdir(os.path.join(winCEpath, 'lib', platform)): - bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)] - incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include] - libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib] - def combine_common(obj, compiler_env): - # TODO this is likely broken, remove in waf 2.1 - (common_bindirs,_1,_2) = compiler_env - return (bindirs + common_bindirs, incdirs, libdirs) - targets[platform] = target_compiler(conf, 'msvc', platform, version, 'x86', vsvars, combine_common) - if targets: - versions[device + ' ' + version] = targets - -@conf -def gather_winphone_targets(conf, versions, version, vc_path, vsvars): - #Looking for WinPhone compilers - targets = {} - for target,realtarget in all_msvc_platforms[::-1]: - targets[target] = target_compiler(conf, 'winphone', realtarget, version, target, vsvars) - if targets: - versions['winphone ' + version] = targets - -@conf -def gather_vswhere_versions(conf, versions): - try: - import json - except ImportError: - Logs.error('Visual Studio 2017 detection requires Python 2.6') - return - - prg_path = os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files (x86)')) - - vswhere = os.path.join(prg_path, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe') - args = [vswhere, '-products', '*', '-legacy', '-format', 'json'] - try: - txt = conf.cmd_and_log(args) - except Errors.WafError as e: - Logs.debug('msvc: vswhere.exe failed %s', e) - return - - if sys.version_info[0] < 3: - txt = txt.decode(Utils.console_encoding()) - - arr = json.loads(txt) - arr.sort(key=lambda x: x['installationVersion']) - for entry in arr: - ver = entry['installationVersion'] - ver = str('.'.join(ver.split('.')[:2])) - path = str(os.path.abspath(entry['installationPath'])) - if os.path.exists(path) and ('msvc %s' % ver) not in versions: - conf.gather_msvc_targets(versions, ver, path) - -@conf -def gather_msvc_versions(conf, versions): - vc_paths = [] - for (v,version,reg) in gather_msvc_detected_versions(): - try: - try: - msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC") - except OSError: - msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++") - path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir') - except OSError: - try: - msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7") - path,type = Utils.winreg.QueryValueEx(msvc_version, version) - except OSError: - continue - else: - vc_paths.append((version, os.path.abspath(str(path)))) - continue - else: - vc_paths.append((version, os.path.abspath(str(path)))) - - wince_supported_platforms = gather_wince_supported_platforms() - - for version,vc_path in vc_paths: - vs_path = os.path.dirname(vc_path) - vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat') - if wince_supported_platforms and os.path.isfile(vsvars): - conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms) - - # WP80 works with 11.0Exp and 11.0, both of which resolve to the same vc_path. - # Stop after one is found. - for version,vc_path in vc_paths: - vs_path = os.path.dirname(vc_path) - vsvars = os.path.join(vs_path, 'VC', 'WPSDK', 'WP80', 'vcvarsphoneall.bat') - if os.path.isfile(vsvars): - conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars) - break - - for version,vc_path in vc_paths: - vs_path = os.path.dirname(vc_path) - conf.gather_msvc_targets(versions, version, vc_path) - -@conf -def gather_icl_versions(conf, versions): - """ - Checks ICL compilers - - :param versions: list to modify - :type versions: list - """ - version_pattern = re.compile(r'^...?.?\....?.?') - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') - except OSError: - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') - except OSError: - return - index = 0 - while 1: - try: - version = Utils.winreg.EnumKey(all_versions, index) - except OSError: - break - index += 1 - if not version_pattern.match(version): - continue - targets = {} - for target,arch in all_icl_platforms: - if target=='intel64': - targetDir='EM64T_NATIVE' - else: - targetDir=target - try: - Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) - icl_version=Utils.winreg.OpenKey(all_versions,version) - path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except OSError: - pass - else: - batch_file=os.path.join(path,'bin','iclvars.bat') - if os.path.isfile(batch_file): - targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) - for target,arch in all_icl_platforms: - try: - icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) - path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except OSError: - continue - else: - batch_file=os.path.join(path,'bin','iclvars.bat') - if os.path.isfile(batch_file): - targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) - major = version[0:2] - versions['intel ' + major] = targets - -@conf -def gather_intel_composer_versions(conf, versions): - """ - Checks ICL compilers that are part of Intel Composer Suites - - :param versions: list to modify - :type versions: list - """ - version_pattern = re.compile(r'^...?.?\...?.?.?') - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites') - except OSError: - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites') - except OSError: - return - index = 0 - while 1: - try: - version = Utils.winreg.EnumKey(all_versions, index) - except OSError: - break - index += 1 - if not version_pattern.match(version): - continue - targets = {} - for target,arch in all_icl_platforms: - if target=='intel64': - targetDir='EM64T_NATIVE' - else: - targetDir=target - try: - try: - defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir) - except OSError: - if targetDir == 'EM64T_NATIVE': - defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T') - else: - raise - uid,type = Utils.winreg.QueryValueEx(defaults, 'SubKey') - Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir) - icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++') - path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except OSError: - pass - else: - batch_file=os.path.join(path,'bin','iclvars.bat') - if os.path.isfile(batch_file): - targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) - # The intel compilervar_arch.bat is broken when used with Visual Studio Express 2012 - # http://software.intel.com/en-us/forums/topic/328487 - compilervars_warning_attr = '_compilervars_warning_key' - if version[0:2] == '13' and getattr(conf, compilervars_warning_attr, True): - setattr(conf, compilervars_warning_attr, False) - patch_url = 'http://software.intel.com/en-us/forums/topic/328487' - compilervars_arch = os.path.join(path, 'bin', 'compilervars_arch.bat') - for vscomntool in ('VS110COMNTOOLS', 'VS100COMNTOOLS'): - if vscomntool in os.environ: - vs_express_path = os.environ[vscomntool] + r'..\IDE\VSWinExpress.exe' - dev_env_path = os.environ[vscomntool] + r'..\IDE\devenv.exe' - if (r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"' in Utils.readf(compilervars_arch) and - not os.path.exists(vs_express_path) and not os.path.exists(dev_env_path)): - Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU ' - '(VSWinExpress.exe) but it does not seem to be installed at %r. ' - 'The intel command line set up will fail to configure unless the file %r' - 'is patched. See: %s') % (vs_express_path, compilervars_arch, patch_url)) - major = version[0:2] - versions['intel ' + major] = targets - -@conf -def detect_msvc(self): - return self.setup_msvc(self.get_msvc_versions()) - -@conf -def get_msvc_versions(self): - """ - :return: platform to compiler configurations - :rtype: dict - """ - dct = Utils.ordered_iter_dict() - self.gather_icl_versions(dct) - self.gather_intel_composer_versions(dct) - self.gather_wsdk_versions(dct) - self.gather_msvc_versions(dct) - self.gather_vswhere_versions(dct) - Logs.debug('msvc: detected versions %r', list(dct.keys())) - return dct - -@conf -def find_lt_names_msvc(self, libname, is_static=False): - """ - Win32/MSVC specific code to glean out information from libtool la files. - this function is not attached to the task_gen class. Returns a triplet: - (library absolute path, library name without extension, whether the library is static) - """ - lt_names=[ - 'lib%s.la' % libname, - '%s.la' % libname, - ] - - for path in self.env.LIBPATH: - for la in lt_names: - laf=os.path.join(path,la) - dll=None - if os.path.exists(laf): - ltdict = Utils.read_la_file(laf) - lt_libdir=None - if ltdict.get('libdir', ''): - lt_libdir = ltdict['libdir'] - if not is_static and ltdict.get('library_names', ''): - dllnames=ltdict['library_names'].split() - dll=dllnames[0].lower() - dll=re.sub(r'\.dll$', '', dll) - return (lt_libdir, dll, False) - elif ltdict.get('old_library', ''): - olib=ltdict['old_library'] - if os.path.exists(os.path.join(path,olib)): - return (path, olib, True) - elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)): - return (lt_libdir, olib, True) - else: - return (None, olib, True) - else: - raise self.errors.WafError('invalid libtool object file: %s' % laf) - return (None, None, None) - -@conf -def libname_msvc(self, libname, is_static=False): - lib = libname.lower() - lib = re.sub(r'\.lib$','',lib) - - if lib in g_msvc_systemlibs: - return lib - - lib=re.sub('^lib','',lib) - - if lib == 'm': - return None - - (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static) - - if lt_path != None and lt_libname != None: - if lt_static: - # file existence check has been made by find_lt_names - return os.path.join(lt_path,lt_libname) - - if lt_path != None: - _libpaths = [lt_path] + self.env.LIBPATH - else: - _libpaths = self.env.LIBPATH - - static_libs=[ - 'lib%ss.lib' % lib, - 'lib%s.lib' % lib, - '%ss.lib' % lib, - '%s.lib' %lib, - ] - - dynamic_libs=[ - 'lib%s.dll.lib' % lib, - 'lib%s.dll.a' % lib, - '%s.dll.lib' % lib, - '%s.dll.a' % lib, - 'lib%s_d.lib' % lib, - '%s_d.lib' % lib, - '%s.lib' %lib, - ] - - libnames=static_libs - if not is_static: - libnames=dynamic_libs + static_libs - - for path in _libpaths: - for libn in libnames: - if os.path.exists(os.path.join(path, libn)): - Logs.debug('msvc: lib found: %s', os.path.join(path,libn)) - return re.sub(r'\.lib$', '',libn) - - #if no lib can be found, just return the libname as msvc expects it - self.fatal('The library %r could not be found' % libname) - return re.sub(r'\.lib$', '', libname) - -@conf -def check_lib_msvc(self, libname, is_static=False, uselib_store=None): - """ - Ideally we should be able to place the lib in the right env var, either STLIB or LIB, - but we don't distinguish static libs from shared libs. - This is ok since msvc doesn't have any special linker flag to select static libs (no env.STLIB_MARKER) - """ - libn = self.libname_msvc(libname, is_static) - - if not uselib_store: - uselib_store = libname.upper() - - if False and is_static: # disabled - self.env['STLIB_' + uselib_store] = [libn] - else: - self.env['LIB_' + uselib_store] = [libn] - -@conf -def check_libs_msvc(self, libnames, is_static=False): - for libname in Utils.to_list(libnames): - self.check_lib_msvc(libname, is_static) - -def configure(conf): - """ - Configuration methods to call for detecting msvc - """ - conf.autodetect(True) - conf.find_msvc() - conf.msvc_common_flags() - conf.cc_load_tools() - conf.cxx_load_tools() - conf.cc_add_flags() - conf.cxx_add_flags() - conf.link_add_flags() - conf.visual_studio_add_flags() - -@conf -def no_autodetect(conf): - conf.env.NO_MSVC_DETECT = 1 - configure(conf) - -@conf -def autodetect(conf, arch=False): - v = conf.env - if v.NO_MSVC_DETECT: - return - - compiler, version, path, includes, libdirs, cpu = conf.detect_msvc() - if arch: - v.DEST_CPU = cpu - - v.PATH = path - v.INCLUDES = includes - v.LIBPATH = libdirs - v.MSVC_COMPILER = compiler - try: - v.MSVC_VERSION = float(version) - except ValueError: - v.MSVC_VERSION = float(version[:-3]) - -def _get_prog_names(conf, compiler): - if compiler == 'intel': - compiler_name = 'ICL' - linker_name = 'XILINK' - lib_name = 'XILIB' - else: - # assumes CL.exe - compiler_name = 'CL' - linker_name = 'LINK' - lib_name = 'LIB' - return compiler_name, linker_name, lib_name - -@conf -def find_msvc(conf): - """Due to path format limitations, limit operation only to native Win32. Yeah it sucks.""" - if sys.platform == 'cygwin': - conf.fatal('MSVC module does not work under cygwin Python!') - - # the autodetection is supposed to be performed before entering in this method - v = conf.env - path = v.PATH - compiler = v.MSVC_COMPILER - version = v.MSVC_VERSION - - compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) - v.MSVC_MANIFEST = (compiler == 'msvc' and version >= 8) or (compiler == 'wsdk' and version >= 6) or (compiler == 'intel' and version >= 11) - - # compiler - cxx = conf.find_program(compiler_name, var='CXX', path_list=path) - - # before setting anything, check if the compiler is really msvc - env = dict(conf.environ) - if path: - env.update(PATH = ';'.join(path)) - if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env): - conf.fatal('the msvc compiler could not be identified') - - # c/c++ compiler - v.CC = v.CXX = cxx - v.CC_NAME = v.CXX_NAME = 'msvc' - - # linker - if not v.LINK_CXX: - conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name, var='LINK_CXX') - - if not v.LINK_CC: - v.LINK_CC = v.LINK_CXX - - # staticlib linker - if not v.AR: - stliblink = conf.find_program(lib_name, path_list=path, var='AR') - if not stliblink: - return - v.ARFLAGS = ['/nologo'] - - # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later - if v.MSVC_MANIFEST: - conf.find_program('MT', path_list=path, var='MT') - v.MTFLAGS = ['/nologo'] - - try: - conf.load('winres') - except Errors.ConfigurationError: - Logs.warn('Resource compiler not found. Compiling resource file is disabled') - -@conf -def visual_studio_add_flags(self): - """visual studio flags found in the system environment""" - v = self.env - if self.environ.get('INCLUDE'): - v.prepend_value('INCLUDES', [x for x in self.environ['INCLUDE'].split(';') if x]) # notice the 'S' - if self.environ.get('LIB'): - v.prepend_value('LIBPATH', [x for x in self.environ['LIB'].split(';') if x]) - -@conf -def msvc_common_flags(conf): - """ - Setup the flags required for executing the msvc compiler - """ - v = conf.env - - v.DEST_BINFMT = 'pe' - v.append_value('CFLAGS', ['/nologo']) - v.append_value('CXXFLAGS', ['/nologo']) - v.append_value('LINKFLAGS', ['/nologo']) - v.DEFINES_ST = '/D%s' - - v.CC_SRC_F = '' - v.CC_TGT_F = ['/c', '/Fo'] - v.CXX_SRC_F = '' - v.CXX_TGT_F = ['/c', '/Fo'] - - if (v.MSVC_COMPILER == 'msvc' and v.MSVC_VERSION >= 8) or (v.MSVC_COMPILER == 'wsdk' and v.MSVC_VERSION >= 6): - v.CC_TGT_F = ['/FC'] + v.CC_TGT_F - v.CXX_TGT_F = ['/FC'] + v.CXX_TGT_F - - v.CPPPATH_ST = '/I%s' # template for adding include paths - - v.AR_TGT_F = v.CCLNK_TGT_F = v.CXXLNK_TGT_F = '/OUT:' - - # CRT specific flags - v.CFLAGS_CRT_MULTITHREADED = v.CXXFLAGS_CRT_MULTITHREADED = ['/MT'] - v.CFLAGS_CRT_MULTITHREADED_DLL = v.CXXFLAGS_CRT_MULTITHREADED_DLL = ['/MD'] - - v.CFLAGS_CRT_MULTITHREADED_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DBG = ['/MTd'] - v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = ['/MDd'] - - v.LIB_ST = '%s.lib' - v.LIBPATH_ST = '/LIBPATH:%s' - v.STLIB_ST = '%s.lib' - v.STLIBPATH_ST = '/LIBPATH:%s' - - if v.MSVC_MANIFEST: - v.append_value('LINKFLAGS', ['/MANIFEST']) - - v.CFLAGS_cshlib = [] - v.CXXFLAGS_cxxshlib = [] - v.LINKFLAGS_cshlib = v.LINKFLAGS_cxxshlib = ['/DLL'] - v.cshlib_PATTERN = v.cxxshlib_PATTERN = '%s.dll' - v.implib_PATTERN = '%s.lib' - v.IMPLIB_ST = '/IMPLIB:%s' - - v.LINKFLAGS_cstlib = [] - v.cstlib_PATTERN = v.cxxstlib_PATTERN = '%s.lib' - - v.cprogram_PATTERN = v.cxxprogram_PATTERN = '%s.exe' - - v.def_PATTERN = '/def:%s' - - -####################################################################################################### -##### conf above, build below - -@after_method('apply_link') -@feature('c', 'cxx') -def apply_flags_msvc(self): - """ - Add additional flags implied by msvc, such as subsystems and pdb files:: - - def build(bld): - bld.stlib(source='main.c', target='bar', subsystem='gruik') - """ - if self.env.CC_NAME != 'msvc' or not getattr(self, 'link_task', None): - return - - is_static = isinstance(self.link_task, ccroot.stlink_task) - - subsystem = getattr(self, 'subsystem', '') - if subsystem: - subsystem = '/subsystem:%s' % subsystem - flags = is_static and 'ARFLAGS' or 'LINKFLAGS' - self.env.append_value(flags, subsystem) - - if not is_static: - for f in self.env.LINKFLAGS: - d = f.lower() - if d[1:] == 'debug': - pdbnode = self.link_task.outputs[0].change_ext('.pdb') - self.link_task.outputs.append(pdbnode) - - if getattr(self, 'install_task', None): - self.pdb_install_task = self.add_install_files( - install_to=self.install_task.install_to, install_from=pdbnode) - break - -@feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib') -@after_method('apply_link') -def apply_manifest(self): - """ - Special linker for MSVC with support for embedding manifests into DLL's - and executables compiled by Visual Studio 2005 or probably later. Without - the manifest file, the binaries are unusable. - See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx - """ - if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None): - out_node = self.link_task.outputs[0] - man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') - self.link_task.outputs.append(man_node) - self.env.DO_MANIFEST = True - -def make_winapp(self, family): - append = self.env.append_unique - append('DEFINES', 'WINAPI_FAMILY=%s' % family) - append('CXXFLAGS', ['/ZW', '/TP']) - for lib_path in self.env.LIBPATH: - append('CXXFLAGS','/AI%s'%lib_path) - -@feature('winphoneapp') -@after_method('process_use') -@after_method('propagate_uselib_vars') -def make_winphone_app(self): - """ - Insert configuration flags for windows phone applications (adds /ZW, /TP...) - """ - make_winapp(self, 'WINAPI_FAMILY_PHONE_APP') - self.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib']) - -@feature('winapp') -@after_method('process_use') -@after_method('propagate_uselib_vars') -def make_windows_app(self): - """ - Insert configuration flags for windows applications (adds /ZW, /TP...) - """ - make_winapp(self, 'WINAPI_FAMILY_DESKTOP_APP') diff --git a/waflib/Tools/nasm.py b/waflib/Tools/nasm.py deleted file mode 100644 index 411d582..0000000 --- a/waflib/Tools/nasm.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2008-2018 (ita) - -""" -Nasm tool (asm processing) -""" - -import os -import waflib.Tools.asm # leave this -from waflib.TaskGen import feature - -@feature('asm') -def apply_nasm_vars(self): - """provided for compatibility""" - self.env.append_value('ASFLAGS', self.to_list(getattr(self, 'nasm_flags', []))) - -def configure(conf): - """ - Detect nasm/yasm and set the variable *AS* - """ - conf.find_program(['nasm', 'yasm'], var='AS') - conf.env.AS_TGT_F = ['-o'] - conf.env.ASLNK_TGT_F = ['-o'] - conf.load('asm') - conf.env.ASMPATH_ST = '-I%s' + os.sep diff --git a/waflib/Tools/nobuild.py b/waflib/Tools/nobuild.py deleted file mode 100644 index 2e4b055..0000000 --- a/waflib/Tools/nobuild.py +++ /dev/null @@ -1,24 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2015 (ita) - -""" -Override the build commands to write empty files. -This is useful for profiling and evaluating the Python overhead. - -To use:: - - def build(bld): - ... - bld.load('nobuild') - -""" - -from waflib import Task -def build(bld): - def run(self): - for x in self.outputs: - x.write('') - for (name, cls) in Task.classes.items(): - cls.run = run - diff --git a/waflib/Tools/perl.py b/waflib/Tools/perl.py deleted file mode 100644 index 32b03fb..0000000 --- a/waflib/Tools/perl.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# andersg at 0x63.nu 2007 -# Thomas Nagy 2016-2018 (ita) - -""" -Support for Perl extensions. A C/C++ compiler is required:: - - def options(opt): - opt.load('compiler_c perl') - def configure(conf): - conf.load('compiler_c perl') - conf.check_perl_version((5,6,0)) - conf.check_perl_ext_devel() - conf.check_perl_module('Cairo') - conf.check_perl_module('Devel::PPPort 4.89') - def build(bld): - bld( - features = 'c cshlib perlext', - source = 'Mytest.xs', - target = 'Mytest', - install_path = '${ARCHDIR_PERL}/auto') - bld.install_files('${ARCHDIR_PERL}', 'Mytest.pm') -""" - -import os -from waflib import Task, Options, Utils, Errors -from waflib.Configure import conf -from waflib.TaskGen import extension, feature, before_method - -@before_method('apply_incpaths', 'apply_link', 'propagate_uselib_vars') -@feature('perlext') -def init_perlext(self): - """ - Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the - *lib* prefix from library names. - """ - self.uselib = self.to_list(getattr(self, 'uselib', [])) - if not 'PERLEXT' in self.uselib: - self.uselib.append('PERLEXT') - self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.perlext_PATTERN - -@extension('.xs') -def xsubpp_file(self, node): - """ - Create :py:class:`waflib.Tools.perl.xsubpp` tasks to process *.xs* files - """ - outnode = node.change_ext('.c') - self.create_task('xsubpp', node, outnode) - self.source.append(outnode) - -class xsubpp(Task.Task): - """ - Process *.xs* files - """ - run_str = '${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' - color = 'BLUE' - ext_out = ['.h'] - -@conf -def check_perl_version(self, minver=None): - """ - Check if Perl is installed, and set the variable PERL. - minver is supposed to be a tuple - """ - res = True - if minver: - cver = '.'.join(map(str,minver)) - else: - cver = '' - - self.start_msg('Checking for minimum perl version %s' % cver) - - perl = self.find_program('perl', var='PERL', value=getattr(Options.options, 'perlbinary', None)) - version = self.cmd_and_log(perl + ["-e", 'printf \"%vd\", $^V']) - if not version: - res = False - version = "Unknown" - elif not minver is None: - ver = tuple(map(int, version.split("."))) - if ver < minver: - res = False - - self.end_msg(version, color=res and 'GREEN' or 'YELLOW') - return res - -@conf -def check_perl_module(self, module): - """ - Check if specified perlmodule is installed. - - The minimum version can be specified by specifying it after modulename - like this:: - - def configure(conf): - conf.check_perl_module("Some::Module 2.92") - """ - cmd = self.env.PERL + ['-e', 'use %s' % module] - self.start_msg('perl module %s' % module) - try: - r = self.cmd_and_log(cmd) - except Errors.WafError: - self.end_msg(False) - return None - self.end_msg(r or True) - return r - -@conf -def check_perl_ext_devel(self): - """ - Check for configuration needed to build perl extensions. - - Sets different xxx_PERLEXT variables in the environment. - - Also sets the ARCHDIR_PERL variable useful as installation path, - which can be overridden by ``--with-perl-archdir`` option. - """ - - env = self.env - perl = env.PERL - if not perl: - self.fatal('find perl first') - - def cmd_perl_config(s): - return perl + ['-MConfig', '-e', 'print \"%s\"' % s] - def cfg_str(cfg): - return self.cmd_and_log(cmd_perl_config(cfg)) - def cfg_lst(cfg): - return Utils.to_list(cfg_str(cfg)) - def find_xsubpp(): - for var in ('privlib', 'vendorlib'): - xsubpp = cfg_lst('$Config{%s}/ExtUtils/xsubpp$Config{exe_ext}' % var) - if xsubpp and os.path.isfile(xsubpp[0]): - return xsubpp - return self.find_program('xsubpp') - - env.LINKFLAGS_PERLEXT = cfg_lst('$Config{lddlflags}') - env.INCLUDES_PERLEXT = cfg_lst('$Config{archlib}/CORE') - env.CFLAGS_PERLEXT = cfg_lst('$Config{ccflags} $Config{cccdlflags}') - env.EXTUTILS_TYPEMAP = cfg_lst('$Config{privlib}/ExtUtils/typemap') - env.XSUBPP = find_xsubpp() - - if not getattr(Options.options, 'perlarchdir', None): - env.ARCHDIR_PERL = cfg_str('$Config{sitearch}') - else: - env.ARCHDIR_PERL = getattr(Options.options, 'perlarchdir') - - env.perlext_PATTERN = '%s.' + cfg_str('$Config{dlext}') - -def options(opt): - """ - Add the ``--with-perl-archdir`` and ``--with-perl-binary`` command-line options. - """ - opt.add_option('--with-perl-binary', type='string', dest='perlbinary', help = 'Specify alternate perl binary', default=None) - opt.add_option('--with-perl-archdir', type='string', dest='perlarchdir', help = 'Specify directory where to install arch specific files', default=None) - diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py deleted file mode 100644 index 01a2c9a..0000000 --- a/waflib/Tools/python.py +++ /dev/null @@ -1,631 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2007-2015 (ita) -# Gustavo Carneiro (gjc), 2007 - -""" -Support for Python, detect the headers and libraries and provide -*use* variables to link C/C++ programs against them:: - - def options(opt): - opt.load('compiler_c python') - def configure(conf): - conf.load('compiler_c python') - conf.check_python_version((2,4,2)) - conf.check_python_headers() - def build(bld): - bld.program(features='pyembed', source='a.c', target='myprog') - bld.shlib(features='pyext', source='b.c', target='mylib') -""" - -import os, sys -from waflib import Errors, Logs, Node, Options, Task, Utils -from waflib.TaskGen import extension, before_method, after_method, feature -from waflib.Configure import conf - -FRAG = ''' -#include -#ifdef __cplusplus -extern "C" { -#endif - void Py_Initialize(void); - void Py_Finalize(void); -#ifdef __cplusplus -} -#endif -int main(int argc, char **argv) -{ - (void)argc; (void)argv; - Py_Initialize(); - Py_Finalize(); - return 0; -} -''' -""" -Piece of C/C++ code used in :py:func:`waflib.Tools.python.check_python_headers` -""" - -INST = ''' -import sys, py_compile -py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3], True) -''' -""" -Piece of Python code used in :py:class:`waflib.Tools.python.pyo` and :py:class:`waflib.Tools.python.pyc` for byte-compiling python files -""" - -DISTUTILS_IMP = ['from distutils.sysconfig import get_config_var, get_python_lib'] - -@before_method('process_source') -@feature('py') -def feature_py(self): - """ - Create tasks to byte-compile .py files and install them, if requested - """ - self.install_path = getattr(self, 'install_path', '${PYTHONDIR}') - install_from = getattr(self, 'install_from', None) - if install_from and not isinstance(install_from, Node.Node): - install_from = self.path.find_dir(install_from) - self.install_from = install_from - - ver = self.env.PYTHON_VERSION - if not ver: - self.bld.fatal('Installing python files requires PYTHON_VERSION, try conf.check_python_version') - - if int(ver.replace('.', '')) > 31: - self.install_32 = True - -@extension('.py') -def process_py(self, node): - """ - Add signature of .py file, so it will be byte-compiled when necessary - """ - assert(hasattr(self, 'install_path')), 'add features="py"' - - # where to install the python file - if self.install_path: - if self.install_from: - self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=True) - else: - self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=True) - - lst = [] - if self.env.PYC: - lst.append('pyc') - if self.env.PYO: - lst.append('pyo') - - if self.install_path: - if self.install_from: - pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.install_from)), self.env) - else: - pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.path)), self.env) - else: - pyd = node.abspath() - - for ext in lst: - if self.env.PYTAG and not self.env.NOPYCACHE: - # __pycache__ installation for python 3.2 - PEP 3147 - name = node.name[:-3] - pyobj = node.parent.get_bld().make_node('__pycache__').make_node("%s.%s.%s" % (name, self.env.PYTAG, ext)) - pyobj.parent.mkdir() - else: - pyobj = node.change_ext(".%s" % ext) - - tsk = self.create_task(ext, node, pyobj) - tsk.pyd = pyd - - if self.install_path: - self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=True) - -class pyc(Task.Task): - """ - Byte-compiling python files - """ - color = 'PINK' - def __str__(self): - node = self.outputs[0] - return node.path_from(node.ctx.launch_node()) - def run(self): - cmd = [Utils.subst_vars('${PYTHON}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd] - ret = self.generator.bld.exec_command(cmd) - return ret - -class pyo(Task.Task): - """ - Byte-compiling python files - """ - color = 'PINK' - def __str__(self): - node = self.outputs[0] - return node.path_from(node.ctx.launch_node()) - def run(self): - cmd = [Utils.subst_vars('${PYTHON}', self.env), Utils.subst_vars('${PYFLAGS_OPT}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd] - ret = self.generator.bld.exec_command(cmd) - return ret - -@feature('pyext') -@before_method('propagate_uselib_vars', 'apply_link') -@after_method('apply_bundle') -def init_pyext(self): - """ - Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the - *lib* prefix from library names. - """ - self.uselib = self.to_list(getattr(self, 'uselib', [])) - if not 'PYEXT' in self.uselib: - self.uselib.append('PYEXT') - # override shlib_PATTERN set by the osx module - self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN = self.env.pyext_PATTERN - self.env.fcshlib_PATTERN = self.env.dshlib_PATTERN = self.env.pyext_PATTERN - - try: - if not self.install_path: - return - except AttributeError: - self.install_path = '${PYTHONARCHDIR}' - -@feature('pyext') -@before_method('apply_link', 'apply_bundle') -def set_bundle(self): - """Mac-specific pyext extension that enables bundles from c_osx.py""" - if Utils.unversioned_sys_platform() == 'darwin': - self.mac_bundle = True - -@before_method('propagate_uselib_vars') -@feature('pyembed') -def init_pyembed(self): - """ - Add the PYEMBED variable. - """ - self.uselib = self.to_list(getattr(self, 'uselib', [])) - if not 'PYEMBED' in self.uselib: - self.uselib.append('PYEMBED') - -@conf -def get_python_variables(self, variables, imports=None): - """ - Spawn a new python process to dump configuration variables - - :param variables: variables to print - :type variables: list of string - :param imports: one import by element - :type imports: list of string - :return: the variable values - :rtype: list of string - """ - if not imports: - try: - imports = self.python_imports - except AttributeError: - imports = DISTUTILS_IMP - - program = list(imports) # copy - program.append('') - for v in variables: - program.append("print(repr(%s))" % v) - os_env = dict(os.environ) - try: - del os_env['MACOSX_DEPLOYMENT_TARGET'] # see comments in the OSX tool - except KeyError: - pass - - try: - out = self.cmd_and_log(self.env.PYTHON + ['-c', '\n'.join(program)], env=os_env) - except Errors.WafError: - self.fatal('The distutils module is unusable: install "python-devel"?') - self.to_log(out) - return_values = [] - for s in out.splitlines(): - s = s.strip() - if not s: - continue - if s == 'None': - return_values.append(None) - elif (s[0] == "'" and s[-1] == "'") or (s[0] == '"' and s[-1] == '"'): - return_values.append(eval(s)) - elif s[0].isdigit(): - return_values.append(int(s)) - else: break - return return_values - -@conf -def test_pyembed(self, mode, msg='Testing pyembed configuration'): - self.check(header_name='Python.h', define_name='HAVE_PYEMBED', msg=msg, - fragment=FRAG, errmsg='Could not build a python embedded interpreter', - features='%s %sprogram pyembed' % (mode, mode)) - -@conf -def test_pyext(self, mode, msg='Testing pyext configuration'): - self.check(header_name='Python.h', define_name='HAVE_PYEXT', msg=msg, - fragment=FRAG, errmsg='Could not build python extensions', - features='%s %sshlib pyext' % (mode, mode)) - -@conf -def python_cross_compile(self, features='pyembed pyext'): - """ - For cross-compilation purposes, it is possible to bypass the normal detection and set the flags that you want: - PYTHON_VERSION='3.4' PYTAG='cpython34' pyext_PATTERN="%s.so" PYTHON_LDFLAGS='-lpthread -ldl' waf configure - - The following variables are used: - PYTHON_VERSION required - PYTAG required - PYTHON_LDFLAGS required - pyext_PATTERN required - PYTHON_PYEXT_LDFLAGS - PYTHON_PYEMBED_LDFLAGS - """ - features = Utils.to_list(features) - if not ('PYTHON_LDFLAGS' in self.environ or 'PYTHON_PYEXT_LDFLAGS' in self.environ or 'PYTHON_PYEMBED_LDFLAGS' in self.environ): - return False - - for x in 'PYTHON_VERSION PYTAG pyext_PATTERN'.split(): - if not x in self.environ: - self.fatal('Please set %s in the os environment' % x) - else: - self.env[x] = self.environ[x] - - xx = self.env.CXX_NAME and 'cxx' or 'c' - if 'pyext' in features: - flags = self.environ.get('PYTHON_PYEXT_LDFLAGS', self.environ.get('PYTHON_LDFLAGS')) - if flags is None: - self.fatal('No flags provided through PYTHON_PYEXT_LDFLAGS as required') - else: - self.parse_flags(flags, 'PYEXT') - self.test_pyext(xx) - if 'pyembed' in features: - flags = self.environ.get('PYTHON_PYEMBED_LDFLAGS', self.environ.get('PYTHON_LDFLAGS')) - if flags is None: - self.fatal('No flags provided through PYTHON_PYEMBED_LDFLAGS as required') - else: - self.parse_flags(flags, 'PYEMBED') - self.test_pyembed(xx) - return True - -@conf -def check_python_headers(conf, features='pyembed pyext'): - """ - Check for headers and libraries necessary to extend or embed python by using the module *distutils*. - On success the environment variables xxx_PYEXT and xxx_PYEMBED are added: - - * PYEXT: for compiling python extensions - * PYEMBED: for embedding a python interpreter - """ - features = Utils.to_list(features) - assert ('pyembed' in features) or ('pyext' in features), "check_python_headers features must include 'pyembed' and/or 'pyext'" - env = conf.env - if not env.CC_NAME and not env.CXX_NAME: - conf.fatal('load a compiler first (gcc, g++, ..)') - - # bypass all the code below for cross-compilation - if conf.python_cross_compile(features): - return - - if not env.PYTHON_VERSION: - conf.check_python_version() - - pybin = env.PYTHON - if not pybin: - conf.fatal('Could not find the python executable') - - # so we actually do all this for compatibility reasons and for obtaining pyext_PATTERN below - v = 'prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split() - try: - lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v]) - except RuntimeError: - conf.fatal("Python development headers not found (-v for details).") - - vals = ['%s = %r' % (x, y) for (x, y) in zip(v, lst)] - conf.to_log("Configuration returned from %r:\n%s\n" % (pybin, '\n'.join(vals))) - - dct = dict(zip(v, lst)) - x = 'MACOSX_DEPLOYMENT_TARGET' - if dct[x]: - env[x] = conf.environ[x] = dct[x] - env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake - - - # Try to get pythonX.Y-config - num = '.'.join(env.PYTHON_VERSION.split('.')[:2]) - conf.find_program([''.join(pybin) + '-config', 'python%s-config' % num, 'python-config-%s' % num, 'python%sm-config' % num], var='PYTHON_CONFIG', msg="python-config", mandatory=False) - - if env.PYTHON_CONFIG: - # check python-config output only once - if conf.env.HAVE_PYTHON_H: - return - - # python2.6-config requires 3 runs - all_flags = [['--cflags', '--libs', '--ldflags']] - if sys.hexversion < 0x2070000: - all_flags = [[k] for k in all_flags[0]] - - xx = env.CXX_NAME and 'cxx' or 'c' - - if 'pyembed' in features: - for flags in all_flags: - conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=flags) - - try: - conf.test_pyembed(xx) - except conf.errors.ConfigurationError: - # python bug 7352 - if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']: - env.append_unique('LIBPATH_PYEMBED', [dct['LIBDIR']]) - conf.test_pyembed(xx) - else: - raise - - if 'pyext' in features: - for flags in all_flags: - conf.check_cfg(msg='Asking python-config for pyext %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEXT', args=flags) - - try: - conf.test_pyext(xx) - except conf.errors.ConfigurationError: - # python bug 7352 - if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']: - env.append_unique('LIBPATH_PYEXT', [dct['LIBDIR']]) - conf.test_pyext(xx) - else: - raise - - conf.define('HAVE_PYTHON_H', 1) - return - - # No python-config, do something else on windows systems - all_flags = dct['LDFLAGS'] + ' ' + dct['CFLAGS'] - conf.parse_flags(all_flags, 'PYEMBED') - - all_flags = dct['LDFLAGS'] + ' ' + dct['LDSHARED'] + ' ' + dct['CFLAGS'] - conf.parse_flags(all_flags, 'PYEXT') - - result = None - if not dct["LDVERSION"]: - dct["LDVERSION"] = env.PYTHON_VERSION - - # further simplification will be complicated - for name in ('python' + dct['LDVERSION'], 'python' + env.PYTHON_VERSION + 'm', 'python' + env.PYTHON_VERSION.replace('.', '')): - - # LIBPATH_PYEMBED is already set; see if it works. - if not result and env.LIBPATH_PYEMBED: - path = env.LIBPATH_PYEMBED - conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n" % path) - result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBPATH_PYEMBED' % name) - - if not result and dct['LIBDIR']: - path = [dct['LIBDIR']] - conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n" % path) - result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBDIR' % name) - - if not result and dct['LIBPL']: - path = [dct['LIBPL']] - conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") - result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in python_LIBPL' % name) - - if not result: - path = [os.path.join(dct['prefix'], "libs")] - conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") - result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) - - if result: - break # do not forget to set LIBPATH_PYEMBED - - if result: - env.LIBPATH_PYEMBED = path - env.append_value('LIB_PYEMBED', [name]) - else: - conf.to_log("\n\n### LIB NOT FOUND\n") - - # under certain conditions, python extensions must link to - # python libraries, not just python embedding programs. - if Utils.is_win32 or dct['Py_ENABLE_SHARED']: - env.LIBPATH_PYEXT = env.LIBPATH_PYEMBED - env.LIB_PYEXT = env.LIB_PYEMBED - - conf.to_log("Include path for Python extensions (found via distutils module): %r\n" % (dct['INCLUDEPY'],)) - env.INCLUDES_PYEXT = [dct['INCLUDEPY']] - env.INCLUDES_PYEMBED = [dct['INCLUDEPY']] - - # Code using the Python API needs to be compiled with -fno-strict-aliasing - if env.CC_NAME == 'gcc': - env.append_value('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) - env.append_value('CFLAGS_PYEXT', ['-fno-strict-aliasing']) - if env.CXX_NAME == 'gcc': - env.append_value('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) - env.append_value('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) - - if env.CC_NAME == "msvc": - from distutils.msvccompiler import MSVCCompiler - dist_compiler = MSVCCompiler() - dist_compiler.initialize() - env.append_value('CFLAGS_PYEXT', dist_compiler.compile_options) - env.append_value('CXXFLAGS_PYEXT', dist_compiler.compile_options) - env.append_value('LINKFLAGS_PYEXT', dist_compiler.ldflags_shared) - - # See if it compiles - conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', uselib='PYEMBED', fragment=FRAG, errmsg='Distutils not installed? Broken python installation? Get python-config now!') - -@conf -def check_python_version(conf, minver=None): - """ - Check if the python interpreter is found matching a given minimum version. - minver should be a tuple, eg. to check for python >= 2.4.2 pass (2,4,2) as minver. - - If successful, PYTHON_VERSION is defined as 'MAJOR.MINOR' (eg. '2.4') - of the actual python version found, and PYTHONDIR and PYTHONARCHDIR - are defined, pointing to the site-packages directories appropriate for - this python version, where modules/packages/extensions should be - installed. - - :param minver: minimum version - :type minver: tuple of int - """ - assert minver is None or isinstance(minver, tuple) - pybin = conf.env.PYTHON - if not pybin: - conf.fatal('could not find the python executable') - - # Get python version string - cmd = pybin + ['-c', 'import sys\nfor x in sys.version_info: print(str(x))'] - Logs.debug('python: Running python command %r', cmd) - lines = conf.cmd_and_log(cmd).split() - assert len(lines) == 5, "found %r lines, expected 5: %r" % (len(lines), lines) - pyver_tuple = (int(lines[0]), int(lines[1]), int(lines[2]), lines[3], int(lines[4])) - - # Compare python version with the minimum required - result = (minver is None) or (pyver_tuple >= minver) - - if result: - # define useful environment variables - pyver = '.'.join([str(x) for x in pyver_tuple[:2]]) - conf.env.PYTHON_VERSION = pyver - - if 'PYTHONDIR' in conf.env: - # Check if --pythondir was specified - pydir = conf.env.PYTHONDIR - elif 'PYTHONDIR' in conf.environ: - # Check environment for PYTHONDIR - pydir = conf.environ['PYTHONDIR'] - else: - # Finally, try to guess - if Utils.is_win32: - (python_LIBDEST, pydir) = conf.get_python_variables( - ["get_config_var('LIBDEST') or ''", - "get_python_lib(standard_lib=0) or ''"]) - else: - python_LIBDEST = None - (pydir,) = conf.get_python_variables( ["get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX]) - if python_LIBDEST is None: - if conf.env.LIBDIR: - python_LIBDEST = os.path.join(conf.env.LIBDIR, 'python' + pyver) - else: - python_LIBDEST = os.path.join(conf.env.PREFIX, 'lib', 'python' + pyver) - - if 'PYTHONARCHDIR' in conf.env: - # Check if --pythonarchdir was specified - pyarchdir = conf.env.PYTHONARCHDIR - elif 'PYTHONARCHDIR' in conf.environ: - # Check environment for PYTHONDIR - pyarchdir = conf.environ['PYTHONARCHDIR'] - else: - # Finally, try to guess - (pyarchdir, ) = conf.get_python_variables( ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX]) - if not pyarchdir: - pyarchdir = pydir - - if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist - conf.define('PYTHONDIR', pydir) - conf.define('PYTHONARCHDIR', pyarchdir) - - conf.env.PYTHONDIR = pydir - conf.env.PYTHONARCHDIR = pyarchdir - - # Feedback - pyver_full = '.'.join(map(str, pyver_tuple[:3])) - if minver is None: - conf.msg('Checking for python version', pyver_full) - else: - minver_str = '.'.join(map(str, minver)) - conf.msg('Checking for python version >= %s' % (minver_str,), pyver_full, color=result and 'GREEN' or 'YELLOW') - - if not result: - conf.fatal('The python version is too old, expecting %r' % (minver,)) - -PYTHON_MODULE_TEMPLATE = ''' -import %s as current_module -version = getattr(current_module, '__version__', None) -if version is not None: - print(str(version)) -else: - print('unknown version') -''' - -@conf -def check_python_module(conf, module_name, condition=''): - """ - Check if the selected python interpreter can import the given python module:: - - def configure(conf): - conf.check_python_module('pygccxml') - conf.check_python_module('re', condition="ver > num(2, 0, 4) and ver <= num(3, 0, 0)") - - :param module_name: module - :type module_name: string - """ - msg = "Checking for python module %r" % module_name - if condition: - msg = '%s (%s)' % (msg, condition) - conf.start_msg(msg) - try: - ret = conf.cmd_and_log(conf.env.PYTHON + ['-c', PYTHON_MODULE_TEMPLATE % module_name]) - except Errors.WafError: - conf.end_msg(False) - conf.fatal('Could not find the python module %r' % module_name) - - ret = ret.strip() - if condition: - conf.end_msg(ret) - if ret == 'unknown version': - conf.fatal('Could not check the %s version' % module_name) - - from distutils.version import LooseVersion - def num(*k): - if isinstance(k[0], int): - return LooseVersion('.'.join([str(x) for x in k])) - else: - return LooseVersion(k[0]) - d = {'num': num, 'ver': LooseVersion(ret)} - ev = eval(condition, {}, d) - if not ev: - conf.fatal('The %s version does not satisfy the requirements' % module_name) - else: - if ret == 'unknown version': - conf.end_msg(True) - else: - conf.end_msg(ret) - -def configure(conf): - """ - Detect the python interpreter - """ - v = conf.env - if getattr(Options.options, 'pythondir', None): - v.PYTHONDIR = Options.options.pythondir - if getattr(Options.options, 'pythonarchdir', None): - v.PYTHONARCHDIR = Options.options.pythonarchdir - if getattr(Options.options, 'nopycache', None): - v.NOPYCACHE=Options.options.nopycache - - if not v.PYTHON: - v.PYTHON = [getattr(Options.options, 'python', None) or sys.executable] - v.PYTHON = Utils.to_list(v.PYTHON) - conf.find_program('python', var='PYTHON') - - v.PYFLAGS = '' - v.PYFLAGS_OPT = '-O' - - v.PYC = getattr(Options.options, 'pyc', 1) - v.PYO = getattr(Options.options, 'pyo', 1) - - try: - v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import imp;print(imp.get_tag())"]).strip() - except Errors.WafError: - pass - -def options(opt): - """ - Add python-specific options - """ - pyopt=opt.add_option_group("Python Options") - pyopt.add_option('--nopyc', dest = 'pyc', action='store_false', default=1, - help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]') - pyopt.add_option('--nopyo', dest='pyo', action='store_false', default=1, - help='Do not install optimised compiled .pyo files (configuration) [Default:install]') - pyopt.add_option('--nopycache',dest='nopycache', action='store_true', - help='Do not use __pycache__ directory to install objects [Default:auto]') - pyopt.add_option('--python', dest="python", - help='python binary to be used [Default: %s]' % sys.executable) - pyopt.add_option('--pythondir', dest='pythondir', - help='Installation path for python modules (py, platform-independent .py and .pyc files)') - pyopt.add_option('--pythonarchdir', dest='pythonarchdir', - help='Installation path for python extension (pyext, platform-dependent .so or .dylib files)') - diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py deleted file mode 100644 index 9f43280..0000000 --- a/waflib/Tools/qt5.py +++ /dev/null @@ -1,796 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -""" -This tool helps with finding Qt5 tools and libraries, -and also provides syntactic sugar for using Qt5 tools. - -The following snippet illustrates the tool usage:: - - def options(opt): - opt.load('compiler_cxx qt5') - - def configure(conf): - conf.load('compiler_cxx qt5') - - def build(bld): - bld( - features = 'qt5 cxx cxxprogram', - uselib = 'QT5CORE QT5GUI QT5OPENGL QT5SVG', - source = 'main.cpp textures.qrc aboutDialog.ui', - target = 'window', - ) - -Here, the UI description and resource files will be processed -to generate code. - -Usage -===== - -Load the "qt5" tool. - -You also need to edit your sources accordingly: - -- the normal way of doing things is to have your C++ files - include the .moc file. - This is regarded as the best practice (and provides much faster - compilations). - It also implies that the include paths have beenset properly. - -- to have the include paths added automatically, use the following:: - - from waflib.TaskGen import feature, before_method, after_method - @feature('cxx') - @after_method('process_source') - @before_method('apply_incpaths') - def add_includes_paths(self): - incs = set(self.to_list(getattr(self, 'includes', ''))) - for x in self.compiled_tasks: - incs.add(x.inputs[0].parent.path_from(self.path)) - self.includes = sorted(incs) - -Note: another tool provides Qt processing that does not require -.moc includes, see 'playground/slow_qt/'. - -A few options (--qt{dir,bin,...}) and environment variables -(QT5_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool, -tool path selection, etc; please read the source for more info. - -The detection uses pkg-config on Linux by default. To force static library detection use: -QT5_XCOMPILE=1 QT5_FORCE_STATIC=1 waf configure -""" - -from __future__ import with_statement - -try: - from xml.sax import make_parser - from xml.sax.handler import ContentHandler -except ImportError: - has_xml = False - ContentHandler = object -else: - has_xml = True - -import os, sys, re -from waflib.Tools import cxx -from waflib import Task, Utils, Options, Errors, Context -from waflib.TaskGen import feature, after_method, extension, before_method -from waflib.Configure import conf -from waflib import Logs - -MOC_H = ['.h', '.hpp', '.hxx', '.hh'] -""" -File extensions associated to .moc files -""" - -EXT_RCC = ['.qrc'] -""" -File extension for the resource (.qrc) files -""" - -EXT_UI = ['.ui'] -""" -File extension for the user interface (.ui) files -""" - -EXT_QT5 = ['.cpp', '.cc', '.cxx', '.C'] -""" -File extensions of C++ files that may require a .moc processing -""" - -class qxx(Task.classes['cxx']): - """ - Each C++ file can have zero or several .moc files to create. - They are known only when the files are scanned (preprocessor) - To avoid scanning the c++ files each time (parsing C/C++), the results - are retrieved from the task cache (bld.node_deps/bld.raw_deps). - The moc tasks are also created *dynamically* during the build. - """ - - def __init__(self, *k, **kw): - Task.Task.__init__(self, *k, **kw) - self.moc_done = 0 - - def runnable_status(self): - """ - Compute the task signature to make sure the scanner was executed. Create the - moc tasks by using :py:meth:`waflib.Tools.qt5.qxx.add_moc_tasks` (if necessary), - then postpone the task execution (there is no need to recompute the task signature). - """ - if self.moc_done: - return Task.Task.runnable_status(self) - else: - for t in self.run_after: - if not t.hasrun: - return Task.ASK_LATER - self.add_moc_tasks() - return Task.Task.runnable_status(self) - - def create_moc_task(self, h_node, m_node): - """ - If several libraries use the same classes, it is possible that moc will run several times (Issue 1318) - It is not possible to change the file names, but we can assume that the moc transformation will be identical, - and the moc tasks can be shared in a global cache. - """ - try: - moc_cache = self.generator.bld.moc_cache - except AttributeError: - moc_cache = self.generator.bld.moc_cache = {} - - try: - return moc_cache[h_node] - except KeyError: - tsk = moc_cache[h_node] = Task.classes['moc'](env=self.env, generator=self.generator) - tsk.set_inputs(h_node) - tsk.set_outputs(m_node) - tsk.env.append_unique('MOC_FLAGS', '-i') - - if self.generator: - self.generator.tasks.append(tsk) - - # direct injection in the build phase (safe because called from the main thread) - gen = self.generator.bld.producer - gen.outstanding.append(tsk) - gen.total += 1 - - return tsk - - else: - # remove the signature, it must be recomputed with the moc task - delattr(self, 'cache_sig') - - def add_moc_tasks(self): - """ - Creates moc tasks by looking in the list of file dependencies ``bld.raw_deps[self.uid()]`` - """ - node = self.inputs[0] - bld = self.generator.bld - - try: - # compute the signature once to know if there is a moc file to create - self.signature() - except KeyError: - # the moc file may be referenced somewhere else - pass - else: - # remove the signature, it must be recomputed with the moc task - delattr(self, 'cache_sig') - - include_nodes = [node.parent] + self.generator.includes_nodes - - moctasks = [] - mocfiles = set() - for d in bld.raw_deps.get(self.uid(), []): - if not d.endswith('.moc'): - continue - - # process that base.moc only once - if d in mocfiles: - continue - mocfiles.add(d) - - # find the source associated with the moc file - h_node = None - base2 = d[:-4] - - # foo.moc from foo.cpp - prefix = node.name[:node.name.rfind('.')] - if base2 == prefix: - h_node = node - else: - # this deviates from the standard - # if bar.cpp includes foo.moc, then assume it is from foo.h - for x in include_nodes: - for e in MOC_H: - h_node = x.find_node(base2 + e) - if h_node: - break - else: - continue - break - if h_node: - m_node = h_node.change_ext('.moc') - else: - raise Errors.WafError('No source found for %r which is a moc file' % d) - - # create the moc task - task = self.create_moc_task(h_node, m_node) - moctasks.append(task) - - # simple scheduler dependency: run the moc task before others - self.run_after.update(set(moctasks)) - self.moc_done = 1 - -class trans_update(Task.Task): - """Updates a .ts files from a list of C++ files""" - run_str = '${QT_LUPDATE} ${SRC} -ts ${TGT}' - color = 'BLUE' - -class XMLHandler(ContentHandler): - """ - Parses ``.qrc`` files - """ - def __init__(self): - ContentHandler.__init__(self) - self.buf = [] - self.files = [] - def startElement(self, name, attrs): - if name == 'file': - self.buf = [] - def endElement(self, name): - if name == 'file': - self.files.append(str(''.join(self.buf))) - def characters(self, cars): - self.buf.append(cars) - -@extension(*EXT_RCC) -def create_rcc_task(self, node): - "Creates rcc and cxx tasks for ``.qrc`` files" - rcnode = node.change_ext('_rc.%d.cpp' % self.idx) - self.create_task('rcc', node, rcnode) - cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) - try: - self.compiled_tasks.append(cpptask) - except AttributeError: - self.compiled_tasks = [cpptask] - return cpptask - -@extension(*EXT_UI) -def create_uic_task(self, node): - "Create uic tasks for user interface ``.ui`` definition files" - - """ - If UIC file is used in more than one bld, we would have a conflict in parallel execution - It is not possible to change the file names (like .self.idx. as for objects) as they have - to be referenced by the source file, but we can assume that the transformation will be identical - and the tasks can be shared in a global cache. - """ - try: - uic_cache = self.bld.uic_cache - except AttributeError: - uic_cache = self.bld.uic_cache = {} - - if node not in uic_cache: - uictask = uic_cache[node] = self.create_task('ui5', node) - uictask.outputs = [node.parent.find_or_declare(self.env.ui_PATTERN % node.name[:-3])] - -@extension('.ts') -def add_lang(self, node): - """Adds all the .ts file into ``self.lang``""" - self.lang = self.to_list(getattr(self, 'lang', [])) + [node] - -@feature('qt5') -@before_method('process_source') -def process_mocs(self): - """ - Processes MOC files included in headers:: - - def build(bld): - bld.program(features='qt5', source='main.cpp', target='app', use='QT5CORE', moc='foo.h') - - The build will run moc on foo.h to create moc_foo.n.cpp. The number in the file name - is provided to avoid name clashes when the same headers are used by several targets. - """ - lst = self.to_nodes(getattr(self, 'moc', [])) - self.source = self.to_list(getattr(self, 'source', [])) - for x in lst: - prefix = x.name[:x.name.rfind('.')] # foo.h -> foo - moc_target = 'moc_%s.%d.cpp' % (prefix, self.idx) - moc_node = x.parent.find_or_declare(moc_target) - self.source.append(moc_node) - - self.create_task('moc', x, moc_node) - -@feature('qt5') -@after_method('apply_link') -def apply_qt5(self): - """ - Adds MOC_FLAGS which may be necessary for moc:: - - def build(bld): - bld.program(features='qt5', source='main.cpp', target='app', use='QT5CORE') - - The additional parameters are: - - :param lang: list of translation files (\\*.ts) to process - :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension - :param update: whether to process the C++ files to update the \\*.ts files (use **waf --translate**) - :type update: bool - :param langname: if given, transform the \\*.ts files into a .qrc files to include in the binary file - :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension - """ - if getattr(self, 'lang', None): - qmtasks = [] - for x in self.to_list(self.lang): - if isinstance(x, str): - x = self.path.find_resource(x + '.ts') - qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.%d.qm' % self.idx))) - - if getattr(self, 'update', None) and Options.options.trans_qt5: - cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [ - a.inputs[0] for a in self.tasks if a.inputs and a.inputs[0].name.endswith('.ui')] - for x in qmtasks: - self.create_task('trans_update', cxxnodes, x.inputs) - - if getattr(self, 'langname', None): - qmnodes = [x.outputs[0] for x in qmtasks] - rcnode = self.langname - if isinstance(rcnode, str): - rcnode = self.path.find_or_declare(rcnode + ('.%d.qrc' % self.idx)) - t = self.create_task('qm2rcc', qmnodes, rcnode) - k = create_rcc_task(self, t.outputs[0]) - self.link_task.inputs.append(k.outputs[0]) - - lst = [] - for flag in self.to_list(self.env.CXXFLAGS): - if len(flag) < 2: - continue - f = flag[0:2] - if f in ('-D', '-I', '/D', '/I'): - if (f[0] == '/'): - lst.append('-' + flag[1:]) - else: - lst.append(flag) - self.env.append_value('MOC_FLAGS', lst) - -@extension(*EXT_QT5) -def cxx_hook(self, node): - """ - Re-maps C++ file extensions to the :py:class:`waflib.Tools.qt5.qxx` task. - """ - return self.create_compiled_task('qxx', node) - -class rcc(Task.Task): - """ - Processes ``.qrc`` files - """ - color = 'BLUE' - run_str = '${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' - ext_out = ['.h'] - - def rcname(self): - return os.path.splitext(self.inputs[0].name)[0] - - def scan(self): - """Parse the *.qrc* files""" - if not has_xml: - Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') - return ([], []) - - parser = make_parser() - curHandler = XMLHandler() - parser.setContentHandler(curHandler) - with open(self.inputs[0].abspath(), 'r') as f: - parser.parse(f) - - nodes = [] - names = [] - root = self.inputs[0].parent - for x in curHandler.files: - nd = root.find_resource(x) - if nd: - nodes.append(nd) - else: - names.append(x) - return (nodes, names) - - def quote_flag(self, x): - """ - Override Task.quote_flag. QT parses the argument files - differently than cl.exe and link.exe - - :param x: flag - :type x: string - :return: quoted flag - :rtype: string - """ - return x - - -class moc(Task.Task): - """ - Creates ``.moc`` files - """ - color = 'BLUE' - run_str = '${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' - - def quote_flag(self, x): - """ - Override Task.quote_flag. QT parses the argument files - differently than cl.exe and link.exe - - :param x: flag - :type x: string - :return: quoted flag - :rtype: string - """ - return x - - -class ui5(Task.Task): - """ - Processes ``.ui`` files - """ - color = 'BLUE' - run_str = '${QT_UIC} ${SRC} -o ${TGT}' - ext_out = ['.h'] - -class ts2qm(Task.Task): - """ - Generates ``.qm`` files from ``.ts`` files - """ - color = 'BLUE' - run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' - -class qm2rcc(Task.Task): - """ - Generates ``.qrc`` files from ``.qm`` files - """ - color = 'BLUE' - after = 'ts2qm' - def run(self): - """Create a qrc file including the inputs""" - txt = '\n'.join(['%s' % k.path_from(self.outputs[0].parent) for k in self.inputs]) - code = '\n\n%s\n\n' % txt - self.outputs[0].write(code) - -def configure(self): - """ - Besides the configuration options, the environment variable QT5_ROOT may be used - to give the location of the qt5 libraries (absolute path). - - The detection uses the program ``pkg-config`` through :py:func:`waflib.Tools.config_c.check_cfg` - """ - self.find_qt5_binaries() - self.set_qt5_libs_dir() - self.set_qt5_libs_to_check() - self.set_qt5_defines() - self.find_qt5_libraries() - self.add_qt5_rpath() - self.simplify_qt5_libs() - - # warn about this during the configuration too - if not has_xml: - Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') - - if 'COMPILER_CXX' not in self.env: - self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') - - # Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC? - frag = '#include \nint main(int argc, char **argv) {return 0;}\n' - uses = 'QT5CORE QT5WIDGETS QT5GUI' - for flag in [[], '-fPIE', '-fPIC', '-std=c++11' , ['-std=c++11', '-fPIE'], ['-std=c++11', '-fPIC']]: - msg = 'See if Qt files compile ' - if flag: - msg += 'with %s' % flag - try: - self.check(features='qt5 cxx', use=uses, uselib_store='qt5', cxxflags=flag, fragment=frag, msg=msg) - except self.errors.ConfigurationError: - pass - else: - break - else: - self.fatal('Could not build a simple Qt application') - - # FreeBSD does not add /usr/local/lib and the pkg-config files do not provide it either :-/ - if Utils.unversioned_sys_platform() == 'freebsd': - frag = '#include \nint main(int argc, char **argv) { QApplication app(argc, argv); return NULL != (void*) (&app);}\n' - try: - self.check(features='qt5 cxx cxxprogram', use=uses, fragment=frag, msg='Can we link Qt programs on FreeBSD directly?') - except self.errors.ConfigurationError: - self.check(features='qt5 cxx cxxprogram', use=uses, uselib_store='qt5', libpath='/usr/local/lib', fragment=frag, msg='Is /usr/local/lib required?') - -@conf -def find_qt5_binaries(self): - """ - Detects Qt programs such as qmake, moc, uic, lrelease - """ - env = self.env - opt = Options.options - - qtdir = getattr(opt, 'qtdir', '') - qtbin = getattr(opt, 'qtbin', '') - - paths = [] - - if qtdir: - qtbin = os.path.join(qtdir, 'bin') - - # the qt directory has been given from QT5_ROOT - deduce the qt binary path - if not qtdir: - qtdir = self.environ.get('QT5_ROOT', '') - qtbin = self.environ.get('QT5_BIN') or os.path.join(qtdir, 'bin') - - if qtbin: - paths = [qtbin] - - # no qtdir, look in the path and in /usr/local/Trolltech - if not qtdir: - paths = self.environ.get('PATH', '').split(os.pathsep) - paths.extend(['/usr/share/qt5/bin', '/usr/local/lib/qt5/bin']) - try: - lst = Utils.listdir('/usr/local/Trolltech/') - except OSError: - pass - else: - if lst: - lst.sort() - lst.reverse() - - # keep the highest version - qtdir = '/usr/local/Trolltech/%s/' % lst[0] - qtbin = os.path.join(qtdir, 'bin') - paths.append(qtbin) - - # at the end, try to find qmake in the paths given - # keep the one with the highest version - cand = None - prev_ver = ['5', '0', '0'] - for qmk in ('qmake-qt5', 'qmake5', 'qmake'): - try: - qmake = self.find_program(qmk, path_list=paths) - except self.errors.ConfigurationError: - pass - else: - try: - version = self.cmd_and_log(qmake + ['-query', 'QT_VERSION']).strip() - except self.errors.WafError: - pass - else: - if version: - new_ver = version.split('.') - if new_ver > prev_ver: - cand = qmake - prev_ver = new_ver - - # qmake could not be found easily, rely on qtchooser - if not cand: - try: - self.find_program('qtchooser') - except self.errors.ConfigurationError: - pass - else: - cmd = self.env.QTCHOOSER + ['-qt=5', '-run-tool=qmake'] - try: - version = self.cmd_and_log(cmd + ['-query', 'QT_VERSION']) - except self.errors.WafError: - pass - else: - cand = cmd - - if cand: - self.env.QMAKE = cand - else: - self.fatal('Could not find qmake for qt5') - - self.env.QT_HOST_BINS = qtbin = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_HOST_BINS']).strip() - paths.insert(0, qtbin) - - def find_bin(lst, var): - if var in env: - return - for f in lst: - try: - ret = self.find_program(f, path_list=paths) - except self.errors.ConfigurationError: - pass - else: - env[var]=ret - break - - find_bin(['uic-qt5', 'uic'], 'QT_UIC') - if not env.QT_UIC: - self.fatal('cannot find the uic compiler for qt5') - - self.start_msg('Checking for uic version') - uicver = self.cmd_and_log(env.QT_UIC + ['-version'], output=Context.BOTH) - uicver = ''.join(uicver).strip() - uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '') - self.end_msg(uicver) - if uicver.find(' 3.') != -1 or uicver.find(' 4.') != -1: - self.fatal('this uic compiler is for qt3 or qt4, add uic for qt5 to your path') - - find_bin(['moc-qt5', 'moc'], 'QT_MOC') - find_bin(['rcc-qt5', 'rcc'], 'QT_RCC') - find_bin(['lrelease-qt5', 'lrelease'], 'QT_LRELEASE') - find_bin(['lupdate-qt5', 'lupdate'], 'QT_LUPDATE') - - env.UIC_ST = '%s -o %s' - env.MOC_ST = '-o' - env.ui_PATTERN = 'ui_%s.h' - env.QT_LRELEASE_FLAGS = ['-silent'] - env.MOCCPPPATH_ST = '-I%s' - env.MOCDEFINES_ST = '-D%s' - -@conf -def set_qt5_libs_dir(self): - env = self.env - qtlibs = getattr(Options.options, 'qtlibs', None) or self.environ.get('QT5_LIBDIR') - if not qtlibs: - try: - qtlibs = self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_LIBS']).strip() - except Errors.WafError: - qtdir = self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip() - qtlibs = os.path.join(qtdir, 'lib') - self.msg('Found the Qt5 libraries in', qtlibs) - env.QTLIBS = qtlibs - -@conf -def find_single_qt5_lib(self, name, uselib, qtlibs, qtincludes, force_static): - env = self.env - if force_static: - exts = ('.a', '.lib') - prefix = 'STLIB' - else: - exts = ('.so', '.lib') - prefix = 'LIB' - - def lib_names(): - for x in exts: - for k in ('', '5') if Utils.is_win32 else ['']: - for p in ('lib', ''): - yield (p, name, k, x) - - for tup in lib_names(): - k = ''.join(tup) - path = os.path.join(qtlibs, k) - if os.path.exists(path): - if env.DEST_OS == 'win32': - libval = ''.join(tup[:-1]) - else: - libval = name - env.append_unique(prefix + '_' + uselib, libval) - env.append_unique('%sPATH_%s' % (prefix, uselib), qtlibs) - env.append_unique('INCLUDES_' + uselib, qtincludes) - env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, name.replace('Qt5', 'Qt'))) - return k - return False - -@conf -def find_qt5_libraries(self): - env = self.env - - qtincludes = self.environ.get('QT5_INCLUDES') or self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_HEADERS']).strip() - force_static = self.environ.get('QT5_FORCE_STATIC') - try: - if self.environ.get('QT5_XCOMPILE'): - self.fatal('QT5_XCOMPILE Disables pkg-config detection') - self.check_cfg(atleast_pkgconfig_version='0.1') - except self.errors.ConfigurationError: - for i in self.qt5_vars: - uselib = i.upper() - if Utils.unversioned_sys_platform() == 'darwin': - # Since at least qt 4.7.3 each library locates in separate directory - fwk = i.replace('Qt5', 'Qt') - frameworkName = fwk + '.framework' - - qtDynamicLib = os.path.join(env.QTLIBS, frameworkName, fwk) - if os.path.exists(qtDynamicLib): - env.append_unique('FRAMEWORK_' + uselib, fwk) - env.append_unique('FRAMEWORKPATH_' + uselib, env.QTLIBS) - self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') - else: - self.msg('Checking for %s' % i, False, 'YELLOW') - env.append_unique('INCLUDES_' + uselib, os.path.join(env.QTLIBS, frameworkName, 'Headers')) - else: - ret = self.find_single_qt5_lib(i, uselib, env.QTLIBS, qtincludes, force_static) - if not force_static and not ret: - ret = self.find_single_qt5_lib(i, uselib, env.QTLIBS, qtincludes, True) - self.msg('Checking for %s' % i, ret, 'GREEN' if ret else 'YELLOW') - else: - path = '%s:%s:%s/pkgconfig:/usr/lib/qt5/lib/pkgconfig:/opt/qt5/lib/pkgconfig:/usr/lib/qt5/lib:/opt/qt5/lib' % ( - self.environ.get('PKG_CONFIG_PATH', ''), env.QTLIBS, env.QTLIBS) - for i in self.qt5_vars: - self.check_cfg(package=i, args='--cflags --libs', mandatory=False, force_static=force_static, pkg_config_path=path) - -@conf -def simplify_qt5_libs(self): - """ - Since library paths make really long command-lines, - and since everything depends on qtcore, remove the qtcore ones from qtgui, etc - """ - env = self.env - def process_lib(vars_, coreval): - for d in vars_: - var = d.upper() - if var == 'QTCORE': - continue - - value = env['LIBPATH_'+var] - if value: - core = env[coreval] - accu = [] - for lib in value: - if lib in core: - continue - accu.append(lib) - env['LIBPATH_'+var] = accu - process_lib(self.qt5_vars, 'LIBPATH_QTCORE') - -@conf -def add_qt5_rpath(self): - """ - Defines rpath entries for Qt libraries - """ - env = self.env - if getattr(Options.options, 'want_rpath', False): - def process_rpath(vars_, coreval): - for d in vars_: - var = d.upper() - value = env['LIBPATH_' + var] - if value: - core = env[coreval] - accu = [] - for lib in value: - if var != 'QTCORE': - if lib in core: - continue - accu.append('-Wl,--rpath='+lib) - env['RPATH_' + var] = accu - process_rpath(self.qt5_vars, 'LIBPATH_QTCORE') - -@conf -def set_qt5_libs_to_check(self): - self.qt5_vars = Utils.to_list(getattr(self, 'qt5_vars', [])) - if not self.qt5_vars: - dirlst = Utils.listdir(self.env.QTLIBS) - - pat = self.env.cxxshlib_PATTERN - if Utils.is_win32: - pat = pat.replace('.dll', '.lib') - if self.environ.get('QT5_FORCE_STATIC'): - pat = self.env.cxxstlib_PATTERN - if Utils.unversioned_sys_platform() == 'darwin': - pat = r"%s\.framework" - re_qt = re.compile(pat%'Qt5?(?P.*)'+'$') - for x in dirlst: - m = re_qt.match(x) - if m: - self.qt5_vars.append("Qt5%s" % m.group('name')) - if not self.qt5_vars: - self.fatal('cannot find any Qt5 library (%r)' % self.env.QTLIBS) - - qtextralibs = getattr(Options.options, 'qtextralibs', None) - if qtextralibs: - self.qt5_vars.extend(qtextralibs.split(',')) - -@conf -def set_qt5_defines(self): - if sys.platform != 'win32': - return - for x in self.qt5_vars: - y=x.replace('Qt5', 'Qt')[2:].upper() - self.env.append_unique('DEFINES_%s' % x.upper(), 'QT_%s_LIB' % y) - -def options(opt): - """ - Command-line options - """ - opt.add_option('--want-rpath', action='store_true', default=False, dest='want_rpath', help='enable the rpath for qt libraries') - for i in 'qtdir qtbin qtlibs'.split(): - opt.add_option('--'+i, type='string', default='', dest=i) - - opt.add_option('--translate', action='store_true', help='collect translation strings', dest='trans_qt5', default=False) - opt.add_option('--qtextralibs', type='string', default='', dest='qtextralibs', help='additional qt libraries on the system to add to default ones, comma separated') - diff --git a/waflib/Tools/ruby.py b/waflib/Tools/ruby.py deleted file mode 100644 index 8d92a79..0000000 --- a/waflib/Tools/ruby.py +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# daniel.svensson at purplescout.se 2008 -# Thomas Nagy 2016-2018 (ita) - -""" -Support for Ruby extensions. A C/C++ compiler is required:: - - def options(opt): - opt.load('compiler_c ruby') - def configure(conf): - conf.load('compiler_c ruby') - conf.check_ruby_version((1,8,0)) - conf.check_ruby_ext_devel() - conf.check_ruby_module('libxml') - def build(bld): - bld( - features = 'c cshlib rubyext', - source = 'rb_mytest.c', - target = 'mytest_ext', - install_path = '${ARCHDIR_RUBY}') - bld.install_files('${LIBDIR_RUBY}', 'Mytest.rb') -""" - -import os -from waflib import Errors, Options, Task, Utils -from waflib.TaskGen import before_method, feature, extension -from waflib.Configure import conf - -@feature('rubyext') -@before_method('apply_incpaths', 'process_source', 'apply_bundle', 'apply_link') -def init_rubyext(self): - """ - Add required variables for ruby extensions - """ - self.install_path = '${ARCHDIR_RUBY}' - self.uselib = self.to_list(getattr(self, 'uselib', '')) - if not 'RUBY' in self.uselib: - self.uselib.append('RUBY') - if not 'RUBYEXT' in self.uselib: - self.uselib.append('RUBYEXT') - -@feature('rubyext') -@before_method('apply_link', 'propagate_uselib_vars') -def apply_ruby_so_name(self): - """ - Strip the *lib* prefix from ruby extensions - """ - self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.rubyext_PATTERN - -@conf -def check_ruby_version(self, minver=()): - """ - Checks if ruby is installed. - If installed the variable RUBY will be set in environment. - The ruby binary can be overridden by ``--with-ruby-binary`` command-line option. - """ - - ruby = self.find_program('ruby', var='RUBY', value=Options.options.rubybinary) - - try: - version = self.cmd_and_log(ruby + ['-e', 'puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() - except Errors.WafError: - self.fatal('could not determine ruby version') - self.env.RUBY_VERSION = version - - try: - ver = tuple(map(int, version.split('.'))) - except Errors.WafError: - self.fatal('unsupported ruby version %r' % version) - - cver = '' - if minver: - cver = '> ' + '.'.join(str(x) for x in minver) - if ver < minver: - self.fatal('ruby is too old %r' % ver) - - self.msg('Checking for ruby version %s' % cver, version) - -@conf -def check_ruby_ext_devel(self): - """ - Check if a ruby extension can be created - """ - if not self.env.RUBY: - self.fatal('ruby detection is required first') - - if not self.env.CC_NAME and not self.env.CXX_NAME: - self.fatal('load a c/c++ compiler first') - - version = tuple(map(int, self.env.RUBY_VERSION.split("."))) - - def read_out(cmd): - return Utils.to_list(self.cmd_and_log(self.env.RUBY + ['-rrbconfig', '-e', cmd])) - - def read_config(key): - return read_out('puts RbConfig::CONFIG[%r]' % key) - - cpppath = archdir = read_config('archdir') - - if version >= (1, 9, 0): - ruby_hdrdir = read_config('rubyhdrdir') - cpppath += ruby_hdrdir - if version >= (2, 0, 0): - cpppath += read_config('rubyarchhdrdir') - cpppath += [os.path.join(ruby_hdrdir[0], read_config('arch')[0])] - - self.check(header_name='ruby.h', includes=cpppath, errmsg='could not find ruby header file', link_header_test=False) - - self.env.LIBPATH_RUBYEXT = read_config('libdir') - self.env.LIBPATH_RUBYEXT += archdir - self.env.INCLUDES_RUBYEXT = cpppath - self.env.CFLAGS_RUBYEXT = read_config('CCDLFLAGS') - self.env.rubyext_PATTERN = '%s.' + read_config('DLEXT')[0] - - # ok this is really stupid, but the command and flags are combined. - # so we try to find the first argument... - flags = read_config('LDSHARED') - while flags and flags[0][0] != '-': - flags = flags[1:] - - # we also want to strip out the deprecated ppc flags - if len(flags) > 1 and flags[1] == "ppc": - flags = flags[2:] - - self.env.LINKFLAGS_RUBYEXT = flags - self.env.LINKFLAGS_RUBYEXT += read_config('LIBS') - self.env.LINKFLAGS_RUBYEXT += read_config('LIBRUBYARG_SHARED') - - if Options.options.rubyarchdir: - self.env.ARCHDIR_RUBY = Options.options.rubyarchdir - else: - self.env.ARCHDIR_RUBY = read_config('sitearchdir')[0] - - if Options.options.rubylibdir: - self.env.LIBDIR_RUBY = Options.options.rubylibdir - else: - self.env.LIBDIR_RUBY = read_config('sitelibdir')[0] - -@conf -def check_ruby_module(self, module_name): - """ - Check if the selected ruby interpreter can require the given ruby module:: - - def configure(conf): - conf.check_ruby_module('libxml') - - :param module_name: module - :type module_name: string - """ - self.start_msg('Ruby module %s' % module_name) - try: - self.cmd_and_log(self.env.RUBY + ['-e', 'require \'%s\';puts 1' % module_name]) - except Errors.WafError: - self.end_msg(False) - self.fatal('Could not find the ruby module %r' % module_name) - self.end_msg(True) - -@extension('.rb') -def process(self, node): - return self.create_task('run_ruby', node) - -class run_ruby(Task.Task): - """ - Task to run ruby files detected by file extension .rb:: - - def options(opt): - opt.load('ruby') - - def configure(ctx): - ctx.check_ruby_version() - - def build(bld): - bld.env.RBFLAGS = '-e puts "hello world"' - bld(source='a_ruby_file.rb') - """ - run_str = '${RUBY} ${RBFLAGS} -I ${SRC[0].parent.abspath()} ${SRC}' - -def options(opt): - """ - Add the ``--with-ruby-archdir``, ``--with-ruby-libdir`` and ``--with-ruby-binary`` options - """ - opt.add_option('--with-ruby-archdir', type='string', dest='rubyarchdir', help='Specify directory where to install arch specific files') - opt.add_option('--with-ruby-libdir', type='string', dest='rubylibdir', help='Specify alternate ruby library path') - opt.add_option('--with-ruby-binary', type='string', dest='rubybinary', help='Specify alternate ruby binary') - diff --git a/waflib/Tools/suncc.py b/waflib/Tools/suncc.py deleted file mode 100644 index 33d34fc..0000000 --- a/waflib/Tools/suncc.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) -# Ralf Habacker, 2006 (rh) - -from waflib import Errors -from waflib.Tools import ccroot, ar -from waflib.Configure import conf - -@conf -def find_scc(conf): - """ - Detects the Sun C compiler - """ - v = conf.env - cc = conf.find_program('cc', var='CC') - try: - conf.cmd_and_log(cc + ['-flags']) - except Errors.WafError: - conf.fatal('%r is not a Sun compiler' % cc) - v.CC_NAME = 'sun' - conf.get_suncc_version(cc) - -@conf -def scc_common_flags(conf): - """ - Flags required for executing the sun C compiler - """ - v = conf.env - - v.CC_SRC_F = [] - v.CC_TGT_F = ['-c', '-o', ''] - - if not v.LINK_CC: - v.LINK_CC = v.CC - - v.CCLNK_SRC_F = '' - v.CCLNK_TGT_F = ['-o', ''] - v.CPPPATH_ST = '-I%s' - v.DEFINES_ST = '-D%s' - - v.LIB_ST = '-l%s' # template for adding libs - v.LIBPATH_ST = '-L%s' # template for adding libpaths - v.STLIB_ST = '-l%s' - v.STLIBPATH_ST = '-L%s' - - v.SONAME_ST = '-Wl,-h,%s' - v.SHLIB_MARKER = '-Bdynamic' - v.STLIB_MARKER = '-Bstatic' - - v.cprogram_PATTERN = '%s' - - v.CFLAGS_cshlib = ['-xcode=pic32', '-DPIC'] - v.LINKFLAGS_cshlib = ['-G'] - v.cshlib_PATTERN = 'lib%s.so' - - v.LINKFLAGS_cstlib = ['-Bstatic'] - v.cstlib_PATTERN = 'lib%s.a' - -def configure(conf): - conf.find_scc() - conf.find_ar() - conf.scc_common_flags() - conf.cc_load_tools() - conf.cc_add_flags() - conf.link_add_flags() - diff --git a/waflib/Tools/suncxx.py b/waflib/Tools/suncxx.py deleted file mode 100644 index 3b384f6..0000000 --- a/waflib/Tools/suncxx.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) -# Ralf Habacker, 2006 (rh) - -from waflib import Errors -from waflib.Tools import ccroot, ar -from waflib.Configure import conf - -@conf -def find_sxx(conf): - """ - Detects the sun C++ compiler - """ - v = conf.env - cc = conf.find_program(['CC', 'c++'], var='CXX') - try: - conf.cmd_and_log(cc + ['-flags']) - except Errors.WafError: - conf.fatal('%r is not a Sun compiler' % cc) - v.CXX_NAME = 'sun' - conf.get_suncc_version(cc) - -@conf -def sxx_common_flags(conf): - """ - Flags required for executing the sun C++ compiler - """ - v = conf.env - - v.CXX_SRC_F = [] - v.CXX_TGT_F = ['-c', '-o', ''] - - if not v.LINK_CXX: - v.LINK_CXX = v.CXX - - v.CXXLNK_SRC_F = [] - v.CXXLNK_TGT_F = ['-o', ''] - v.CPPPATH_ST = '-I%s' - v.DEFINES_ST = '-D%s' - - v.LIB_ST = '-l%s' # template for adding libs - v.LIBPATH_ST = '-L%s' # template for adding libpaths - v.STLIB_ST = '-l%s' - v.STLIBPATH_ST = '-L%s' - - v.SONAME_ST = '-Wl,-h,%s' - v.SHLIB_MARKER = '-Bdynamic' - v.STLIB_MARKER = '-Bstatic' - - v.cxxprogram_PATTERN = '%s' - - v.CXXFLAGS_cxxshlib = ['-xcode=pic32', '-DPIC'] - v.LINKFLAGS_cxxshlib = ['-G'] - v.cxxshlib_PATTERN = 'lib%s.so' - - v.LINKFLAGS_cxxstlib = ['-Bstatic'] - v.cxxstlib_PATTERN = 'lib%s.a' - -def configure(conf): - conf.find_sxx() - conf.find_ar() - conf.sxx_common_flags() - conf.cxx_load_tools() - conf.cxx_add_flags() - conf.link_add_flags() - diff --git a/waflib/Tools/tex.py b/waflib/Tools/tex.py deleted file mode 100644 index eaf9fdb..0000000 --- a/waflib/Tools/tex.py +++ /dev/null @@ -1,543 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) - -""" -TeX/LaTeX/PDFLaTeX/XeLaTeX support - -Example:: - - def configure(conf): - conf.load('tex') - if not conf.env.LATEX: - conf.fatal('The program LaTex is required') - - def build(bld): - bld( - features = 'tex', - type = 'latex', # pdflatex or xelatex - source = 'document.ltx', # mandatory, the source - outs = 'ps', # 'pdf' or 'ps pdf' - deps = 'crossreferencing.lst', # to give dependencies directly - prompt = 1, # 0 for the batch mode - ) - -Notes: - -- To configure with a special program, use:: - - $ PDFLATEX=luatex waf configure - -- This tool does not use the target attribute of the task generator - (``bld(target=...)``); the target file name is built from the source - base name and the output type(s) -""" - -import os, re -from waflib import Utils, Task, Errors, Logs, Node -from waflib.TaskGen import feature, before_method - -re_bibunit = re.compile(r'\\(?Pputbib)\[(?P[^\[\]]*)\]',re.M) -def bibunitscan(self): - """ - Parses TeX inputs and try to find the *bibunit* file dependencies - - :return: list of bibunit files - :rtype: list of :py:class:`waflib.Node.Node` - """ - node = self.inputs[0] - - nodes = [] - if not node: - return nodes - - code = node.read() - for match in re_bibunit.finditer(code): - path = match.group('file') - if path: - found = None - for k in ('', '.bib'): - # add another loop for the tex include paths? - Logs.debug('tex: trying %s%s', path, k) - fi = node.parent.find_resource(path + k) - if fi: - found = True - nodes.append(fi) - # no break - if not found: - Logs.debug('tex: could not find %s', path) - - Logs.debug('tex: found the following bibunit files: %s', nodes) - return nodes - -exts_deps_tex = ['', '.ltx', '.tex', '.bib', '.pdf', '.png', '.eps', '.ps', '.sty'] -"""List of typical file extensions included in latex files""" - -exts_tex = ['.ltx', '.tex'] -"""List of typical file extensions that contain latex""" - -re_tex = re.compile(r'\\(?Pusepackage|RequirePackage|include|bibliography([^\[\]{}]*)|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P[^{}]*)}',re.M) -"""Regexp for expressions that may include latex files""" - -g_bibtex_re = re.compile('bibdata', re.M) -"""Regexp for bibtex files""" - -g_glossaries_re = re.compile('\\@newglossary', re.M) -"""Regexp for expressions that create glossaries""" - -class tex(Task.Task): - """ - Compiles a tex/latex file. - - .. inheritance-diagram:: waflib.Tools.tex.latex waflib.Tools.tex.xelatex waflib.Tools.tex.pdflatex - """ - - bibtex_fun, _ = Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False) - bibtex_fun.__doc__ = """ - Execute the program **bibtex** - """ - - makeindex_fun, _ = Task.compile_fun('${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}', shell=False) - makeindex_fun.__doc__ = """ - Execute the program **makeindex** - """ - - makeglossaries_fun, _ = Task.compile_fun('${MAKEGLOSSARIES} ${SRCFILE}', shell=False) - makeglossaries_fun.__doc__ = """ - Execute the program **makeglossaries** - """ - - def exec_command(self, cmd, **kw): - """ - Executes TeX commands without buffering (latex may prompt for inputs) - - :return: the return code - :rtype: int - """ - if self.env.PROMPT_LATEX: - # capture the outputs in configuration tests - kw['stdout'] = kw['stderr'] = None - return super(tex, self).exec_command(cmd, **kw) - - def scan_aux(self, node): - """ - Recursive regex-based scanner that finds included auxiliary files. - """ - nodes = [node] - re_aux = re.compile(r'\\@input{(?P[^{}]*)}', re.M) - - def parse_node(node): - code = node.read() - for match in re_aux.finditer(code): - path = match.group('file') - found = node.parent.find_or_declare(path) - if found and found not in nodes: - Logs.debug('tex: found aux node %r', found) - nodes.append(found) - parse_node(found) - parse_node(node) - return nodes - - def scan(self): - """ - Recursive regex-based scanner that finds latex dependencies. It uses :py:attr:`waflib.Tools.tex.re_tex` - - Depending on your needs you might want: - - * to change re_tex:: - - from waflib.Tools import tex - tex.re_tex = myregex - - * or to change the method scan from the latex tasks:: - - from waflib.Task import classes - classes['latex'].scan = myscanfunction - """ - node = self.inputs[0] - - nodes = [] - names = [] - seen = [] - if not node: - return (nodes, names) - - def parse_node(node): - if node in seen: - return - seen.append(node) - code = node.read() - for match in re_tex.finditer(code): - - multibib = match.group('type') - if multibib and multibib.startswith('bibliography'): - multibib = multibib[len('bibliography'):] - if multibib.startswith('style'): - continue - else: - multibib = None - - for path in match.group('file').split(','): - if path: - add_name = True - found = None - for k in exts_deps_tex: - - # issue 1067, scan in all texinputs folders - for up in self.texinputs_nodes: - Logs.debug('tex: trying %s%s', path, k) - found = up.find_resource(path + k) - if found: - break - - - for tsk in self.generator.tasks: - if not found or found in tsk.outputs: - break - else: - nodes.append(found) - add_name = False - for ext in exts_tex: - if found.name.endswith(ext): - parse_node(found) - break - - # multibib stuff - if found and multibib and found.name.endswith('.bib'): - try: - self.multibibs.append(found) - except AttributeError: - self.multibibs = [found] - - # no break, people are crazy - if add_name: - names.append(path) - parse_node(node) - - for x in nodes: - x.parent.get_bld().mkdir() - - Logs.debug("tex: found the following : %s and names %s", nodes, names) - return (nodes, names) - - def check_status(self, msg, retcode): - """ - Checks an exit status and raise an error with a particular message - - :param msg: message to display if the code is non-zero - :type msg: string - :param retcode: condition - :type retcode: boolean - """ - if retcode != 0: - raise Errors.WafError('%r command exit status %r' % (msg, retcode)) - - def info(self, *k, **kw): - try: - info = self.generator.bld.conf.logger.info - except AttributeError: - info = Logs.info - info(*k, **kw) - - def bibfile(self): - """ - Parses *.aux* files to find bibfiles to process. - If present, execute :py:meth:`waflib.Tools.tex.tex.bibtex_fun` - """ - for aux_node in self.aux_nodes: - try: - ct = aux_node.read() - except EnvironmentError: - Logs.error('Error reading %s: %r', aux_node.abspath()) - continue - - if g_bibtex_re.findall(ct): - self.info('calling bibtex') - - self.env.env = {} - self.env.env.update(os.environ) - self.env.env.update({'BIBINPUTS': self.texinputs(), 'BSTINPUTS': self.texinputs()}) - self.env.SRCFILE = aux_node.name[:-4] - self.check_status('error when calling bibtex', self.bibtex_fun()) - - for node in getattr(self, 'multibibs', []): - self.env.env = {} - self.env.env.update(os.environ) - self.env.env.update({'BIBINPUTS': self.texinputs(), 'BSTINPUTS': self.texinputs()}) - self.env.SRCFILE = node.name[:-4] - self.check_status('error when calling bibtex', self.bibtex_fun()) - - def bibunits(self): - """ - Parses *.aux* file to find bibunit files. If there are bibunit files, - runs :py:meth:`waflib.Tools.tex.tex.bibtex_fun`. - """ - try: - bibunits = bibunitscan(self) - except OSError: - Logs.error('error bibunitscan') - else: - if bibunits: - fn = ['bu' + str(i) for i in range(1, len(bibunits) + 1)] - if fn: - self.info('calling bibtex on bibunits') - - for f in fn: - self.env.env = {'BIBINPUTS': self.texinputs(), 'BSTINPUTS': self.texinputs()} - self.env.SRCFILE = f - self.check_status('error when calling bibtex', self.bibtex_fun()) - - def makeindex(self): - """ - Searches the filesystem for *.idx* files to process. If present, - runs :py:meth:`waflib.Tools.tex.tex.makeindex_fun` - """ - self.idx_node = self.inputs[0].change_ext('.idx') - try: - idx_path = self.idx_node.abspath() - os.stat(idx_path) - except OSError: - self.info('index file %s absent, not calling makeindex', idx_path) - else: - self.info('calling makeindex') - - self.env.SRCFILE = self.idx_node.name - self.env.env = {} - self.check_status('error when calling makeindex %s' % idx_path, self.makeindex_fun()) - - def bibtopic(self): - """ - Lists additional .aux files from the bibtopic package - """ - p = self.inputs[0].parent.get_bld() - if os.path.exists(os.path.join(p.abspath(), 'btaux.aux')): - self.aux_nodes += p.ant_glob('*[0-9].aux') - - def makeglossaries(self): - """ - Lists additional glossaries from .aux files. If present, runs the makeglossaries program. - """ - src_file = self.inputs[0].abspath() - base_file = os.path.basename(src_file) - base, _ = os.path.splitext(base_file) - for aux_node in self.aux_nodes: - try: - ct = aux_node.read() - except EnvironmentError: - Logs.error('Error reading %s: %r', aux_node.abspath()) - continue - - if g_glossaries_re.findall(ct): - if not self.env.MAKEGLOSSARIES: - raise Errors.WafError("The program 'makeglossaries' is missing!") - Logs.warn('calling makeglossaries') - self.env.SRCFILE = base - self.check_status('error when calling makeglossaries %s' % base, self.makeglossaries_fun()) - return - - def texinputs(self): - """ - Returns the list of texinput nodes as a string suitable for the TEXINPUTS environment variables - - :rtype: string - """ - return os.pathsep.join([k.abspath() for k in self.texinputs_nodes]) + os.pathsep - - def run(self): - """ - Runs the whole TeX build process - - Multiple passes are required depending on the usage of cross-references, - bibliographies, glossaries, indexes and additional contents - The appropriate TeX compiler is called until the *.aux* files stop changing. - """ - env = self.env - - if not env.PROMPT_LATEX: - env.append_value('LATEXFLAGS', '-interaction=batchmode') - env.append_value('PDFLATEXFLAGS', '-interaction=batchmode') - env.append_value('XELATEXFLAGS', '-interaction=batchmode') - - # important, set the cwd for everybody - self.cwd = self.inputs[0].parent.get_bld() - - self.info('first pass on %s', self.__class__.__name__) - - # Hash .aux files before even calling the LaTeX compiler - cur_hash = self.hash_aux_nodes() - - self.call_latex() - - # Find the .aux files again since bibtex processing can require it - self.hash_aux_nodes() - - self.bibtopic() - self.bibfile() - self.bibunits() - self.makeindex() - self.makeglossaries() - - for i in range(10): - # There is no need to call latex again if the .aux hash value has not changed - prev_hash = cur_hash - cur_hash = self.hash_aux_nodes() - if not cur_hash: - Logs.error('No aux.h to process') - if cur_hash and cur_hash == prev_hash: - break - - # run the command - self.info('calling %s', self.__class__.__name__) - self.call_latex() - - def hash_aux_nodes(self): - """ - Returns a hash of the .aux file contents - - :rtype: string or bytes - """ - try: - self.aux_nodes - except AttributeError: - try: - self.aux_nodes = self.scan_aux(self.inputs[0].change_ext('.aux')) - except IOError: - return None - return Utils.h_list([Utils.h_file(x.abspath()) for x in self.aux_nodes]) - - def call_latex(self): - """ - Runs the TeX compiler once - """ - self.env.env = {} - self.env.env.update(os.environ) - self.env.env.update({'TEXINPUTS': self.texinputs()}) - self.env.SRCFILE = self.inputs[0].abspath() - self.check_status('error when calling latex', self.texfun()) - -class latex(tex): - "Compiles LaTeX files" - texfun, vars = Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) - -class pdflatex(tex): - "Compiles PdfLaTeX files" - texfun, vars = Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) - -class xelatex(tex): - "XeLaTeX files" - texfun, vars = Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}', shell=False) - -class dvips(Task.Task): - "Converts dvi files to postscript" - run_str = '${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}' - color = 'BLUE' - after = ['latex', 'pdflatex', 'xelatex'] - -class dvipdf(Task.Task): - "Converts dvi files to pdf" - run_str = '${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}' - color = 'BLUE' - after = ['latex', 'pdflatex', 'xelatex'] - -class pdf2ps(Task.Task): - "Converts pdf files to postscript" - run_str = '${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}' - color = 'BLUE' - after = ['latex', 'pdflatex', 'xelatex'] - -@feature('tex') -@before_method('process_source') -def apply_tex(self): - """ - Creates :py:class:`waflib.Tools.tex.tex` objects, and - dvips/dvipdf/pdf2ps tasks if necessary (outs='ps', etc). - """ - if not getattr(self, 'type', None) in ('latex', 'pdflatex', 'xelatex'): - self.type = 'pdflatex' - - outs = Utils.to_list(getattr(self, 'outs', [])) - - # prompt for incomplete files (else the batchmode is used) - try: - self.generator.bld.conf - except AttributeError: - default_prompt = False - else: - default_prompt = True - self.env.PROMPT_LATEX = getattr(self, 'prompt', default_prompt) - - deps_lst = [] - - if getattr(self, 'deps', None): - deps = self.to_list(self.deps) - for dep in deps: - if isinstance(dep, str): - n = self.path.find_resource(dep) - if not n: - self.bld.fatal('Could not find %r for %r' % (dep, self)) - if not n in deps_lst: - deps_lst.append(n) - elif isinstance(dep, Node.Node): - deps_lst.append(dep) - - for node in self.to_nodes(self.source): - if self.type == 'latex': - task = self.create_task('latex', node, node.change_ext('.dvi')) - elif self.type == 'pdflatex': - task = self.create_task('pdflatex', node, node.change_ext('.pdf')) - elif self.type == 'xelatex': - task = self.create_task('xelatex', node, node.change_ext('.pdf')) - - task.env = self.env - - # add the manual dependencies - if deps_lst: - for n in deps_lst: - if not n in task.dep_nodes: - task.dep_nodes.append(n) - - # texinputs is a nasty beast - if hasattr(self, 'texinputs_nodes'): - task.texinputs_nodes = self.texinputs_nodes - else: - task.texinputs_nodes = [node.parent, node.parent.get_bld(), self.path, self.path.get_bld()] - lst = os.environ.get('TEXINPUTS', '') - if self.env.TEXINPUTS: - lst += os.pathsep + self.env.TEXINPUTS - if lst: - lst = lst.split(os.pathsep) - for x in lst: - if x: - if os.path.isabs(x): - p = self.bld.root.find_node(x) - if p: - task.texinputs_nodes.append(p) - else: - Logs.error('Invalid TEXINPUTS folder %s', x) - else: - Logs.error('Cannot resolve relative paths in TEXINPUTS %s', x) - - if self.type == 'latex': - if 'ps' in outs: - tsk = self.create_task('dvips', task.outputs, node.change_ext('.ps')) - tsk.env.env = dict(os.environ) - if 'pdf' in outs: - tsk = self.create_task('dvipdf', task.outputs, node.change_ext('.pdf')) - tsk.env.env = dict(os.environ) - elif self.type == 'pdflatex': - if 'ps' in outs: - self.create_task('pdf2ps', task.outputs, node.change_ext('.ps')) - self.source = [] - -def configure(self): - """ - Find the programs tex, latex and others without raising errors. - """ - v = self.env - for p in 'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps makeglossaries'.split(): - try: - self.find_program(p, var=p.upper()) - except self.errors.ConfigurationError: - pass - v.DVIPSFLAGS = '-Ppdf' - diff --git a/waflib/Tools/vala.py b/waflib/Tools/vala.py deleted file mode 100644 index 822ec50..0000000 --- a/waflib/Tools/vala.py +++ /dev/null @@ -1,355 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Ali Sabil, 2007 -# Radosław Szkodziński, 2010 - -""" -At this point, vala is still unstable, so do not expect -this tool to be too stable either (apis, etc) -""" - -import re -from waflib import Build, Context, Errors, Logs, Node, Options, Task, Utils -from waflib.TaskGen import extension, taskgen_method -from waflib.Configure import conf - -class valac(Task.Task): - """ - Compiles vala files - """ - #run_str = "${VALAC} ${VALAFLAGS}" # ideally - #vars = ['VALAC_VERSION'] - vars = ["VALAC", "VALAC_VERSION", "VALAFLAGS"] - ext_out = ['.h'] - - def run(self): - cmd = self.env.VALAC + self.env.VALAFLAGS - resources = getattr(self, 'vala_exclude', []) - cmd.extend([a.abspath() for a in self.inputs if a not in resources]) - ret = self.exec_command(cmd, cwd=self.vala_dir_node.abspath()) - - if ret: - return ret - - if self.generator.dump_deps_node: - self.generator.dump_deps_node.write('\n'.join(self.generator.packages)) - - return ret - -@taskgen_method -def init_vala_task(self): - """ - Initializes the vala task with the relevant data (acts as a constructor) - """ - self.profile = getattr(self, 'profile', 'gobject') - - self.packages = packages = Utils.to_list(getattr(self, 'packages', [])) - self.use = Utils.to_list(getattr(self, 'use', [])) - if packages and not self.use: - self.use = packages[:] # copy - - if self.profile == 'gobject': - if not 'GOBJECT' in self.use: - self.use.append('GOBJECT') - - def addflags(flags): - self.env.append_value('VALAFLAGS', flags) - - if self.profile: - addflags('--profile=%s' % self.profile) - - valatask = self.valatask - - # output directory - if hasattr(self, 'vala_dir'): - if isinstance(self.vala_dir, str): - valatask.vala_dir_node = self.path.get_bld().make_node(self.vala_dir) - try: - valatask.vala_dir_node.mkdir() - except OSError: - raise self.bld.fatal('Cannot create the vala dir %r' % valatask.vala_dir_node) - else: - valatask.vala_dir_node = self.vala_dir - else: - valatask.vala_dir_node = self.path.get_bld() - addflags('--directory=%s' % valatask.vala_dir_node.abspath()) - - if hasattr(self, 'thread'): - if self.profile == 'gobject': - if not 'GTHREAD' in self.use: - self.use.append('GTHREAD') - else: - #Vala doesn't have threading support for dova nor posix - Logs.warn('Profile %s means no threading support', self.profile) - self.thread = False - - if self.thread: - addflags('--thread') - - self.is_lib = 'cprogram' not in self.features - if self.is_lib: - addflags('--library=%s' % self.target) - - h_node = valatask.vala_dir_node.find_or_declare('%s.h' % self.target) - valatask.outputs.append(h_node) - addflags('--header=%s' % h_node.name) - - valatask.outputs.append(valatask.vala_dir_node.find_or_declare('%s.vapi' % self.target)) - - if getattr(self, 'gir', None): - gir_node = valatask.vala_dir_node.find_or_declare('%s.gir' % self.gir) - addflags('--gir=%s' % gir_node.name) - valatask.outputs.append(gir_node) - - self.vala_target_glib = getattr(self, 'vala_target_glib', getattr(Options.options, 'vala_target_glib', None)) - if self.vala_target_glib: - addflags('--target-glib=%s' % self.vala_target_glib) - - addflags(['--define=%s' % x for x in Utils.to_list(getattr(self, 'vala_defines', []))]) - - packages_private = Utils.to_list(getattr(self, 'packages_private', [])) - addflags(['--pkg=%s' % x for x in packages_private]) - - def _get_api_version(): - api_version = '1.0' - if hasattr(Context.g_module, 'API_VERSION'): - version = Context.g_module.API_VERSION.split(".") - if version[0] == "0": - api_version = "0." + version[1] - else: - api_version = version[0] + ".0" - return api_version - - self.includes = Utils.to_list(getattr(self, 'includes', [])) - valatask.install_path = getattr(self, 'install_path', '') - - valatask.vapi_path = getattr(self, 'vapi_path', '${DATAROOTDIR}/vala/vapi') - valatask.pkg_name = getattr(self, 'pkg_name', self.env.PACKAGE) - valatask.header_path = getattr(self, 'header_path', '${INCLUDEDIR}/%s-%s' % (valatask.pkg_name, _get_api_version())) - valatask.install_binding = getattr(self, 'install_binding', True) - - self.vapi_dirs = vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', [])) - #includes = [] - - if hasattr(self, 'use'): - local_packages = Utils.to_list(self.use)[:] # make sure to have a copy - seen = [] - while len(local_packages) > 0: - package = local_packages.pop() - if package in seen: - continue - seen.append(package) - - # check if the package exists - try: - package_obj = self.bld.get_tgen_by_name(package) - except Errors.WafError: - continue - - # in practice the other task is already processed - # but this makes it explicit - package_obj.post() - package_name = package_obj.target - task = getattr(package_obj, 'valatask', None) - if task: - for output in task.outputs: - if output.name == package_name + ".vapi": - valatask.set_run_after(task) - if package_name not in packages: - packages.append(package_name) - if output.parent not in vapi_dirs: - vapi_dirs.append(output.parent) - if output.parent not in self.includes: - self.includes.append(output.parent) - - if hasattr(package_obj, 'use'): - lst = self.to_list(package_obj.use) - lst.reverse() - local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages - - addflags(['--pkg=%s' % p for p in packages]) - - for vapi_dir in vapi_dirs: - if isinstance(vapi_dir, Node.Node): - v_node = vapi_dir - else: - v_node = self.path.find_dir(vapi_dir) - if not v_node: - Logs.warn('Unable to locate Vala API directory: %r', vapi_dir) - else: - addflags('--vapidir=%s' % v_node.abspath()) - - self.dump_deps_node = None - if self.is_lib and self.packages: - self.dump_deps_node = valatask.vala_dir_node.find_or_declare('%s.deps' % self.target) - valatask.outputs.append(self.dump_deps_node) - - if self.is_lib and valatask.install_binding: - headers_list = [o for o in valatask.outputs if o.suffix() == ".h"] - if headers_list: - self.install_vheader = self.add_install_files(install_to=valatask.header_path, install_from=headers_list) - - vapi_list = [o for o in valatask.outputs if (o.suffix() in (".vapi", ".deps"))] - if vapi_list: - self.install_vapi = self.add_install_files(install_to=valatask.vapi_path, install_from=vapi_list) - - gir_list = [o for o in valatask.outputs if o.suffix() == '.gir'] - if gir_list: - self.install_gir = self.add_install_files( - install_to=getattr(self, 'gir_path', '${DATAROOTDIR}/gir-1.0'), install_from=gir_list) - - if hasattr(self, 'vala_resources'): - nodes = self.to_nodes(self.vala_resources) - valatask.vala_exclude = getattr(valatask, 'vala_exclude', []) + nodes - valatask.inputs.extend(nodes) - for x in nodes: - addflags(['--gresources', x.abspath()]) - -@extension('.vala', '.gs') -def vala_file(self, node): - """ - Compile a vala file and bind the task to *self.valatask*. If an existing vala task is already set, add the node - to its inputs. The typical example is:: - - def build(bld): - bld.program( - packages = 'gtk+-2.0', - target = 'vala-gtk-example', - use = 'GTK GLIB', - source = 'vala-gtk-example.vala foo.vala', - vala_defines = ['DEBUG'] # adds --define= values to the command-line - - # the following arguments are for libraries - #gir = 'hello-1.0', - #gir_path = '/tmp', - #vapi_path = '/tmp', - #pkg_name = 'hello' - # disable installing of gir, vapi and header - #install_binding = False - - # profile = 'xyz' # adds --profile= to enable profiling - # thread = True, # adds --thread, except if profile is on or not on 'gobject' - # vala_target_glib = 'xyz' # adds --target-glib=, can be given through the command-line option --vala-target-glib= - ) - - - :param node: vala file - :type node: :py:class:`waflib.Node.Node` - """ - - try: - valatask = self.valatask - except AttributeError: - valatask = self.valatask = self.create_task('valac') - self.init_vala_task() - - valatask.inputs.append(node) - name = node.name[:node.name.rfind('.')] + '.c' - c_node = valatask.vala_dir_node.find_or_declare(name) - valatask.outputs.append(c_node) - self.source.append(c_node) - -@extension('.vapi') -def vapi_file(self, node): - try: - valatask = self.valatask - except AttributeError: - valatask = self.valatask = self.create_task('valac') - self.init_vala_task() - valatask.inputs.append(node) - -@conf -def find_valac(self, valac_name, min_version): - """ - Find the valac program, and execute it to store the version - number in *conf.env.VALAC_VERSION* - - :param valac_name: program name - :type valac_name: string or list of string - :param min_version: minimum version acceptable - :type min_version: tuple of int - """ - valac = self.find_program(valac_name, var='VALAC') - try: - output = self.cmd_and_log(valac + ['--version']) - except Errors.WafError: - valac_version = None - else: - ver = re.search(r'\d+.\d+.\d+', output).group().split('.') - valac_version = tuple([int(x) for x in ver]) - - self.msg('Checking for %s version >= %r' % (valac_name, min_version), - valac_version, valac_version and valac_version >= min_version) - if valac and valac_version < min_version: - self.fatal("%s version %r is too old, need >= %r" % (valac_name, valac_version, min_version)) - - self.env.VALAC_VERSION = valac_version - return valac - -@conf -def check_vala(self, min_version=(0,8,0), branch=None): - """ - Check if vala compiler from a given branch exists of at least a given - version. - - :param min_version: minimum version acceptable (0.8.0) - :type min_version: tuple - :param branch: first part of the version number, in case a snapshot is used (0, 8) - :type branch: tuple of int - """ - if self.env.VALA_MINVER: - min_version = self.env.VALA_MINVER - if self.env.VALA_MINVER_BRANCH: - branch = self.env.VALA_MINVER_BRANCH - if not branch: - branch = min_version[:2] - try: - find_valac(self, 'valac-%d.%d' % (branch[0], branch[1]), min_version) - except self.errors.ConfigurationError: - find_valac(self, 'valac', min_version) - -@conf -def check_vala_deps(self): - """ - Load the gobject and gthread packages if they are missing. - """ - if not self.env.HAVE_GOBJECT: - pkg_args = {'package': 'gobject-2.0', - 'uselib_store': 'GOBJECT', - 'args': '--cflags --libs'} - if getattr(Options.options, 'vala_target_glib', None): - pkg_args['atleast_version'] = Options.options.vala_target_glib - self.check_cfg(**pkg_args) - - if not self.env.HAVE_GTHREAD: - pkg_args = {'package': 'gthread-2.0', - 'uselib_store': 'GTHREAD', - 'args': '--cflags --libs'} - if getattr(Options.options, 'vala_target_glib', None): - pkg_args['atleast_version'] = Options.options.vala_target_glib - self.check_cfg(**pkg_args) - -def configure(self): - """ - Use the following to enforce minimum vala version:: - - def configure(conf): - conf.env.VALA_MINVER = (0, 10, 0) - conf.load('vala') - """ - self.load('gnu_dirs') - self.check_vala_deps() - self.check_vala() - self.add_os_flags('VALAFLAGS') - self.env.append_unique('VALAFLAGS', ['-C']) - -def options(opt): - """ - Load the :py:mod:`waflib.Tools.gnu_dirs` tool and add the ``--vala-target-glib`` command-line option - """ - opt.load('gnu_dirs') - valaopts = opt.add_option_group('Vala Compiler Options') - valaopts.add_option('--vala-target-glib', default=None, - dest='vala_target_glib', metavar='MAJOR.MINOR', - help='Target version of glib for Vala GObject code generation') - diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py deleted file mode 100644 index 74d6c05..0000000 --- a/waflib/Tools/waf_unit_test.py +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Carlos Rafael Giani, 2006 -# Thomas Nagy, 2010-2018 (ita) - -""" -Unit testing system for C/C++/D and interpreted languages providing test execution: - -* in parallel, by using ``waf -j`` -* partial (only the tests that have changed) or full (by using ``waf --alltests``) - -The tests are declared by adding the **test** feature to programs:: - - def options(opt): - opt.load('compiler_cxx waf_unit_test') - def configure(conf): - conf.load('compiler_cxx waf_unit_test') - def build(bld): - bld(features='cxx cxxprogram test', source='main.cpp', target='app') - # or - bld.program(features='test', source='main2.cpp', target='app2') - -When the build is executed, the program 'test' will be built and executed without arguments. -The success/failure is detected by looking at the return code. The status and the standard output/error -are stored on the build context. - -The results can be displayed by registering a callback function. Here is how to call -the predefined callback:: - - def build(bld): - bld(features='cxx cxxprogram test', source='main.c', target='app') - from waflib.Tools import waf_unit_test - bld.add_post_fun(waf_unit_test.summary) - -By passing --dump-test-scripts the build outputs corresponding python files -(with extension _run.py) that are useful for debugging purposes. -""" - -import os, shlex, sys -from waflib.TaskGen import feature, after_method, taskgen_method -from waflib import Utils, Task, Logs, Options -from waflib.Tools import ccroot -testlock = Utils.threading.Lock() - -SCRIPT_TEMPLATE = """#! %(python)s -import subprocess, sys -cmd = %(cmd)r -# if you want to debug with gdb: -#cmd = ['gdb', '-args'] + cmd -env = %(env)r -status = subprocess.call(cmd, env=env, cwd=%(cwd)r, shell=isinstance(cmd, str)) -sys.exit(status) -""" - -@taskgen_method -def handle_ut_cwd(self, key): - """ - Task generator method, used internally to limit code duplication. - This method may disappear anytime. - """ - cwd = getattr(self, key, None) - if cwd: - if isinstance(cwd, str): - # we want a Node instance - if os.path.isabs(cwd): - self.ut_cwd = self.bld.root.make_node(cwd) - else: - self.ut_cwd = self.path.make_node(cwd) - -@feature('test_scripts') -def make_interpreted_test(self): - """Create interpreted unit tests.""" - for x in ['test_scripts_source', 'test_scripts_template']: - if not hasattr(self, x): - Logs.warn('a test_scripts taskgen i missing %s' % x) - return - - self.ut_run, lst = Task.compile_fun(self.test_scripts_template, shell=getattr(self, 'test_scripts_shell', False)) - - script_nodes = self.to_nodes(self.test_scripts_source) - for script_node in script_nodes: - tsk = self.create_task('utest', [script_node]) - tsk.vars = lst + tsk.vars - tsk.env['SCRIPT'] = script_node.path_from(tsk.get_cwd()) - - self.handle_ut_cwd('test_scripts_cwd') - - env = getattr(self, 'test_scripts_env', None) - if env: - self.ut_env = env - else: - self.ut_env = dict(os.environ) - - paths = getattr(self, 'test_scripts_paths', {}) - for (k,v) in paths.items(): - p = self.ut_env.get(k, '').split(os.pathsep) - if isinstance(v, str): - v = v.split(os.pathsep) - self.ut_env[k] = os.pathsep.join(p + v) - -@feature('test') -@after_method('apply_link', 'process_use') -def make_test(self): - """Create the unit test task. There can be only one unit test task by task generator.""" - if not getattr(self, 'link_task', None): - return - - tsk = self.create_task('utest', self.link_task.outputs) - if getattr(self, 'ut_str', None): - self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) - tsk.vars = lst + tsk.vars - - self.handle_ut_cwd('ut_cwd') - - if not hasattr(self, 'ut_paths'): - paths = [] - for x in self.tmp_use_sorted: - try: - y = self.bld.get_tgen_by_name(x).link_task - except AttributeError: - pass - else: - if not isinstance(y, ccroot.stlink_task): - paths.append(y.outputs[0].parent.abspath()) - self.ut_paths = os.pathsep.join(paths) + os.pathsep - - if not hasattr(self, 'ut_env'): - self.ut_env = dct = dict(os.environ) - def add_path(var): - dct[var] = self.ut_paths + dct.get(var,'') - if Utils.is_win32: - add_path('PATH') - elif Utils.unversioned_sys_platform() == 'darwin': - add_path('DYLD_LIBRARY_PATH') - add_path('LD_LIBRARY_PATH') - else: - add_path('LD_LIBRARY_PATH') - - if not hasattr(self, 'ut_cmd'): - self.ut_cmd = getattr(Options.options, 'testcmd', False) - -@taskgen_method -def add_test_results(self, tup): - """Override and return tup[1] to interrupt the build immediately if a test does not run""" - Logs.debug("ut: %r", tup) - try: - self.utest_results.append(tup) - except AttributeError: - self.utest_results = [tup] - try: - self.bld.utest_results.append(tup) - except AttributeError: - self.bld.utest_results = [tup] - -@Task.deep_inputs -class utest(Task.Task): - """ - Execute a unit test - """ - color = 'PINK' - after = ['vnum', 'inst'] - vars = [] - - def runnable_status(self): - """ - Always execute the task if `waf --alltests` was used or no - tests if ``waf --notests`` was used - """ - if getattr(Options.options, 'no_tests', False): - return Task.SKIP_ME - - ret = super(utest, self).runnable_status() - if ret == Task.SKIP_ME: - if getattr(Options.options, 'all_tests', False): - return Task.RUN_ME - return ret - - def get_test_env(self): - """ - In general, tests may require any library built anywhere in the project. - Override this method if fewer paths are needed - """ - return self.generator.ut_env - - def post_run(self): - super(utest, self).post_run() - if getattr(Options.options, 'clear_failed_tests', False) and self.waf_unit_test_results[1]: - self.generator.bld.task_sigs[self.uid()] = None - - def run(self): - """ - Execute the test. The execution is always successful, and the results - are stored on ``self.generator.bld.utest_results`` for postprocessing. - - Override ``add_test_results`` to interrupt the build - """ - if hasattr(self.generator, 'ut_run'): - return self.generator.ut_run(self) - - self.ut_exec = getattr(self.generator, 'ut_exec', [self.inputs[0].abspath()]) - ut_cmd = getattr(self.generator, 'ut_cmd', False) - if ut_cmd: - self.ut_exec = shlex.split(ut_cmd % ' '.join(self.ut_exec)) - - return self.exec_command(self.ut_exec) - - def exec_command(self, cmd, **kw): - self.generator.bld.log_command(cmd, kw) - if getattr(Options.options, 'dump_test_scripts', False): - script_code = SCRIPT_TEMPLATE % { - 'python': sys.executable, - 'env': self.get_test_env(), - 'cwd': self.get_cwd().abspath(), - 'cmd': cmd - } - script_file = self.inputs[0].abspath() + '_run.py' - Utils.writef(script_file, script_code) - os.chmod(script_file, Utils.O755) - if Logs.verbose > 1: - Logs.info('Test debug file written as %r' % script_file) - - proc = Utils.subprocess.Popen(cmd, cwd=self.get_cwd().abspath(), env=self.get_test_env(), - stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE, shell=isinstance(cmd,str)) - (stdout, stderr) = proc.communicate() - self.waf_unit_test_results = tup = (self.inputs[0].abspath(), proc.returncode, stdout, stderr) - testlock.acquire() - try: - return self.generator.add_test_results(tup) - finally: - testlock.release() - - def get_cwd(self): - return getattr(self.generator, 'ut_cwd', self.inputs[0].parent) - -def summary(bld): - """ - Display an execution summary:: - - def build(bld): - bld(features='cxx cxxprogram test', source='main.c', target='app') - from waflib.Tools import waf_unit_test - bld.add_post_fun(waf_unit_test.summary) - """ - lst = getattr(bld, 'utest_results', []) - if lst: - Logs.pprint('CYAN', 'execution summary') - - total = len(lst) - tfail = len([x for x in lst if x[1]]) - - Logs.pprint('GREEN', ' tests that pass %d/%d' % (total-tfail, total)) - for (f, code, out, err) in lst: - if not code: - Logs.pprint('GREEN', ' %s' % f) - - Logs.pprint('GREEN' if tfail == 0 else 'RED', ' tests that fail %d/%d' % (tfail, total)) - for (f, code, out, err) in lst: - if code: - Logs.pprint('RED', ' %s' % f) - -def set_exit_code(bld): - """ - If any of the tests fail waf will exit with that exit code. - This is useful if you have an automated build system which need - to report on errors from the tests. - You may use it like this: - - def build(bld): - bld(features='cxx cxxprogram test', source='main.c', target='app') - from waflib.Tools import waf_unit_test - bld.add_post_fun(waf_unit_test.set_exit_code) - """ - lst = getattr(bld, 'utest_results', []) - for (f, code, out, err) in lst: - if code: - msg = [] - if out: - msg.append('stdout:%s%s' % (os.linesep, out.decode('utf-8'))) - if err: - msg.append('stderr:%s%s' % (os.linesep, err.decode('utf-8'))) - bld.fatal(os.linesep.join(msg)) - - -def options(opt): - """ - Provide the ``--alltests``, ``--notests`` and ``--testcmd`` command-line options. - """ - opt.add_option('--notests', action='store_true', default=False, help='Exec no unit tests', dest='no_tests') - opt.add_option('--alltests', action='store_true', default=False, help='Exec all unit tests', dest='all_tests') - opt.add_option('--clear-failed', action='store_true', default=False, - help='Force failed unit tests to run again next time', dest='clear_failed_tests') - opt.add_option('--testcmd', action='store', default=False, dest='testcmd', - help='Run the unit tests using the test-cmd string example "--testcmd="valgrind --error-exitcode=1 %s" to run under valgrind') - opt.add_option('--dump-test-scripts', action='store_true', default=False, - help='Create python scripts to help debug tests', dest='dump_test_scripts') - diff --git a/waflib/Tools/winres.py b/waflib/Tools/winres.py deleted file mode 100644 index 9be1ed6..0000000 --- a/waflib/Tools/winres.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Brant Young, 2007 - -"Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}" - -import re -from waflib import Task -from waflib.TaskGen import extension -from waflib.Tools import c_preproc - -@extension('.rc') -def rc_file(self, node): - """ - Binds the .rc extension to a winrc task - """ - obj_ext = '.rc.o' - if self.env.WINRC_TGT_F == '/fo': - obj_ext = '.res' - rctask = self.create_task('winrc', node, node.change_ext(obj_ext)) - try: - self.compiled_tasks.append(rctask) - except AttributeError: - self.compiled_tasks = [rctask] - -re_lines = re.compile( - r'(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|'\ - r'(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)', - re.IGNORECASE | re.MULTILINE) - -class rc_parser(c_preproc.c_parser): - """ - Calculates dependencies in .rc files - """ - def filter_comments(self, node): - """ - Overrides :py:meth:`waflib.Tools.c_preproc.c_parser.filter_comments` - """ - code = node.read() - if c_preproc.use_trigraphs: - for (a, b) in c_preproc.trig_def: - code = code.split(a).join(b) - code = c_preproc.re_nl.sub('', code) - code = c_preproc.re_cpp.sub(c_preproc.repl, code) - ret = [] - for m in re.finditer(re_lines, code): - if m.group(2): - ret.append((m.group(2), m.group(3))) - else: - ret.append(('include', m.group(5))) - return ret - -class winrc(Task.Task): - """ - Compiles resource files - """ - run_str = '${WINRC} ${WINRCFLAGS} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' - color = 'BLUE' - def scan(self): - tmp = rc_parser(self.generator.includes_nodes) - tmp.start(self.inputs[0], self.env) - return (tmp.nodes, tmp.names) - -def configure(conf): - """ - Detects the programs RC or windres, depending on the C/C++ compiler in use - """ - v = conf.env - if not v.WINRC: - if v.CC_NAME == 'msvc': - conf.find_program('RC', var='WINRC', path_list=v.PATH) - v.WINRC_TGT_F = '/fo' - v.WINRC_SRC_F = '' - else: - conf.find_program('windres', var='WINRC', path_list=v.PATH) - v.WINRC_TGT_F = '-o' - v.WINRC_SRC_F = '-i' - diff --git a/waflib/Tools/xlc.py b/waflib/Tools/xlc.py deleted file mode 100644 index 134dd41..0000000 --- a/waflib/Tools/xlc.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) -# Ralf Habacker, 2006 (rh) -# Yinon Ehrlich, 2009 -# Michael Kuhn, 2009 - -from waflib.Tools import ccroot, ar -from waflib.Configure import conf - -@conf -def find_xlc(conf): - """ - Detects the Aix C compiler - """ - cc = conf.find_program(['xlc_r', 'xlc'], var='CC') - conf.get_xlc_version(cc) - conf.env.CC_NAME = 'xlc' - -@conf -def xlc_common_flags(conf): - """ - Flags required for executing the Aix C compiler - """ - v = conf.env - - v.CC_SRC_F = [] - v.CC_TGT_F = ['-c', '-o'] - - if not v.LINK_CC: - v.LINK_CC = v.CC - - v.CCLNK_SRC_F = [] - v.CCLNK_TGT_F = ['-o'] - v.CPPPATH_ST = '-I%s' - v.DEFINES_ST = '-D%s' - - v.LIB_ST = '-l%s' # template for adding libs - v.LIBPATH_ST = '-L%s' # template for adding libpaths - v.STLIB_ST = '-l%s' - v.STLIBPATH_ST = '-L%s' - v.RPATH_ST = '-Wl,-rpath,%s' - - v.SONAME_ST = [] - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - - v.LINKFLAGS_cprogram = ['-Wl,-brtl'] - v.cprogram_PATTERN = '%s' - - v.CFLAGS_cshlib = ['-fPIC'] - v.LINKFLAGS_cshlib = ['-G', '-Wl,-brtl,-bexpfull'] - v.cshlib_PATTERN = 'lib%s.so' - - v.LINKFLAGS_cstlib = [] - v.cstlib_PATTERN = 'lib%s.a' - -def configure(conf): - conf.find_xlc() - conf.find_ar() - conf.xlc_common_flags() - conf.cc_load_tools() - conf.cc_add_flags() - conf.link_add_flags() - diff --git a/waflib/Tools/xlcxx.py b/waflib/Tools/xlcxx.py deleted file mode 100644 index 76aa59b..0000000 --- a/waflib/Tools/xlcxx.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2018 (ita) -# Ralf Habacker, 2006 (rh) -# Yinon Ehrlich, 2009 -# Michael Kuhn, 2009 - -from waflib.Tools import ccroot, ar -from waflib.Configure import conf - -@conf -def find_xlcxx(conf): - """ - Detects the Aix C++ compiler - """ - cxx = conf.find_program(['xlc++_r', 'xlc++'], var='CXX') - conf.get_xlc_version(cxx) - conf.env.CXX_NAME = 'xlc++' - -@conf -def xlcxx_common_flags(conf): - """ - Flags required for executing the Aix C++ compiler - """ - v = conf.env - - v.CXX_SRC_F = [] - v.CXX_TGT_F = ['-c', '-o'] - - if not v.LINK_CXX: - v.LINK_CXX = v.CXX - - v.CXXLNK_SRC_F = [] - v.CXXLNK_TGT_F = ['-o'] - v.CPPPATH_ST = '-I%s' - v.DEFINES_ST = '-D%s' - - v.LIB_ST = '-l%s' # template for adding libs - v.LIBPATH_ST = '-L%s' # template for adding libpaths - v.STLIB_ST = '-l%s' - v.STLIBPATH_ST = '-L%s' - v.RPATH_ST = '-Wl,-rpath,%s' - - v.SONAME_ST = [] - v.SHLIB_MARKER = [] - v.STLIB_MARKER = [] - - v.LINKFLAGS_cxxprogram= ['-Wl,-brtl'] - v.cxxprogram_PATTERN = '%s' - - v.CXXFLAGS_cxxshlib = ['-fPIC'] - v.LINKFLAGS_cxxshlib = ['-G', '-Wl,-brtl,-bexpfull'] - v.cxxshlib_PATTERN = 'lib%s.so' - - v.LINKFLAGS_cxxstlib = [] - v.cxxstlib_PATTERN = 'lib%s.a' - -def configure(conf): - conf.find_xlcxx() - conf.find_ar() - conf.xlcxx_common_flags() - conf.cxx_load_tools() - conf.cxx_add_flags() - conf.link_add_flags() - -- cgit v1.2.1