Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
331b81bf32
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.cache/
|
||||
venv/
|
||||
*.pyc
|
||||
__pycache__/
|
||||
|
||||
@ -5,7 +7,7 @@ __pycache__/
|
||||
test/*/CMakeLists.txt
|
||||
test/*/build*/
|
||||
test/*/cmake/update.py
|
||||
test/*/cmake/lib/
|
||||
test/*/cmake/autocmake/
|
||||
test/*/cmake/downloaded/
|
||||
test/*/setup
|
||||
|
||||
|
38
.travis.yml
38
.travis.yml
@ -5,6 +5,7 @@ matrix:
|
||||
include:
|
||||
|
||||
- os: linux
|
||||
python: 2.7
|
||||
compiler: gcc
|
||||
env: SOURCES=ubuntu-toolchain-r-test
|
||||
addons:
|
||||
@ -28,6 +29,30 @@ matrix:
|
||||
# boost
|
||||
- libboost-all-dev
|
||||
|
||||
- os: linux
|
||||
python: 3.5
|
||||
compiler: gcc
|
||||
env: SOURCES=ubuntu-toolchain-r-test
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# compilers
|
||||
- g++
|
||||
- gfortran
|
||||
# math libraries
|
||||
- libblas-dev
|
||||
- liblapack-dev
|
||||
- libatlas-base-dev
|
||||
# mpi
|
||||
- openmpi-bin
|
||||
- libopenmpi-dev
|
||||
# python library, development version
|
||||
- libpython2.7
|
||||
# boost
|
||||
- libboost-all-dev
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
compiler: gcc
|
||||
@ -40,20 +65,21 @@ install:
|
||||
pip install virtualenv
|
||||
elif [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
pip install --user virtualenv
|
||||
curl https://cmake.org/files/v3.5/cmake-3.5.2-Linux-x86_64.tar.gz | tar xvz
|
||||
export PATH=~/cmake-3.5.2-Linux-x86_64/bin:$PATH
|
||||
export LD_LIBARY_PATH=~/cmake-3.5.2-Linux-x86_64/lib:$LD_LIBRARY_PATH
|
||||
fi
|
||||
- virtualenv venv
|
||||
- source venv/bin/activate
|
||||
- pip install pep8 pytest
|
||||
- pip install -r requirements.txt
|
||||
|
||||
script:
|
||||
# pep8 tests
|
||||
- pep8 --ignore=E501 update.py
|
||||
- pep8 --ignore=E501 test/test.py
|
||||
- pep8 --ignore=E501 lib/config.py
|
||||
- pep8 --ignore E501 update.py
|
||||
- pep8 --ignore E501,E265 autocmake
|
||||
# unit tests
|
||||
- py.test -vv update.py
|
||||
- py.test -vv autocmake/*
|
||||
- py.test -vv test/test.py
|
||||
- py.test -vv lib/config.py
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
@ -7,7 +7,8 @@
|
||||
|
||||
- Miroslav Ilias (Windows, portability, earliest adopter testing and feedback, math library testing)
|
||||
- Ivan Hrasko (Windows, Appveyor testing)
|
||||
- Dan Jonsson (idea for configuration file approach)
|
||||
- Dan Jonsson (idea for configuration file approach which preceded YAML solution)
|
||||
- Roberto Di Remigio (design ideas and testing, OS X testing, Boost)
|
||||
|
||||
For a list of all the contributions see https://github.com/scisoft/autocmake/contributors.
|
||||
For a list of all the contributions,
|
||||
see https://github.com/coderefinery/autocmake/contributors.
|
||||
|
3
LICENSE
3
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2016, Jonas Juselius and Radovan Bast
|
||||
Copyright (c) 2015-2016 by Radovan Bast, Jonas Juselius, and contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@ -25,4 +25,3 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
20
README.md
20
README.md
@ -1,23 +1,29 @@
|
||||
[](https://travis-ci.org/scisoft/autocmake/builds)
|
||||
[](https://ci.appveyor.com/project/bast/autocmake/history)
|
||||
[](https://travis-ci.org/coderefinery/autocmake/builds)
|
||||
[](http://autocmake.readthedocs.org)
|
||||
[](../master/LICENSE)
|
||||
|
||||
|
||||
# Autocmake
|
||||

|
||||
|
||||
A CMake plugin composer.
|
||||
Licensed under [BSD-3](../master/LICENSE).
|
||||
See http://autocmake.org.
|
||||
|
||||
|
||||
### Projects using Autocmake
|
||||
## Documentation
|
||||
|
||||
- [Numgrid](https://github.com/bast/numgrid/)
|
||||
- [XCint](https://github.com/bast/xcint/)
|
||||
- [Latest stable code](http://autocmake.readthedocs.io/en/stable-0.x/) (stable-0.x branch)
|
||||
- [Bleeding edge code](http://autocmake.readthedocs.io/en/latest/) (master branch)
|
||||
|
||||
|
||||
## Projects using Autocmake
|
||||
|
||||
- [Numgrid](https://github.com/dftlibs/numgrid/)
|
||||
- [XCint](https://github.com/dftlibs/xcint/)
|
||||
- [DIRAC](http://diracprogram.org)
|
||||
- [mathlib-tester](https://github.com/miroi/mathlibs-tester)
|
||||
- [Fortran Input Reader](https://github.com/miroi/fortran_input_reader)
|
||||
- [PCMSolver](https://github.com/PCMSolver/pcmsolver)
|
||||
- GRASP: General-purpose Relativistic Atomic Structure Program
|
||||
- [MRChem](https://github.com/MRChemSoft/mrchem)
|
||||
|
||||
If you use Autocmake, please link to your project via a pull request.
|
||||
|
57
appveyor.yml
57
appveyor.yml
@ -1,57 +0,0 @@
|
||||
# OS: 64-bit Windows Server 2012 R2
|
||||
# Compilers: 64-bit MinGw-w64 5.1.0 (downloaded during script execution)
|
||||
# Python: 2.7, 64-bit
|
||||
# "ps:" commands are executed in PowerShell
|
||||
|
||||
# build version format: 1.0.1, 1.0.2, ...
|
||||
version: 1.0.{build}
|
||||
|
||||
# prepare environment
|
||||
environment:
|
||||
# set custom path (will be more extended later in build_script section)
|
||||
path: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Git\cmd;C:\Program Files\7-Zip;C:\Program Files (x86)\CMake\bin
|
||||
# set MinGw-w64 (64-bit) version 5.1.0 download URL
|
||||
url: http://kent.dl.sourceforge.net/project/mingw-w64/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/5.1.0/threads-posix/seh/x86_64-5.1.0-release-posix-seh-rt_v4-rev0.7z
|
||||
matrix:
|
||||
# - python: C:\Python27;C:\Python27\Scripts
|
||||
- python: C:\Python27-x64;C:\Python27-x64\Scripts
|
||||
# - python: C:\Python34;C:\Python34\Scripts
|
||||
# - python: C:\Python34-x64;C:\Python34-x64\Scripts
|
||||
|
||||
build_script:
|
||||
# add location of used Python to path
|
||||
- set path=%path%;%python%
|
||||
|
||||
# create dir for custom software and move there
|
||||
- mkdir C:\software && cd C:\software
|
||||
|
||||
# download and unpack MinGw-w64 compilers
|
||||
- ps: wget $env:url -OutFile MinGW.7z
|
||||
- 7z x MinGW.7z > NUL
|
||||
# add compilers binary dir to path
|
||||
- set path=%path%;C:\software\mingw64\bin
|
||||
|
||||
# download and unpack the OpenBLAS library, integer*4 (or i32lp64) version
|
||||
- ps: wget http://skylink.dl.sourceforge.net/project/openblas/v0.2.14/OpenBLAS-v0.2.14-Win64-int32.zip -OutFile OpenBLAS-v0.2.14-Win64-int32.zip
|
||||
- 7z x OpenBLAS-v0.2.14-Win64-int32.zip > NUL
|
||||
# add both OpenBLAS dynamic (libopenblas.dll) and static (libopenblas.a) library files dir to path
|
||||
- set path=%path%;C:\software\OpenBLAS-v0.2.14-Win64-int32\bin;C:\software\OpenBLAS-v0.2.14-Win64-int32\lib;C:\software\OpenBLAS-v0.2.14-Win64-int32\include
|
||||
|
||||
# download and upgrade pip
|
||||
- ps: wget https://bootstrap.pypa.io/get-pip.py -OutFile get-pip.py
|
||||
- python get-pip.py
|
||||
|
||||
# install py.test
|
||||
- pip install pytest
|
||||
|
||||
# go back to project source dir
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
|
||||
test_script:
|
||||
# show environment
|
||||
- echo %path%
|
||||
- py.test --version
|
||||
# run tests
|
||||
- py.test -vv update.py
|
||||
- py.test -vv test/test.py
|
||||
- py.test -vv lib/config.py
|
1
autocmake/__init__.py
Normal file
1
autocmake/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__version__ = '1.0.0-alpha-x'
|
@ -1,12 +1,5 @@
|
||||
|
||||
# Copyright (c) 2015 by Radovan Bast and Jonas Juselius
|
||||
# See https://github.com/scisoft/autocmake/blob/master/LICENSE
|
||||
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
|
||||
def module_exists(module_name):
|
||||
@ -23,10 +16,12 @@ def check_cmake_exists(cmake_command):
|
||||
Check whether CMake is installed. If not, print
|
||||
informative error message and quits.
|
||||
"""
|
||||
p = subprocess.Popen('%s --version' % cmake_command,
|
||||
shell=True,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE)
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
p = Popen('{0} --version'.format(cmake_command),
|
||||
shell=True,
|
||||
stdin=PIPE,
|
||||
stdout=PIPE)
|
||||
if not ('cmake version' in p.communicate()[0].decode('UTF-8')):
|
||||
sys.stderr.write(' This code is built using CMake\n\n')
|
||||
sys.stderr.write(' CMake is not found\n')
|
||||
@ -46,7 +41,7 @@ def setup_build_path(build_path):
|
||||
fname = os.path.join(build_path, 'CMakeCache.txt')
|
||||
if os.path.exists(fname):
|
||||
sys.stderr.write('aborting setup\n')
|
||||
sys.stderr.write('build directory %s which contains CMakeCache.txt already exists\n' % build_path)
|
||||
sys.stderr.write('build directory {0} which contains CMakeCache.txt already exists\n'.format(build_path))
|
||||
sys.stderr.write('remove the build directory and then rerun setup\n')
|
||||
sys.exit(1)
|
||||
else:
|
||||
@ -74,7 +69,7 @@ def adapt_cmake_command_to_platform(cmake_command, platform):
|
||||
"""
|
||||
if platform == 'win32':
|
||||
pos = cmake_command.find('cmake')
|
||||
s = ['set %s &&' % e for e in cmake_command[:pos].split()]
|
||||
s = ['set {0} &&'.format(e) for e in cmake_command[:pos].split()]
|
||||
s.append(cmake_command[pos:])
|
||||
return ' '.join(s)
|
||||
else:
|
||||
@ -85,33 +80,40 @@ def run_cmake(command, build_path, default_build_path):
|
||||
"""
|
||||
Execute CMake command.
|
||||
"""
|
||||
from subprocess import Popen, PIPE
|
||||
from shutil import rmtree
|
||||
|
||||
topdir = os.getcwd()
|
||||
os.chdir(build_path)
|
||||
p = subprocess.Popen(command,
|
||||
shell=True,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
p = Popen(command,
|
||||
shell=True,
|
||||
stdin=PIPE,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE)
|
||||
stdout_coded, stderr_coded = p.communicate()
|
||||
stdout = stdout_coded.decode('UTF-8')
|
||||
stderr = stderr_coded.decode('UTF-8')
|
||||
|
||||
# print cmake output to screen
|
||||
print(stdout)
|
||||
|
||||
if stderr:
|
||||
sys.stderr.write(stderr)
|
||||
sys.exit(1)
|
||||
# print cmake output to screen
|
||||
print(stdout)
|
||||
|
||||
# write cmake output to file
|
||||
f = open('cmake_output', 'w')
|
||||
f.write(stdout)
|
||||
f.close()
|
||||
with open('cmake_output', 'w') as f:
|
||||
f.write(stdout)
|
||||
|
||||
# change directory and return
|
||||
os.chdir(topdir)
|
||||
|
||||
if 'Configuring incomplete' in stdout:
|
||||
# configuration was not successful
|
||||
if (build_path == default_build_path):
|
||||
# remove build_path iff not set by the user
|
||||
# otherwise removal can be dangerous
|
||||
shutil.rmtree(default_build_path)
|
||||
rmtree(default_build_path)
|
||||
else:
|
||||
# configuration was successful
|
||||
save_setup_command(sys.argv, build_path)
|
||||
@ -136,9 +138,8 @@ def save_setup_command(argv, build_path):
|
||||
Save setup command to a file.
|
||||
"""
|
||||
file_name = os.path.join(build_path, 'setup_command')
|
||||
f = open(file_name, 'w')
|
||||
f.write(' '.join(argv[:]) + '\n')
|
||||
f.close()
|
||||
with open(file_name, 'w') as f:
|
||||
f.write(' '.join(argv[:]) + '\n')
|
||||
|
||||
|
||||
def configure(root_directory, build_path, cmake_command, only_show):
|
||||
@ -158,7 +159,7 @@ def configure(root_directory, build_path, cmake_command, only_show):
|
||||
|
||||
cmake_command = adapt_cmake_command_to_platform(cmake_command, sys.platform)
|
||||
|
||||
print('%s\n' % cmake_command)
|
||||
print('{0}\n'.format(cmake_command))
|
||||
if only_show:
|
||||
sys.exit(0)
|
||||
|
1
autocmake/external/__init__.py
vendored
Normal file
1
autocmake/external/__init__.py
vendored
Normal file
@ -0,0 +1 @@
|
||||
# empty - this line is here to avoid problem when fetching empty files from web
|
228
lib/docopt/docopt.py → autocmake/external/docopt.py
vendored
228
lib/docopt/docopt.py → autocmake/external/docopt.py
vendored
@ -11,7 +11,7 @@ import re
|
||||
|
||||
|
||||
__all__ = ['docopt']
|
||||
__version__ = '0.6.1'
|
||||
__version__ = '0.6.2'
|
||||
|
||||
|
||||
class DocoptLanguageError(Exception):
|
||||
@ -47,18 +47,18 @@ class Pattern(object):
|
||||
if not hasattr(self, 'children'):
|
||||
return self
|
||||
uniq = list(set(self.flat())) if uniq is None else uniq
|
||||
for i, child in enumerate(self.children):
|
||||
if not hasattr(child, 'children'):
|
||||
assert child in uniq
|
||||
self.children[i] = uniq[uniq.index(child)]
|
||||
for i, c in enumerate(self.children):
|
||||
if not hasattr(c, 'children'):
|
||||
assert c in uniq
|
||||
self.children[i] = uniq[uniq.index(c)]
|
||||
else:
|
||||
child.fix_identities(uniq)
|
||||
c.fix_identities(uniq)
|
||||
|
||||
def fix_repeating_arguments(self):
|
||||
"""Fix elements that should accumulate/increment values."""
|
||||
either = [list(child.children) for child in transform(self).children]
|
||||
either = [list(c.children) for c in self.either.children]
|
||||
for case in either:
|
||||
for e in [child for child in case if case.count(child) > 1]:
|
||||
for e in [c for c in case if case.count(c) > 1]:
|
||||
if type(e) is Argument or type(e) is Option and e.argcount:
|
||||
if e.value is None:
|
||||
e.value = []
|
||||
@ -68,40 +68,47 @@ class Pattern(object):
|
||||
e.value = 0
|
||||
return self
|
||||
|
||||
|
||||
def transform(pattern):
|
||||
"""Expand pattern into an (almost) equivalent one, but with single Either.
|
||||
|
||||
Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d)
|
||||
Quirks: [-a] => (-a), (-a...) => (-a -a)
|
||||
|
||||
"""
|
||||
result = []
|
||||
groups = [[pattern]]
|
||||
while groups:
|
||||
children = groups.pop(0)
|
||||
parents = [Required, Optional, OptionsShortcut, Either, OneOrMore]
|
||||
if any(t in map(type, children) for t in parents):
|
||||
child = [c for c in children if type(c) in parents][0]
|
||||
children.remove(child)
|
||||
if type(child) is Either:
|
||||
for c in child.children:
|
||||
@property
|
||||
def either(self):
|
||||
"""Transform pattern into an equivalent, with only top-level Either."""
|
||||
# Currently the pattern will not be equivalent, but more "narrow",
|
||||
# although good enough to reason about list arguments.
|
||||
ret = []
|
||||
groups = [[self]]
|
||||
while groups:
|
||||
children = groups.pop(0)
|
||||
types = [type(c) for c in children]
|
||||
if Either in types:
|
||||
either = [c for c in children if type(c) is Either][0]
|
||||
children.pop(children.index(either))
|
||||
for c in either.children:
|
||||
groups.append([c] + children)
|
||||
elif type(child) is OneOrMore:
|
||||
groups.append(child.children * 2 + children)
|
||||
elif Required in types:
|
||||
required = [c for c in children if type(c) is Required][0]
|
||||
children.pop(children.index(required))
|
||||
groups.append(list(required.children) + children)
|
||||
elif Optional in types:
|
||||
optional = [c for c in children if type(c) is Optional][0]
|
||||
children.pop(children.index(optional))
|
||||
groups.append(list(optional.children) + children)
|
||||
elif AnyOptions in types:
|
||||
optional = [c for c in children if type(c) is AnyOptions][0]
|
||||
children.pop(children.index(optional))
|
||||
groups.append(list(optional.children) + children)
|
||||
elif OneOrMore in types:
|
||||
oneormore = [c for c in children if type(c) is OneOrMore][0]
|
||||
children.pop(children.index(oneormore))
|
||||
groups.append(list(oneormore.children) * 2 + children)
|
||||
else:
|
||||
groups.append(child.children + children)
|
||||
else:
|
||||
result.append(children)
|
||||
return Either(*[Required(*e) for e in result])
|
||||
ret.append(children)
|
||||
return Either(*[Required(*e) for e in ret])
|
||||
|
||||
|
||||
class LeafPattern(Pattern):
|
||||
|
||||
"""Leaf/terminal node of a pattern tree."""
|
||||
class ChildPattern(Pattern):
|
||||
|
||||
def __init__(self, name, value=None):
|
||||
self.name, self.value = name, value
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r)' % (self.__class__.__name__, self.name, self.value)
|
||||
@ -130,9 +137,7 @@ class LeafPattern(Pattern):
|
||||
return True, left_, collected + [match]
|
||||
|
||||
|
||||
class BranchPattern(Pattern):
|
||||
|
||||
"""Branch/inner node of a pattern tree."""
|
||||
class ParentPattern(Pattern):
|
||||
|
||||
def __init__(self, *children):
|
||||
self.children = list(children)
|
||||
@ -144,15 +149,15 @@ class BranchPattern(Pattern):
|
||||
def flat(self, *types):
|
||||
if type(self) in types:
|
||||
return [self]
|
||||
return sum([child.flat(*types) for child in self.children], [])
|
||||
return sum([c.flat(*types) for c in self.children], [])
|
||||
|
||||
|
||||
class Argument(LeafPattern):
|
||||
class Argument(ChildPattern):
|
||||
|
||||
def single_match(self, left):
|
||||
for n, pattern in enumerate(left):
|
||||
if type(pattern) is Argument:
|
||||
return n, Argument(self.name, pattern.value)
|
||||
for n, p in enumerate(left):
|
||||
if type(p) is Argument:
|
||||
return n, Argument(self.name, p.value)
|
||||
return None, None
|
||||
|
||||
@classmethod
|
||||
@ -165,23 +170,25 @@ class Argument(LeafPattern):
|
||||
class Command(Argument):
|
||||
|
||||
def __init__(self, name, value=False):
|
||||
self.name, self.value = name, value
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
def single_match(self, left):
|
||||
for n, pattern in enumerate(left):
|
||||
if type(pattern) is Argument:
|
||||
if pattern.value == self.name:
|
||||
for n, p in enumerate(left):
|
||||
if type(p) is Argument:
|
||||
if p.value == self.name:
|
||||
return n, Command(self.name, True)
|
||||
else:
|
||||
break
|
||||
return None, None
|
||||
|
||||
|
||||
class Option(LeafPattern):
|
||||
class Option(ChildPattern):
|
||||
|
||||
def __init__(self, short=None, long=None, argcount=0, value=False):
|
||||
assert argcount in (0, 1)
|
||||
self.short, self.long, self.argcount = short, long, argcount
|
||||
self.short, self.long = short, long
|
||||
self.argcount, self.value = argcount, value
|
||||
self.value = None if value is False and argcount else value
|
||||
|
||||
@classmethod
|
||||
@ -202,9 +209,9 @@ class Option(LeafPattern):
|
||||
return class_(short, long, argcount, value)
|
||||
|
||||
def single_match(self, left):
|
||||
for n, pattern in enumerate(left):
|
||||
if self.name == pattern.name:
|
||||
return n, pattern
|
||||
for n, p in enumerate(left):
|
||||
if self.name == p.name:
|
||||
return n, p
|
||||
return None, None
|
||||
|
||||
@property
|
||||
@ -216,34 +223,34 @@ class Option(LeafPattern):
|
||||
self.argcount, self.value)
|
||||
|
||||
|
||||
class Required(BranchPattern):
|
||||
class Required(ParentPattern):
|
||||
|
||||
def match(self, left, collected=None):
|
||||
collected = [] if collected is None else collected
|
||||
l = left
|
||||
c = collected
|
||||
for pattern in self.children:
|
||||
matched, l, c = pattern.match(l, c)
|
||||
for p in self.children:
|
||||
matched, l, c = p.match(l, c)
|
||||
if not matched:
|
||||
return False, left, collected
|
||||
return True, l, c
|
||||
|
||||
|
||||
class Optional(BranchPattern):
|
||||
class Optional(ParentPattern):
|
||||
|
||||
def match(self, left, collected=None):
|
||||
collected = [] if collected is None else collected
|
||||
for pattern in self.children:
|
||||
m, left, collected = pattern.match(left, collected)
|
||||
for p in self.children:
|
||||
m, left, collected = p.match(left, collected)
|
||||
return True, left, collected
|
||||
|
||||
|
||||
class OptionsShortcut(Optional):
|
||||
class AnyOptions(Optional):
|
||||
|
||||
"""Marker/placeholder for [options] shortcut."""
|
||||
|
||||
|
||||
class OneOrMore(BranchPattern):
|
||||
class OneOrMore(ParentPattern):
|
||||
|
||||
def match(self, left, collected=None):
|
||||
assert len(self.children) == 1
|
||||
@ -265,13 +272,13 @@ class OneOrMore(BranchPattern):
|
||||
return False, left, collected
|
||||
|
||||
|
||||
class Either(BranchPattern):
|
||||
class Either(ParentPattern):
|
||||
|
||||
def match(self, left, collected=None):
|
||||
collected = [] if collected is None else collected
|
||||
outcomes = []
|
||||
for pattern in self.children:
|
||||
matched, _, _ = outcome = pattern.match(left, collected)
|
||||
for p in self.children:
|
||||
matched, _, _ = outcome = p.match(left, collected)
|
||||
if matched:
|
||||
outcomes.append(outcome)
|
||||
if outcomes:
|
||||
@ -279,18 +286,12 @@ class Either(BranchPattern):
|
||||
return False, left, collected
|
||||
|
||||
|
||||
class Tokens(list):
|
||||
class TokenStream(list):
|
||||
|
||||
def __init__(self, source, error=DocoptExit):
|
||||
def __init__(self, source, error):
|
||||
self += source.split() if hasattr(source, 'split') else source
|
||||
self.error = error
|
||||
|
||||
@staticmethod
|
||||
def from_pattern(source):
|
||||
source = re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source)
|
||||
source = [s for s in re.split('\s+|(\S*<.*?>)', source) if s]
|
||||
return Tokens(source, error=DocoptLanguageError)
|
||||
|
||||
def move(self):
|
||||
return self.pop(0) if len(self) else None
|
||||
|
||||
@ -323,7 +324,7 @@ def parse_long(tokens, options):
|
||||
raise tokens.error('%s must not have an argument' % o.long)
|
||||
else:
|
||||
if value is None:
|
||||
if tokens.current() in [None, '--']:
|
||||
if tokens.current() is None:
|
||||
raise tokens.error('%s requires argument' % o.long)
|
||||
value = tokens.move()
|
||||
if tokens.error is DocoptExit:
|
||||
@ -354,7 +355,7 @@ def parse_shorts(tokens, options):
|
||||
value = None
|
||||
if o.argcount != 0:
|
||||
if left == '':
|
||||
if tokens.current() in [None, '--']:
|
||||
if tokens.current() is None:
|
||||
raise tokens.error('%s requires argument' % short)
|
||||
value = tokens.move()
|
||||
else:
|
||||
@ -367,7 +368,8 @@ def parse_shorts(tokens, options):
|
||||
|
||||
|
||||
def parse_pattern(source, options):
|
||||
tokens = Tokens.from_pattern(source)
|
||||
tokens = TokenStream(re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source),
|
||||
DocoptLanguageError)
|
||||
result = parse_expr(tokens, options)
|
||||
if tokens.current() is not None:
|
||||
raise tokens.error('unexpected ending: %r' % ' '.join(tokens))
|
||||
@ -414,7 +416,7 @@ def parse_atom(tokens, options):
|
||||
return [result]
|
||||
elif token == 'options':
|
||||
tokens.move()
|
||||
return [OptionsShortcut()]
|
||||
return [AnyOptions()]
|
||||
elif token.startswith('--') and token != '--':
|
||||
return parse_long(tokens, options)
|
||||
elif token.startswith('-') and token not in ('-', '--'):
|
||||
@ -450,26 +452,27 @@ def parse_argv(tokens, options, options_first=False):
|
||||
|
||||
|
||||
def parse_defaults(doc):
|
||||
defaults = []
|
||||
for s in parse_section('options:', doc):
|
||||
# FIXME corner case "bla: options: --foo"
|
||||
_, _, s = s.partition(':') # get rid of "options:"
|
||||
split = re.split('\n[ \t]*(-\S+?)', '\n' + s)[1:]
|
||||
split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])]
|
||||
options = [Option.parse(s) for s in split if s.startswith('-')]
|
||||
defaults += options
|
||||
return defaults
|
||||
# in python < 2.7 you can't pass flags=re.MULTILINE
|
||||
split = re.split('\n *(<\S+?>|-\S+?)', doc)[1:]
|
||||
split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])]
|
||||
options = [Option.parse(s) for s in split if s.startswith('-')]
|
||||
#arguments = [Argument.parse(s) for s in split if s.startswith('<')]
|
||||
#return options, arguments
|
||||
return options
|
||||
|
||||
|
||||
def parse_section(name, source):
|
||||
pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)',
|
||||
re.IGNORECASE | re.MULTILINE)
|
||||
return [s.strip() for s in pattern.findall(source)]
|
||||
def printable_usage(doc):
|
||||
# in python < 2.7 you can't pass flags=re.IGNORECASE
|
||||
usage_split = re.split(r'([Uu][Ss][Aa][Gg][Ee]:)', doc)
|
||||
if len(usage_split) < 3:
|
||||
raise DocoptLanguageError('"usage:" (case-insensitive) not found.')
|
||||
if len(usage_split) > 3:
|
||||
raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
|
||||
return re.split(r'\n\s*\n', ''.join(usage_split[1:]))[0].strip()
|
||||
|
||||
|
||||
def formal_usage(section):
|
||||
_, _, section = section.partition(':') # drop "usage:"
|
||||
pu = section.split()
|
||||
def formal_usage(printable_usage):
|
||||
pu = printable_usage.split()[1:] # split and drop "usage:"
|
||||
return '( ' + ' '.join(') | (' if s == pu[0] else s for s in pu[1:]) + ' )'
|
||||
|
||||
|
||||
@ -509,7 +512,7 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
|
||||
If passed, the object will be printed if --version is in
|
||||
`argv`.
|
||||
options_first : bool (default: False)
|
||||
Set to True to require options precede positional arguments,
|
||||
Set to True to require options preceed positional arguments,
|
||||
i.e. to forbid options and positional arguments intermix.
|
||||
|
||||
Returns
|
||||
@ -523,15 +526,15 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
|
||||
-------
|
||||
>>> from docopt import docopt
|
||||
>>> doc = '''
|
||||
... Usage:
|
||||
... my_program tcp <host> <port> [--timeout=<seconds>]
|
||||
... my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
|
||||
... my_program (-h | --help | --version)
|
||||
...
|
||||
... Options:
|
||||
... -h, --help Show this screen and exit.
|
||||
... --baud=<n> Baudrate [default: 9600]
|
||||
... '''
|
||||
Usage:
|
||||
my_program tcp <host> <port> [--timeout=<seconds>]
|
||||
my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
|
||||
my_program (-h | --help | --version)
|
||||
|
||||
Options:
|
||||
-h, --help Show this screen and exit.
|
||||
--baud=<n> Baudrate [default: 9600]
|
||||
'''
|
||||
>>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30']
|
||||
>>> docopt(doc, argv)
|
||||
{'--baud': '9600',
|
||||
@ -550,15 +553,9 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
|
||||
at https://github.com/docopt/docopt#readme
|
||||
|
||||
"""
|
||||
argv = sys.argv[1:] if argv is None else argv
|
||||
|
||||
usage_sections = parse_section('usage:', doc)
|
||||
if len(usage_sections) == 0:
|
||||
raise DocoptLanguageError('"usage:" (case-insensitive) not found.')
|
||||
if len(usage_sections) > 1:
|
||||
raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
|
||||
DocoptExit.usage = usage_sections[0]
|
||||
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
DocoptExit.usage = printable_usage(doc)
|
||||
options = parse_defaults(doc)
|
||||
pattern = parse_pattern(formal_usage(DocoptExit.usage), options)
|
||||
# [default] syntax for argument is disabled
|
||||
@ -566,13 +563,14 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
|
||||
# same_name = [d for d in arguments if d.name == a.name]
|
||||
# if same_name:
|
||||
# a.value = same_name[0].value
|
||||
argv = parse_argv(Tokens(argv), list(options), options_first)
|
||||
argv = parse_argv(TokenStream(argv, DocoptExit), list(options),
|
||||
options_first)
|
||||
pattern_options = set(pattern.flat(Option))
|
||||
for options_shortcut in pattern.flat(OptionsShortcut):
|
||||
for ao in pattern.flat(AnyOptions):
|
||||
doc_options = parse_defaults(doc)
|
||||
options_shortcut.children = list(set(doc_options) - pattern_options)
|
||||
ao.children = list(set(doc_options) - pattern_options)
|
||||
#if any_options:
|
||||
# options_shortcut.children += [Option(o.short, o.long, o.argcount)
|
||||
# ao.children += [Option(o.short, o.long, o.argcount)
|
||||
# for o in argv if type(o) is Option]
|
||||
extras(help, version, argv, doc)
|
||||
matched, left, collected = pattern.fix().match(argv)
|
46
autocmake/extract.py
Normal file
46
autocmake/extract.py
Normal file
@ -0,0 +1,46 @@
|
||||
def extract_list(config, section):
|
||||
from collections import Iterable
|
||||
l = []
|
||||
if 'modules' in config:
|
||||
for module in config['modules']:
|
||||
for k, v in module.items():
|
||||
for x in v:
|
||||
if section in x:
|
||||
if isinstance(x[section], Iterable) and not isinstance(x[section], str):
|
||||
for y in x[section]:
|
||||
l.append(y)
|
||||
else:
|
||||
l.append(x[section])
|
||||
return l
|
||||
|
||||
|
||||
def to_d(l):
|
||||
"""
|
||||
Converts list of dicts to dict.
|
||||
"""
|
||||
_d = {}
|
||||
for x in l:
|
||||
for k, v in x.items():
|
||||
_d[k] = v
|
||||
return _d
|
||||
|
||||
|
||||
def test_to_d():
|
||||
l = [{'a': 'b'}, {'c': 'd'}]
|
||||
d = {'a': 'b', 'c': 'd'}
|
||||
assert to_d(l) == d
|
||||
|
||||
|
||||
def to_l(x):
|
||||
"""
|
||||
Converts list of dicts to dict.
|
||||
"""
|
||||
if isinstance(x, str):
|
||||
return [x]
|
||||
else:
|
||||
return x
|
||||
|
||||
|
||||
def test_to_l():
|
||||
assert to_l('foo') == ['foo']
|
||||
assert to_l(['foo', 'bar']) == ['foo', 'bar']
|
176
autocmake/generate.py
Normal file
176
autocmake/generate.py
Normal file
@ -0,0 +1,176 @@
|
||||
def gen_cmake_command(config):
|
||||
"""
|
||||
Generate CMake command.
|
||||
"""
|
||||
from autocmake.extract import extract_list
|
||||
|
||||
s = []
|
||||
s.append("\n\ndef gen_cmake_command(options, arguments):")
|
||||
s.append(' """')
|
||||
s.append(" Generate CMake command based on options and arguments.")
|
||||
s.append(' """')
|
||||
s.append(" command = []")
|
||||
|
||||
for env in config['export']:
|
||||
s.append(' command.append({0})'.format(env))
|
||||
|
||||
s.append(" command.append(arguments['--cmake-executable'])")
|
||||
|
||||
for definition in config['define']:
|
||||
s.append(' command.append({0})'.format(definition))
|
||||
|
||||
s.append(" command.append('-DCMAKE_BUILD_TYPE={0}'.format(arguments['--type']))")
|
||||
s.append(" command.append('-G \"{0}\"'.format(arguments['--generator']))")
|
||||
s.append(" if arguments['--cmake-options'] != \"''\":")
|
||||
s.append(" command.append(arguments['--cmake-options'])")
|
||||
s.append(" if arguments['--prefix']:")
|
||||
s.append(" command.append('-DCMAKE_INSTALL_PREFIX=\"{0}\"'.format(arguments['--prefix']))")
|
||||
|
||||
s.append("\n return ' '.join(command)")
|
||||
|
||||
return '\n'.join(s)
|
||||
|
||||
|
||||
def autogenerated_notice():
|
||||
from datetime import date
|
||||
from . import __version__
|
||||
|
||||
current_year = date.today().year
|
||||
year_range = '2015-{0}'.format(current_year)
|
||||
|
||||
s = []
|
||||
s.append('# This file is autogenerated by Autocmake v{0} http://autocmake.org'.format(__version__))
|
||||
s.append('# Copyright (c) {0} by Radovan Bast, Jonas Juselius, and contributors.'.format(year_range))
|
||||
|
||||
return '\n'.join(s)
|
||||
|
||||
|
||||
def gen_setup(config, relative_path, setup_script_name):
|
||||
"""
|
||||
Generate setup script.
|
||||
"""
|
||||
from autocmake.extract import extract_list
|
||||
|
||||
s = []
|
||||
s.append('#!/usr/bin/env python')
|
||||
s.append('\n{0}'.format(autogenerated_notice()))
|
||||
s.append('\nimport os')
|
||||
s.append('import sys')
|
||||
|
||||
s.append("\nsys.path.insert(0, '{0}')".format(relative_path))
|
||||
|
||||
s.append('from autocmake import configure')
|
||||
s.append('from autocmake.external import docopt')
|
||||
|
||||
s.append('\n\noptions = """')
|
||||
s.append('Usage:')
|
||||
s.append(' ./{0} [options] [<builddir>]'.format(setup_script_name))
|
||||
s.append(' ./{0} (-h | --help)'.format(setup_script_name))
|
||||
s.append('\nOptions:')
|
||||
|
||||
options = []
|
||||
|
||||
for opt in config['docopt']:
|
||||
first = opt.split()[0].strip()
|
||||
rest = ' '.join(opt.split()[1:]).strip()
|
||||
options.append([first, rest])
|
||||
|
||||
options.append(['--type=<TYPE>', 'Set the CMake build type (debug, release, or relwithdeb) [default: release].'])
|
||||
options.append(['--generator=<STRING>', 'Set the CMake build system generator [default: Unix Makefiles].'])
|
||||
options.append(['--show', 'Show CMake command and exit.'])
|
||||
options.append(['--cmake-executable=<CMAKE_EXECUTABLE>', 'Set the CMake executable [default: cmake].'])
|
||||
options.append(['--cmake-options=<STRING>', "Define options to CMake [default: '']."])
|
||||
options.append(['--prefix=<PATH>', 'Set the install path for make install.'])
|
||||
options.append(['<builddir>', 'Build directory.'])
|
||||
options.append(['-h --help', 'Show this screen.'])
|
||||
|
||||
s.append(align_options(options))
|
||||
|
||||
s.append('"""')
|
||||
|
||||
s.append(gen_cmake_command(config))
|
||||
|
||||
s.append("\n")
|
||||
s.append("# parse command line args")
|
||||
s.append("try:")
|
||||
s.append(" arguments = docopt.docopt(options, argv=None)")
|
||||
s.append("except docopt.DocoptExit:")
|
||||
s.append(r" sys.stderr.write('ERROR: bad input to {0}\n'.format(sys.argv[0]))")
|
||||
s.append(" sys.stderr.write(options)")
|
||||
s.append(" sys.exit(-1)")
|
||||
s.append("\n")
|
||||
s.append("# use extensions to validate/post-process args")
|
||||
s.append("if configure.module_exists('extensions'):")
|
||||
s.append(" import extensions")
|
||||
s.append(" arguments = extensions.postprocess_args(sys.argv, arguments)")
|
||||
s.append("\n")
|
||||
s.append("root_directory = os.path.dirname(os.path.realpath(__file__))")
|
||||
s.append("\n")
|
||||
s.append("build_path = arguments['<builddir>']")
|
||||
s.append("\n")
|
||||
s.append("# create cmake command")
|
||||
s.append("cmake_command = '{0} {1}'.format(gen_cmake_command(options, arguments), root_directory)")
|
||||
s.append("\n")
|
||||
s.append("# run cmake")
|
||||
s.append("configure.configure(root_directory, build_path, cmake_command, arguments['--show'])")
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def gen_cmakelists(project_name, min_cmake_version, relative_path, modules):
|
||||
"""
|
||||
Generate CMakeLists.txt.
|
||||
"""
|
||||
import os
|
||||
|
||||
s = []
|
||||
|
||||
s.append(autogenerated_notice())
|
||||
|
||||
s.append('\n# set minimum cmake version')
|
||||
s.append('cmake_minimum_required(VERSION {0} FATAL_ERROR)'.format(min_cmake_version))
|
||||
|
||||
s.append('\n# project name')
|
||||
s.append('project({0})'.format(project_name))
|
||||
|
||||
s.append('\n# do not rebuild if rules (compiler flags) change')
|
||||
s.append('set(CMAKE_SKIP_RULE_DEPENDENCY TRUE)')
|
||||
|
||||
s.append('\n# if CMAKE_BUILD_TYPE undefined, we set it to Debug')
|
||||
s.append('if(NOT CMAKE_BUILD_TYPE)')
|
||||
s.append(' set(CMAKE_BUILD_TYPE "Debug")')
|
||||
s.append('endif()')
|
||||
|
||||
if len(modules) > 0:
|
||||
s.append('\n# directories which hold included cmake modules')
|
||||
|
||||
module_paths = [module.path for module in modules]
|
||||
module_paths.append('downloaded') # this is done to be able to find fetched modules when testing
|
||||
module_paths = list(set(module_paths))
|
||||
module_paths.sort() # we do this to always get the same order and to minimize diffs
|
||||
for directory in module_paths:
|
||||
rel_cmake_module_path = os.path.join(relative_path, directory)
|
||||
# on windows cmake corrects this so we have to make it wrong again
|
||||
rel_cmake_module_path = rel_cmake_module_path.replace('\\', '/')
|
||||
s.append('set(CMAKE_MODULE_PATH ${{CMAKE_MODULE_PATH}} ${{PROJECT_SOURCE_DIR}}/{0})'.format(rel_cmake_module_path))
|
||||
|
||||
if len(modules) > 0:
|
||||
s.append('\n# included cmake modules')
|
||||
for module in modules:
|
||||
s.append('include({0})'.format(os.path.splitext(module.name)[0]))
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def align_options(options):
|
||||
"""
|
||||
Indents flags and aligns help texts.
|
||||
"""
|
||||
l = 0
|
||||
for opt in options:
|
||||
if len(opt[0]) > l:
|
||||
l = len(opt[0])
|
||||
s = []
|
||||
for opt in options:
|
||||
s.append(' {0}{1} {2}'.format(opt[0], ' ' * (l - len(opt[0])), opt[1]))
|
||||
return '\n'.join(s)
|
66
autocmake/interpolate.py
Normal file
66
autocmake/interpolate.py
Normal file
@ -0,0 +1,66 @@
|
||||
def replace(s, d):
|
||||
from re import findall
|
||||
|
||||
if isinstance(s, str):
|
||||
for var in findall(r"%\(([A-Za-z0-9_]*)\)", s):
|
||||
s = s.replace("%({0})".format(var), str(d[var]))
|
||||
return s
|
||||
|
||||
|
||||
def test_replace():
|
||||
assert replace('hey %(foo) ho %(bar)',
|
||||
{'foo': 'hey', 'bar': 'ho'}) == 'hey hey ho ho'
|
||||
|
||||
|
||||
def interpolate(d, d_map):
|
||||
from collections import Mapping, Iterable
|
||||
from copy import copy
|
||||
|
||||
for k, v in d.items():
|
||||
if isinstance(v, Mapping):
|
||||
d[k] = interpolate(d[k], d_map)
|
||||
elif isinstance(v, Iterable) and not isinstance(v, str):
|
||||
l = []
|
||||
for x in v:
|
||||
if isinstance(x, Mapping):
|
||||
l.append(interpolate(x, d_map))
|
||||
else:
|
||||
l.append(replace(x, d_map))
|
||||
d[k] = copy(l)
|
||||
else:
|
||||
d[k] = replace(d[k], d_map)
|
||||
return d
|
||||
|
||||
|
||||
def test_interpolate():
|
||||
d = {'foo': 'hey',
|
||||
'bar': 'ho',
|
||||
'one': 'hey %(foo) ho %(bar)',
|
||||
'two': {'one': 'hey %(foo) ho %(bar)',
|
||||
'two': 'raboof'}}
|
||||
d_interpolated = {'foo': 'hey',
|
||||
'bar': 'ho',
|
||||
'one': 'hey hey ho ho',
|
||||
'two': {'one': 'hey hey ho ho',
|
||||
'two': 'raboof'}}
|
||||
assert interpolate(d, d) == d_interpolated
|
||||
|
||||
|
||||
def test_interpolate_int():
|
||||
d = {'foo': 1,
|
||||
'bar': 2,
|
||||
'one': 'hey %(foo) ho %(bar)',
|
||||
'two': {'one': 'hey %(foo) ho %(bar)',
|
||||
'two': 'raboof'}}
|
||||
d_interpolated = {'foo': 1,
|
||||
'bar': 2,
|
||||
'one': 'hey 1 ho 2',
|
||||
'two': {'one': 'hey 1 ho 2',
|
||||
'two': 'raboof'}}
|
||||
assert interpolate(d, d) == d_interpolated
|
||||
|
||||
|
||||
def test_interpolate_nested():
|
||||
d2 = {'modules': [{'fc': [{'source': '%(url_root)fc_optional.cmake'}]}], 'url_root': 'downloaded/downloaded_'}
|
||||
d2_interpolated = {'modules': [{'fc': [{'source': 'downloaded/downloaded_fc_optional.cmake'}]}], 'url_root': 'downloaded/downloaded_'}
|
||||
assert interpolate(d2, d2) == d2_interpolated
|
132
autocmake/parse_rst.py
Normal file
132
autocmake/parse_rst.py
Normal file
@ -0,0 +1,132 @@
|
||||
def parse_cmake_module(s_in, overrides={}):
|
||||
import sys
|
||||
from collections import Mapping, Iterable, defaultdict
|
||||
from autocmake.parse_yaml import parse_yaml
|
||||
|
||||
# we do not use the nicer sys.version_info.major
|
||||
# for compatibility with Python < 2.7
|
||||
if sys.version_info[0] > 2:
|
||||
from io import StringIO
|
||||
else:
|
||||
from StringIO import StringIO
|
||||
|
||||
parsed_config = defaultdict(lambda: None)
|
||||
|
||||
if 'autocmake.yml configuration::' not in s_in:
|
||||
return parsed_config
|
||||
|
||||
s_out = []
|
||||
is_rst_line = False
|
||||
for line in s_in.split('\n'):
|
||||
if is_rst_line:
|
||||
if len(line) > 0:
|
||||
if line[0] != '#':
|
||||
is_rst_line = False
|
||||
else:
|
||||
is_rst_line = False
|
||||
if is_rst_line:
|
||||
s_out.append(line[2:])
|
||||
if '#.rst:' in line:
|
||||
is_rst_line = True
|
||||
|
||||
autocmake_entry = '\n'.join(s_out).split('autocmake.yml configuration::')[1]
|
||||
autocmake_entry = autocmake_entry.replace('\n ', '\n')
|
||||
|
||||
buf = StringIO(autocmake_entry)
|
||||
config = parse_yaml(buf, overrides)
|
||||
|
||||
for k, v in config.items():
|
||||
if isinstance(v, Iterable) and not isinstance(v, str):
|
||||
parsed_config[k] = [x for x in config[k]]
|
||||
else:
|
||||
parsed_config[k] = [config[k]]
|
||||
|
||||
return parsed_config
|
||||
|
||||
|
||||
def test_parse_cmake_module():
|
||||
|
||||
s = r'''#.rst:
|
||||
#
|
||||
# Foo ...
|
||||
#
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt:
|
||||
# - "--cxx=<CXX> C++ compiler [default: g++]."
|
||||
# - "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."
|
||||
# export: "'CXX={0}'.format(arguments['--cxx'])"
|
||||
# define: "'-DEXTRA_CXXFLAGS=\"{0}\"'.format(arguments['--extra-cxx-flags'])"
|
||||
|
||||
enable_language(CXX)
|
||||
|
||||
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
||||
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
||||
endif()'''
|
||||
|
||||
parsed_config = parse_cmake_module(s)
|
||||
assert parsed_config['docopt'] == ["--cxx=<CXX> C++ compiler [default: g++].", "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."]
|
||||
|
||||
|
||||
def test_parse_cmake_module_no_key():
|
||||
|
||||
s = '''#.rst:
|
||||
#
|
||||
# Foo ...
|
||||
#
|
||||
# Bar ...
|
||||
|
||||
enable_language(CXX)
|
||||
|
||||
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
||||
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
||||
endif()'''
|
||||
|
||||
parsed_config = parse_cmake_module(s)
|
||||
assert parsed_config['docopt'] is None
|
||||
|
||||
|
||||
def test_parse_cmake_module_interpolate():
|
||||
|
||||
s = r'''#.rst:
|
||||
#
|
||||
# Foo ...
|
||||
#
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# major: 1
|
||||
# minor: 2
|
||||
# patch: 3
|
||||
# a: v%(major)
|
||||
# b: v%(minor)
|
||||
# c: v%(patch)
|
||||
|
||||
enable_language(CXX)'''
|
||||
|
||||
parsed_config = parse_cmake_module(s)
|
||||
assert parsed_config['a'] == ['v1']
|
||||
assert parsed_config['b'] == ['v2']
|
||||
assert parsed_config['c'] == ['v3']
|
||||
|
||||
|
||||
def test_parse_cmake_module_overrides():
|
||||
|
||||
s = r'''#.rst:
|
||||
#
|
||||
# Foo ...
|
||||
#
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# major: 1
|
||||
# minor: 2
|
||||
# patch: 3
|
||||
# a: v%(major)
|
||||
# b: v%(minor)
|
||||
# c: v%(patch)
|
||||
|
||||
enable_language(CXX)'''
|
||||
|
||||
parsed_config = parse_cmake_module(s, {'minor': 4})
|
||||
assert parsed_config['a'] == ['v1']
|
||||
assert parsed_config['b'] == ['v4']
|
||||
assert parsed_config['c'] == ['v3']
|
30
autocmake/parse_yaml.py
Normal file
30
autocmake/parse_yaml.py
Normal file
@ -0,0 +1,30 @@
|
||||
def parse_yaml(stream, overrides={}):
|
||||
import yaml
|
||||
import sys
|
||||
from autocmake.interpolate import interpolate
|
||||
|
||||
try:
|
||||
config = yaml.load(stream, yaml.SafeLoader)
|
||||
except yaml.YAMLError as exc:
|
||||
print(exc)
|
||||
sys.exit(-1)
|
||||
|
||||
for k in config:
|
||||
if k in overrides:
|
||||
config[k] = overrides[k]
|
||||
|
||||
config = interpolate(config, config)
|
||||
return config
|
||||
|
||||
|
||||
def test_parse_yaml():
|
||||
text = """foo: bar
|
||||
this: that
|
||||
var: '%(foo)'
|
||||
list:
|
||||
- a: '%(foo)'
|
||||
- b: '%(foo)'
|
||||
- c: '%(foo)'"""
|
||||
|
||||
assert parse_yaml(text) == {'foo': 'bar', 'this': 'that', 'var': 'bar',
|
||||
'list': [{'a': 'bar'}, {'b': 'bar'}, {'c': 'bar'}]}
|
22
doc/conf.py
22
doc/conf.py
@ -14,15 +14,15 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
|
||||
sys.path.append(os.path.relpath(os.path.abspath('.')))
|
||||
import extract_rst
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
import extract_rst
|
||||
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
from autocmake import __version__ as _version
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
@ -52,17 +52,17 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Autocmake'
|
||||
copyright = u'2015, Radovan Bast and Jonas Juselius'
|
||||
author = u'Radovan Bast and Jonas Juselius'
|
||||
copyright = u'2015-2016, Radovan Bast, Jonas Juselius, and contributors'
|
||||
author = u'Radovan Bast, Jonas Juselius, and contributors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.0'
|
||||
release = _version
|
||||
# The short X.Y version.
|
||||
version = '.'.join(release.split('.')[0:2])
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@ -228,7 +228,7 @@ latex_elements = {
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'Autocmake.tex', u'Autocmake Documentation',
|
||||
u'Radovan Bast and Jonas Juselius', 'manual'),
|
||||
author, 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
|
@ -9,12 +9,12 @@ This documentation is refreshed upon each push to the central repository.
|
||||
|
||||
The module reference documentation is generated from the module sources using
|
||||
``#.rst:`` tags (compare for instance
|
||||
http://autocmake.readthedocs.org/en/latest/module-reference.html#cc-cmake with
|
||||
https://github.com/scisoft/autocmake/blob/master/modules/cc.cmake).
|
||||
http://autocmake.readthedocs.io/en/latest/module-reference.html#cc-cmake with
|
||||
https://github.com/coderefinery/autocmake/blob/master/modules/cc.cmake).
|
||||
|
||||
Please note that the lines following ``# autocmake.cfg configuration::`` are
|
||||
understood by the ``update.py`` script to infer autocmake.cfg code from the
|
||||
Please note that the lines following ``# autocmake.yml configuration::`` are
|
||||
understood by the ``update.py`` script to infer autocmake.yml code from the
|
||||
documentation. As an example consider
|
||||
https://github.com/scisoft/autocmake/blob/master/modules/cc.cmake#L20-L25.
|
||||
https://github.com/coderefinery/autocmake/blob/master/modules/cc.cmake#L20-L26.
|
||||
Here, ``update.py`` will infer the configurations for ``docopt``, ``export``,
|
||||
and ``define``.
|
||||
|
@ -5,12 +5,16 @@ Testing Autocmake
|
||||
|
||||
You will need to install `pytest <http://pytest.org/>`__.
|
||||
|
||||
Check also the `Travis <https://github.com/scisoft/autocmake/blob/master/.travis.yml>`__
|
||||
Check also the `Travis <https://github.com/coderefinery/autocmake/blob/master/.travis.yml>`__
|
||||
build and test recipe for other requirements.
|
||||
|
||||
Your contributions and changes should preserve the test set. You can run locally all tests with::
|
||||
Your contributions and changes should preserve the test set and be PEP8 conform.
|
||||
You can run locally all tests with::
|
||||
|
||||
$ py.test test/test.py
|
||||
$ pep8 --ignore E501 update.py
|
||||
$ pep8 --ignore E501,E265 autocmake
|
||||
$ py.test -vv autocmake/*
|
||||
$ py.test -vv test/test.py
|
||||
|
||||
You can also select individual tests, for example those with ``fc_blas`` string in the name::
|
||||
|
||||
@ -19,8 +23,5 @@ You can also select individual tests, for example those with ``fc_blas`` string
|
||||
For more options, see the ``py.test`` flags.
|
||||
|
||||
This test set is run upon each push to the central repository.
|
||||
See also the `Travis <https://travis-ci.org/scisoft/autocmake/builds>`__
|
||||
See also the `Travis <https://travis-ci.org/coderefinery/autocmake/builds>`__
|
||||
build and test history.
|
||||
|
||||
In addition we also test Autocmake on a Windows CI server: `Appveyor <https://ci.appveyor.com/project/bast/autocmake/history>`__.
|
||||
This is controlled by `Appveyor <https://github.com/scisoft/autocmake/blob/master/appveyor.yml>`__.
|
||||
|
@ -12,48 +12,48 @@ infrastructure files which will be needed to build the project::
|
||||
|
||||
$ mkdir cmake # does not have to be called "cmake" - take the name you prefer
|
||||
$ cd cmake
|
||||
$ wget https://github.com/scisoft/autocmake/raw/master/update.py
|
||||
$ wget https://github.com/coderefinery/autocmake/raw/master/update.py
|
||||
$ virtualenv venv
|
||||
$ source venv/bin/activate
|
||||
$ pip install pyyaml
|
||||
$ python update.py --self
|
||||
|
||||
On the MS Windows system, you can use the PowerShell wget-replacement::
|
||||
|
||||
$ Invoke-WebRequest https://github.com/scisoft/autocmake/raw/master/update.py -OutFile update.py
|
||||
$ Invoke-WebRequest https://github.com/coderefinery/autocmake/raw/master/update.py -OutFile update.py
|
||||
|
||||
This creates (or updates) the following files (an existing ``autocmake.cfg`` is
|
||||
This creates (or updates) the following files (an existing ``autocmake.yml`` is
|
||||
not overwritten by the script)::
|
||||
|
||||
cmake/
|
||||
autocmake.cfg # edit this file
|
||||
autocmake.yml # edit this file
|
||||
update.py # no need to edit
|
||||
lib/
|
||||
config.py # no need to edit
|
||||
docopt/
|
||||
docopt.py # no need to edit
|
||||
autocmake/ # no need to edit
|
||||
... # no need to edit
|
||||
|
||||
Note that all other listed files are overwritten (use version control).
|
||||
Note that ``update.py`` and files under ``autocmake/``
|
||||
are overwritten (use version control).
|
||||
|
||||
|
||||
Generating the CMake infrastructure
|
||||
-----------------------------------
|
||||
|
||||
Now customize ``autocmake.cfg`` to your needs
|
||||
(see :ref:`autocmake_cfg`)
|
||||
Now customize ``autocmake.yml`` to your needs
|
||||
(see :ref:`autocmake_yml`)
|
||||
and then run the ``update.py`` script which
|
||||
creates ``CMakeLists.txt`` and a setup script in the target path::
|
||||
|
||||
$ python update.py ..
|
||||
|
||||
The script also downloads external CMake modules specified in ``autocmake.cfg`` to a directory
|
||||
The script also downloads external CMake modules specified in ``autocmake.yml`` to a directory
|
||||
called ``downloaded/``::
|
||||
|
||||
cmake/
|
||||
autocmake.cfg # edit this file
|
||||
autocmake.yml # edit this file
|
||||
update.py # no need to edit
|
||||
lib/
|
||||
config.py # no need to edit
|
||||
docopt/
|
||||
docopt.py # no need to edit
|
||||
downloaded/ # contains CMake modules fetched from the web
|
||||
autocmake/ # no need to edit
|
||||
... # no need to edit
|
||||
downloaded/ # contains CMake modules fetched from the web
|
||||
|
||||
|
||||
Building the project
|
||||
|
@ -1,115 +1,101 @@
|
||||
|
||||
.. _autocmake_cfg:
|
||||
.. _autocmake_yml:
|
||||
|
||||
Configuring autocmake.cfg
|
||||
Configuring autocmake.yml
|
||||
=========================
|
||||
|
||||
The script ``autocmake.cfg`` is the high level place where you configure
|
||||
The script ``autocmake.yml`` is the high level place where you configure
|
||||
your project. Here is an example. We will discuss it in detail further
|
||||
below::
|
||||
|
||||
[project]
|
||||
name: numgrid
|
||||
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake
|
||||
url_root: https://github.com/coderefinery/autocmake/raw/master/
|
||||
|
||||
[cc]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/cc.cmake
|
||||
|
||||
[cxx]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/cxx.cmake
|
||||
|
||||
[flags]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/compilers/GNU.CXX.cmake
|
||||
https://github.com/scisoft/autocmake/raw/master/compilers/Intel.CXX.cmake
|
||||
|
||||
[rpath]
|
||||
source: custom/rpath.cmake
|
||||
|
||||
[definitions]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/definitions.cmake
|
||||
|
||||
[coverage]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/code_coverage.cmake
|
||||
|
||||
[safeguards]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/safeguards.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/src.cmake
|
||||
|
||||
[googletest]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/googletest.cmake
|
||||
|
||||
[custom]
|
||||
source: custom/api.cmake
|
||||
custom/test.cmake
|
||||
modules:
|
||||
- compilers:
|
||||
- source:
|
||||
- '%(url_root)modules/fc.cmake'
|
||||
- '%(url_root)modules/cc.cmake'
|
||||
- '%(url_root)modules/cxx.cmake'
|
||||
- flags:
|
||||
- source:
|
||||
- '%(url_root)compilers/GNU.CXX.cmake'
|
||||
- '%(url_root)compilers/Intel.CXX.cmake'
|
||||
- 'compilers/Clang.CXX.cmake'
|
||||
- plugins:
|
||||
- source:
|
||||
- '%(url_root)modules/ccache.cmake'
|
||||
- 'custom/rpath.cmake'
|
||||
- '%(url_root)modules/definitions.cmake'
|
||||
- '%(url_root)modules/code_coverage.cmake'
|
||||
- '%(url_root)modules/safeguards.cmake'
|
||||
- '%(url_root)modules/default_build_paths.cmake'
|
||||
- '%(url_root)modules/src.cmake'
|
||||
- '%(url_root)modules/googletest.cmake'
|
||||
- 'custom/api.cmake'
|
||||
- 'custom/test.cmake'
|
||||
|
||||
|
||||
Name and order of sections
|
||||
--------------------------
|
||||
|
||||
We see that the configuration file has sections.
|
||||
The only section where the name matters is ``[project]``::
|
||||
First we define the project name (here "numgrid"). This section has to be there
|
||||
and it has to be called "project" (but it does not have to be on top).
|
||||
|
||||
[project]
|
||||
name: numgrid
|
||||
min_cmake_version: 2.8
|
||||
We also have to define ``min_cmake_version``.
|
||||
|
||||
This is where we define the project name (here "numgrid"). This section has to
|
||||
be there and it has to be called "project" (but it does not have to be on top).
|
||||
The definition ``url_root`` is an interpolation (see :ref:`interpolation`) and
|
||||
we use it to avoid retyping the same line over and over and to be able to
|
||||
change it in one place. The explicit name "url_root" has no special meaning to
|
||||
Autocmake and we could have chosen a different name.
|
||||
|
||||
The names of the other sections do not matter to Autocmake. You could name them like this::
|
||||
The section ``modules`` is a list of CMake plugins. The names of the list
|
||||
elements (here "compilers", "flags", and "plugins") does not matter to
|
||||
Autocmake. We could have called them "one", "two", and "whatever", but it would
|
||||
not make much sense. It is better to choose names that are meaningful to you
|
||||
and readers of your code.
|
||||
|
||||
[project]
|
||||
name: numgrid
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[one]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake
|
||||
|
||||
[two]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/cc.cmake
|
||||
|
||||
[whatever]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/cxx.cmake
|
||||
|
||||
But it would not make much sense. It is better to choose names that are
|
||||
meaningful to you.
|
||||
|
||||
The order of the sections does matter and the sections will be processed in the
|
||||
exact order as you specify them in ``autocmake.cfg``.
|
||||
The order of the elements under ``modules`` does matter and the list will be
|
||||
processed in the exact order as you specify them in ``autocmake.yml``.
|
||||
|
||||
|
||||
Minimal example
|
||||
---------------
|
||||
|
||||
As a minimal example we take an ``autocmake.cfg`` which only contains::
|
||||
As a minimal example we take an ``autocmake.yml`` which only contains::
|
||||
|
||||
[project]
|
||||
name: minime
|
||||
min_cmake_version: 2.8
|
||||
|
||||
If you don't have the ``update.py`` script yet, you need to fetch it from the web::
|
||||
|
||||
$ wget https://github.com/coderefinery/autocmake/raw/master/update.py
|
||||
|
||||
First we make sure that the ``update.py`` script is up-to-date and that it has access
|
||||
to all libraries it needs::
|
||||
|
||||
$ python update.py --self
|
||||
|
||||
- creating .gitignore
|
||||
- fetching lib/config.py
|
||||
- fetching lib/docopt/docopt.py
|
||||
- fetching autocmake/configure.py
|
||||
- fetching autocmake/__init__.py
|
||||
- fetching autocmake/external/docopt.py
|
||||
- fetching autocmake/external/__init__.py
|
||||
- fetching autocmake/generate.py
|
||||
- fetching autocmake/extract.py
|
||||
- fetching autocmake/interpolate.py
|
||||
- fetching autocmake/parse_rst.py
|
||||
- fetching autocmake/parse_yaml.py
|
||||
- fetching update.py
|
||||
|
||||
Good. Now we can generate ``CMakeLists.txt`` and the setup script::
|
||||
|
||||
$ python update ..
|
||||
$ python update.py ..
|
||||
|
||||
- parsing autocmake.cfg
|
||||
- parsing autocmake.yml
|
||||
- generating CMakeLists.txt
|
||||
- generating setup script
|
||||
|
||||
@ -147,38 +133,38 @@ the following default options::
|
||||
--show Show CMake command and exit.
|
||||
--cmake-executable=<CMAKE_EXECUTABLE> Set the CMake executable [default: cmake].
|
||||
--cmake-options=<STRING> Define options to CMake [default: ''].
|
||||
--prefix=<PATH> Set the install path for make install.
|
||||
<builddir> Build directory.
|
||||
-h --help Show this screen.
|
||||
|
||||
That's not too bad although currently we cannot do much with this since there
|
||||
are no sources listed, no targets, hence nothing to build. We need to flesh out
|
||||
``CMakeLists.txt`` by extending ``autocmake.cfg``
|
||||
and this is what we will do in the next section.
|
||||
``CMakeLists.txt`` by extending ``autocmake.yml`` and this is what we will do
|
||||
in the next section.
|
||||
|
||||
|
||||
Assembling CMake plugins
|
||||
------------------------
|
||||
|
||||
The preferred way to extend ``CMakeLists.txt`` is by editing ``autocmake.cfg``
|
||||
The preferred way to extend ``CMakeLists.txt`` is by editing ``autocmake.yml``
|
||||
and using the ``source`` option::
|
||||
|
||||
[fc]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake
|
||||
- compilers:
|
||||
- source:
|
||||
- '%(url_root)modules/fc.cmake'
|
||||
- '%(url_root)modules/cc.cmake'
|
||||
- '%(url_root)modules/cxx.cmake'
|
||||
|
||||
This will download ``fc.cmake`` and include it in ``CMakeLists.txt``.
|
||||
This will download ``fc.cmake``, ``cc.cmake``, and ``cxx.cmake``, and include
|
||||
them in ``CMakeLists.txt``, in this order.
|
||||
|
||||
You can also include local CMake modules, e.g.::
|
||||
|
||||
[rpath]
|
||||
source: custom/rpath.cmake
|
||||
- source:
|
||||
- 'custom/rpath.cmake'
|
||||
|
||||
It is also OK to include several modules at once::
|
||||
|
||||
[flags]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/compilers/GNU.CXX.cmake
|
||||
https://github.com/scisoft/autocmake/raw/master/compilers/Intel.CXX.cmake
|
||||
|
||||
The modules will be included in the same order as they appear in ``autocmake.cfg``.
|
||||
It is also OK to include several modules at once as we have seen above. The
|
||||
modules will be included in the same order as they appear in ``autocmake.yml``.
|
||||
|
||||
|
||||
Fetching files without including them in CMakeLists.txt
|
||||
@ -187,9 +173,9 @@ Fetching files without including them in CMakeLists.txt
|
||||
Sometimes you want to fetch a file without including it in ``CMakeLists.txt``.
|
||||
This can be done with the ``fetch`` option. This is for instance done by the
|
||||
``git_info.cmake`` module (see
|
||||
https://github.com/scisoft/autocmake/blob/master/modules/git_info/git_info.cmake#L10-L11).
|
||||
https://github.com/coderefinery/autocmake/blob/master/modules/git_info/git_info.cmake#L10-L13).
|
||||
|
||||
If ``fetch`` is invoked in ``autocmake.cfg``, then the fetched file is placed
|
||||
If ``fetch`` is invoked in ``autocmake.yml``, then the fetched file is placed
|
||||
under ``downloaded/``. If ``fetch`` is invoked from within a CMake module
|
||||
documentation (see below), then the fetched file is placed into the same
|
||||
directory as the CMake module file which fetches it.
|
||||
@ -199,11 +185,11 @@ Generating setup options
|
||||
------------------------
|
||||
|
||||
Options for the setup script can be generated with the ``docopt``
|
||||
option. As an example, the following ``autocmake.cfg`` snippet will add a
|
||||
option. As an example, the following ``autocmake.yml`` snippet will add a
|
||||
``--something`` flag::
|
||||
|
||||
[my_section]
|
||||
docopt: --something Enable something [default: False].
|
||||
- my_section:
|
||||
- docopt: "--something Enable something [default: False]."
|
||||
|
||||
|
||||
Setting CMake options
|
||||
@ -213,9 +199,9 @@ Configure-time CMake options can be generated with the ``define`` option.
|
||||
Consider the following example which toggles the CMake variable
|
||||
``ENABLE_SOMETHING``::
|
||||
|
||||
[my_section]
|
||||
docopt: --something Enable something [default: False].
|
||||
define: '-DENABLE_SOMETHING={0}'.format(arguments['--something'])
|
||||
- my_section:
|
||||
- docopt: "--something Enable something [default: False]."
|
||||
- define: "'-DENABLE_SOMETHING={0}'.format(arguments['--enable-something'])"
|
||||
|
||||
|
||||
Setting environment variables
|
||||
@ -224,33 +210,23 @@ Setting environment variables
|
||||
You can export environment variables at configure-time using the ``export``
|
||||
option. Consider the following example::
|
||||
|
||||
[cc]
|
||||
docopt: --cc=<CC> C compiler [default: gcc].
|
||||
--extra-cc-flags=<EXTRA_CFLAGS> Extra C compiler flags [default: ''].
|
||||
export: 'CC=%s' % arguments['--cc']
|
||||
define: '-DEXTRA_CFLAGS="%s"' % arguments['--extra-cc-flags']
|
||||
docopt:
|
||||
- "--cc=<CC> C compiler [default: gcc]."
|
||||
- "--extra-cc-flags=<EXTRA_CFLAGS> Extra C compiler flags [default: '']."
|
||||
export: "'CC={0}'.format(arguments['--cc'])"
|
||||
define: "'-DEXTRA_CFLAGS=\"{0}\"'.format(arguments['--extra-cc-flags'])"
|
||||
|
||||
|
||||
Auto-generating configurations from the documentation
|
||||
-----------------------------------------------------
|
||||
|
||||
To avoid a boring re-typing of boilerplate ``autocmake.cfg`` code it is possible
|
||||
To avoid a boring re-typing of boilerplate ``autocmake.yml`` code it is possible
|
||||
to auto-generate configurations from the documentation. This is the case
|
||||
for many core modules which come with own options once you have sourced them.
|
||||
|
||||
The lines following ``# autocmake.cfg configuration::`` are
|
||||
understood by the ``update.py`` script to infer ``autocmake.cfg`` code from the
|
||||
The lines following ``# autocmake.yml configuration::`` are
|
||||
understood by the ``update.py`` script to infer ``autocmake.yml`` code from the
|
||||
documentation. As an example consider
|
||||
https://github.com/scisoft/autocmake/blob/master/modules/cc.cmake#L20-L25.
|
||||
https://github.com/coderefinery/autocmake/blob/master/modules/cc.cmake#L20-L26.
|
||||
Here, ``update.py`` will infer the configurations for ``docopt``, ``export``,
|
||||
and ``define``.
|
||||
|
||||
|
||||
Overriding documented configurations
|
||||
------------------------------------
|
||||
|
||||
Configurable documented defaults can be achieved using interpolations. See for
|
||||
instance
|
||||
https://github.com/scisoft/autocmake/blob/master/modules/boost/boost.cmake#L33-L36.
|
||||
These can be modified within ``autocmake.cfg`` with a dictionary, e.g.:
|
||||
https://github.com/scisoft/autocmake/blob/master/test/boost_libs/cmake/autocmake.cfg#L9
|
||||
|
@ -3,7 +3,7 @@
|
||||
Customizing CMake modules
|
||||
=========================
|
||||
|
||||
The ``update.py`` script assembles modules listed in ``autocmake.cfg`` into
|
||||
The ``update.py`` script assembles modules listed in ``autocmake.yml`` into
|
||||
``CMakeLists.txt``. Those that are fetched from the web are placed inside
|
||||
``downloaded/``. You have several options to customize downloaded CMake
|
||||
modules:
|
||||
@ -22,7 +22,7 @@ Adapt local copies of CMake modules
|
||||
|
||||
A slightly better solution is to download the CMake modules that you wish you customize
|
||||
to a separate directory (e.g. ``custom/``) and source the customized CMake
|
||||
modules in ``autocmake.cfg``. Alternatively you can serve your custom modules
|
||||
modules in ``autocmake.yml``. Alternatively you can serve your custom modules
|
||||
from your own http server.
|
||||
|
||||
|
||||
@ -34,19 +34,30 @@ the branched customized versions. This will make it easier for you
|
||||
to stay up-to-date with upstream development.
|
||||
|
||||
|
||||
Overriding defaults
|
||||
Overriding settings
|
||||
-------------------
|
||||
|
||||
Some modules use interpolations to set defaults, see for instance
|
||||
https://github.com/scisoft/autocmake/blob/master/modules/boost/boost.cmake#L33-L36.
|
||||
These can be modified within ``autocmake.cfg``, e.g.:
|
||||
https://github.com/scisoft/autocmake/blob/master/test/boost_libs/cmake/autocmake.cfg#L9
|
||||
If you source a module which contains directives such as
|
||||
``define``,
|
||||
``docopt``,
|
||||
``export``, or
|
||||
``fetch``, and you wish to modify those,
|
||||
then you can override these settings in ``autocmake.yml``.
|
||||
Settings in ``autocmake.yml`` take precedence over
|
||||
settings imported by a sourced module.
|
||||
|
||||
As an example consider the Boost module which defines and uses
|
||||
interpolation variables ``major``, ``minor``, ``patch``, and ``components``, see
|
||||
https://github.com/coderefinery/autocmake/blob/master/modules/boost/boost.cmake#L52-L55.
|
||||
|
||||
The recommended way to customize these is in ``autocmake.yml``, e.g.:
|
||||
https://github.com/coderefinery/autocmake/blob/master/test/boost_libs/cmake/autocmake.yml#L12-L17.
|
||||
|
||||
|
||||
Create own CMake modules
|
||||
------------------------
|
||||
|
||||
Of course you can also create own modules and source them in ``autocmake.cfg``.
|
||||
Of course you can also create own modules and source them in ``autocmake.yml``.
|
||||
|
||||
|
||||
Contribute customizations to the "standard library"
|
||||
@ -54,5 +65,5 @@ Contribute customizations to the "standard library"
|
||||
|
||||
If you think that your customization will be useful for other users as well,
|
||||
you may consider contributing the changes directly to
|
||||
https://github.com/scisoft/autocmake/. We very much encourage such
|
||||
https://github.com/coderefinery/autocmake/. We very much encourage such
|
||||
contributions. But we also strive for generality and portability.
|
||||
|
@ -1,10 +1,10 @@
|
||||
|
||||
|
||||
Example Hello World project
|
||||
Example hello world project
|
||||
===========================
|
||||
|
||||
This is a brief example for the busy and impatient programmer. For a longer
|
||||
tour please see :ref:`autocmake_cfg`.
|
||||
tour please see :ref:`autocmake_yml`.
|
||||
|
||||
We start with a mixed Fortran-C project with the following sources::
|
||||
|
||||
@ -23,40 +23,49 @@ there. This is not necessary for Autocmake but it is a generally good practice::
|
||||
|
||||
Now we create ``cmake/`` and fetch ``update.py``::
|
||||
|
||||
$ mkdir cmake
|
||||
$ cd cmake/
|
||||
$ wget https://raw.githubusercontent.com/scisoft/autocmake/master/update.py
|
||||
$ mkdir cmake # does not have to be called "cmake" - take the name you prefer
|
||||
$ cd cmake
|
||||
$ wget https://github.com/coderefinery/autocmake/raw/master/update.py
|
||||
$ python update.py --self
|
||||
|
||||
Now from top-level our file tree looks like this::
|
||||
|
||||
.
|
||||
|-- cmake
|
||||
| |-- autocmake.cfg
|
||||
| |-- lib
|
||||
| | |-- config.py
|
||||
| | `-- docopt
|
||||
| | `-- docopt.py
|
||||
| |-- autocmake
|
||||
| | |-- __init__.py
|
||||
| | |-- configure.py
|
||||
| | |-- external
|
||||
| | | |-- __init__.py
|
||||
| | | `-- docopt.py
|
||||
| | |-- extract.py
|
||||
| | |-- generate.py
|
||||
| | |-- interpolate.py
|
||||
| | |-- parse_rst.py
|
||||
| | `-- parse_yaml.py
|
||||
| |-- autocmake.yml
|
||||
| `-- update.py
|
||||
`-- src
|
||||
|-- feature1.F90
|
||||
|-- feature2.c
|
||||
`-- main.F90
|
||||
|
||||
Now we edit ``cmake/autocmake.cfg`` to look like this::
|
||||
Now we edit ``cmake/autocmake.yml`` to look like this::
|
||||
|
||||
[project]
|
||||
name: hello
|
||||
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake
|
||||
url_root: https://github.com/coderefinery/autocmake/raw/master/
|
||||
|
||||
[cc]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/cc.cmake
|
||||
|
||||
[src]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/src.cmake
|
||||
modules:
|
||||
- compilers:
|
||||
- source:
|
||||
- '%(url_root)modules/fc.cmake'
|
||||
- '%(url_root)modules/cc.cmake'
|
||||
- src_support:
|
||||
- source:
|
||||
- '%(url_root)modules/src.cmake'
|
||||
|
||||
What we have specified here is the project name and that we wish Fortran and C
|
||||
support. The ``src.cmake`` module tells CMake to include a ``src/CMakeLists.txt``.
|
||||
@ -76,20 +85,32 @@ Now we have everything to generate ``CMakeLists.txt`` and a setup script::
|
||||
$ cd cmake
|
||||
$ python update ..
|
||||
|
||||
- parsing autocmake.yml
|
||||
- assembling modules: [##############################] (3/3)
|
||||
- generating CMakeLists.txt
|
||||
- generating setup script
|
||||
|
||||
And this is what we got::
|
||||
|
||||
.
|
||||
|-- CMakeLists.txt
|
||||
|-- cmake
|
||||
| |-- autocmake.cfg
|
||||
| |-- autocmake
|
||||
| | |-- __init__.py
|
||||
| | |-- configure.py
|
||||
| | |-- external
|
||||
| | | |-- __init__.py
|
||||
| | | `-- docopt.py
|
||||
| | |-- extract.py
|
||||
| | |-- generate.py
|
||||
| | |-- interpolate.py
|
||||
| | |-- parse_rst.py
|
||||
| | `-- parse_yaml.py
|
||||
| |-- autocmake.yml
|
||||
| |-- downloaded
|
||||
| | |-- autocmake_cc.cmake
|
||||
| | |-- autocmake_fc.cmake
|
||||
| | `-- autocmake_src.cmake
|
||||
| |-- lib
|
||||
| | |-- config.py
|
||||
| | `-- docopt
|
||||
| | `-- docopt.py
|
||||
| `-- update.py
|
||||
|-- setup
|
||||
`-- src
|
||||
@ -100,12 +121,12 @@ And this is what we got::
|
||||
|
||||
Now we are ready to build::
|
||||
|
||||
$ python setup --fc=gfortran --cc=gcc
|
||||
$ ./setup --fc=gfortran --cc=gcc
|
||||
|
||||
FC=gfortran CC=gcc cmake -DEXTRA_FCFLAGS="''" -DENABLE_FC_SUPPORT="ON" -DEXTRA_CFLAGS="''" -DCMAKE_BUILD_TYPE=release -G "Unix Makefiles" None /home/user/example
|
||||
FC=gfortran CC=gcc cmake -DEXTRA_FCFLAGS="''" -DEXTRA_CFLAGS="''" -DCMAKE_BUILD_TYPE=release -G "Unix Makefiles" /home/user/hello
|
||||
|
||||
-- The C compiler identification is GNU 4.9.2
|
||||
-- The CXX compiler identification is GNU 4.9.2
|
||||
-- The C compiler identification is GNU 6.1.1
|
||||
-- The CXX compiler identification is GNU 6.1.1
|
||||
-- Check for working C compiler: /usr/bin/gcc
|
||||
-- Check for working C compiler: /usr/bin/gcc -- works
|
||||
-- Detecting C compiler ABI info
|
||||
@ -118,7 +139,7 @@ Now we are ready to build::
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- The Fortran compiler identification is GNU 4.9.2
|
||||
-- The Fortran compiler identification is GNU 6.1.1
|
||||
-- Check for working Fortran compiler: /usr/bin/gfortran
|
||||
-- Check for working Fortran compiler: /usr/bin/gfortran -- works
|
||||
-- Detecting Fortran compiler ABI info
|
||||
@ -127,14 +148,14 @@ Now we are ready to build::
|
||||
-- Checking whether /usr/bin/gfortran supports Fortran 90 -- yes
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /home/user/example/build
|
||||
-- Build files have been written to: /home/user/hello/build
|
||||
|
||||
configure step is done
|
||||
now you need to compile the sources:
|
||||
$ cd build
|
||||
$ make
|
||||
|
||||
$ cd build/
|
||||
$ cd build
|
||||
$ make
|
||||
|
||||
Scanning dependencies of target hello.x
|
||||
|
@ -4,6 +4,18 @@ FAQ for developers
|
||||
==================
|
||||
|
||||
|
||||
Which files do I need to edit?
|
||||
------------------------------
|
||||
|
||||
Let us start with files which you normally never edit: ``CMakeLists.txt`` and
|
||||
``setup`` - these are generated based on ``autocmake.yml``. Have a look in
|
||||
``autocmake.yml`` and you will see all CMake files which are assembled into
|
||||
``CMakeLists.txt``. You can edit those files. If you change the order of files
|
||||
listed in ``autocmake.yml`` or if you add or remove CMake modules, then you
|
||||
need to rerun the ``update.py`` script to refresh ``CMakeLists.txt`` and
|
||||
``setup``.
|
||||
|
||||
|
||||
Autocmake does not do feature X - I really need feature X and a setup flag --X
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
@ -19,18 +31,22 @@ naming)::
|
||||
|
||||
cmake/custom/my_feature.cmake
|
||||
|
||||
And include this feature to the main ``CMakeLists.txt`` in ``autocmake.cfg``::
|
||||
And include this feature to the main ``CMakeLists.txt`` in ``autocmake.yml``
|
||||
under the ``modules`` section::
|
||||
|
||||
[my_feature]
|
||||
source: custom/my_feature.cmake
|
||||
modules:
|
||||
- my_feature:
|
||||
- source:
|
||||
- custom/my_feature.cmake
|
||||
|
||||
Now your code is included in the main ``CMakeLists.txt``. Perhaps you also
|
||||
want a setup script flag to toggle the feature::
|
||||
|
||||
[my_feature]
|
||||
source: custom/my_feature.cmake
|
||||
docopt: --my-feature Enable my feature [default: False].
|
||||
define: '-DENABLE_MY_FEATURE={0}'.format(arguments['--my-feature'])
|
||||
- my_feature:
|
||||
- docopt: "--enable-my-feature Enable my feature [default: False]."
|
||||
- define: "'-DENABLE_MY_FEATURE={0}'.format(arguments['--enable-my-feature'])"
|
||||
- source:
|
||||
- custom/my_feature.cmake
|
||||
|
||||
Implement your ideas, test them, and share them. If your module is portable,
|
||||
good code quality, and of general interest, you can suggest it to be part of
|
||||
@ -43,17 +59,16 @@ How can I get a setup flag --X that toggles a CMake variable?
|
||||
The following will add a ``--something`` flag which toggles the CMake variable
|
||||
``ENABLE_SOMETHING``::
|
||||
|
||||
[my_section]
|
||||
docopt: --something Enable something [default: False].
|
||||
define: '-DENABLE_SOMETHING={0}'.format(arguments['--something'])
|
||||
- my_section:
|
||||
- docopt: "--something Enable something [default: False]."
|
||||
- define: "'-DENABLE_SOMETHING={0}'.format(arguments['--enable-something'])"
|
||||
|
||||
|
||||
Can I change the name of the setup script?
|
||||
------------------------------------------
|
||||
|
||||
Yes you can do that in ``autocmake.cfg``. Here we for instance change the name to "configure"::
|
||||
Yes you can do that in ``autocmake.yml``. Here we for instance change the name to "configure"::
|
||||
|
||||
[project]
|
||||
name: myproject
|
||||
min_cmake_version: 2.8
|
||||
setup_script: configure
|
||||
@ -70,12 +85,13 @@ realized in Autocmake.
|
||||
Should I include and track also files generated by Autocmake in my repository?
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Yes, you probably want to do that. Autocmake generates a number of files which
|
||||
in principle could be generated at configure- or build-time. However, you
|
||||
probably do not want the users of your code to run any Autocmake scripts like
|
||||
``update.py`` to generate the files they need to build the project. The users
|
||||
of your code will run ``setup`` directly and expect everything to just work
|
||||
(TM).
|
||||
Yes, you probably want to do that. Autocmake downloads and generates a number
|
||||
of files which in principle could be generated at configure- or build-time.
|
||||
However, you probably do not want the users of your code to run any Autocmake
|
||||
scripts like ``update.py`` to generate the files they need to build the
|
||||
project. The users of your code will run ``setup`` directly and typically expect
|
||||
everything to just work (TM). Note also that the users of your code will
|
||||
not need to install the pyyaml package.
|
||||
|
||||
|
||||
The update.py script is overwriting my CMakeLists.txt and setup, isn't this bad?
|
||||
@ -93,7 +109,7 @@ But I need to manually edit and customize CMakeLists.txt and setup every time I
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
You typically never need to manually edit and customize ``CMakeLists.txt`` and
|
||||
``setup`` directly. You can introduce customizations in ``autocmake.cfg``
|
||||
``setup`` directly. You can introduce customizations in ``autocmake.yml``
|
||||
which get assembled into the front-end scripts.
|
||||
|
||||
|
||||
@ -101,19 +117,21 @@ Where is a good place to list my sources and targets?
|
||||
-----------------------------------------------------
|
||||
|
||||
As mentioned above ``CMakeLists.txt`` is not a good place because this file is
|
||||
generated from ``autocmake.cfg`` and your modifications would become
|
||||
generated from ``autocmake.yml`` and your modifications would become
|
||||
overwritten at some point. A good standard is to organize your sources under
|
||||
``src/`` and to list your sources and targets in ``src/CMakeLists.txt``. You
|
||||
can include the latter in ``autocmake.cfg`` using::
|
||||
can include the latter in ``autocmake.yml`` using::
|
||||
|
||||
[src]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/src.cmake
|
||||
- my_sources:
|
||||
- source:
|
||||
- https://github.com/coderefinery/autocmake/raw/master/modules/src.cmake
|
||||
|
||||
If you really don't like to do it this way, you can describe your sources and
|
||||
If you really do not like to do it this way, you can describe your sources and
|
||||
targets in a custom module in a local file and include it like this::
|
||||
|
||||
[my_sources]
|
||||
source: custom/my_sources.cmake
|
||||
- my_sources:
|
||||
- source:
|
||||
- custom/my_sources.cmake
|
||||
|
||||
|
||||
How can I do some more sophisticated validation of setup flags?
|
||||
@ -121,7 +139,7 @@ How can I do some more sophisticated validation of setup flags?
|
||||
|
||||
Sometimes you need to do more sophisticated validation and post-processing
|
||||
of setup flags. This can be done by placing a module called ``extensions.py``
|
||||
under ``cmake/`` (or wherever you have ``autocmake.cfg``).
|
||||
under ``cmake/`` (or wherever you have ``autocmake.yml``).
|
||||
This file should implement a function with the following signature:
|
||||
|
||||
.. code-block:: python
|
||||
|
34
doc/developers/interpolation.rst
Normal file
34
doc/developers/interpolation.rst
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
.. _interpolation:
|
||||
|
||||
Interpolation
|
||||
=============
|
||||
|
||||
In a custom extension to the YAML specification you can define and reuse
|
||||
variables like this (observe how we interpolate ``url_root``, ``major``,
|
||||
``minor``, ``patch``, and ``components`` in this example)::
|
||||
|
||||
url_root: https://github.com/coderefinery/autocmake/raw/master/
|
||||
major: 1
|
||||
minor: 48
|
||||
patch: 0
|
||||
components: ""
|
||||
fetch:
|
||||
- "%(url_root)modules/boost/boost_unpack.cmake"
|
||||
- "%(url_root)modules/boost/boost_userconfig.cmake"
|
||||
- "%(url_root)modules/boost/boost_configure.cmake"
|
||||
- "%(url_root)modules/boost/boost_build.cmake"
|
||||
- "%(url_root)modules/boost/boost_install.cmake"
|
||||
- "%(url_root)modules/boost/boost_headers.cmake"
|
||||
- "%(url_root)modules/boost/boost_cleanup.cmake"
|
||||
- "http://sourceforge.net/projects/boost/files/boost/%(major).%(minor).%(patch)/boost_%(major)_%(minor)_%(patch).zip"
|
||||
docopt:
|
||||
- "--boost-headers=<BOOST_INCLUDEDIR> Include directories for Boost [default: '']."
|
||||
- "--boost-libraries=<BOOST_LIBRARYDIR> Library directories for Boost [default: '']."
|
||||
- "--build-boost=<FORCE_CUSTOM_BOOST> Deactivate Boost detection and build on-the-fly <ON/OFF> [default: OFF]."
|
||||
define:
|
||||
- "'-DBOOST_INCLUDEDIR=\"{0}\"'.format(arguments['--boost-headers'])"
|
||||
- "'-DBOOST_LIBRARYDIR=\"{0}\"'.format(arguments['--boost-libraries'])"
|
||||
- "'-DFORCE_CUSTOM_BOOST={0}'.format(arguments['--build-boost'])"
|
||||
- "'-DBOOST_MINIMUM_REQUIRED=\"%(major).%(minor).%(patch)\"'"
|
||||
- "'-DBOOST_COMPONENTS_REQUIRED=\"%(components)\"'"
|
@ -20,11 +20,11 @@ Sometimes you may want to avoid using the latest version of a CMake module and
|
||||
rather fetch an older version, for example with the hash ``abcd123``. To
|
||||
achieve this, instead of::
|
||||
|
||||
[foo]
|
||||
source: https://github.com/scisoft/autocmake/raw/master/modules/foo.cmake
|
||||
- my_feature:
|
||||
- source: https://github.com/coderefinery/autocmake/raw/master/modules/foo.cmake
|
||||
|
||||
pin the version to ``abcd123`` (you do not need to specify the full Git hash, a unique
|
||||
beginning will do)::
|
||||
|
||||
[foo]
|
||||
source: https://github.com/scisoft/autocmake/raw/abcd123/modules/foo.cmake
|
||||
- my_feature:
|
||||
- source: https://github.com/coderefinery/autocmake/raw/abcd123/modules/foo.cmake
|
||||
|
@ -73,7 +73,7 @@ def main():
|
||||
if s_out != '':
|
||||
output.append('\n\n%s' % file_name)
|
||||
output.append('-'*len(file_name))
|
||||
output.append('`[Source code] <https://github.com/scisoft/autocmake/blob/master/modules/%s>`__' % full_file_name)
|
||||
output.append('`[Source code] <https://github.com/coderefinery/autocmake/blob/master/modules/%s>`__' % full_file_name)
|
||||
output.append(s_out)
|
||||
|
||||
with open(os.path.join(THIS_DIR, 'module-reference.rst'), 'w') as f:
|
||||
|
@ -7,9 +7,10 @@ Building libraries and executables from sources can be a complex task. Several
|
||||
solutions exist to this problem: GNU Makefiles is the traditional approach.
|
||||
Today, CMake is one of the trendier alternatives which can generate Makefiles
|
||||
starting from a file called ``CMakeLists.txt``.
|
||||
|
||||
Autocmake composes CMake building blocks into a CMake project and generates
|
||||
``CMakeLists.txt`` as well as a setup script, which serves as a front-end to
|
||||
``CMakeLists.txt``. All this is done based on a lightweight ``autocmake.cfg``
|
||||
``CMakeLists.txt``. All this is done based on a lightweight ``autocmake.yml``
|
||||
file::
|
||||
|
||||
python update.py --self
|
||||
@ -19,14 +20,14 @@ file::
|
||||
| and updates the update.py script |
|
||||
| |
|
||||
v Developer maintaining
|
||||
autocmake.cfg Autocmake
|
||||
autocmake.yml Autocmake
|
||||
| |
|
||||
| python update.py .. |
|
||||
| |
|
||||
v v
|
||||
CMakeLists.txt (and setup front-end)
|
||||
| |
|
||||
| python setup |
|
||||
| python setup or ./setup |
|
||||
| which invokes CMake |
|
||||
v User of the code
|
||||
Makefile (or something else) |
|
||||
@ -37,7 +38,7 @@ file::
|
||||
Build/install/test targets
|
||||
|
||||
Our main motivation to create Autocmake as a CMake framework library and
|
||||
CMake module composer was to simplify CMake code transfer between codes. We got
|
||||
CMake module composer is to simplify CMake code transfer between programs. We got
|
||||
tired of manually diffing and copy-pasting boiler-plate CMake code and watching
|
||||
it diverge while maintaining the CMake infrastructure in a growing number of
|
||||
scientific projects which typically have very similar requirements:
|
||||
|
@ -3,13 +3,11 @@
|
||||
Requirements and dependencies
|
||||
=============================
|
||||
|
||||
Autocmake update and test scripts require Python 2.7 or higher. We try to also
|
||||
support Python 3 (tested with Python 3.4). If the script fails with Python 3,
|
||||
consider this a bug and please file an issue.
|
||||
Autocmake update and test scripts require Python 2.7 or higher. We also
|
||||
support Python 3 (we automatically test with 2.7 and 3.5).
|
||||
|
||||
The generated setup script runs with Python >= 2.7 (also tested with Python
|
||||
3.4; probably also lower).
|
||||
The generated setup script runs with Python >= 2.6 (also tested with Python
|
||||
3.5).
|
||||
|
||||
.. todo::
|
||||
|
||||
Figure out lower Python version bound for setup.
|
||||
To generate ``CMakeLists.txt`` and the ``setup`` script, Autocmake
|
||||
requires the pyyaml package.
|
||||
|
@ -27,6 +27,7 @@ For developers who use Autocmake
|
||||
developers/example.rst
|
||||
developers/customizing-modules.rst
|
||||
developers/updating-modules.rst
|
||||
developers/interpolation.rst
|
||||
|
||||
|
||||
For users of projects which use Autocmake
|
||||
|
@ -47,4 +47,9 @@ How can I select CMake options via the setup script?
|
||||
|
||||
Like this::
|
||||
|
||||
$ python setup --cmake-options="-DTHIS_OPTION=ON -DTHAT_OPTION=OFF"
|
||||
$ python setup --cmake-options='"-DTHIS_OPTION=ON -DTHAT_OPTION=OFF"'
|
||||
|
||||
We use two sets of quotes because the shell swallows one set of them before
|
||||
passing the arguments to Python. Yeah that's not nice, but nothing we can do
|
||||
about it on the Python side. If you do not use two sets of quotes then the
|
||||
setup command may end up incorrectly saved in `build/setup_command`.
|
||||
|
@ -1,7 +0,0 @@
|
||||
# CMakeLists.txt and setup script will be generated from this file
|
||||
# see: http://autocmake.readthedocs.org/en/latest/developers/configuration.html
|
||||
|
||||
# uncomment the following three lines and set the project name
|
||||
# [project]
|
||||
# name: myproject
|
||||
# min_cmake_version: 2.8
|
7
example/autocmake.yml
Normal file
7
example/autocmake.yml
Normal file
@ -0,0 +1,7 @@
|
||||
# CMakeLists.txt and setup script will be generated from this file
|
||||
# see: http://autocmake.readthedocs.io/en/latest/developers/configuration.html
|
||||
# adapt the following lines and expand
|
||||
|
||||
name: myproject
|
||||
|
||||
min_cmake_version: 2.8
|
BIN
img/autocmake.png
Normal file
BIN
img/autocmake.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
90
img/autocmake.svg
Normal file
90
img/autocmake.svg
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 744.09448819 1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="autocmake.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="255.71429"
|
||||
inkscape:cy="520"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1001"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g3411">
|
||||
<rect
|
||||
y="326.18109"
|
||||
x="72.047241"
|
||||
height="400"
|
||||
width="600"
|
||||
id="rect3407"
|
||||
style="fill:#0e4089;fill-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3401"
|
||||
d="m 308.00113,650.73649 c 0,-0.42522 5.41704,-26.15959 12.03787,-57.1875 6.62083,-31.0279 12.97185,-60.80188 14.1134,-66.16438 l 2.07552,-9.75 15.3241,0 15.32411,0 0.19153,66.9375 0.19153,66.93751 -29.62903,0 c -19.84348,0 -29.62903,-0.25534 -29.62903,-0.77313 z m 71.0849,-51.16438 c -0.0908,-28.56562 -0.19938,-58.34999 -0.24129,-66.1875 -0.0419,-7.8375 0.0685,-14.67187 0.24533,-15.1875 0.24153,-0.70421 3.74313,-0.9375 14.07204,-0.9375 7.56277,0 13.90344,0.25313 14.09042,0.5625 0.33225,0.54975 29.7486,132.27474 29.7486,133.21275 0,0.26112 -12.99375,0.47476 -28.875,0.47476 l -28.875,0 -0.1651,-51.93751 z m 33.9151,-88.28869 0,-7.52381 -41.22185,0 -41.22186,0 -0.21564,6.9375 -0.21565,6.9375 -7.875,0 -7.875,0 -0.21565,-6.9375 -0.21564,-6.9375 -9.37402,0 -9.37401,0 0.21466,-7.3125 0.21466,-7.3125 76.5,0 76.5,0 0.21562,6.9375 c 0.1638,5.26821 -0.0165,6.9383 -0.75,6.94082 -5.8743,0.0202 -16.4307,0.58678 -16.74262,0.89865 -0.21953,0.21958 -0.55058,3.56584 -0.7356,7.43614 l -0.33638,7.03689 -8.63805,0.21131 -8.63797,0.2113 0,-7.5238 z m -36.7508,-29.8988 c -1.20169,-0.401 -1.01461,-80.3489 0.1883,-80.46723 2.44805,-0.24081 8.48431,0.23383 8.86144,0.6968 0.23316,0.28623 1.1451,4.40167 2.02652,9.14542 0.88143,4.74375 4.16729,22.41712 7.30192,39.27415 3.13463,16.85703 5.55114,30.79733 5.37002,30.97845 -0.38858,0.38858 -22.65342,0.73772 -23.7482,0.37241 z m -32.72028,-1.8842 c 0.24284,-0.96756 3.82423,-18.4238 7.95865,-38.79165 4.13442,-20.36785 7.70756,-37.63246 7.94032,-38.3658 0.34778,-1.09576 1.28287,-1.33336 5.24765,-1.33336 l 4.82446,0 0,40.125 0,40.125 -13.20631,0 -13.20631,0 0.44154,-1.75919 z"
|
||||
style="fill:#ffffff" />
|
||||
<rect
|
||||
y="482.86636"
|
||||
x="77.082703"
|
||||
height="62.629459"
|
||||
width="589.92908"
|
||||
id="rect3409"
|
||||
style="fill:#0e4089;fill-opacity:1" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3403"
|
||||
y="531.68109"
|
||||
x="192.04724"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:'Pet Me 64';-inkscape-font-specification:'Pet Me 64 Medium';fill:#ffffff"
|
||||
y="531.68109"
|
||||
x="192.04724"
|
||||
id="tspan3405"
|
||||
sodipodi:role="line">Autocmake</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
@ -5,11 +5,14 @@
|
||||
# Autocmake update time.
|
||||
# Note that the build-up commands are not Windows-compatible!
|
||||
#
|
||||
# Your autocmake.cfg should look like this::
|
||||
# Your autocmake.yml should look like this::
|
||||
#
|
||||
# [boost]
|
||||
# override: {'major': 1, 'minor': 59, 'patch': 0, 'components': 'chrono;timer;system'}
|
||||
# source: https://github.com/scisoft/autocmake/raw/master/modules/boost/boost.cmake
|
||||
# - boost:
|
||||
# - major: 1
|
||||
# - minor: 59
|
||||
# - patch: 0
|
||||
# - components: "chrono;timer;system"
|
||||
# - source: "https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost.cmake"
|
||||
#
|
||||
# Cross-dependencies between required components are not checked for.
|
||||
# For example, Boost.Timer depends on Boost.Chrono and Boost.System thus you
|
||||
@ -43,39 +46,41 @@
|
||||
# MPI_FOUND
|
||||
# BUILD_CUSTOM_BOOST
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# major=1
|
||||
# minor=48
|
||||
# patch=0
|
||||
# components=''
|
||||
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_unpack.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_userconfig.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_configure.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_build.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_install.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_headers.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_cleanup.cmake
|
||||
# http://sourceforge.net/projects/boost/files/boost/%(major)s.%(minor)s.%(patch)s/boost_%(major)s_%(minor)s_%(patch)s.zip
|
||||
# docopt: --boost-headers=<BOOST_INCLUDEDIR> Include directories for Boost [default: ''].
|
||||
# --boost-libraries=<BOOST_LIBRARYDIR> Library directories for Boost [default: ''].
|
||||
# --build-boost=<FORCE_CUSTOM_BOOST> Deactivate Boost detection and build on-the-fly <ON/OFF> [default: OFF].
|
||||
# define: '-DBOOST_INCLUDEDIR="{0}"'.format(arguments['--boost-headers'])
|
||||
# '-DBOOST_LIBRARYDIR="{0}"'.format(arguments['--boost-libraries'])
|
||||
# '-DFORCE_CUSTOM_BOOST="{0}"'.format(arguments['--build-boost'])
|
||||
# '-DBOOST_MINIMUM_REQUIRED="%(major)s.%(minor)s.%(patch)s"'
|
||||
# '-DBOOST_COMPONENTS_REQUIRED="%(components)s"'
|
||||
# url_root: https://github.com/coderefinery/autocmake/raw/master/
|
||||
# major: 1
|
||||
# minor: 48
|
||||
# patch: 0
|
||||
# components: ""
|
||||
# fetch:
|
||||
# - "%(url_root)modules/boost/boost_unpack.cmake"
|
||||
# - "%(url_root)modules/boost/boost_userconfig.cmake"
|
||||
# - "%(url_root)modules/boost/boost_configure.cmake"
|
||||
# - "%(url_root)modules/boost/boost_build.cmake"
|
||||
# - "%(url_root)modules/boost/boost_install.cmake"
|
||||
# - "%(url_root)modules/boost/boost_headers.cmake"
|
||||
# - "%(url_root)modules/boost/boost_cleanup.cmake"
|
||||
# - "http://sourceforge.net/projects/boost/files/boost/%(major).%(minor).%(patch)/boost_%(major)_%(minor)_%(patch).zip"
|
||||
# docopt:
|
||||
# - "--boost-headers=<BOOST_INCLUDEDIR> Include directories for Boost [default: '']."
|
||||
# - "--boost-libraries=<BOOST_LIBRARYDIR> Library directories for Boost [default: '']."
|
||||
# - "--build-boost=<FORCE_CUSTOM_BOOST> Deactivate Boost detection and build on-the-fly <ON/OFF> [default: OFF]."
|
||||
# define:
|
||||
# - "'-DBOOST_INCLUDEDIR=\"{0}\"'.format(arguments['--boost-headers'])"
|
||||
# - "'-DBOOST_LIBRARYDIR=\"{0}\"'.format(arguments['--boost-libraries'])"
|
||||
# - "'-DFORCE_CUSTOM_BOOST={0}'.format(arguments['--build-boost'])"
|
||||
# - "'-DBOOST_MINIMUM_REQUIRED=\"%(major).%(minor).%(patch)\"'"
|
||||
# - "'-DBOOST_COMPONENTS_REQUIRED=\"%(components)\"'"
|
||||
|
||||
# FIXME Maintainer should be able to choose between fail (end-user has to satisfy dependency
|
||||
# on its own) and soft-fail (self-build of Boost)
|
||||
# Underscore-separated version number
|
||||
string(REGEX REPLACE "\\." "_" BOOSTVER ${BOOST_MINIMUM_REQUIRED})
|
||||
|
||||
# Where the Boost .zip archive is located
|
||||
# CMAKE_CURRENT_LIST_DIR is undefined in CMake 2.8.2
|
||||
# see https://public.kitware.com/Bug/print_bug_page.php?bug_id=11675
|
||||
# workaround: create CMAKE_CURRENT_LIST_DIR
|
||||
get_filename_component(CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
set(BOOST_ARCHIVE_LOCATION ${CMAKE_CURRENT_LIST_DIR})
|
||||
set(BOOST_ARCHIVE_LOCATION ${PROJECT_SOURCE_DIR}/cmake/downloaded)
|
||||
|
||||
set(BOOST_ARCHIVE boost_${BOOSTVER}.zip)
|
||||
|
||||
# FIXME These are possibly not always good settings
|
||||
|
@ -17,12 +17,13 @@
|
||||
#
|
||||
# CFLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --cc=<CC> C compiler [default: gcc].
|
||||
# --extra-cc-flags=<EXTRA_CFLAGS> Extra C compiler flags [default: ''].
|
||||
# export: 'CC={0}'.format(arguments['--cc'])
|
||||
# define: '-DEXTRA_CFLAGS="{0}"'.format(arguments['--extra-cc-flags'])
|
||||
# docopt:
|
||||
# - "--cc=<CC> C compiler [default: gcc]."
|
||||
# - "--extra-cc-flags=<EXTRA_CFLAGS> Extra C compiler flags [default: '']."
|
||||
# export: "'CC={0}'.format(arguments['--cc'])"
|
||||
# define: "'-DEXTRA_CFLAGS=\"{0}\"'.format(arguments['--extra-cc-flags'])"
|
||||
|
||||
enable_language(C)
|
||||
|
||||
|
@ -10,10 +10,10 @@
|
||||
#
|
||||
# CCACHE_FOUND
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --ccache=<USE_CCACHE> Toggle use of ccache <ON/OFF> [default: ON].
|
||||
# define: '-DUSE_CCACHE="{0}"'.format(arguments['--ccache'])
|
||||
# docopt: "--ccache=<USE_CCACHE> Toggle use of ccache <ON/OFF> [default: ON]."
|
||||
# define: "'-DUSE_CCACHE={0}'.format(arguments['--ccache'])"
|
||||
|
||||
if(USE_CCACHE)
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
|
@ -8,10 +8,10 @@
|
||||
# CMAKE_C_FLAGS
|
||||
# CMAKE_CXX_FLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --coverage Enable code coverage [default: False].
|
||||
# define: '-DENABLE_CODE_COVERAGE=%s' % arguments['--coverage']
|
||||
# docopt: "--coverage Enable code coverage [default: False]."
|
||||
# define: "'-DENABLE_CODE_COVERAGE={0}'.format(arguments['--coverage'])"
|
||||
|
||||
option(ENABLE_CODE_COVERAGE "Enable code coverage" OFF)
|
||||
|
||||
|
@ -17,12 +17,13 @@
|
||||
#
|
||||
# CXXFLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --cxx=<CXX> C++ compiler [default: g++].
|
||||
# --extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: ''].
|
||||
# export: 'CXX={0}'.format(arguments['--cxx'])
|
||||
# define: '-DEXTRA_CXXFLAGS="{0}"'.format(arguments['--extra-cxx-flags'])
|
||||
# docopt:
|
||||
# - "--cxx=<CXX> C++ compiler [default: g++]."
|
||||
# - "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."
|
||||
# export: "'CXX={0}'.format(arguments['--cxx'])"
|
||||
# define: "'-DEXTRA_CXXFLAGS=\"{0}\"'.format(arguments['--extra-cxx-flags'])"
|
||||
|
||||
enable_language(CXX)
|
||||
|
||||
|
@ -7,10 +7,10 @@
|
||||
#
|
||||
# PREPROCESSOR_DEFINITIONS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --add-definitions=<STRING> Add preprocesor definitions [default: ''].
|
||||
# define: '-DPREPROCESSOR_DEFINITIONS="%s"' % arguments['--add-definitions']
|
||||
# docopt: "--add-definitions=<STRING> Add preprocesor definitions [default: '']."
|
||||
# define: "'-DPREPROCESSOR_DEFINITIONS=\"{0}\"'.format(arguments['--add-definitions'])"
|
||||
|
||||
if(NOT "${PREPROCESSOR_DEFINITIONS}" STREQUAL "")
|
||||
add_definitions(${PREPROCESSOR_DEFINITIONS})
|
||||
|
@ -21,12 +21,13 @@
|
||||
#
|
||||
# FCFLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --fc=<FC> Fortran compiler [default: gfortran].
|
||||
# --extra-fc-flags=<EXTRA_FCFLAGS> Extra Fortran compiler flags [default: ''].
|
||||
# export: 'FC={0}'.format(arguments['--fc'])
|
||||
# define: '-DEXTRA_FCFLAGS="{0}"'.format(arguments['--extra-fc-flags'])
|
||||
# docopt:
|
||||
# - "--fc=<FC> Fortran compiler [default: gfortran]."
|
||||
# - "--extra-fc-flags=<EXTRA_FCFLAGS> Extra Fortran compiler flags [default: '']."
|
||||
# export: "'FC={0}'.format(arguments['--fc'])"
|
||||
# define: "'-DEXTRA_FCFLAGS=\"{0}\"'.format(arguments['--extra-fc-flags'])"
|
||||
|
||||
enable_language(Fortran)
|
||||
|
||||
|
@ -26,14 +26,16 @@
|
||||
#
|
||||
# FCFLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --fc=<FC> Fortran compiler [default: gfortran].
|
||||
# --extra-fc-flags=<EXTRA_FCFLAGS> Extra Fortran compiler flags [default: ''].
|
||||
# --fc-support=<FC_SUPPORT> Toggle Fortran language support (ON/OFF) [default: ON].
|
||||
# export: 'FC={0}'.format(arguments['--fc'])
|
||||
# define: '-DEXTRA_FCFLAGS="{0}"'.format(arguments['--extra-fc-flags'])
|
||||
# '-DENABLE_FC_SUPPORT="{0}"'.format(arguments['--fc-support'])
|
||||
# docopt:
|
||||
# - "--fc=<FC> Fortran compiler [default: gfortran]."
|
||||
# - "--extra-fc-flags=<EXTRA_FCFLAGS> Extra Fortran compiler flags [default: '']."
|
||||
# - "--fc-support=<FC_SUPPORT> Toggle Fortran language support (ON/OFF) [default: ON]."
|
||||
# export: "'FC={0}'.format(arguments['--fc'])"
|
||||
# define:
|
||||
# - "'-DEXTRA_FCFLAGS=\"{0}\"'.format(arguments['--extra-fc-flags'])"
|
||||
# - "'-DENABLE_FC_SUPPORT={0}'.format(arguments['--fc-support'])"
|
||||
|
||||
option(ENABLE_FC_SUPPORT "Enable Fortran language support" ON)
|
||||
|
||||
|
@ -65,6 +65,6 @@ function(generate_git_info_header _header_location _header_name)
|
||||
|
||||
add_custom_target(
|
||||
git_info
|
||||
ALL DEPENDS ${_header_location}/${_header_name}
|
||||
ALL DEPENDS ${PROJECT_BINARY_DIR}/git_info.h
|
||||
)
|
||||
endfunction()
|
||||
|
@ -6,11 +6,11 @@
|
||||
#
|
||||
# GOOGLETEST_ROOT
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# define: '-DGOOGLETEST_ROOT=external/googletest'
|
||||
# define: "'-DGOOGLETEST_ROOT=external/googletest/googletest'"
|
||||
|
||||
set(GOOGLETEST_ROOT external/googletest CACHE STRING "Google Test source root")
|
||||
set(GOOGLETEST_ROOT external/googletest/googletest CACHE STRING "Google Test source root")
|
||||
|
||||
message(STATUS "GOOGLETEST_ROOT set to ${GOOGLETEST_ROOT}")
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
#
|
||||
# CMAKE_Fortran_FLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --int64 Enable 64bit integers [default: False].
|
||||
# define: '-DENABLE_64BIT_INTEGERS=%s' % arguments['--int64']
|
||||
# docopt: "--int64 Enable 64bit integers [default: False]."
|
||||
# define: "'-DENABLE_64BIT_INTEGERS={0}'.format(arguments['--int64'])"
|
||||
|
||||
option(ENABLE_64BIT_INTEGERS "Enable 64-bit integers" OFF)
|
||||
|
||||
|
@ -8,12 +8,14 @@
|
||||
# ACCELERATE_LIBRARIES - describe me, uncached
|
||||
# ACCELERATE_INCLUDE_DIR - describe me, uncached
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --accelerate Find and link to ACCELERATE [default: False].
|
||||
# define: '-DENABLE_ACCELERATE=%s' % arguments['--accelerate']
|
||||
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/find/find_libraries.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/find/find_include_files.cmake
|
||||
# url_root: https://github.com/coderefinery/autocmake/raw/master/
|
||||
# docopt: "--accelerate Find and link to ACCELERATE [default: False]."
|
||||
# define: "'-DENABLE_ACCELERATE={0}'.format(arguments['--accelerate'])"
|
||||
# fetch:
|
||||
# - "%(url_root)modules/find/find_libraries.cmake"
|
||||
# - "%(url_root)modules/find/find_include_files.cmake"
|
||||
|
||||
option(ENABLE_ACCELERATE "Find and link to ACCELERATE" OFF)
|
||||
|
||||
|
@ -8,10 +8,10 @@
|
||||
# ACML_LIBRARIES
|
||||
# ACML_INCLUDE_DIR
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --acml Find and link to ACML [default: False].
|
||||
# define: '-DENABLE_ACML=%s' % arguments['--acml']
|
||||
# docopt: "--acml Find and link to ACML [default: False]."
|
||||
# define: "'-DENABLE_ACML={0}'.format(arguments['--acml'])"
|
||||
|
||||
option(ENABLE_ACML "Find and link to ACML" OFF)
|
||||
|
||||
|
@ -8,10 +8,10 @@
|
||||
# ATLAS_LIBRARIES
|
||||
# ATLAS_INCLUDE_DIR
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --atlas Find and link to ATLAS [default: False].
|
||||
# define: '-DENABLE_ATLAS=%s' % arguments['--atlas']
|
||||
# docopt: "--atlas Find and link to ATLAS [default: False]."
|
||||
# define: "'-DENABLE_ATLAS={0}'.format(arguments['--atlas'])"
|
||||
|
||||
option(ENABLE_ATLAS "Find and link to ATLAS" OFF)
|
||||
|
||||
|
@ -8,10 +8,10 @@
|
||||
# BLAS_LIBRARIES
|
||||
# BLAS_INCLUDE_DIR
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --blas Find and link to BLAS [default: False].
|
||||
# define: '-DENABLE_BLAS=%s' % arguments['--blas']
|
||||
# docopt: "--blas Find and link to BLAS [default: False]."
|
||||
# define: "'-DENABLE_BLAS={0}'.format(arguments['--blas'])"
|
||||
|
||||
option(ENABLE_BLAS "Find and link to BLAS" OFF)
|
||||
|
||||
|
@ -8,12 +8,14 @@
|
||||
# CBLAS_LIBRARIES - describe me, uncached
|
||||
# CBLAS_INCLUDE_DIR - describe me, uncached
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --cblas Find and link to CBLAS [default: False].
|
||||
# define: '-DENABLE_CBLAS=%s' % arguments['--cblas']
|
||||
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/find/find_libraries.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/find/find_include_files.cmake
|
||||
# url_root: https://github.com/coderefinery/autocmake/raw/master/
|
||||
# docopt: "--cblas Find and link to CBLAS [default: False]."
|
||||
# define: "'-DENABLE_CBLAS={0}'.format(arguments['--cblas'])"
|
||||
# fetch:
|
||||
# - "%(url_root)modules/find/find_libraries.cmake"
|
||||
# - "%(url_root)modules/find/find_include_files.cmake"
|
||||
|
||||
option(ENABLE_CBLAS "Find and link to CBLAS" OFF)
|
||||
|
||||
|
@ -8,10 +8,10 @@
|
||||
# GOTO_LIBRARIES
|
||||
# GOTO_INCLUDE_DIR
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --goto Find and link to GOTO [default: False].
|
||||
# define: '-DENABLE_GOTO=%s' % arguments['--goto']
|
||||
# docopt: "--goto Find and link to GOTO [default: False]."
|
||||
# define: "'-DENABLE_GOTO={0}'.format(arguments['--goto'])"
|
||||
|
||||
option(ENABLE_GOTO "Find and link to GOTO" OFF)
|
||||
|
||||
|
@ -8,10 +8,10 @@
|
||||
# LAPACK_LIBRARIES
|
||||
# LAPACK_INCLUDE_DIR
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --lapack Find and link to LAPACK [default: False].
|
||||
# define: '-DENABLE_LAPACK=%s' % arguments['--lapack']
|
||||
# docopt: "--lapack Find and link to LAPACK [default: False]."
|
||||
# define: "'-DENABLE_LAPACK={0}'.format(arguments['--lapack'])"
|
||||
|
||||
option(ENABLE_LAPACK "Find and link to LAPACK" OFF)
|
||||
|
||||
|
@ -8,12 +8,14 @@
|
||||
# LAPACKE_LIBRARIES - describe me, uncached
|
||||
# LAPACKE_INCLUDE_DIR - describe me, uncached
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --lapacke Find and link to LAPACKE [default: False].
|
||||
# define: '-DENABLE_LAPACKE=%s' % arguments['--lapacke']
|
||||
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/find/find_libraries.cmake
|
||||
# https://github.com/scisoft/autocmake/raw/master/modules/find/find_include_files.cmake
|
||||
# url_root: https://github.com/coderefinery/autocmake/raw/master/
|
||||
# docopt: "--lapacke Find and link to LAPACKE [default: False]."
|
||||
# define: "'-DENABLE_LAPACKE={0}'.format(arguments['--lapacke'])"
|
||||
# fetch:
|
||||
# - "%(url_root)modules/find/find_libraries.cmake"
|
||||
# - "%(url_root)modules/find/find_include_files.cmake"
|
||||
|
||||
option(ENABLE_LAPACKE "Find and link to LAPACKE" OFF)
|
||||
|
||||
|
@ -37,18 +37,20 @@
|
||||
# MKL_ROOT
|
||||
# MKLROOT
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --blas=<BLAS> Detect and link BLAS library (auto or off) [default: auto].
|
||||
# --lapack=<LAPACK> Detect and link LAPACK library (auto or off) [default: auto].
|
||||
# --mkl=<MKL> Pass MKL flag to the Intel compiler and linker and skip BLAS/LAPACK detection (sequential, parallel, cluster, or off) [default: off].
|
||||
# define: '-DENABLE_BLAS=%s' % arguments['--blas']
|
||||
# '-DENABLE_LAPACK=%s' % arguments['--lapack']
|
||||
# '-DMKL_FLAG=%s' % arguments['--mkl']
|
||||
# '-DMATH_LIB_SEARCH_ORDER="MKL;ESSL;OPENBLAS;ATLAS;ACML;SYSTEM_NATIVE"'
|
||||
# '-DBLAS_LANG=Fortran'
|
||||
# '-DLAPACK_LANG=Fortran'
|
||||
# warning: 'This module is deprecated and will be removed in future versions'
|
||||
# docopt:
|
||||
# - "--blas=<BLAS> Detect and link BLAS library (auto or off) [default: auto]."
|
||||
# - "--lapack=<LAPACK> Detect and link LAPACK library (auto or off) [default: auto]."
|
||||
# - "--mkl=<MKL> Pass MKL flag to the Intel compiler and linker and skip BLAS/LAPACK detection (sequential, parallel, cluster, or off) [default: off]."
|
||||
# define:
|
||||
# - "'-DENABLE_BLAS={0}'.format(arguments['--blas'])"
|
||||
# - "'-DENABLE_LAPACK={0}'.format(arguments['--lapack'])"
|
||||
# - "'-DMKL_FLAG={0}'.format(arguments['--mkl'])"
|
||||
# - "'-DMATH_LIB_SEARCH_ORDER=\"MKL;ESSL;OPENBLAS;ATLAS;ACML;SYSTEM_NATIVE\"'"
|
||||
# - "'-DBLAS_LANG=Fortran'"
|
||||
# - "'-DLAPACK_LANG=Fortran'"
|
||||
# warning: "the math_libs.cmake module is deprecated and will be removed in future versions"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# ENABLE_STATIC_LINKING
|
||||
@ -506,7 +508,7 @@ if (ENABLE_STATIC_LINKING)
|
||||
BLAS_TYPE MATCHES SYSTEM_NATIVE OR
|
||||
BLAS_TYPE MATCHES OPENBLAS)
|
||||
#cc_blas_static with ATLAS on travis-ci needs -lm
|
||||
set(MATH_LIBS ${MATH_LIBS} -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -lm)
|
||||
set(MATH_LIBS ${MATH_LIBS} -Wl,--whole-archive -lpthread -ldl -Wl,--no-whole-archive -lm)
|
||||
endif()
|
||||
if (LAPACK_TYPE MATCHES MKL OR
|
||||
BLAS_TYPE MATCHES MKL)
|
||||
|
@ -13,10 +13,10 @@
|
||||
# CMAKE_C_FLAGS
|
||||
# CMAKE_CXX_FLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --mpi Enable MPI parallelization [default: False].
|
||||
# define: '-DENABLE_MPI=%s' % arguments['--mpi']
|
||||
# docopt: "--mpi Enable MPI parallelization [default: False]."
|
||||
# define: "'-DENABLE_MPI={0}'.format(arguments['--mpi'])"
|
||||
|
||||
option(ENABLE_MPI "Enable MPI parallelization" OFF)
|
||||
|
||||
|
@ -13,33 +13,14 @@
|
||||
# CMAKE_C_FLAGS
|
||||
# CMAKE_CXX_FLAGS
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --omp Enable OpenMP parallelization [default: False].
|
||||
# define: '-DENABLE_OPENMP=%s' % arguments['--omp']
|
||||
# docopt: "--omp Enable OpenMP parallelization [default: False]."
|
||||
# define: "'-DENABLE_OPENMP={0}'.format(arguments['--omp'])"
|
||||
|
||||
option(ENABLE_OPENMP "Enable OpenMP parallelization" OFF)
|
||||
|
||||
if(ENABLE_OPENMP)
|
||||
if(DEFINED CMAKE_Fortran_COMPILER_ID)
|
||||
# we do this in a pedestrian way because the Fortran support is relatively recent
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES GNU)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fopenmp")
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES Intel)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -openmp")
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES PGI)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -mp")
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES XL)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qsmp")
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES Cray)
|
||||
# do nothing in this case
|
||||
endif()
|
||||
set(OPENMP_FOUND TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT OPENMP_FOUND)
|
||||
find_package(OpenMP)
|
||||
@ -53,5 +34,35 @@ if(ENABLE_OPENMP)
|
||||
if(DEFINED CMAKE_CXX_COMPILER_ID)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||
endif()
|
||||
if(DEFINED CMAKE_Fortran_COMPILER_ID)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEFINED CMAKE_Fortran_COMPILER_ID AND NOT DEFINED OpenMP_Fortran_FLAGS)
|
||||
# we do this in a pedestrian way because the Fortran support is relatively recent
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES GNU)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fopenmp")
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES Intel)
|
||||
if(WIN32)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Qopenmp")
|
||||
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel" AND
|
||||
"${CMAKE_Fortran_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -openmp")
|
||||
else()
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qopenmp")
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES PGI)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -mp")
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES XL)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qsmp")
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES Cray)
|
||||
# do nothing in this case
|
||||
endif()
|
||||
set(OPENMP_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -15,10 +15,10 @@
|
||||
# PYTHON_VERSION_MINOR - Python minor version found e.g. 5
|
||||
# PYTHON_VERSION_PATCH - Python patch version found e.g. 2
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
# autocmake.yml configuration::
|
||||
#
|
||||
# docopt: --python=<PYTHON_INTERPRETER> The Python interpreter (development version) to use. [default: ''].
|
||||
# define: '-DPYTHON_INTERPRETER="%s"' % arguments['--python']
|
||||
# docopt: "--python=<PYTHON_INTERPRETER> The Python interpreter (development version) to use. [default: '']."
|
||||
# define: "'-DPYTHON_INTERPRETER=\"{0}\"'.format(arguments['--python'])"
|
||||
|
||||
if("${PYTHON_INTERPRETER}" STREQUAL "")
|
||||
find_package(PythonInterp REQUIRED)
|
||||
|
43
modules/save_flags.cmake
Normal file
43
modules/save_flags.cmake
Normal file
@ -0,0 +1,43 @@
|
||||
#.rst:
|
||||
#
|
||||
# Take care of updating the cache for fresh configurations.
|
||||
#
|
||||
# Variables modified (provided the corresponding language is enabled)::
|
||||
#
|
||||
# DEFAULT_Fortran_FLAGS_SET
|
||||
# DEFAULT_C_FLAGS_SET
|
||||
# DEFAULT_CXX_FLAGS_SET
|
||||
|
||||
macro(save_compiler_flags lang)
|
||||
if (NOT DEFINED DEFAULT_${lang}_FLAGS_SET)
|
||||
mark_as_advanced(DEFAULT_${lang}_FLAGS_SET)
|
||||
|
||||
set (DEFAULT_${lang}_FLAGS_SET ON
|
||||
CACHE INTERNAL
|
||||
"Flag that the default ${lang} compiler flags have been set.")
|
||||
|
||||
set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS}"
|
||||
CACHE STRING
|
||||
"Flags used by the compiler during all builds." FORCE)
|
||||
|
||||
set(CMAKE_${lang}_FLAGS_DEBUG "${CMAKE_${lang}_FLAGS_DEBUG}"
|
||||
CACHE STRING
|
||||
"Flags used by the compiler during debug builds." FORCE)
|
||||
|
||||
set(CMAKE_${lang}_FLAGS_RELEASE "${CMAKE_${lang}_FLAGS_RELEASE}"
|
||||
CACHE STRING
|
||||
"Flags used by the compiler during release builds." FORCE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
if(DEFINED CMAKE_Fortran_COMPILER_ID)
|
||||
save_compiler_flags(Fortran)
|
||||
endif()
|
||||
|
||||
if(DEFINED CMAKE_C_COMPILER_ID)
|
||||
save_compiler_flags(C)
|
||||
endif()
|
||||
|
||||
if(DEFINED CMAKE_CXX_COMPILER_ID)
|
||||
save_compiler_flags(CXX)
|
||||
endif()
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
pep8
|
||||
pytest
|
||||
pyyaml
|
@ -1,16 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[boost]
|
||||
override: {'major': 1, 'minor': 48, 'patch': 0}
|
||||
source: ../../../modules/boost/boost.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
14
test/boost_header_only/cmake/autocmake.yml
Normal file
14
test/boost_header_only/cmake/autocmake.yml
Normal file
@ -0,0 +1,14 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- boost:
|
||||
- major: 1
|
||||
- minor: 48
|
||||
- patch: 0
|
||||
- source: ../../../modules/boost/boost.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,25 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[mpi]
|
||||
source: ../../../modules/mpi.cmake
|
||||
|
||||
[python_interpreter]
|
||||
source: ../../../modules/python_interpreter.cmake
|
||||
|
||||
[python_libs]
|
||||
source: ../../../modules/python_libs.cmake
|
||||
|
||||
[boost]
|
||||
override: {'major': 1, 'minor': 59, 'patch': 0, 'components': 'mpi;serialization;python'}
|
||||
source: ../../../modules/boost/boost.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
21
test/boost_libs/cmake/autocmake.yml
Normal file
21
test/boost_libs/cmake/autocmake.yml
Normal file
@ -0,0 +1,21 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- mpi:
|
||||
- source: ../../../modules/mpi.cmake
|
||||
- python_interpreter:
|
||||
- source: ../../../modules/python_interpreter.cmake
|
||||
- python_libs:
|
||||
- source: ../../../modules/python_libs.cmake
|
||||
- boost:
|
||||
- major: 1
|
||||
- minor: 59
|
||||
- patch: 0
|
||||
- components: 'mpi;serialization;python'
|
||||
- source: ../../../modules/boost/boost.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,12 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
9
test/cxx/cmake/autocmake.yml
Normal file
9
test/cxx/cmake/autocmake.yml
Normal file
@ -0,0 +1,9 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[math]
|
||||
source: ../../../modules/math/accelerate.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
11
test/cxx_accelerate/cmake/autocmake.yml
Normal file
11
test/cxx_accelerate/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- math:
|
||||
- source: ../../../modules/math/accelerate.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[math]
|
||||
source: ../../../modules/math/cblas.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
11
test/cxx_cblas/cmake/autocmake.yml
Normal file
11
test/cxx_cblas/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- math:
|
||||
- source: ../../../modules/math/cblas.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,12 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
9
test/extra_cmake_options/cmake/autocmake.yml
Normal file
9
test/extra_cmake_options/cmake/autocmake.yml
Normal file
@ -0,0 +1,9 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,12 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: ../../../modules/fc.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
9
test/fc/cmake/autocmake.yml
Normal file
9
test/fc/cmake/autocmake.yml
Normal file
@ -0,0 +1,9 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- fc:
|
||||
- source: ../../../modules/fc.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: ../../../modules/fc.cmake
|
||||
|
||||
[math]
|
||||
source: ../../../modules/math/blas.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
11
test/fc_blas/cmake/autocmake.yml
Normal file
11
test/fc_blas/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- fc:
|
||||
- source: ../../../modules/fc.cmake
|
||||
- math:
|
||||
- source: ../../../modules/math/blas.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: ../../../modules/fc.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
||||
|
||||
[git_info]
|
||||
source: ../../../modules/git_info/git_info.cmake
|
11
test/fc_git_info/cmake/autocmake.yml
Normal file
11
test/fc_git_info/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- fc:
|
||||
- source: ../../../modules/fc.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
||||
- git_info:
|
||||
- source: ../../../modules/git_info/git_info.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: ../../../modules/fc.cmake
|
||||
|
||||
[int64]
|
||||
source: ../../../modules/int64.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
11
test/fc_int64/cmake/autocmake.yml
Normal file
11
test/fc_int64/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- fc:
|
||||
- source: ../../../modules/fc.cmake
|
||||
- int64:
|
||||
- source: ../../../modules/int64.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: ../../../modules/fc.cmake
|
||||
|
||||
[math]
|
||||
source: ../../../modules/math/lapack.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
11
test/fc_lapack/cmake/autocmake.yml
Normal file
11
test/fc_lapack/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- fc:
|
||||
- source: ../../../modules/fc.cmake
|
||||
- math:
|
||||
- source: ../../../modules/math/lapack.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[fc]
|
||||
source: ../../../modules/fc.cmake
|
||||
|
||||
[omp]
|
||||
source: ../../../modules/omp.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
11
test/fc_omp/cmake/autocmake.yml
Normal file
11
test/fc_omp/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- fc:
|
||||
- source: ../../../modules/fc.cmake
|
||||
- omp:
|
||||
- source: ../../../modules/omp.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[python_interpreter]
|
||||
source: ../../../modules/python_interpreter.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
13
test/python_interpreter/cmake/autocmake.yml
Normal file
13
test/python_interpreter/cmake/autocmake.yml
Normal file
@ -0,0 +1,13 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- python_interpreter:
|
||||
- source: ../../../modules/python_interpreter.cmake
|
||||
- python_libs:
|
||||
- source: ../../../modules/python_libs.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,15 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[python_interpreter]
|
||||
source: ../../../modules/python_interpreter.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
11
test/python_interpreter_custom/cmake/autocmake.yml
Normal file
11
test/python_interpreter_custom/cmake/autocmake.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- python_interpreter:
|
||||
- source: ../../../modules/python_interpreter.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,18 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[python_interpreter]
|
||||
source: ../../../modules/python_interpreter.cmake
|
||||
|
||||
[python_libs]
|
||||
source: ../../../modules/python_libs.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
13
test/python_libs/cmake/autocmake.yml
Normal file
13
test/python_libs/cmake/autocmake.yml
Normal file
@ -0,0 +1,13 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- python_interpreter:
|
||||
- source: ../../../modules/python_interpreter.cmake
|
||||
- python_libs:
|
||||
- source: ../../../modules/python_libs.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
@ -1,18 +0,0 @@
|
||||
[project]
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
|
||||
[cxx]
|
||||
source: ../../../modules/cxx.cmake
|
||||
|
||||
[python_interpreter]
|
||||
source: ../../../modules/python_interpreter.cmake
|
||||
|
||||
[python_libs]
|
||||
source: ../../../modules/python_libs.cmake
|
||||
|
||||
[default_build_paths]
|
||||
source: ../../../modules/default_build_paths.cmake
|
||||
|
||||
[src]
|
||||
source: ../../../modules/src.cmake
|
13
test/python_libs_custom/cmake/autocmake.yml
Normal file
13
test/python_libs_custom/cmake/autocmake.yml
Normal file
@ -0,0 +1,13 @@
|
||||
name: example
|
||||
min_cmake_version: 2.8
|
||||
modules:
|
||||
- cxx:
|
||||
- source: ../../../modules/cxx.cmake
|
||||
- python_interpreter:
|
||||
- source: ../../../modules/python_interpreter.cmake
|
||||
- python_libs:
|
||||
- source: ../../../modules/python_libs.cmake
|
||||
- default_build_paths:
|
||||
- source: ../../../modules/default_build_paths.cmake
|
||||
- src:
|
||||
- source: ../../../modules/src.cmake
|
30
test/test.py
30
test/test.py
@ -10,15 +10,11 @@ import pytest
|
||||
|
||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
skip_on_windows = pytest.mark.skipif('sys.platform == "win32"', reason="not working on windows")
|
||||
skip_on_osx = pytest.mark.skipif('sys.platform == "darwin"', reason="not working on osx")
|
||||
skip_on_linux = pytest.mark.skipif('sys.platform == "linux2"', reason="not working on linux")
|
||||
skip_always = pytest.mark.skipif('1 == 1', reason="tests are broken")
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def exe(command):
|
||||
"""
|
||||
Executes command and returns string representations of stdout and stderr captured from the console.
|
||||
@ -42,8 +38,6 @@ def exe(command):
|
||||
|
||||
return stdout, stderr
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def configure_build_and_exe(name, setup_command, launcher=None):
|
||||
|
||||
@ -52,15 +46,9 @@ def configure_build_and_exe(name, setup_command, launcher=None):
|
||||
os.chdir(os.path.join(HERE, name, 'cmake'))
|
||||
shutil.copy(os.path.join('..', '..', '..', 'update.py'), 'update.py')
|
||||
|
||||
dst_dir = 'lib'
|
||||
if not os.path.exists(dst_dir):
|
||||
os.makedirs(dst_dir)
|
||||
shutil.copy(os.path.join('..', '..', '..', dst_dir, 'config.py'), dst_dir)
|
||||
|
||||
dst_dir = os.path.join('lib', 'docopt')
|
||||
if not os.path.exists(dst_dir):
|
||||
os.makedirs(dst_dir)
|
||||
shutil.copy(os.path.join('..', '..', '..', dst_dir, 'docopt.py'), dst_dir)
|
||||
if os.path.exists('autocmake'):
|
||||
shutil.rmtree('autocmake')
|
||||
shutil.copytree(os.path.join('..', '..', '..', 'autocmake'), 'autocmake')
|
||||
|
||||
stdout, stderr = exe('python update.py ..')
|
||||
os.chdir(os.path.join(HERE, name))
|
||||
@ -90,8 +78,6 @@ def configure_build_and_exe(name, setup_command, launcher=None):
|
||||
|
||||
assert 'PASSED' in stdout
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_extra_cmake_options():
|
||||
configure_build_and_exe('extra_cmake_options', 'python setup --cxx=g++ --cmake-options="-DENABLE_SOMETHING=OFF -DENABLE_FOO=ON"')
|
||||
@ -119,24 +105,20 @@ def test_fc_omp():
|
||||
configure_build_and_exe('fc_omp', 'python setup --omp --fc=gfortran')
|
||||
|
||||
|
||||
@skip_on_windows
|
||||
def test_fc_blas():
|
||||
configure_build_and_exe('fc_blas', 'python setup --fc=gfortran --blas')
|
||||
|
||||
|
||||
@skip_on_windows
|
||||
def test_fc_lapack():
|
||||
configure_build_and_exe('fc_lapack', 'python setup --fc=gfortran --lapack')
|
||||
|
||||
|
||||
@skip_on_osx
|
||||
@skip_on_windows
|
||||
def test_cxx_cblas():
|
||||
configure_build_and_exe('cxx_cblas', 'python setup --cxx=g++ --cblas')
|
||||
|
||||
|
||||
@skip_on_linux
|
||||
@skip_on_windows
|
||||
def test_cxx_accelerate():
|
||||
configure_build_and_exe('cxx_accelerate', 'python setup --cxx=g++ --accelerate')
|
||||
|
||||
@ -150,23 +132,19 @@ def test_python_interpreter_custom():
|
||||
configure_build_and_exe('python_interpreter_custom', setup)
|
||||
|
||||
|
||||
@skip_on_windows
|
||||
def test_python_libs():
|
||||
configure_build_and_exe('python_libs', 'python setup --cxx=g++')
|
||||
|
||||
|
||||
@skip_on_windows
|
||||
def test_python_libs_custom():
|
||||
python_executable = sys.executable
|
||||
configure_build_and_exe('python_libs_custom', 'python setup --cxx=g++ --python={}'.format(python_executable))
|
||||
configure_build_and_exe('python_libs_custom', 'python setup --cxx=g++ --python={0}'.format(python_executable))
|
||||
|
||||
|
||||
@skip_on_windows
|
||||
def test_boost_header_only():
|
||||
configure_build_and_exe('boost_header_only', 'python setup --cxx=g++')
|
||||
|
||||
|
||||
@skip_on_osx
|
||||
@skip_on_windows
|
||||
def test_boost_libs():
|
||||
configure_build_and_exe('boost_libs', 'python setup --cxx=g++ --mpi')
|
||||
|
789
update.py
789
update.py
@ -2,41 +2,278 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import ast
|
||||
import collections
|
||||
|
||||
# we do not use the nicer sys.version_info.major
|
||||
# for compatibility with Python < 2.7
|
||||
if sys.version_info[0] > 2:
|
||||
from io import StringIO
|
||||
from configparser import ConfigParser
|
||||
import urllib.request
|
||||
|
||||
class URLopener(urllib.request.FancyURLopener):
|
||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||
sys.stderr.write("ERROR: could not fetch %s\n" % url)
|
||||
sys.exit(-1)
|
||||
else:
|
||||
from StringIO import StringIO
|
||||
from ConfigParser import ConfigParser
|
||||
import urllib
|
||||
|
||||
class URLopener(urllib.FancyURLopener):
|
||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||
sys.stderr.write("ERROR: could not fetch %s\n" % url)
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
AUTOCMAKE_GITHUB_URL = 'https://github.com/scisoft/autocmake'
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||
sys.stderr.write("ERROR: update.py requires at least Python 2.7\n")
|
||||
sys.exit(-1)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
AUTOCMAKE_GITHUB_URL = 'https://github.com/coderefinery/autocmake/raw/master/'
|
||||
|
||||
|
||||
def check_for_yaml():
|
||||
try:
|
||||
import yaml
|
||||
except:
|
||||
sys.stderr.write("ERROR: you need to install the pyyaml package\n")
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
def print_progress_bar(text, done, total, width):
|
||||
"""
|
||||
Print progress bar.
|
||||
"""
|
||||
if total > 0:
|
||||
n = int(float(width) * float(done) / float(total))
|
||||
sys.stdout.write("\r{0} [{1}{2}] ({3}/{4})".format(text, '#' * n, ' ' * (width - n), done, total))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def flat_add(l, x):
|
||||
if isinstance(x, int):
|
||||
l.append(x)
|
||||
return l
|
||||
elif isinstance(x, str):
|
||||
l.append(x)
|
||||
return l
|
||||
else:
|
||||
return l + x
|
||||
|
||||
|
||||
def fetch_modules(config, relative_path, download_directory):
|
||||
"""
|
||||
Assemble modules which will
|
||||
be included in CMakeLists.txt.
|
||||
"""
|
||||
from collections import Iterable, namedtuple, defaultdict
|
||||
from autocmake.extract import extract_list, to_d, to_l
|
||||
from autocmake.parse_rst import parse_cmake_module
|
||||
|
||||
cleaned_config = defaultdict(lambda: [])
|
||||
|
||||
modules = []
|
||||
Module = namedtuple('Module', 'path name')
|
||||
|
||||
num_sources = len(extract_list(config, 'source'))
|
||||
|
||||
print_progress_bar(text='- assembling modules:',
|
||||
done=0,
|
||||
total=num_sources,
|
||||
width=30)
|
||||
|
||||
if 'modules' in config:
|
||||
i = 0
|
||||
for t in config['modules']:
|
||||
for k, v in t.items():
|
||||
|
||||
d = to_d(v)
|
||||
for _k, _v in to_d(v).items():
|
||||
cleaned_config[_k] = flat_add(cleaned_config[_k], _v)
|
||||
|
||||
# fetch sources and parse them
|
||||
if 'source' in d:
|
||||
for src in to_l(d['source']):
|
||||
i += 1
|
||||
|
||||
# we download the file
|
||||
module_name = os.path.basename(src)
|
||||
if 'http' in src:
|
||||
path = download_directory
|
||||
name = 'autocmake_{0}'.format(module_name)
|
||||
dst = os.path.join(download_directory, 'autocmake_{0}'.format(module_name))
|
||||
fetch_url(src, dst)
|
||||
file_name = dst
|
||||
fetch_dst_directory = download_directory
|
||||
else:
|
||||
if os.path.exists(src):
|
||||
path = os.path.dirname(src)
|
||||
name = module_name
|
||||
file_name = src
|
||||
fetch_dst_directory = path
|
||||
else:
|
||||
sys.stderr.write("ERROR: {0} does not exist\n".format(src))
|
||||
sys.exit(-1)
|
||||
|
||||
# we infer config from the module documentation
|
||||
# dictionary d overrides the configuration in the module documentation
|
||||
# this allows to override interpolation inside the module
|
||||
with open(file_name, 'r') as f:
|
||||
parsed_config = parse_cmake_module(f.read(), d)
|
||||
for _k2, _v2 in parsed_config.items():
|
||||
if _k2 not in to_d(v):
|
||||
# we add to clean_config only if the entry does not exist
|
||||
# in parent autocmake.yml already
|
||||
# this allows to override
|
||||
cleaned_config[_k2] = flat_add(cleaned_config[_k2], _v2)
|
||||
|
||||
modules.append(Module(path=path, name=name))
|
||||
print_progress_bar(text='- assembling modules:',
|
||||
done=i,
|
||||
total=num_sources,
|
||||
width=30)
|
||||
print('')
|
||||
|
||||
return modules, cleaned_config
|
||||
|
||||
|
||||
def process_yaml(argv):
|
||||
from autocmake.parse_yaml import parse_yaml
|
||||
from autocmake.generate import gen_cmakelists, gen_setup
|
||||
from autocmake.extract import extract_list
|
||||
|
||||
project_root = argv[1]
|
||||
if not os.path.isdir(project_root):
|
||||
sys.stderr.write("ERROR: {0} is not a directory\n".format(project_root))
|
||||
sys.exit(-1)
|
||||
|
||||
# read config file
|
||||
print('- parsing autocmake.yml')
|
||||
with open('autocmake.yml', 'r') as stream:
|
||||
config = parse_yaml(stream)
|
||||
|
||||
if 'name' in config:
|
||||
project_name = config['name']
|
||||
else:
|
||||
sys.stderr.write("ERROR: you have to specify the project name in autocmake.yml\n")
|
||||
sys.exit(-1)
|
||||
if ' ' in project_name.rstrip():
|
||||
sys.stderr.write("ERROR: project name contains a space\n")
|
||||
sys.exit(-1)
|
||||
|
||||
if 'min_cmake_version' in config:
|
||||
min_cmake_version = config['min_cmake_version']
|
||||
else:
|
||||
sys.stderr.write("ERROR: you have to specify min_cmake_version in autocmake.yml\n")
|
||||
sys.exit(-1)
|
||||
|
||||
if 'setup_script' in config:
|
||||
setup_script_name = config['setup_script']
|
||||
else:
|
||||
setup_script_name = 'setup'
|
||||
|
||||
# get relative path from setup script to this directory
|
||||
relative_path = os.path.relpath(os.path.abspath('.'), project_root)
|
||||
|
||||
download_directory = 'downloaded'
|
||||
if not os.path.exists(download_directory):
|
||||
os.makedirs(download_directory)
|
||||
|
||||
# fetch modules from the web or from relative paths
|
||||
modules, cleaned_config = fetch_modules(config, relative_path, download_directory)
|
||||
|
||||
# fetch files which are not parsed
|
||||
for src in cleaned_config['fetch']:
|
||||
dst = os.path.join(download_directory, os.path.basename(src))
|
||||
fetch_url(src, dst)
|
||||
|
||||
# print warnings
|
||||
for warning in cleaned_config['warning']:
|
||||
print('- WARNING: {0}'.format(warning))
|
||||
|
||||
# create CMakeLists.txt
|
||||
print('- generating CMakeLists.txt')
|
||||
s = gen_cmakelists(project_name, min_cmake_version, relative_path, modules)
|
||||
with open(os.path.join(project_root, 'CMakeLists.txt'), 'w') as f:
|
||||
f.write('{0}\n'.format('\n'.join(s)))
|
||||
|
||||
# create setup script
|
||||
print('- generating setup script')
|
||||
s = gen_setup(cleaned_config, relative_path, setup_script_name)
|
||||
file_path = os.path.join(project_root, setup_script_name)
|
||||
with open(file_path, 'w') as f:
|
||||
f.write('{0}\n'.format('\n'.join(s)))
|
||||
if sys.platform != 'win32':
|
||||
make_executable(file_path)
|
||||
|
||||
|
||||
def main(argv):
|
||||
"""
|
||||
Main function.
|
||||
"""
|
||||
|
||||
if len(argv) != 2:
|
||||
sys.stderr.write("\nYou can update a project in two steps.\n\n")
|
||||
sys.stderr.write("Step 1: Update or create infrastructure files\n")
|
||||
sys.stderr.write(" which will be needed to configure and build the project:\n")
|
||||
sys.stderr.write(" $ {0} --self\n\n".format(argv[0]))
|
||||
sys.stderr.write("Step 2: Create CMakeLists.txt and setup script in PROJECT_ROOT:\n")
|
||||
sys.stderr.write(" $ {0} <PROJECT_ROOT>\n".format(argv[0]))
|
||||
sys.stderr.write(" example:\n")
|
||||
sys.stderr.write(" $ {0} ..\n".format(argv[0]))
|
||||
sys.exit(-1)
|
||||
|
||||
if argv[1] in ['-h', '--help']:
|
||||
print('Usage:')
|
||||
for t, h in [('python update.py --self',
|
||||
'Update this script and fetch or update infrastructure files under autocmake/.'),
|
||||
('python update.py <builddir>',
|
||||
'(Re)generate CMakeLists.txt and setup script and fetch or update CMake modules.'),
|
||||
('python update.py (-h | --help)',
|
||||
'Show this help text.')]:
|
||||
print(' {0:30} {1}'.format(t, h))
|
||||
sys.exit(0)
|
||||
|
||||
if argv[1] == '--self':
|
||||
# update self
|
||||
if not os.path.isfile('autocmake.yml'):
|
||||
print('- fetching example autocmake.yml')
|
||||
fetch_url(
|
||||
src='{0}example/autocmake.yml'.format(AUTOCMAKE_GITHUB_URL),
|
||||
dst='autocmake.yml'
|
||||
)
|
||||
if not os.path.isfile('.gitignore'):
|
||||
print('- creating .gitignore')
|
||||
with open('.gitignore', 'w') as f:
|
||||
f.write('*.pyc\n')
|
||||
for f in ['autocmake/configure.py',
|
||||
'autocmake/__init__.py',
|
||||
'autocmake/external/docopt.py',
|
||||
'autocmake/external/__init__.py',
|
||||
'autocmake/generate.py',
|
||||
'autocmake/extract.py',
|
||||
'autocmake/interpolate.py',
|
||||
'autocmake/parse_rst.py',
|
||||
'autocmake/parse_yaml.py',
|
||||
'update.py']:
|
||||
print('- fetching {0}'.format(f))
|
||||
fetch_url(
|
||||
src='{0}{1}'.format(AUTOCMAKE_GITHUB_URL, f),
|
||||
dst='{0}'.format(f)
|
||||
)
|
||||
sys.exit(0)
|
||||
|
||||
process_yaml(argv)
|
||||
|
||||
|
||||
def make_executable(path):
|
||||
# http://stackoverflow.com/a/30463972
|
||||
mode = os.stat(path).st_mode
|
||||
mode |= (mode & 0o444) >> 2 # copy R bits to X
|
||||
os.chmod(path, mode)
|
||||
|
||||
|
||||
def fetch_url(src, dst):
|
||||
"""
|
||||
Fetch file from URL src and save it to dst.
|
||||
"""
|
||||
# we do not use the nicer sys.version_info.major
|
||||
# for compatibility with Python < 2.7
|
||||
if sys.version_info[0] > 2:
|
||||
import urllib.request
|
||||
|
||||
class URLopener(urllib.request.FancyURLopener):
|
||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||
sys.stderr.write("ERROR: could not fetch {0}\n".format(url))
|
||||
sys.exit(-1)
|
||||
else:
|
||||
import urllib
|
||||
|
||||
class URLopener(urllib.FancyURLopener):
|
||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||
sys.stderr.write("ERROR: could not fetch {0}\n".format(url))
|
||||
sys.exit(-1)
|
||||
|
||||
dirname = os.path.dirname(dst)
|
||||
if dirname != '':
|
||||
if not os.path.isdir(dirname):
|
||||
@ -45,505 +282,7 @@ def fetch_url(src, dst):
|
||||
opener = URLopener()
|
||||
opener.retrieve(src, dst)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def print_progress_bar(text, done, total, width):
|
||||
"""
|
||||
Print progress bar.
|
||||
"""
|
||||
n = int(float(width) * float(done) / float(total))
|
||||
sys.stdout.write("\r%s [%s%s] (%i/%i)" % (text, '#' * n,
|
||||
' ' * (width - n), done, total))
|
||||
sys.stdout.flush()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def align_options(options):
|
||||
"""
|
||||
Indents flags and aligns help texts.
|
||||
"""
|
||||
l = 0
|
||||
for opt in options:
|
||||
if len(opt[0]) > l:
|
||||
l = len(opt[0])
|
||||
s = []
|
||||
for opt in options:
|
||||
s.append(' %s%s %s' % (opt[0], ' ' * (l - len(opt[0])), opt[1]))
|
||||
return '\n'.join(s)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def gen_cmake_command(config):
|
||||
"""
|
||||
Generate CMake command.
|
||||
"""
|
||||
s = []
|
||||
|
||||
s.append("\n\ndef gen_cmake_command(options, arguments):")
|
||||
s.append(' """')
|
||||
s.append(" Generate CMake command based on options and arguments.")
|
||||
s.append(' """')
|
||||
s.append(" command = []")
|
||||
|
||||
# take care of environment variables
|
||||
for section in config.sections():
|
||||
if config.has_option(section, 'export'):
|
||||
for env in config.get(section, 'export').split('\n'):
|
||||
s.append(' command.append(%s)' % env)
|
||||
|
||||
s.append(" command.append('%s' % arguments['--cmake-executable'])")
|
||||
|
||||
# take care of cmake definitions
|
||||
for section in config.sections():
|
||||
if config.has_option(section, 'define'):
|
||||
for definition in config.get(section, 'define').split('\n'):
|
||||
s.append(' command.append(%s)' % definition)
|
||||
|
||||
s.append(" command.append('-DCMAKE_BUILD_TYPE=%s' % arguments['--type'])")
|
||||
s.append(" command.append('-G \"%s\"' % arguments['--generator'])")
|
||||
s.append(" if arguments['--cmake-options'] != \"''\":")
|
||||
s.append(" command.append('%s' % arguments['--cmake-options'])")
|
||||
s.append(" if arguments['--prefix']:")
|
||||
s.append(" command.append('-DCMAKE_INSTALL_PREFIX=\"{0}\"'.format(arguments['--prefix']))")
|
||||
|
||||
s.append("\n return ' '.join(command)")
|
||||
|
||||
return '\n'.join(s)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def autogenerated_notice():
|
||||
start_year = 2015
|
||||
year_range = str(start_year)
|
||||
current_year = datetime.date.today().year
|
||||
if current_year > start_year:
|
||||
year_range += '-%s' % current_year
|
||||
s = []
|
||||
s.append('# This file is autogenerated by Autocmake http://autocmake.org')
|
||||
s.append('# Copyright (c) %s by Radovan Bast and Jonas Juselius' % year_range)
|
||||
return '\n'.join(s)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def gen_setup(config, relative_path, setup_script_name):
|
||||
"""
|
||||
Generate setup script.
|
||||
"""
|
||||
s = []
|
||||
s.append('#!/usr/bin/env python')
|
||||
s.append('\n%s' % autogenerated_notice())
|
||||
s.append('\nimport os')
|
||||
s.append('import sys')
|
||||
|
||||
s.append("\nsys.path.insert(0, '{0}')".format(relative_path))
|
||||
s.append("sys.path.insert(0, '{0}')".format(os.path.join(relative_path, 'lib')))
|
||||
s.append("sys.path.insert(0, '{0}')".format(os.path.join(relative_path, 'lib', 'docopt')))
|
||||
|
||||
s.append('import config')
|
||||
s.append('import docopt')
|
||||
|
||||
s.append('\n\noptions = """')
|
||||
s.append('Usage:')
|
||||
s.append(' ./{0} [options] [<builddir>]'.format(setup_script_name))
|
||||
s.append(' ./{0} (-h | --help)'.format(setup_script_name))
|
||||
s.append('\nOptions:')
|
||||
|
||||
options = []
|
||||
for section in config.sections():
|
||||
if config.has_option(section, 'docopt'):
|
||||
for opt in config.get(section, 'docopt').split('\n'):
|
||||
first = opt.split()[0].strip()
|
||||
rest = ' '.join(opt.split()[1:]).strip()
|
||||
options.append([first, rest])
|
||||
|
||||
options.append(['--type=<TYPE>', 'Set the CMake build type (debug, release, or relwithdeb) [default: release].'])
|
||||
options.append(['--generator=<STRING>', 'Set the CMake build system generator [default: Unix Makefiles].'])
|
||||
options.append(['--show', 'Show CMake command and exit.'])
|
||||
options.append(['--cmake-executable=<CMAKE_EXECUTABLE>', 'Set the CMake executable [default: cmake].'])
|
||||
options.append(['--cmake-options=<STRING>', "Define options to CMake [default: '']."])
|
||||
options.append(['--prefix=<PATH>', 'Set the install path for make install.'])
|
||||
options.append(['<builddir>', 'Build directory.'])
|
||||
options.append(['-h --help', 'Show this screen.'])
|
||||
|
||||
s.append(align_options(options))
|
||||
|
||||
s.append('"""')
|
||||
|
||||
s.append(gen_cmake_command(config))
|
||||
|
||||
s.append("\n")
|
||||
s.append("# parse command line args")
|
||||
s.append("try:")
|
||||
s.append(" arguments = docopt.docopt(options, argv=None)")
|
||||
s.append("except docopt.DocoptExit:")
|
||||
s.append(r" sys.stderr.write('ERROR: bad input to %s\n' % sys.argv[0])")
|
||||
s.append(" sys.stderr.write(options)")
|
||||
s.append(" sys.exit(-1)")
|
||||
s.append("\n")
|
||||
s.append("# use extensions to validate/post-process args")
|
||||
s.append("if config.module_exists('extensions'):")
|
||||
s.append(" import extensions")
|
||||
s.append(" arguments = extensions.postprocess_args(sys.argv, arguments)")
|
||||
s.append("\n")
|
||||
s.append("root_directory = os.path.dirname(os.path.realpath(__file__))")
|
||||
s.append("\n")
|
||||
s.append("build_path = arguments['<builddir>']")
|
||||
s.append("\n")
|
||||
s.append("# create cmake command")
|
||||
s.append("cmake_command = '%s %s' % (gen_cmake_command(options, arguments), root_directory)")
|
||||
s.append("\n")
|
||||
s.append("# run cmake")
|
||||
s.append("config.configure(root_directory, build_path, cmake_command, arguments['--show'])")
|
||||
|
||||
return s
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def gen_cmakelists(project_name, min_cmake_version, relative_path, modules):
|
||||
"""
|
||||
Generate CMakeLists.txt.
|
||||
"""
|
||||
s = []
|
||||
|
||||
s.append(autogenerated_notice())
|
||||
|
||||
s.append('\n# set minimum cmake version')
|
||||
s.append('cmake_minimum_required(VERSION %s FATAL_ERROR)' % min_cmake_version)
|
||||
|
||||
s.append('\n# project name')
|
||||
s.append('project(%s)' % project_name)
|
||||
|
||||
s.append('\n# do not rebuild if rules (compiler flags) change')
|
||||
s.append('set(CMAKE_SKIP_RULE_DEPENDENCY TRUE)')
|
||||
|
||||
s.append('\n# if CMAKE_BUILD_TYPE undefined, we set it to Debug')
|
||||
s.append('if(NOT CMAKE_BUILD_TYPE)')
|
||||
s.append(' set(CMAKE_BUILD_TYPE "Debug")')
|
||||
s.append('endif()')
|
||||
|
||||
if len(modules) > 0:
|
||||
s.append('\n# directories which hold included cmake modules')
|
||||
|
||||
module_paths = [module.path for module in modules]
|
||||
module_paths.append('downloaded') # this is done to be able to find fetched modules when testing
|
||||
module_paths = list(set(module_paths))
|
||||
module_paths.sort() # we do this to always get the same order and to minimize diffs
|
||||
for directory in module_paths:
|
||||
rel_cmake_module_path = os.path.join(relative_path, directory)
|
||||
# on windows cmake corrects this so we have to make it wrong again
|
||||
rel_cmake_module_path = rel_cmake_module_path.replace('\\', '/')
|
||||
s.append('set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/%s)' % rel_cmake_module_path)
|
||||
|
||||
if len(modules) > 0:
|
||||
s.append('\n# included cmake modules')
|
||||
for module in modules:
|
||||
s.append('include(%s)' % os.path.splitext(module.name)[0])
|
||||
|
||||
return s
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def prepend_or_set(config, section, option, value, defaults):
|
||||
"""
|
||||
If option is already set, then value is prepended.
|
||||
If option is not set, then it is created and set to value.
|
||||
This is used to prepend options with values which come from the module documentation.
|
||||
"""
|
||||
if value:
|
||||
if config.has_option(section, option):
|
||||
value += '\n%s' % config.get(section, option, 0, defaults)
|
||||
config.set(section, option, value)
|
||||
return config
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def fetch_modules(config, relative_path):
|
||||
"""
|
||||
Assemble modules which will
|
||||
be included in CMakeLists.txt.
|
||||
"""
|
||||
|
||||
download_directory = 'downloaded'
|
||||
if not os.path.exists(download_directory):
|
||||
os.makedirs(download_directory)
|
||||
|
||||
l = list(filter(lambda x: config.has_option(x, 'source'),
|
||||
config.sections()))
|
||||
n = len(l)
|
||||
|
||||
modules = []
|
||||
Module = collections.namedtuple('Module', 'path name')
|
||||
|
||||
warnings = []
|
||||
|
||||
if n > 0: # otherwise division by zero in print_progress_bar
|
||||
i = 0
|
||||
print_progress_bar(text='- assembling modules:', done=0, total=n, width=30)
|
||||
for section in config.sections():
|
||||
if config.has_option(section, 'source'):
|
||||
for src in config.get(section, 'source').split('\n'):
|
||||
module_name = os.path.basename(src)
|
||||
if 'http' in src:
|
||||
path = download_directory
|
||||
name = 'autocmake_%s' % module_name
|
||||
dst = os.path.join(download_directory, 'autocmake_%s' % module_name)
|
||||
fetch_url(src, dst)
|
||||
file_name = dst
|
||||
fetch_dst_directory = download_directory
|
||||
else:
|
||||
if os.path.exists(src):
|
||||
path = os.path.dirname(src)
|
||||
name = module_name
|
||||
file_name = src
|
||||
fetch_dst_directory = path
|
||||
else:
|
||||
sys.stderr.write("ERROR: %s does not exist\n" % src)
|
||||
sys.exit(-1)
|
||||
|
||||
if config.has_option(section, 'override'):
|
||||
defaults = ast.literal_eval(config.get(section, 'override'))
|
||||
else:
|
||||
defaults = {}
|
||||
|
||||
# we infer config from the module documentation
|
||||
with open(file_name, 'r') as f:
|
||||
parsed_config = parse_cmake_module(f.read(), defaults)
|
||||
if parsed_config['warning']:
|
||||
warnings.append('WARNING from {0}: {1}'.format(module_name, parsed_config['warning']))
|
||||
config = prepend_or_set(config, section, 'docopt', parsed_config['docopt'], defaults)
|
||||
config = prepend_or_set(config, section, 'define', parsed_config['define'], defaults)
|
||||
config = prepend_or_set(config, section, 'export', parsed_config['export'], defaults)
|
||||
if parsed_config['fetch']:
|
||||
for src in parsed_config['fetch'].split('\n'):
|
||||
dst = os.path.join(fetch_dst_directory, os.path.basename(src))
|
||||
fetch_url(src, dst)
|
||||
|
||||
modules.append(Module(path=path, name=name))
|
||||
i += 1
|
||||
print_progress_bar(
|
||||
text='- assembling modules:',
|
||||
done=i,
|
||||
total=n,
|
||||
width=30
|
||||
)
|
||||
if config.has_option(section, 'fetch'):
|
||||
# when we fetch directly from autocmake.cfg
|
||||
# we download into downloaded/
|
||||
for src in config.get(section, 'fetch').split('\n'):
|
||||
dst = os.path.join(download_directory, os.path.basename(src))
|
||||
fetch_url(src, dst)
|
||||
print('')
|
||||
|
||||
if warnings != []:
|
||||
print('- %s' % '\n- '.join(warnings))
|
||||
|
||||
return modules
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def main(argv):
|
||||
"""
|
||||
Main function.
|
||||
"""
|
||||
if len(argv) != 2:
|
||||
sys.stderr.write("\nYou can update a project in two steps.\n\n")
|
||||
sys.stderr.write("Step 1: Update or create infrastructure files\n")
|
||||
sys.stderr.write(" which will be needed to configure and build the project:\n")
|
||||
sys.stderr.write(" $ %s --self\n\n" % argv[0])
|
||||
sys.stderr.write("Step 2: Create CMakeLists.txt and setup script in PROJECT_ROOT:\n")
|
||||
sys.stderr.write(" $ %s <PROJECT_ROOT>\n" % argv[0])
|
||||
sys.stderr.write(" example:\n")
|
||||
sys.stderr.write(" $ %s ..\n" % argv[0])
|
||||
sys.exit(-1)
|
||||
|
||||
if argv[1] in ['-h', '--help']:
|
||||
print('Usage:')
|
||||
print(' python update.py --self Update this script and fetch or update infrastructure files under lib/.')
|
||||
print(' python update.py <builddir> (Re)generate CMakeLists.txt and setup script and fetch or update CMake modules.')
|
||||
print(' python update.py (-h | --help) Show this help text.')
|
||||
sys.exit(0)
|
||||
|
||||
if argv[1] == '--self':
|
||||
# update self
|
||||
if not os.path.isfile('autocmake.cfg'):
|
||||
print('- fetching example autocmake.cfg')
|
||||
fetch_url(
|
||||
src='%s/raw/master/example/autocmake.cfg' % AUTOCMAKE_GITHUB_URL,
|
||||
dst='autocmake.cfg'
|
||||
)
|
||||
if not os.path.isfile('.gitignore'):
|
||||
print('- creating .gitignore')
|
||||
with open('.gitignore', 'w') as f:
|
||||
f.write('*.pyc\n')
|
||||
print('- fetching lib/config.py')
|
||||
fetch_url(
|
||||
src='%s/raw/master/lib/config.py' % AUTOCMAKE_GITHUB_URL,
|
||||
dst='lib/config.py'
|
||||
)
|
||||
print('- fetching lib/docopt/docopt.py')
|
||||
fetch_url(
|
||||
src='%s/raw/master/lib/docopt/docopt.py' % AUTOCMAKE_GITHUB_URL,
|
||||
dst='lib/docopt/docopt.py'
|
||||
)
|
||||
print('- fetching update.py')
|
||||
fetch_url(
|
||||
src='%s/raw/master/update.py' % AUTOCMAKE_GITHUB_URL,
|
||||
dst='update.py'
|
||||
)
|
||||
sys.exit(0)
|
||||
|
||||
project_root = argv[1]
|
||||
if not os.path.isdir(project_root):
|
||||
sys.stderr.write("ERROR: %s is not a directory\n" % project_root)
|
||||
sys.exit(-1)
|
||||
|
||||
# read config file
|
||||
print('- parsing autocmake.cfg')
|
||||
config = ConfigParser(dict_type=collections.OrderedDict)
|
||||
config.read('autocmake.cfg')
|
||||
|
||||
if not config.has_option('project', 'name'):
|
||||
sys.stderr.write("ERROR: you have to specify the project name\n")
|
||||
sys.stderr.write(" in autocmake.cfg under [project]\n")
|
||||
sys.exit(-1)
|
||||
project_name = config.get('project', 'name')
|
||||
if ' ' in project_name.rstrip():
|
||||
sys.stderr.write("ERROR: project name contains a space\n")
|
||||
sys.exit(-1)
|
||||
|
||||
if not config.has_option('project', 'min_cmake_version'):
|
||||
sys.stderr.write("ERROR: you have to specify the min_cmake_version for CMake\n")
|
||||
sys.stderr.write(" in autocmake.cfg under [project]\n")
|
||||
sys.exit(-1)
|
||||
min_cmake_version = config.get('project', 'min_cmake_version')
|
||||
|
||||
if config.has_option('project', 'setup_script'):
|
||||
setup_script_name = config.get('project', 'setup_script')
|
||||
else:
|
||||
setup_script_name = 'setup'
|
||||
|
||||
# get relative path from setup script to this directory
|
||||
relative_path = os.path.relpath(os.path.abspath('.'), project_root)
|
||||
|
||||
# fetch modules from the web or from relative paths
|
||||
modules = fetch_modules(config, relative_path)
|
||||
|
||||
# create CMakeLists.txt
|
||||
print('- generating CMakeLists.txt')
|
||||
s = gen_cmakelists(project_name, min_cmake_version, relative_path, modules)
|
||||
with open(os.path.join(project_root, 'CMakeLists.txt'), 'w') as f:
|
||||
f.write('%s\n' % '\n'.join(s))
|
||||
|
||||
# create setup script
|
||||
print('- generating setup script')
|
||||
s = gen_setup(config, relative_path, setup_script_name)
|
||||
file_path = os.path.join(project_root, setup_script_name)
|
||||
with open(file_path, 'w') as f:
|
||||
f.write('%s\n' % '\n'.join(s))
|
||||
if sys.platform != 'win32':
|
||||
make_executable(file_path)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# http://stackoverflow.com/a/30463972
|
||||
def make_executable(path):
|
||||
mode = os.stat(path).st_mode
|
||||
mode |= (mode & 0o444) >> 2 # copy R bits to X
|
||||
os.chmod(path, mode)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def parse_cmake_module(s_in, defaults={}):
|
||||
|
||||
parsed_config = collections.defaultdict(lambda: None)
|
||||
|
||||
if 'autocmake.cfg configuration::' not in s_in:
|
||||
return parsed_config
|
||||
|
||||
s_out = []
|
||||
is_rst_line = False
|
||||
for line in s_in.split('\n'):
|
||||
if is_rst_line:
|
||||
if len(line) > 0:
|
||||
if line[0] != '#':
|
||||
is_rst_line = False
|
||||
else:
|
||||
is_rst_line = False
|
||||
if is_rst_line:
|
||||
s_out.append(line[2:])
|
||||
if '#.rst:' in line:
|
||||
is_rst_line = True
|
||||
|
||||
autocmake_entry = '\n'.join(s_out).split('autocmake.cfg configuration::')[1]
|
||||
autocmake_entry = autocmake_entry.replace('\n ', '\n')
|
||||
|
||||
# we prepend a fake section heading so that we can parse it with configparser
|
||||
autocmake_entry = '[foo]\n' + autocmake_entry
|
||||
|
||||
buf = StringIO(autocmake_entry)
|
||||
config = ConfigParser(dict_type=collections.OrderedDict)
|
||||
config.readfp(buf)
|
||||
|
||||
for section in config.sections():
|
||||
for s in ['docopt', 'define', 'export', 'fetch', 'warning']:
|
||||
if config.has_option(section, s):
|
||||
parsed_config[s] = config.get(section, s, 0, defaults)
|
||||
|
||||
return parsed_config
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_parse_cmake_module():
|
||||
|
||||
s = '''#.rst:
|
||||
#
|
||||
# Foo ...
|
||||
#
|
||||
# autocmake.cfg configuration::
|
||||
#
|
||||
# docopt: --cxx=<CXX> C++ compiler [default: g++].
|
||||
# --extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: ''].
|
||||
# export: 'CXX=%s' % arguments['--cxx']
|
||||
# define: '-DEXTRA_CXXFLAGS="%s"' % arguments['--extra-cxx-flags']
|
||||
|
||||
enable_language(CXX)
|
||||
|
||||
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
||||
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
||||
endif()'''
|
||||
|
||||
parsed_config = parse_cmake_module(s)
|
||||
assert parsed_config['docopt'] == "--cxx=<CXX> C++ compiler [default: g++].\n--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."
|
||||
|
||||
s = '''#.rst:
|
||||
#
|
||||
# Foo ...
|
||||
#
|
||||
# Bar ...
|
||||
|
||||
enable_language(CXX)
|
||||
|
||||
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
||||
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
||||
endif()'''
|
||||
|
||||
parsed_config = parse_cmake_module(s)
|
||||
assert parsed_config['docopt'] is None
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_for_yaml()
|
||||
main(sys.argv)
|
||||
|
Loading…
x
Reference in New Issue
Block a user