예제 #1
0
def check_cpp_default(cnf:Context, name:str, version:Optional[str]):
    u"Adds a requirement checker"
    if name.startswith('boost'):
        return

    if name.startswith('python_'):
        _check_cpp_python(cnf, name, version)
    else:
        cnf.check_cfg(package         = name,
                      uselib_store    = name,
                      args            = '--cflags --libs',
                      atleast_version = version)
예제 #2
0
    def configure(cls, cnf:Context):
        u"setup configure"
        cnf.env.append_value('SYS_INCS', 'BOOST')
        libs, vers = cls.getlibs()
        if not len(libs):
            return

        if not cnf.options.boost_includes and not cnf.options.boost_libs:
            cls.__getboostfromconda(cnf)

        cnf.check_boost(lib = ' '.join(libs-set(cls._H_ONLY)), mandatory = True)
        if 'LIB_BOOST' not in cnf.env:
            cnf.env['LIB_BOOST']= []
        elif sys.platform.startswith("win32"):
            cnf.env['LIB_BOOST']= [i.replace("-sgd-", "-gd-") for i in cnf.env["LIB_BOOST"]]
        else:
            path = Path(cnf.env["LIBPATH_BOOST"][0])
            good = []
            for i in cnf.env["LIB_BOOST"]:
                if i.endswith('.so') and (path/f"lib{i}").exists():
                    good.append(i)
                elif (path/f"lib{i[:i.find('.so')+3]}").exists():
                    good.append(i[:i.find('.so')])
                else:
                    raise KeyError(f"missing $path/lib$i")
            cnf.env["LIB_BOOST"] = good
        cnf.env['DEFINES_BOOST']= ['HAVE_BOOST=1']
        if LooseVersion(cnf.env.BOOST_VERSION.replace('_', '.')) < vers:
            cnf.fatal('Boost version is too old: %s < %s'
                      % (str(vers), str(cnf.env.BOOST_VERSION)))
예제 #3
0
def build_python_version_file(bld: Context):
    "creates a version.py file"
    bld(features='subst',
        source=bld.srcnode.find_resource(
            __package__.replace(".", "/") + '/_version.template'),
        target="version.py",
        name=str(bld.path) + ":version",
        version=_version(),
        lasthash=lasthash(),
        lastdate=lastdate(),
        isdirty=isdirty(),
        timestamp=lasttimestamp(),
        cpp_compiler_name=bld.cpp_compiler_name(),
        **bld.installcodepath())
예제 #4
0
def check_cpp_compiler(cnf:Context, name:str, version:Optional[str]):
    u"checks the compiler version"
    if cnf.env['COMPILER_CXX'] != name:
        return

    curr = cnf.env['CC_VERSION']
    if _ismsvc(cnf):
        curr = cnf.env['MSVC_VERSION']
    if isinstance(curr, float):
        curr = str(curr)
    elif isinstance(curr, tuple):
        curr = '.'.join(curr)

    if LooseVersion(curr) < version:
        cnf.fatal(cnf.env['COMPILER_CXX']
                  +' version '+curr
                  +' should be greater than '+version)
예제 #5
0
 def options(opt: Context):
     "add options"
     return (opt.add_option_group("Python Options").add_option(
         "--nolinting",
         help="Discard linting jobs",
         default=True,
         dest="DO_PY_LINTING",
         action="store_false",
     ))
예제 #6
0
    def __make_deps(cls, bld: Context, name: str, items: Sequence) -> List:
        if cls.INCLUDE_PYEXTS:
            pyext = set(bld.env.pyextmodules)
            if any(i.get_name() == name + ':pyext'
                   for i in bld.get_all_task_gen()):
                pyext.add(name)

            return list(pymoduledependencies(items, name) & pyext)
        return []
예제 #7
0
    def __getboostfromconda(cnf:Context):
        rem = 'PYTHON' not in cnf.env
        if rem:
            cnf.find_program("python", var="PYTHON", mandatory=False)
        if 'PYTHON' in cnf.env:
            path = Path(cnf.env["PYTHON"][0]).parent

            if sys.platform.startswith("win32"):
                path /= "Library"

            for _ in range(3):
                if (path/"include"/"boost").exists() and (path/"lib").exists():
                    cnf.options.boost_includes = str(path/"include")
                    cnf.options.boost_libs     = str(path/"lib")
                    break
                path = path.parent
        if rem:
            del cnf.env['PYTHON']
