From 1ab86a0d02bc6fae8e48f8e3020790142a49059a Mon Sep 17 00:00:00 2001 From: Radovan Bast Date: Tue, 29 Mar 2016 07:14:30 +0200 Subject: [PATCH 1/5] rm leftovers --- README.md | 1 - doc/contributors/testing.rst | 3 --- 2 files changed, 4 deletions(-) diff --git a/README.md b/README.md index bcd963a..6a5c965 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/doc/contributors/testing.rst b/doc/contributors/testing.rst index f4843ae..6f5b040 100644 --- a/doc/contributors/testing.rst +++ b/doc/contributors/testing.rst @@ -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 `__ build and test history. - -In addition we also test Autocmake on a Windows CI server: `Appveyor `__. -This is controlled by `Appveyor `__. From 431a329e2b1dbec33998c33286ca77265b49c57f Mon Sep 17 00:00:00 2001 From: Radovan Bast Date: Sun, 10 Apr 2016 16:49:32 +0200 Subject: [PATCH 2/5] use with statement for I/O --- lib/config.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/config.py b/lib/config.py index a635d40..84e8b2a 100644 --- a/lib/config.py +++ b/lib/config.py @@ -101,9 +101,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: @@ -136,9 +135,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): From 7bfa3fb6dbfc92153cbdd105bcf7d28b003d83d6 Mon Sep 17 00:00:00 2001 From: Radovan Bast Date: Sun, 10 Apr 2016 17:03:41 +0200 Subject: [PATCH 3/5] more local imports --- lib/config.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/config.py b/lib/config.py index 84e8b2a..bad6347 100644 --- a/lib/config.py +++ b/lib/config.py @@ -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('%s --version' % 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') @@ -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') @@ -110,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) From 8edce7af967d39ecbc85e6a7adc59a1ab309e469 Mon Sep 17 00:00:00 2001 From: Radovan Bast Date: Sun, 10 Apr 2016 17:20:01 +0200 Subject: [PATCH 4/5] use format() instead of % --- lib/config.py | 8 +++--- update.py | 75 +++++++++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/lib/config.py b/lib/config.py index bad6347..71de04e 100644 --- a/lib/config.py +++ b/lib/config.py @@ -23,7 +23,7 @@ def check_cmake_exists(cmake_command): """ from subprocess import Popen, PIPE - p = Popen('%s --version' % cmake_command, + p = Popen('{} --version'.format(cmake_command), shell=True, stdin=PIPE, stdout=PIPE) @@ -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: @@ -159,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) diff --git a/update.py b/update.py index f3e78f7..fc26890 100644 --- a/update.py +++ b/update.py @@ -15,7 +15,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 @@ -24,7 +24,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) @@ -53,7 +53,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() @@ -70,7 +70,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) # ------------------------------------------------------------------------------ @@ -92,20 +92,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']))") @@ -117,14 +117,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) # ------------------------------------------------------------------------------ @@ -136,7 +133,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') @@ -181,7 +178,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") @@ -195,7 +192,7 @@ def gen_setup(config, relative_path, setup_script_name): s.append("build_path = arguments['']") 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'])") @@ -214,10 +211,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)') @@ -238,12 +235,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 @@ -258,7 +255,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 @@ -293,8 +290,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 @@ -305,7 +302,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'): @@ -343,7 +340,7 @@ def fetch_modules(config, relative_path): print('') if warnings != []: - print('- %s' % '\n- '.join(warnings)) + print('- {}'.format('\n- '.join(warnings))) return modules @@ -358,11 +355,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 \n" % argv[0]) + sys.stderr.write(" $ {} \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']: @@ -377,7 +374,7 @@ def main(argv): if not os.path.isfile('autocmake.cfg'): print('- fetching example autocmake.cfg') fetch_url( - src='%s/raw/master/example/autocmake.cfg' % AUTOCMAKE_GITHUB_URL, + src='{}/raw/master/example/autocmake.cfg'.format(AUTOCMAKE_GITHUB_URL), dst='autocmake.cfg' ) if not os.path.isfile('.gitignore'): @@ -386,24 +383,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 @@ -441,14 +438,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) @@ -515,8 +512,8 @@ def test_parse_cmake_module(): # # docopt: --cxx= C++ compiler [default: g++]. # --extra-cxx-flags= 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) From ea962bf0742cedc727a997e9b7b25738f0cdf465 Mon Sep 17 00:00:00 2001 From: Radovan Bast Date: Sun, 10 Apr 2016 17:24:49 +0200 Subject: [PATCH 5/5] update --cmake-options example; fixes #169 --- doc/users/faq.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/users/faq.rst b/doc/users/faq.rst index b46e833..1efae3e 100644 --- a/doc/users/faq.rst +++ b/doc/users/faq.rst @@ -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`.