-
Notifications
You must be signed in to change notification settings - Fork 0
Writing a configure script
The configuration is done by the function main(project, build)
found in the file .config/project.py
.
For the purpose of this tutorial, let's say we will configure a project that create a library, its python binding and an executable that use the library. Finally, we will copy some script files in the build directory.
All variable defined at the root of the configure script are available from the environment.
# The project name
NAME = "my-fancy-project"
# The version name (could be "alpha" for example)
VERSION_NAME = "prototype"
configure.py provides some handy tools
from configure import tools, path, platform
from configure.lang import cxx
from configure.lang import c
For example, we retrieve the build type (defaulting to 'DEBUG'),
and print a message with tools.status()
.
def main(project, build):
build_type = project.env.get('BUILD_TYPE', 'DEBUG')
project.env.build_set('BUILD_TYPE', build_type)
tools.status(
"Configuring project", project.env.NAME, '(%s)' % project.env.VERSION_NAME,
'in', build.directory, '(%s)' % build_type
)
Let's say we need a C++ compiler, gcc everywhere but windows:
if platform.IS_WINDOWS:
Compiler = cxx.msvc.Compiler
else:
Compiler = cxx.gcc.Compiler
To build our Compiler
class previously selected, we prepare some defines:
if build_type == 'DEBUG':
defines = ['MY_PROJECT_DEBUG']
And now, the compiler itself:
compiler = Compiler(
project, build,
position_independent_code = True,
standard = 'c++11',
defines = defines,
include_directories = [
path.join(build.directory, 'src'),
path.absolute(project.directory, 'src'),
],
use_build_type_flags = True,
)
status("CXX compiler is", compiler.binary)
Let me explain each argument (see doc on C++ compilers for all possible arguments):
-
project
andbuild
: The variable given to your main function. -
position_independent_code
: see gcc-fPIC
flag. -
standard
: The standard used, here c++11. -
defines
: A list of defines, here debug flags. -
include_directories
: Additional include directories. -
use_build_type_flags
: Use basic debugging flags and optimisation flags. -
hidden_visibility
: Hide not exported symbols.
Searching for C library with libraries.simple()
function:
libs = []
for name in ['z', 'bz2']:
libs.append(c.libraries.simple(name, compiler, shared=True))
Complex libraries can be implemented separately, let's say we need Boost and Python:
boost = cxx.libraries.BoostLibrary(
compiler,
components=['system', 'filesystem', 'python3', 'thread'],
preferred_shared=False,
python3_shared=True,
)
python = c.libraries.PythonLibrary(compiler, shared=True)
Let's start with the library called my
:
libmy = compiler.link_shared_library(
'libmy',
tools.glob("src/libmy/*.cpp", recursive=True),
directory = 'release/lib',
libraries = libs + boost.libraries,
defines = ['MY_BUILD_DYNAMIC_LIBRARY'],
)
A precompiled header:
boost_python_pch = compiler.generate_precompiled_header(
"src/boost/python.hpp"
)
A Boost.Python module:
libmy_binding = compiler.link_dynamic_library(
'my',
['src/my_binding.cpp'],
ext = python.ext,
directory = "release/lib/python",
libraries = boost.libraries + python.libraries + [libmy] + libs,
precompiled_headers = [boost_python_pch],
)
We force the extension to be the one that python understand to be a python module extension and use libraries and precompiled header defined earlier. We can finally build our executable:
my_client = compiler.link_executable(
"my",
["src/my.cpp"],
directory = "release/bin",
libraries=[libmy] + libs + boost.libraries,
)
Let's copy some files (for this tutorial ;)):
for src in glob("scripts/*.py", recursive=True):
build.fs.copy(src, path.join('release', src))