예제 #8
0
def _check_cpp_python(cnf:Context, name:str, version:Optional[str]):
    base     = name[len('python_'):]
    cond     = 'ver >= num('+str(version).replace('.',',')+')'
    cnf.check_python_module(base, condition = cond)
    paths    = get_python_paths(cnf, name, version)
    lib, inc = paths['lib'], paths['inc']
    line     = f' -I{inc} -I{Path(inc).parent} -L{lib}'
    iswin    = sys.platform.startswith('win')
    if not iswin:
        line += ' -lm'

    if base.endswith("-c"):
        base = base[:-2]

    bases    = set(PYTHON_MODULE_LIBS.get(base, (base,)))
    fullname = "--dummy--"
    for basename in set(bases):
        for fullname in (
                pre+basename+suf
                for pre in ('', 'lib')
                for suf in ('.so', '.dll', '.lib')
        ):
            if (Path(lib) / fullname).exists():
                if sys.platform.startswith('win') and fullname.startswith('lib'):
                    line  += f' -llib{basename}'
                else:
                    line  += f' -l{basename}'
                bases -=  {basename}
                break

    for basename in bases:
        for lib in (pre+basename+'.a' for pre in ('', 'lib')):
            if (Path(lib) / fullname).exists():
                if '-Wl,-Bstatic' not in line:
                    line += f' -Wl,-Bstatic -L{lib}'
                line += f' l{basename}'
                break

    cnf.parse_flags(line, uselib_store = base)
    for suf in ('', '.exe', '.bat', '.sh'):
        test = (paths['bin']/base).with_suffix(suf)
        if test.exists():
            setattr(cnf.env, f"BIN_{base}",  [str(test)])
            cnf.env.append_value(f'DEFINES_{base}', f'BIN_{base}="{test}"')
예제 #9
0
def get_python_paths(cnf:Context, name:str, version: Optional[str]) -> Dict[str, Path]:
    "get the python path"
    rem = not getattr(cnf.env, 'PYTHON')
    if rem:
        cnf.find_program("python", var="PYTHON", mandatory=False)

    if not getattr(cnf.env, 'PYTHON'):
        check_cpp_default(cnf, name, version)

    root = Path(cnf.env["PYTHON"][0]).parent
    if rem:
        del cnf.env['PYTHON']

    path = root/'Library' if sys.platform.startswith('win') else root.parent
    return dict(
        root = root.resolve(),
        inc  = (path/'include').resolve(),
        lib  = (path/'lib').resolve(),
        bin  = (path/'bin').resolve()
    )
예제 #10
0
def copyfiles(bld: Context, arg, items: Sequence, install=False):
    "copy py modules to build root path"
    if len(items) == 0:
        return

    if bld.cmd != "build" and install:
        bld.install_files(bld.installcodepath(arg, direct=True),
                          items,
                          cwd=bld.path,
                          relative_trick=True)
        return

    def _kword(_):
        return 'Copying'

    if arg != '':
        copyroot(bld, arg).mkdir()
    for src, tgt in copytargets(bld, arg, items):
        bld(rule=copytask,
            name=str(src) + ':' + _kword(None).lower(),
            source=[src],
            target=[tgt],
            cls_keyword=_kword)
예제 #11
0
    def configure(cls, cnf:Context):
        u"setup configure"
        if not _isrequired() or cls._DONE:
            return
        cls._DONE = True

        name  = cnf.env['COMPILER_CXX']
        cxx   = cnf.options.cxxflaglist
        links = cnf.options.linkflaglist

        # add options
        for i, j in OPTIONS.items():
            if i not in cxx and getattr(cnf.options, i[1:]+'flags'):
                cxx += ' ' + i
            if i in cxx and name in j:
                cxx   = cxx.replace(i, j[name].get('cxx', ''))
                links = links.strip()+" "+j[name].get('links', '')

        # add default flags
        if cxx[0] == "+":
            cxx = cls.defaultcxx(cnf).strip()+" "+cxx[1:]

        # add warnings
        cxx  +=  ' ' + ' '.join(WARNINGS.get(name, WARNINGS[...]))

        cxx   = cls.convertFlags(cnf, cxx)
        links = cls.convertFlags(cnf, links)

        cnf.check(features  = 'cxx cxxprogram',
                  cxxflags  = cxx,
                  linkflags = links,
                  mandatory = True)

        cnf.env.append_unique('CXXFLAGS',  Utils.to_list(cxx))
        cnf.env.append_unique('LINKFLAGS', Utils.to_list(links))
        cnf.env.append_unique('INCLUDES',  ['../'])
예제 #12
0
def buildpyext(bld     : Context,
               name    : str,
               version : str,
               pysrc   : Sequence,
               csrc    : List,
               **kwargs):
    "builds a python extension"
    if len(csrc) == 0:
        return

    if name not in bld.env.pyextmodules and not haspyext(csrc):
        return

    mod    = '_core' if len(pysrc) else name
    parent = copyroot(bld, name if len(pysrc) else None)
    target = parent.path_from(bld.bldnode.make_node(bld.path.relpath()))+"/"+mod

    node   = bld(features = 'subst',
                 source   = bld.srcnode.find_resource(__package__.replace('.', '/')
                                                      +'/_module.template'),
                 target   = name+"module.cpp",
                 name     = str(bld.path)+":pybind11",
                 nsname   = name,
                 module   = mod,
                 version  = version)
    csrc.append(node.target)

    args = copyargs(kwargs)
    args.setdefault('source',   csrc)

    args.setdefault('target',   target)
    args.setdefault('features', []).append('pyext')
    args.setdefault('name',     name+":pyext")
    args.update(**bld.installcodepath(name if pysrc else ""))

    bld.shlib(**args)
