2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 04:22:16 +00:00

First attempt at faber-based build system.

This commit is contained in:
Stefan Seefeld
2017-11-10 02:08:40 -05:00
parent 9ad3313d1f
commit ebba009a9f
6 changed files with 351 additions and 23 deletions

View File

@@ -4,7 +4,7 @@ environment:
# /E:ON and /V:ON options are not enabled in the batch script intepreter
# See: http://stackoverflow.com/a/13751649/163740
CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\ci\\run_with_env.cmd"
BOOST_PREFIX: C:\Libraries\boost_1_60_0
BOOST_PREFIX: C:\Libraries\boost_1_63_0
matrix:
@@ -15,7 +15,8 @@ environment:
- PYTHON: "C:\\Python27"
PYTHON_VERSION: "2.7.x" # currently 2.7.9
PYTHON_ARCH: "32"
ARCH: "x86"
MSVC: "14.0"
ARCH: x86
#- PYTHON: "C:\\Python27-x64"
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
@@ -26,9 +27,11 @@ environment:
# PYTHON_VERSION: "3.5.x" # currently 3.4.3
# PYTHON_ARCH: "32"
#- PYTHON: "C:\\Python35-x64"
# PYTHON_VERSION: "3.5.x" # currently 3.4.3
# PYTHON_ARCH: "64"
- PYTHON: "C:\\Python36-x64"
PYTHON_VERSION: "3.6.x"
PYTHON_ARCH: "64"
MSVC: "12.0"
ARCH: x86_64
install:
# If there is a newer build queued for the same PR, cancel this one.
@@ -68,21 +71,22 @@ install:
# compiled extensions and are not provided as pre-built wheel packages,
# pip will build them from source using the MSVC compiler matching the
# target Python version and architecture
- easy_install scons
- |
curl -LfsS -o faber.tar.gz https://github.com/stefanseefeld/faber/archive/release/0.2.tar.gz
tar xf faber.tar.gz
CD faber-release-0.2
python setup.py install
CD ..
# report the available MSVC compilers
- python -m faber.tools.msvc
- easy_install sphinx
- pip install numpy
#- "%CMD_IN_ENV% pip install -r dev-requirements.txt"
build_script:
# Build the compiled extension
#- "%CMD_IN_ENV% python setup.py build"
- scons config arch=%ARCH% --boost-include=%BOOST_PREFIX%
- scons arch=%ARCH% --verbose
- faber --with-boost-include=%BOOST_PREFIX% target.arch=%ARCH% msvc.version=%MSVC%
test_script:
# Run the project tests
#- "%CMD_IN_ENV% python setup.py nosetests"
- scons test arch=%ARCH% --verbose
- faber --with-boost-include=%BOOST_PREFIX% test.report target.arch=%ARCH% msvc.version=%MSVC%
after_test:
# If tests are successful, create binary packages for the project.
@@ -97,4 +101,4 @@ after_test:
#on_success:
# - TODO: upload the content of dist/*.whl to a public wheelhouse
#
#

3
.ci/faber Normal file
View File

@@ -0,0 +1,3 @@
from faber.tools.python import python
p = python(command='$PYTHON')

View File

@@ -26,12 +26,10 @@ matrix:
- compiler: gcc
env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11
- compiler: clang
# clang generates an 'illegal instruction' error in the NumPy check.
# Perhaps we need to upgrade clang to a newer version ?
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 OPTIONS=--no-numpy
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98
- compiler: clang
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 OPTIONS=--no-numpy
- env: PYTHON=python DOC=1
env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11
#- env: PYTHON=python DOC=1
addons:
@@ -77,16 +75,28 @@ install:
./bootstrap.sh
./b2 tools/bcp
mkdir -p $HOME/Boost
# Install Boost.Python prerequisites, but not Boost.Python itself.
dist/bin/bcp python tools/boostbook tools/quickbook $HOME/Boost &> /dev/null
rm -rf $HOME/Boost/boost/python*
popd
# Install Faber, the build tool.
date=2017-11-09
#wget https://github.com/stefanseefeld/faber/archive/snapshot/$date.tar.gz
wget https://github.com/stefanseefeld/faber/archive/release/0.2.tar.gz
tar xf 0.2.tar.gz
pushd faber-release-0.2
sudo python setup.py install
popd
fi
before_script:
- scons --version
- sed -e "s/\$PYTHON/$PYTHON/g" .ci/faber > ~/.faber
- $PYTHON --version
- faber -h
script:
- scons config --python=$PYTHON --boost-include=$HOME/Boost $OPTIONS
- if [ "$DOC" ]; then scons doc; else scons && scons test; fi
- faber --with-boost-include=$HOME/Boost test.report cxx.name=$CXX cxxflags=$CXXFLAGS
#- if [ "$DOC" ]; then scons doc; else scons && scons test; fi
after_success:
# Upload docs only when building upstream.

