-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
06396fa
commit 7377844
Showing
11 changed files
with
447 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# -*- python -*- | ||
# | ||
# Copyright (c) 2016 Stefan Seefeld | ||
# All rights reserved. | ||
# | ||
# This file is part of Faber. It is made available under the | ||
# Boost Software License, Version 1.0. | ||
# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
# | ||
# This example demonstrates how to configure a project. | ||
# | ||
# Run with: | ||
# | ||
# * `faber cxxflags=-I/usr/include/python2.7 libs=python2.7` | ||
# * `faber cxxflags=-std=c++14` | ||
# * `faber --with-python-inc=/usr/include/python2.7 --with-python-lib=python2.7` | ||
# | ||
# To remove config artefacts run with: | ||
# | ||
# * `faber .config-clean` | ||
|
||
from faber.artefacts.binary import binary | ||
from faber.tools.compiler import define, include, linkpath, libs | ||
from faber.types import cxx, c | ||
from faber.config.try_link import * | ||
from faber.config import report, c_checks, cxx_checks, try_run | ||
from faber import scheduler | ||
|
||
python_inc = options.get_with('python-inc') | ||
python_linkpath = options.get_with('python-linkpath') | ||
python_lib = options.get_with('python-lib') | ||
if python_inc: | ||
features |= include(python_inc) | ||
if python_linkpath: | ||
features |= linkpath(python_linkpath) | ||
if python_lib: | ||
features |= libs(python_lib) | ||
|
||
pysrc=""" | ||
#include <Python.h> | ||
int main() | ||
{ | ||
Py_Initialize(); | ||
} | ||
""" | ||
checks = [c_checks.sizeof('char', cxx, features=features), | ||
c_checks.sizeof('long', cxx, features=features), | ||
try_link('pytest', pysrc, cxx, features, | ||
define('HAS_PYTHON=1'), | ||
define('HAS_PYTHON=0')), | ||
cxx_checks.has_cxx11(features, define('HAS_CXX11')), | ||
cxx_checks.has_cxx14(features, define('HAS_CXX14')), | ||
cxx_checks.has_cxx17(features, define('HAS_CXX17'))] | ||
|
||
config = report('config', checks) | ||
bin = binary('check', 'main.cpp', dependencies=config, features=config.use) | ||
report = rule(action('run', '$(>)'), 'report', bin, attrs=notfile|always) | ||
|
||
default = report |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// | ||
// Copyright (c) 2016 Stefan Seefeld | ||
// All rights reserved. | ||
// | ||
// This file is part of Faber. It is made available under the | ||
// Boost Software License, Version 1.0. | ||
// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <iostream> | ||
|
||
#ifdef HAS_CXX11 | ||
# define cxx11 "defined" | ||
#else | ||
# define cxx11 "undefined" | ||
#endif | ||
#ifdef HAS_CXX14 | ||
# define cxx14 "defined" | ||
#else | ||
# define cxx14 "undefined" | ||
#endif | ||
#ifdef HAS_CXX17 | ||
# define cxx17 "defined" | ||
#else | ||
# define cxx17 "undefined" | ||
#endif | ||
|
||
|
||
int main() | ||
{ | ||
std::cout << "HAS_PYTHON=" << HAS_PYTHON << '\n' | ||
<< "HAS_CXX11 " << cxx11 << '\n' | ||
<< "HAS_CXX14 " << cxx14 << '\n' | ||
<< "HAS_CXX17 " << cxx17 << '\n' | ||
<< std::endl; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# | ||
# Copyright (c) 2016 Stefan Seefeld | ||
# All rights reserved. | ||
# | ||
# This file is part of Faber. It is made available under the | ||
# Boost Software License, Version 1.0. | ||
# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
from ..artefact import artefact, notfile | ||
from ..rule import depend | ||
from .. import output | ||
|
||
|
||
class report(artefact): | ||
|
||
def __init__(self, name, checks): | ||
use = [c.use for c in checks] | ||
artefact.__init__(self, name, attrs=notfile, use=use) | ||
depend(self, checks) | ||
self.checks = checks | ||
|
||
def _report(self): | ||
|
||
max_name_length = max(len(c.qname) for c in self.checks) | ||
print(output.coloured('configuration check results:', attrs=['bold'])) | ||
for c in self.checks: | ||
print(' {:{}} : {} {}' | ||
.format(c.qname, max_name_length, c.result, '(cached)' if c.cached else '')) | ||
|
||
def __status__(self, status): | ||
artefact.__status__(self, status) | ||
self._report() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# | ||
# Copyright (c) 2016 Stefan Seefeld | ||
# All rights reserved. | ||
# | ||
# This file is part of Faber. It is made available under the | ||
# Boost Software License, Version 1.0. | ||
# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
from .try_run import check_output | ||
from .. import types | ||
|
||
|
||
class sizeof(check_output): | ||
|
||
src = """#include <stdio.h> | ||
int main(){{ printf("%i", sizeof({}));}}""" | ||
|
||
def __init__(self, c_type, lang_type=types.c, features=()): | ||
check_output.__init__(self, 'sizeof_' + c_type, sizeof.src.format(c_type), lang_type, | ||
features) | ||
|
||
def post_process(self, output): | ||
self.result = int(output) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# | ||
# Copyright (c) 2016 Stefan Seefeld | ||
# All rights reserved. | ||
# | ||
# This file is part of Faber. It is made available under the | ||
# Boost Software License, Version 1.0. | ||
# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
from ..feature import conditional | ||
from ..artefact import artefact, notfile, nocare | ||
from ..module import module | ||
import sqlite3 | ||
import hashlib | ||
import os | ||
import os.path | ||
import logging | ||
|
||
logger = logging.getLogger('config') | ||
|
||
|
||
class cache(object): | ||
|
||
def __init__(self): | ||
if not os.path.exists(module.current.builddir): | ||
os.makedirs(module.current.builddir) | ||
self.filename = os.path.join(module.current.builddir, '.configcache') | ||
self.conn = sqlite3.connect(self.filename) | ||
# Create table if it doesn't exist yet. | ||
if not next(self.conn.execute('SELECT name FROM sqlite_master ' | ||
'WHERE type="table" AND name="checks"'), None): | ||
self.conn.execute('CREATE TABLE checks ' | ||
'(key TEXT, status INTEGER, type TEXT, value TEXT)') | ||
|
||
def __del__(self): | ||
self.conn.commit() | ||
|
||
def clean(self): | ||
self.conn.close() | ||
os.remove(self.filename) | ||
del self | ||
|
||
def __contains__(self, key): | ||
with self.conn: | ||
a = self.conn.execute('SELECT key FROM checks WHERE key=?', (key,)) | ||
value = next(a, None) | ||
return bool(value) | ||
|
||
def __setitem__(self, key, value): | ||
status, result = value[0], value[1] | ||
with self.conn: | ||
self.conn.execute('INSERT INTO checks VALUES(?,?,?,?)', | ||
(key, status, type(result).__name__, str(result))) | ||
|
||
def __getitem__(self, key): | ||
with self.conn: | ||
a = self.conn.execute('SELECT status, type, value FROM checks WHERE key=?', | ||
(key,)) | ||
status, type, value = next(a, (None, None, None)) | ||
value = {'str': lambda x: x, | ||
'unicode': lambda x: x, | ||
'bool': lambda x: eval(x), | ||
'int': lambda x: int(x)}[type](value) | ||
return status, value | ||
|
||
|
||
class check(artefact): | ||
"""A check is an artefact that performs some tests (typically involving compilation), | ||
then stores the result in a cache, so it doesn't need to be performed again, | ||
until the cache is explicitly cleared.""" | ||
|
||
cache = cache() if module.current else None # to support sphinx' autoclass | ||
|
||
def __init__(self, name, features=(), if_=(), ifnot=()): | ||
|
||
self.result = None | ||
artefact.__init__(self, name, attrs=notfile|nocare, features=features) | ||
# The 'condition' here is simply the value of the check's status member. | ||
self.use = conditional(lambda ctx: self.status, self, if_, ifnot) | ||
key = str((self.name, str(self.features))).encode('utf-8') | ||
self._cache_key = hashlib.md5(key).hexdigest() | ||
self.cached = self._cache_key in check.cache | ||
if self.cached: | ||
self.status, self.result = check.cache[self._cache_key] | ||
|
||
def __status__(self, status): | ||
logger.debug('check.__status__({})'.format(status)) | ||
if self.cached: | ||
return # the cached value takes precedence | ||
artefact.__status__(self, status) | ||
if not self.status or self.result is None: | ||
self.result = self.status | ||
check.cache[self._cache_key] = (self.status, self.result) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# | ||
# Copyright (c) 2016 Stefan Seefeld | ||
# All rights reserved. | ||
# | ||
# This file is part of Faber. It is made available under the | ||
# Boost Software License, Version 1.0. | ||
# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
from .try_compile import try_compile | ||
from .. import types | ||
|
||
|
||
class has_cxx11(try_compile): | ||
|
||
src = r"""#if __cplusplus < 201103L | ||
#error no C++11 | ||
#endif""" | ||
|
||
def __init__(self, features=(), if_=(), ifnot=()): | ||
try_compile.__init__(self, 'has_cxx11', has_cxx11.src, types.cxx, features, | ||
if_, ifnot) | ||
|
||
|
||
class has_cxx14(try_compile): | ||
|
||
src = r"""#if __cplusplus < 201402L | ||
#error no C++14 | ||
#endif""" | ||
|
||
def __init__(self, features=(), if_=(), ifnot=()): | ||
try_compile.__init__(self, 'has_cxx14', has_cxx14.src, types.cxx, features, | ||
if_, ifnot) | ||
|
||
|
||
class has_cxx17(try_compile): | ||
|
||
src = r"""#if __cplusplus < 201500L | ||
#error no C++17 | ||
#endif""" | ||
|
||
def __init__(self, features=(), if_=(), ifnot=()): | ||
try_compile.__init__(self, 'has_cxx17', has_cxx17.src, types.cxx, features, | ||
if_, ifnot) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# | ||
# Copyright (c) 2016 Stefan Seefeld | ||
# All rights reserved. | ||
# | ||
# This file is part of Faber. It is made available under the | ||
# Boost Software License, Version 1.0. | ||
# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
from .check import check | ||
from ..artefact import intermediate, always | ||
from ..tools.compiler import compiler | ||
from ..rule import rule, alias | ||
from ..artefacts.object import object | ||
|
||
|
||
class try_compile(check): | ||
"""Try to compile a chunk of source code.""" | ||
|
||
def __init__(self, name, source, type, features=(), if_=(), ifnot=()): | ||
|
||
check.__init__(self, name, features, if_, ifnot) | ||
compiler.check_instance_for_type(type, features) | ||
if not self.cached: | ||
# create source file | ||
src = type.synthesize_name(self.name) | ||
|
||
def generate(targets, _): | ||
with open(targets[0]._filename, 'w') as os: | ||
os.write(source) | ||
src = rule(generate, src, attrs=intermediate|always) | ||
obj = object(self.name, src, attrs=intermediate, features=self.features) | ||
alias(self, obj) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# | ||
# Copyright (c) 2016 Stefan Seefeld | ||
# All rights reserved. | ||
# | ||
# This file is part of Faber. It is made available under the | ||
# Boost Software License, Version 1.0. | ||
# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
from .check import check | ||
from ..artefact import intermediate, always | ||
from ..tools.compiler import compiler | ||
from ..rule import rule, alias | ||
from ..artefacts.binary import binary | ||
|
||
|
||
class try_link(check): | ||
"""Try to compile and link a chunk of source code.""" | ||
|
||
def __init__(self, name, source, type, features=(), if_=(), ifnot=()): | ||
|
||
check.__init__(self, name, features, if_, ifnot) | ||
compiler.check_instance_for_type(type, features) | ||
if not self.cached: | ||
# create source file | ||
src = type.synthesize_name(self.name) | ||
|
||
def generate(targets, _): | ||
with open(targets[0]._filename, 'w') as os: | ||
os.write(source) | ||
src = rule(generate, src, attrs=intermediate|always) | ||
bin = binary(self.name, src, attrs=intermediate, features=self.features) | ||
alias(self, bin) |
Oops, something went wrong.