예제 #13
0
    def options(opt: Context):
        "defines options for conda setup"
        from ..shellvars import ENV_DEFAULT
        grp = opt.add_option_group('Condasetup Options')
        grp.add_option(
            '-e',
            '--envname',
            dest='condaenv',
            action='store',
            default=ENV_DEFAULT[0],
            help=("conda environment name: one can use 'branch'" +
                  " to automatically use the current git branch name"))

        grp.add_option('--suggested',
                       dest='suggested',
                       action='store_true',
                       default=False,
                       help="install suggested modules as well")

        grp.add_option('--pinned',
                       dest='pinned',
                       action='store',
                       default='',
                       help="packages with pinned versions")

        grp.add_option('-m',
                       '--min-version',
                       dest='minversion',
                       action='store_true',
                       default=False,
                       help="install requirement minimum versions by default")

        grp.add_option('-r',
                       '--runtime-only',
                       dest='runtimeonly',
                       action='store_true',
                       default=False,
                       help="install only runtime modules")

        grp.add_option('-p',
                       '--packages',
                       dest='packages',
                       action='store',
                       default='',
                       help="consider only these packages")
예제 #14
0
    def programversion(cnf: Context,
                       name: str,
                       minver: LooseVersion,
                       reg=None,
                       mandatory=True) -> bool:
        "check version of a program"
        if reg is None:
            areg = name
        else:
            areg = reg

        try:
            cnf.find_program(name, var=name.upper())
        except:  # pylint: disable=bare-except
            if mandatory:
                raise
            else:
                return False

        cmd = [getattr(cnf.env, name.upper())[0], "--version"]

        found = cnf.cmd_and_log(cmd).split('\n')
        found = [line for line in found if len(line)]
        found = next((line for line in found if areg in line),
                     found[-1]).split()[-1]
        found = found[found.rfind(' ') + 1:].replace(',', '').strip()
        if found.startswith('v'):
            found = found[1:]

        if LooseVersion(found) < minver:
            if not mandatory:
                return False
            if reg is None:
                cnf.fatal('The %s version is too old, expecting %r' %
                          (name, minver))
            else:
                cnf.fatal('The %s (%s) version is too old, expecting %r' %
                          (name, str(reg), minver))
        return True
예제 #15
0
def store(cnf: Context, flg: str):
    "store more python flags"
    if hascompiler(cnf):
        for item in 'PYEXT', 'PYEMBED':
            cnf.parse_flags(flg, uselib_store=item)
예제 #16
0
 def load(opt: Context):
     "applies load from all basic items"
     outp = glob.get('toload', lambda _: None)(opt)
     if len(outp):
         opt.load(outp)
예제 #17
0
 def configure(cnf: Context):
     "get conda script"
     cnf.env.CONDA_DEFAULT_ENV = os.environ['CONDA_DEFAULT_ENV']
     cnf.find_program("conda", var="CONDA", mandatory=True)
예제 #18
0
def check_cpp_gtest(cnf:Context, name:str, version:Optional[str]):
    "check for gtest"
    path = get_python_paths(cnf, name, version)['lib']
    vers = libmain = lib = inc = None
    for i in range(3):
        inc     = path/"include"/"gtest"
        if sys.platform.startswith('win'):
            libmain = path/"lib"/f"{name}_main-md.lib"
            lib     = path/"lib"/f"{name}-md.lib"
        else:
            libmain = path/"lib"/f"lib{name}_main.a"
            lib     = path/"lib"/f"lib{name}.a"
        if inc.exists() and lib.exists():
            break
        path = path.parent
    else:
        cnf.start_msg(f"Checking for conda module {name} (>= {version})")
        cnf.end_msg(False)
        cnf.fatal('Could not find the conda module ' +name)
        return

    setattr(cnf.env, f"INCLUDES_{name}",  [str(inc.parent)])
    setattr(cnf.env, f"STLIBPATH_{name}", [str(lib.parent)])
    setattr(cnf.env, f"STLIB_{name}",     [i.stem.replace('lib', '') for i in (lib, libmain)])
    if sys.platform.startswith('win'):
        setattr(cnf.env, f"DEFINES_{name}", ['GTEST_LANG_CX11=1', '_HAS_TR1_NAMESPACE=1'])
    else:
        setattr(cnf.env, f"LIB_{name}",       ['pthread'])
    if version is None:
        cnf.start_msg(f"Checking for conda module {name} (>= {version})")
        cnf.end_msg(True)
        return

    cond = 'ver >= num('+str(version).replace('.',',')+')'
    cnf.check_python_module(name, condition = cond)
예제 #19
0
def options(opt:Context):
    u"add options"
    if _isrequired():
        opt.add_option_group(CXX_OPTION_GROUP)