80
fabscript Normal file
View File

@@ -0,0 +1,80 @@
# -*- python -*-
#
# Copyright (c) 2016 Stefan Seefeld
# All rights reserved.
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from faber.feature import set
from faber.types import cxx
from faber.tools.compiler import cxxflags, define, include
from faber.tools.python import python
from faber.config import report, cxx_checks
from faber.config.try_run import try_run
features += include('include')
features += define('BOOST_ALL_NO_LIB') # disable auto-linking
boost_include = options.get_with('boost-include')
if boost_include:
features += include(boost_include)
python = python.instance()
features |= set(python.include, python.linkpath, python.libs)
class has_numpy(try_run):
src = r"""
// If defined, enforces linking against PythonXXd.lib, which
// is usually not included in Python environments.
#undef _DEBUG
#include "Python.h"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "numpy/arrayobject.h"
#if PY_VERSION_HEX >= 0x03000000
void *initialize() { import_array();}
#else
void initialize() { import_array();}
#endif
int main()
{
int result = 0;
Py_Initialize();
initialize();
if (PyErr_Occurred())
{
result = 1;
}
else
{
npy_intp dims = 2;
PyObject * a = PyArray_SimpleNew(1, &dims, NPY_INT);
if (!a) result = 1;
Py_DECREF(a);
}
Py_Finalize();
return result;
}
"""
def __init__(self, features=()):
inc = ''
try:
inc = python.check_python('import numpy; print(numpy.get_include())')
features |= include(inc)
except Exception:
# ignore errors, the check will fail during compilation...
pass
try_run.__init__(self, 'has_numpy', has_numpy.src, cxx, features,
if_=(include(inc), define('HAS_NUMPY')))
checks = [cxx_checks.has_cxx11(features, define('HAS_CXX11')),
has_numpy(features)]
config = report('config', checks)
src = module('src', features=config.use)
test = module('test', features=config.use)
default = src.default

58
src/fabscript Normal file
View File

@@ -0,0 +1,58 @@
# -*- python -*-
#
# Copyright (c) 2016 Stefan Seefeld
# All rights reserved.
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from faber.feature import set
from faber.artefacts.library import library
from faber.tools.compiler import define
root = module('..')
bpl = library('boost_python',
['list.cpp',
'long.cpp',
'dict.cpp',
'tuple.cpp',
'str.cpp',
'slice.cpp',
'converter/from_python.cpp',
'converter/registry.cpp',
'converter/type_id.cpp',
'object/enum.cpp',
'object/class.cpp',
'object/function.cpp',
'object/inheritance.cpp',
'object/life_support.cpp',
'object/pickle_support.cpp',
'errors.cpp',
'module.cpp',
'converter/builtin_converters.cpp',
'converter/arg_to_python_base.cpp',
'object/iterator.cpp',
'object/stl_iterator.cpp',
'object_protocol.cpp',
'object_operators.cpp',
'wrapper.cpp',
'import.cpp',
'exec.cpp',
'object/function_doc_signature.cpp'],
dependencies=root.config,
features=features + define('BOOST_PYTHON_SOURCE'))
bnl = library('boost_numpy',
['numpy/dtype.cpp',
'numpy/matrix.cpp',
'numpy/ndarray.cpp',
'numpy/numpy.cpp',
'numpy/scalars.cpp',
'numpy/ufunc.cpp',
bpl],
dependencies=root.config,
features=features + define('BOOST_NUMPY_SOURCE'),
condition=set.define.contains('HAS_NUMPY'))
default = [bpl, bnl]

173
test/fabscript Normal file
View File

