diff options
author | Jack Lloyd <[email protected]> | 2017-12-09 18:13:58 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-12-10 12:16:49 -0500 |
commit | bfcf7075e158b18411dfd7661bd0c5d1ab429e59 (patch) | |
tree | e851d7d824049b904877cd74dc01f53854ff8804 | |
parent | da5db8c7220d1d0d71f7778628ae82d73ebdb013 (diff) |
Generate the CMake using a template file
Less code in configure.py == betters
-rwxr-xr-x | configure.py | 245 | ||||
-rw-r--r-- | src/build-data/cmake.in | 62 |
2 files changed, 131 insertions, 176 deletions
diff --git a/configure.py b/configure.py index 00b8cb0a2..c441b258d 100755 --- a/configure.py +++ b/configure.py @@ -1140,13 +1140,16 @@ class CompilerInfo(InfoObject): # pylint: disable=too-many-instance-attributes return self.visibility_attribute return '' - def mach_abi_link_flags(self, options): + def mach_abi_link_flags(self, options, with_debug_info=None): """ Return the machine specific ABI flags """ + if with_debug_info is None: + with_debug_info = options.with_debug_info + def all_group(): - if options.with_debug_info and 'all-debug' in self.mach_abi_linking: + if with_debug_info and 'all-debug' in self.mach_abi_linking: return 'all-debug' return 'all' @@ -1192,12 +1195,17 @@ class CompilerInfo(InfoObject): # pylint: disable=too-many-instance-attributes def cc_lang_flags(self): return self.lang_flags - def cc_compile_flags(self, options): - def gen_flags(): - if options.with_debug_info: + def cc_compile_flags(self, options, with_debug_info=None, enable_optimizations=None): + def gen_flags(with_debug_info, enable_optimizations): + if with_debug_info is None: + with_debug_info = options.with_debug_info + if enable_optimizations is None: + enable_optimizations = not options.no_optimizations + + if with_debug_info: yield self.debug_info_flags - if not options.no_optimizations: + if enable_optimizations: if options.optimize_for_size: if self.size_optimization_flags != '': yield self.size_optimization_flags @@ -1222,7 +1230,7 @@ class CompilerInfo(InfoObject): # pylint: disable=too-many-instance-attributes if all_arch in self.mach_opt_flags: yield self.mach_opt_flags[all_arch][0] - return (' '.join(gen_flags())).strip() + return (' '.join(gen_flags(with_debug_info, enable_optimizations))).strip() @staticmethod def _so_link_search(osname, debug_info): @@ -1618,185 +1626,69 @@ def gen_bakefile(build_config, options, external_libs): f.close() -class CmakeGenerator(object): - def __init__(self, build_paths, using_mods, cc, options, template_vars): - self._build_paths = build_paths - self._using_mods = using_mods - self._cc = cc - - self._options_release = copy.deepcopy(options) - self._options_release.no_optimizations = False - self._options_release.with_debug_info = False - - self._options_debug = copy.deepcopy(options) - self._options_debug.no_optimizations = True - self._options_debug.with_debug_info = True - - self._template_vars = template_vars +def generate_cmake(source_paths, build_paths, using_mods, cc, options, template_vars): - @staticmethod - def _escape(input_str): + def escape(input_str): return input_str.replace('(', '\\(').replace(')', '\\)').replace('#', '\\#').replace('$', '\\$') - @staticmethod - def _cmake_normalize(source): + def cmake_normalize(source): return os.path.normpath(source).replace('\\', '/') - @staticmethod - def _create_target_rules(sources): - target = {'sources': {}, 'frameworks': set(), 'libs': set()} - for source in sources: - target['sources'][source] = {'isa_flags': set()} - return target - - def _add_target_details(self, target, using_mod): - libs_or_frameworks_needed = False - for source_path in target['sources']: - for mod_source in using_mod.source: - if source_path == mod_source: - libs_or_frameworks_needed = True - for isa in using_mod.need_isa: - isa_flag = self._cc.isa_flags_for(isa, self._template_vars['arch']) - target['sources'][source_path]['isa_flags'].add(isa_flag) - if libs_or_frameworks_needed: - if self._options_release.os in using_mod.libs: - for lib in using_mod.libs[self._options_release.os]: - target['libs'].add(lib) - if self._options_release.os in using_mod.frameworks: - for framework in using_mod.frameworks[self._options_release.os]: - target['frameworks'].add('"-framework %s"' % framework) - - @staticmethod - def _generate_target_sources_list(fd, target_name, target): - fd.write('set(%s\n' % target_name) - sorted_sources = sorted(target['sources'].keys()) - for source in sorted_sources: - fd.write(' "${CMAKE_CURRENT_LIST_DIR}/%s"\n' % CmakeGenerator._cmake_normalize(source)) - fd.write(')\n\n') - - @staticmethod - def _generate_target_source_files_isa_properties(fd, target): - sorted_sources = sorted(target['sources'].keys()) - for source in sorted_sources: - joined_isa_flags = ' '.join(target['sources'][source]['isa_flags']) - if joined_isa_flags: - fd.write('set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/%s" PROPERTIES COMPILE_FLAGS "%s")\n' - % (CmakeGenerator._cmake_normalize(source), joined_isa_flags)) + def generate_source_list(src_list): + s = "" + for source in sorted(src_list): + s += ' "${CMAKE_CURRENT_LIST_DIR}/%s"\n' % cmake_normalize(source) + return s + + def generate_isa_properties(mods): + isa_map = {} # map from src file -> ISA flags + for mod in mods: + + isa_flags = set() + for isa in mod.need_isa: + flag = cc.isa_flags_for(isa, template_vars['arch']) + if flag != "": + isa_flags.add(flag) + + if isa_flags: + isa_flags = ' '.join(isa_flags) + for src_file in mod.source: + isa_map[src_file] = isa_flags + + output = "" + prop_template = 'set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/%s" PROPERTIES COMPILE_FLAGS "%s")\n' + for k in sorted(isa_map.keys()): + output += prop_template % (os.path.normpath(k), isa_map[k]) + return output - @staticmethod - def _write_header(fd): - fd.write('cmake_minimum_required(VERSION 2.8.0)\n') - fd.write('project(botan)\n\n') - fd.write('if(POLICY CMP0042)\n') - fd.write('cmake_policy(SET CMP0042 NEW)\n') - fd.write('endif()\n\n') - - def _write_footer(self, fd, library_link, cli_link, tests_link): - fd.write('\n') - - fd.write('option(ENABLED_OPTIONAL_WARINIGS "If enabled more strict warning policy will be used" OFF)\n') - fd.write('option(ENABLED_LTO "If enabled link time optimization will be used" OFF)\n\n') - - fd.write('set(COMPILER_FEATURES_RELEASE %s %s %s)\n' - % (self._cc.cc_lang_flags(), - self._cc.cc_compile_flags(self._options_release), - self._cc.mach_abi_link_flags(self._options_release))) - - fd.write('set(COMPILER_FEATURES_DEBUG %s %s %s)\n' - % (self._cc.cc_lang_flags(), - self._cc.cc_compile_flags(self._options_debug), - self._cc.mach_abi_link_flags(self._options_debug))) - - fd.write('set(COMPILER_FEATURES $<$<NOT:$<CONFIG:DEBUG>>:${COMPILER_FEATURES_RELEASE}>' - +' $<$<CONFIG:DEBUG>:${COMPILER_FEATURES_DEBUG}>)\n') - - fd.write('set(SHARED_FEATURES %s)\n' % self._escape(self._template_vars['shared_flags'])) - fd.write('set(STATIC_FEATURES -DBOTAN_DLL=)\n') - - fd.write('set(COMPILER_WARNINGS %s)\n' % self._cc.cc_warning_flags(self._options_release)) - fd.write('set(COMPILER_INCLUDE_DIRS build/include build/include/external)\n') - fd.write('if(ENABLED_LTO)\n') - fd.write(' set(COMPILER_FEATURES ${COMPILER_FEATURES} -lto)\n') - fd.write('endif()\n') - fd.write('if(ENABLED_OPTIONAL_WARINIGS)\n') - fd.write(' set(COMPILER_OPTIONAL_WARNINGS -Wsign-promo -Wctor-dtor-privacy -Wdeprecated -Winit-self' + - ' -Wnon-virtual-dtor -Wunused-macros -Wold-style-cast -Wuninitialized)\n') - fd.write('endif()\n\n') - - fd.write('add_library(${PROJECT_NAME} STATIC ${BOTAN_SOURCES})\n') - fd.write('target_link_libraries(${PROJECT_NAME} PUBLIC %s)\n' - % library_link) - fd.write('target_compile_options(${PROJECT_NAME} PUBLIC ${COMPILER_WARNINGS} ${COMPILER_FEATURES}' + - ' ${COMPILER_OPTIONAL_WARNINGS} PRIVATE ${STATIC_FEATURES})\n') - - fd.write('target_include_directories(${PROJECT_NAME} PUBLIC ${COMPILER_INCLUDE_DIRS})\n\n') - fd.write('set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-static)\n\n') - - fd.write('add_library(${PROJECT_NAME}_shared SHARED ${BOTAN_SOURCES})\n') - fd.write('target_link_libraries(${PROJECT_NAME}_shared PUBLIC %s)\n' - % library_link) - fd.write('target_compile_options(${PROJECT_NAME}_shared PUBLIC ${COMPILER_WARNINGS}' + - ' ${COMPILER_FEATURES} ${COMPILER_OPTIONAL_WARNINGS} PRIVATE ${SHARED_FEATURES})\n') - fd.write('target_include_directories(${PROJECT_NAME}_shared PUBLIC ${COMPILER_INCLUDE_DIRS})\n') - fd.write('set_target_properties(${PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME ${PROJECT_NAME})\n\n') - - fd.write('add_executable(${PROJECT_NAME}_cli ${BOTAN_CLI})\n') - fd.write('target_link_libraries(${PROJECT_NAME}_cli PRIVATE ${PROJECT_NAME}_shared %s)\n' - % cli_link) - fd.write('set_target_properties(${PROJECT_NAME}_cli PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-cli)\n\n') - - fd.write('add_executable(${PROJECT_NAME}_tests ${BOTAN_TESTS})\n') - fd.write('target_link_libraries(${PROJECT_NAME}_tests PRIVATE ${PROJECT_NAME}_shared %s)\n' - % tests_link) - fd.write('set_target_properties(${PROJECT_NAME}_tests PROPERTIES OUTPUT_NAME botan-test)\n\n') - - fd.write('set(GLOBAL_CONFIGURATION_FILES configure.py .gitignore news.rst readme.rst)\n') - fd.write('file(GLOB_RECURSE CONFIGURATION_FILES src/configs/* )\n') - fd.write('file(GLOB_RECURSE DOCUMENTATION_FILES doc/* )\n') - fd.write('file(GLOB_RECURSE HEADER_FILES src/*.h )\n') - fd.write('file(GLOB_RECURSE INFO_FILES src/lib/*info.txt )\n') - fd.write('add_custom_target(CONFIGURATION_DUMMY SOURCES ' + - '${GLOBAL_CONFIGURATION_FILES} ${CONFIGURATION_FILES} ' + - '${DOCUMENTATION_FILES} ${INFO_FILES} ${HEADER_FILES})\n') + def libs_used(mods): + libs = set() + for mod in mods: + if options.os in mod.libs: + for lib in mod.libs[options.os]: + libs.add(lib) + if options.os in mod.frameworks: + for framework in mod.frameworks[options.os]: + libs.add('"-framework %s"' % framework) - def generate(self): - library_target_configuration = self._create_target_rules(self._build_paths.lib_sources) - tests_target_configuration = self._create_target_rules(self._build_paths.test_sources) - cli_target_configuration = self._create_target_rules(self._build_paths.cli_sources) - - for module in self._using_mods: - self._add_target_details(library_target_configuration, module) - self._add_target_details(tests_target_configuration, module) - self._add_target_details(cli_target_configuration, module) - - library_target_libs_and_frameworks = '%s %s' % ( - ' '.join(library_target_configuration['frameworks']), - ' '.join(library_target_configuration['libs']), - ) - tests_target_libs_and_frameworks = '%s %s' % ( - ' '.join(tests_target_configuration['frameworks']), - ' '.join(tests_target_configuration['libs']) - ) - cli_target_libs_and_frameworks = '%s %s' % ( - ' '.join(cli_target_configuration['frameworks']), - ' '.join(cli_target_configuration['libs']) - ) + return ' '.join(sorted(libs)) - with open('CMakeLists.txt', 'w') as f: - self._write_header(f) - self._generate_target_sources_list(f, 'BOTAN_SOURCES', library_target_configuration) - self._generate_target_sources_list(f, 'BOTAN_CLI', cli_target_configuration) - self._generate_target_sources_list(f, 'BOTAN_TESTS', tests_target_configuration) - self._generate_target_source_files_isa_properties(f, library_target_configuration) - self._generate_target_source_files_isa_properties(f, cli_target_configuration) - self._generate_target_source_files_isa_properties(f, tests_target_configuration) + cmake_template = os.path.join(source_paths.build_data_dir, 'cmake.in') - self._write_footer(f, - library_target_libs_and_frameworks, - tests_target_libs_and_frameworks, - cli_target_libs_and_frameworks) + # Create cmake-specific variables + cmake_vars = copy.deepcopy(template_vars) + cmake_vars['cmake_shared_flags'] = escape(template_vars['shared_flags']) + cmake_vars['cc_compile_flags'] = cc.cc_compile_flags(options, False, True) + cmake_vars['cc_compile_debug_flags'] = cc.cc_compile_flags(options, True, False) + cmake_vars['cxx_abi_debug_flags'] = cc.mach_abi_link_flags(options, True) + cmake_vars['cmake_lib_sources'] = generate_source_list(build_paths.lib_sources) + cmake_vars['cmake_cli_sources'] = generate_source_list(build_paths.cli_sources) + cmake_vars['cmake_test_sources'] = generate_source_list(build_paths.test_sources) + cmake_vars['cmake_compile_properties'] = generate_isa_properties(using_mods) + cmake_vars['cmake_libs_used'] = libs_used(using_mods) + return process_template(cmake_template, cmake_vars) class MakefileListsGenerator(object): def __init__(self, build_paths, options, modules, cc, arch, osinfo): @@ -3230,7 +3122,8 @@ def main_action_configure_build(info_modules, source_paths, options, gen_bakefile(build_config, options, template_vars['link_to']) if options.with_cmake: - CmakeGenerator(build_config, using_mods, cc, options, template_vars).generate() + with open('CMakeLists.txt', 'w') as f: + f.write(generate_cmake(source_paths, build_config, using_mods, cc, options, template_vars)) write_template(template_vars['makefile_path'], makefile_template) diff --git a/src/build-data/cmake.in b/src/build-data/cmake.in new file mode 100644 index 000000000..4fa906008 --- /dev/null +++ b/src/build-data/cmake.in @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 2.8.0) +project(botan) + +if(POLICY CMP0042) +cmake_policy(SET CMP0042 NEW) +endif() + +set(BOTAN_SOURCES +%{cmake_lib_sources}) + +set(BOTAN_CLI +%{cmake_cli_sources}) + +set(BOTAN_TESTS +%{cmake_test_sources}) + +%{cmake_compile_properties} + +option(ENABLED_OPTIONAL_WARINIGS "If enabled more strict warning policy will be used" OFF) +option(ENABLED_LTO "If enabled link time optimization will be used" OFF) + +set(COMPILER_FEATURES_RELEASE %{cc_lang_flags} %{cc_compile_flags} %{cxx_abi_flags}) +set(COMPILER_FEATURES_DEBUG %{cc_lang_flags} %{cc_compile_debug_flags} %{cxx_abi_debug_flags}) +set(COMPILER_FEATURES $<$<NOT:$<CONFIG:DEBUG>>:${COMPILER_FEATURES_RELEASE}> $<$<CONFIG:DEBUG>:${COMPILER_FEATURES_DEBUG}>) +set(SHARED_FEATURES %{cmake_shared_flags}) +set(STATIC_FEATURES -DBOTAN_DLL=) +set(COMPILER_WARNINGS %{cc_warning_flags}) +set(COMPILER_INCLUDE_DIRS build/include build/include/external) +if(ENABLED_LTO) + set(COMPILER_FEATURES ${COMPILER_FEATURES} -lto) +endif() +if(ENABLED_OPTIONAL_WARINIGS) + set(COMPILER_OPTIONAL_WARNINGS -Wsign-promo -Wctor-dtor-privacy -Wdeprecated -Winit-self -Wnon-virtual-dtor -Wunused-macros -Wold-style-cast -Wuninitialized) +endif() + +add_library(${PROJECT_NAME} STATIC ${BOTAN_SOURCES}) +target_link_libraries(${PROJECT_NAME} PUBLIC %{cmake_libs_used}) +target_compile_options(${PROJECT_NAME} PUBLIC ${COMPILER_WARNINGS} ${COMPILER_FEATURES} ${COMPILER_OPTIONAL_WARNINGS} PRIVATE ${STATIC_FEATURES}) +target_include_directories(${PROJECT_NAME} PUBLIC ${COMPILER_INCLUDE_DIRS}) + +set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-static) + +add_library(${PROJECT_NAME}_shared SHARED ${BOTAN_SOURCES}) +target_link_libraries(${PROJECT_NAME}_shared PUBLIC %{cmake_libs_used}) +target_compile_options(${PROJECT_NAME}_shared PUBLIC ${COMPILER_WARNINGS} ${COMPILER_FEATURES} ${COMPILER_OPTIONAL_WARNINGS} PRIVATE ${SHARED_FEATURES}) +target_include_directories(${PROJECT_NAME}_shared PUBLIC ${COMPILER_INCLUDE_DIRS}) +set_target_properties(${PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME ${PROJECT_NAME}) + +add_executable(${PROJECT_NAME}_cli ${BOTAN_CLI}) +target_link_libraries(${PROJECT_NAME}_cli PRIVATE ${PROJECT_NAME}_shared ) +set_target_properties(${PROJECT_NAME}_cli PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-cli) + +add_executable(${PROJECT_NAME}_tests ${BOTAN_TESTS}) +target_link_libraries(${PROJECT_NAME}_tests PRIVATE ${PROJECT_NAME}_shared ) +set_target_properties(${PROJECT_NAME}_tests PROPERTIES OUTPUT_NAME botan-test) + +set(GLOBAL_CONFIGURATION_FILES configure.py .gitignore news.rst readme.rst) +file(GLOB_RECURSE CONFIGURATION_FILES src/configs/* ) +file(GLOB_RECURSE DOCUMENTATION_FILES doc/* ) +file(GLOB_RECURSE HEADER_FILES src/*.h ) +file(GLOB_RECURSE INFO_FILES src/lib/*info.txt ) +add_custom_target(CONFIGURATION_DUMMY SOURCES ${GLOBAL_CONFIGURATION_FILES} ${CONFIGURATION_FILES} ${DOCUMENTATION_FILES} ${INFO_FILES} ${HEADER_FILES}) |