Merge branch 'master' into yaml

This commit is contained in:
Radovan Bast 2016-04-10 17:26:02 +02:00
commit 69478cb27e
5 changed files with 63 additions and 65 deletions

View File

@ -1,5 +1,4 @@
[![Build Status](https://travis-ci.org/scisoft/autocmake.svg?branch=master)](https://travis-ci.org/scisoft/autocmake/builds)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/scisoft/autocmake?branch=master&svg=true)](https://ci.appveyor.com/project/bast/autocmake/history)
[![Documentation Status](https://readthedocs.org/projects/autocmake/badge/?version=latest)](http://autocmake.readthedocs.org)
[![License](https://img.shields.io/badge/license-%20BSD--3-blue.svg)](../master/LICENSE)

View File

@ -21,6 +21,3 @@ 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>`__
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>`__.

View File

@ -47,4 +47,8 @@ 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. If you do not use two sets
of quotes then the setup command may end up incorrectly saved in `build/setup_command`.

View File

@ -3,10 +3,8 @@
# See https://github.com/scisoft/autocmake/blob/master/LICENSE
import subprocess
import os
import sys
import shutil
def module_exists(module_name):
@ -23,10 +21,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('{} --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 +46,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 {} 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 +74,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 {} &&'.format(e) for e in cmake_command[:pos].split()]
s.append(cmake_command[pos:])
return ' '.join(s)
else:
@ -85,13 +85,16 @@ 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')
@ -101,9 +104,8 @@ def run_cmake(command, build_path, default_build_path):
# 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:
@ -111,7 +113,7 @@ def run_cmake(command, build_path, default_build_path):
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('{}\n'.format(cmake_command))
if only_show:
sys.exit(0)

View File

@ -14,7 +14,7 @@ if sys.version_info[0] > 2:
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.stderr.write("ERROR: could not fetch {}\n".format(url))
sys.exit(-1)
else:
from StringIO import StringIO
@ -22,7 +22,7 @@ else:
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.stderr.write("ERROR: could not fetch {}\n".format(url))
sys.exit(-1)
@ -119,7 +119,7 @@ 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,
sys.stdout.write("\r{0} [{1}{2}] ({3}/{4})".format(text, '#' * n,
' ' * (width - n), done, total))
sys.stdout.flush()
@ -136,7 +136,7 @@ def align_options(options):
l = len(opt[0])
s = []
for opt in options:
s.append(' %s%s %s' % (opt[0], ' ' * (l - len(opt[0])), opt[1]))
s.append(' {0}{1} {2}'.format(opt[0], ' ' * (l - len(opt[0])), opt[1]))
return '\n'.join(s)
# ------------------------------------------------------------------------------
@ -158,20 +158,20 @@ def gen_cmake_command(config):
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({})'.format(env))
s.append(" command.append('%s' % arguments['--cmake-executable'])")
s.append(" command.append(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({})'.format(definition))
s.append(" command.append('-DCMAKE_BUILD_TYPE=%s' % arguments['--type'])")
s.append(" command.append('-G \"%s\"' % arguments['--generator'])")
s.append(" command.append('-DCMAKE_BUILD_TYPE={}'.format(arguments['--type']))")
s.append(" command.append('-G \"{}\"'.format(arguments['--generator']))")
s.append(" if arguments['--cmake-options'] != \"''\":")
s.append(" command.append('%s' % 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']))")
@ -183,14 +183,11 @@ def gen_cmake_command(config):
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
year_range = '2015-{}'.format(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)
s.append('# Copyright (c) {} by Radovan Bast and Jonas Juselius'.format(year_range))
return '\n'.join(s)
# ------------------------------------------------------------------------------
@ -202,7 +199,7 @@ def gen_setup(config, relative_path, setup_script_name):
"""
s = []
s.append('#!/usr/bin/env python')
s.append('\n%s' % autogenerated_notice())
s.append('\n{}'.format(autogenerated_notice()))
s.append('\nimport os')
s.append('import sys')
@ -247,7 +244,7 @@ def gen_setup(config, relative_path, setup_script_name):
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(r" sys.stderr.write('ERROR: bad input to {}\n'.format(sys.argv[0]))")
s.append(" sys.stderr.write(options)")
s.append(" sys.exit(-1)")
s.append("\n")
@ -261,7 +258,7 @@ def gen_setup(config, relative_path, setup_script_name):
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("cmake_command = '{0} {1}'.format(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'])")
@ -280,10 +277,10 @@ def gen_cmakelists(project_name, min_cmake_version, relative_path, modules):
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('cmake_minimum_required(VERSION {} FATAL_ERROR)'.format(min_cmake_version))
s.append('\n# project name')
s.append('project(%s)' % project_name)
s.append('project({})'.format(project_name))
s.append('\n# do not rebuild if rules (compiler flags) change')
s.append('set(CMAKE_SKIP_RULE_DEPENDENCY TRUE)')
@ -304,12 +301,12 @@ def gen_cmakelists(project_name, min_cmake_version, relative_path, modules):
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)
s.append('set(CMAKE_MODULE_PATH ${{CMAKE_MODULE_PATH}} ${{PROJECT_SOURCE_DIR}}/{})'.format(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])
s.append('include({})'.format(os.path.splitext(module.name)[0]))
return s
@ -324,7 +321,7 @@ def prepend_or_set(config, section, option, value, defaults):
"""
if value:
if config.has_option(section, option):
value += '\n%s' % config.get(section, option, 0, defaults)
value += '\n{}'.format(config.get(section, option, 0, defaults))
config.set(section, option, value)
return config
@ -359,8 +356,8 @@ def fetch_modules(config, relative_path):
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)
name = 'autocmake_{}'.format(module_name)
dst = os.path.join(download_directory, 'autocmake_{}'.format(module_name))
fetch_url(src, dst)
file_name = dst
fetch_dst_directory = download_directory
@ -371,7 +368,7 @@ def fetch_modules(config, relative_path):
file_name = src
fetch_dst_directory = path
else:
sys.stderr.write("ERROR: %s does not exist\n" % src)
sys.stderr.write("ERROR: {} does not exist\n".format(src))
sys.exit(-1)
if config.has_option(section, 'override'):
@ -409,7 +406,7 @@ def fetch_modules(config, relative_path):
print('')
if warnings != []:
print('- %s' % '\n- '.join(warnings))
print('- {}'.format('\n- '.join(warnings)))
return modules
@ -424,11 +421,11 @@ def main(argv):
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(" $ {} --self\n\n".format(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(" $ {} <PROJECT_ROOT>\n".format(argv[0]))
sys.stderr.write(" example:\n")
sys.stderr.write(" $ %s ..\n" % argv[0])
sys.stderr.write(" $ {} ..\n".format(argv[0]))
sys.exit(-1)
if argv[1] in ['-h', '--help']:
@ -443,7 +440,7 @@ def main(argv):
if not os.path.isfile('autocmake.yml'):
print('- fetching example autocmake.yml') # FIXME
fetch_url(
src='%s/raw/master/example/autocmake.yml' % AUTOCMAKE_GITHUB_URL,
src='{}/raw/master/example/autocmake.yml'.format(AUTOCMAKE_GITHUB_URL),
dst='autocmake.yml'
)
if not os.path.isfile('.gitignore'):
@ -452,24 +449,24 @@ def main(argv):
f.write('*.pyc\n')
print('- fetching lib/config.py')
fetch_url(
src='%s/raw/master/lib/config.py' % AUTOCMAKE_GITHUB_URL,
src='{}/raw/master/lib/config.py'.format(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,
src='{}/raw/master/lib/docopt/docopt.py'.format(AUTOCMAKE_GITHUB_URL),
dst='lib/docopt/docopt.py'
)
print('- fetching update.py')
fetch_url(
src='%s/raw/master/update.py' % AUTOCMAKE_GITHUB_URL,
src='{}/raw/master/update.py'.format(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.stderr.write("ERROR: {} is not a directory\n".format(project_root))
sys.exit(-1)
# read config file
@ -506,14 +503,14 @@ def main(argv):
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))
f.write('{}\n'.format('\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))
f.write('{}\n'.format('\n'.join(s)))
if sys.platform != 'win32':
make_executable(file_path)
@ -581,8 +578,8 @@ def test_parse_cmake_module():
#
# 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']
# export: 'CXX={}'.format(arguments['--cxx'])
# define: '-DEXTRA_CXXFLAGS="{}"'.format(arguments['--extra-cxx-flags'])
enable_language(CXX)