@@ -0,0 +1,173 @@
# -*- python -*-
#
# Copyright (c) 2016 Stefan Seefeld
# All rights reserved.
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from faber import platform
from faber.feature import set
from faber.tools.compiler import runpath
from faber.tools.python import python, pythonpath
from faber.artefacts.object import object
from faber.artefacts.binary import binary
from faber.artefacts.python import extension
from faber.test import test, report, fail
src = module('..src')
python_libs=python.instance().libs
features |= runpath(src.bpl.path, base='')
def extension_test(name, ext=[], script=None, np=False,
features=features, condition=None):
"""Create a Python extension test `name`.
Arguments:
* name: the name of the test.
* ext: extensions to be compiled, <name> if none are given.
* script: the test script to execute, <name>.py if none is given.
* np: if true, add boost_numpy to sources
* features: pre-defined features
* condition: any condition under which to run the test
Return:
* the test artefact"""
features=features.copy()
extensions = []
libs = [src.bnl, src.bpl] if np else [src.bpl]
for e in ext or [name]:
if type(e) is str: # build from a single source file
n = e if e != name else e + '_ext'
s = [e + '.cpp']
else: # build from a list of source files
n = e[0] if e[0] != name else e[0] + '_ext'
s = [n + '.cpp' for n in e]
e = extension(n, s + libs, features=features)
features |= pythonpath(e.path, base='')
extensions.append(e)
if not script:
script = name+'.py'
return test(name, script, run=python.run, dependencies=extensions,
features=features, condition=condition)
tests = []
for t in [('injected',),
('properties',),
('return_arg',),
('staticmethod',),
('boost_shared_ptr',),
('enable_shared_from_this',),
('andreas_beyer',),
('polymorphism',),
('polymorphism2',),
('wrapper_held_type',),
('minimal',),
('args',),
('raw_ctor',),
('exception_translator',),
('test_enum', ['enum_ext']),
('test_cltree', ['cltree']),
('newtest', ['m1', 'm2']),
('const_argument',),
('keywords_test', ['keywords']),
('test_pointer_adoption',),
('operators',),
('operators_wrapper',),
('callbacks',),
('defaults',),
('object',),
('list',),
('long',),
('dict',),
('tuple',),
('str',),
('slice',),
('virtual_functions',),
('back_reference',),
('implicit',),
('data_members',),
('ben_scott1',),
('bienstman1',),
('bienstman2',),
('bienstman3',),
('multi_arg_constructor',),
('iterator', ['iterator', 'input_iterator']),
('stl_iterator',),
('extract',),
('crossmod_opaque', ['crossmod_opaque_a', 'crossmod_opaque_b']),
('opaque',),
('voidptr',),
('pickle1',),
('pickle2',),
('pickle3',),
('pickle4',),
('nested',),
('docstring',),
('pytype_function',),
('vector_indexing_suite',),
('pointer_vector',),
('builtin_converters', [], 'test_builtin_converters.py'),
('map_indexing_suite',
[['map_indexing_suite', 'int_map_indexing_suite', 'a_map_indexing_suite']])]:
tests.append(extension_test(*t))
tests.append(extension_test('shared_ptr',
condition=set.define.contains('HAS_CXX11')))
tests.append(extension_test('polymorphism2_auto_ptr',
condition=set.define.contains('HAS_CXX11').not_()))
tests.append(extension_test('auto_ptr',
condition=set.define.contains('HAS_CXX11')))
import_ = binary('import_', ['import_.cpp', src.bpl], features=features|python_libs)
if platform.os == 'Windows':
command = """set PATH=$(runpath);%PATH%
$(>[1]) $(>[2])"""
else:
command = 'LD_LIBRARY_PATH=$(runpath) $(>[1]) $(>[2])'
tests.append(test('import', [import_, 'import_.py'],
run=action('run', command),
features=features))
tests.append(extension_test('calling_conventions',
condition=platform.os == 'Windows'))
tests.append(extension_test('calling_conventions_mf',
condition=platform.os == 'Windows'))
for t in ['destroy_test',
'pointer_type_id_test',
'bases',
'pointee',
'if_else',
'pointee',
'result',
'upcast',
'select_from_python_test']:
tests.append(test(t, binary(t, [t + '.cpp', src.bpl], features=features), features=features, run=True))
for t in ['indirect_traits_test',
'string_literal',
'borrowed',
'object_manager',
'copy_ctor_mutates_rhs',
'select_holder',
'select_arg_to_python_test']:
tests.append(test(t, object(t, [t + '.cpp'], features=features)))
for t in ['raw_pyobject_fail1',
'raw_pyobject_fail2',
'as_to_python_function',
'object_fail1']:
tests.append(test(t, object(t, [t + '.cpp'], features=features), expected=fail))
for t in ['numpy/dtype',
'numpy/ufunc',
'numpy/templates',
'numpy/ndarray',
'numpy/indexing',
'numpy/shapes']:
tests.append(extension_test(t, np=True,
condition=set.define.contains('HAS_NUMPY')))
default = report('report', tests, fail_on_failures=True)