def write_source_groups(self, context, cmake_file): """ Writes source groups of project files into CMakwLists.txt """ write_comment(cmake_file, 'Source groups') source_group_list = sorted(context.source_groups) for source_group in source_group_list: source_group_var = self.get_source_group_var(context, source_group) cmake_file.write('set({}\n'.format(source_group_var)) for src_file in context.source_groups[source_group]: fmt = ' "{}"\n' if context.file_contexts[src_file].excluded_from_build: fmt = '#' + fmt message( context, "file {} is excluded from build. Written but commented. " "No support in CMake yet.".format(src_file), 'warn4') cmake_file.write(fmt.format(src_file)) cmake_file.write(')\n') cmake_file.write('source_group("{}" FILES ${{{}}})\n\n'.format( source_group, source_group_var)) cmake_file.write('set(ALL_FILES\n') for source_group in source_group_list: cmake_file.write(' ${{{}}}\n'.format( context.files.get_source_group_var(context, source_group))) cmake_file.write(')\n\n')
def add_additional_code(context, file_to_add, cmake_file): """ Add additional file with CMake code inside :param context: the context of converter :type context: Context :param cmake_file: CMakeLists.txt IO wrapper :type cmake_file: _io.TextIOWrapper :param file_to_add: the file who contains CMake code :type file_to_add: str """ if file_to_add != '': try: fc = open(file_to_add) write_comment(cmake_file, 'Provides from external file.') for line in fc: cmake_file.write(line) fc.close() cmake_file.write('\n') message(context, 'File of Code is added = ' + file_to_add, 'warn') except OSError as e: message(context, str(e), 'error') message( context, 'Wrong data file ! Code was not added, please verify file name or path !', 'error')
def __write_global_configuration_types(root_cmake, configuration_types_list): write_comment(root_cmake, 'Global configuration types') root_cmake.write('set(CMAKE_CONFIGURATION_TYPES\n') for configuration_type in configuration_types_list: root_cmake.write(' \"{0}\"\n'.format(configuration_type)) root_cmake.write(' CACHE STRING "" FORCE\n)\n\n')
def write_include_directories(context, cmake_file): """ Write include directories of given context to given CMakeLists.txt file :param context: current context data :type context: Context :param cmake_file: CMakeLists.txt IO wrapper :type cmake_file: _io.TextIOWrapper """ has_includes = is_settings_has_data(context.sln_configurations_map, context.settings, 'inc_dirs') if has_includes: write_comment(cmake_file, 'Include directories') include_directories_specifier = 'PUBLIC' if context.private_include_directories: include_directories_specifier = 'PRIVATE' write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='target_include_directories(${{PROJECT_NAME}} {}'. format(include_directories_specifier), end_text=')', property_name='inc_dirs', separator=';\n', in_quotes=True) if has_includes: cmake_file.write('\n')
def __write_subdirectories(root_cmake, subdirectories_set, subdirectories_to_project_name): write_comment(root_cmake, 'Sub-projects') subdirectories = list(subdirectories_set) subdirectories.sort(key=str.lower) for subdirectory in subdirectories: binary_dir = '' if '.' in subdirectory[:1]: binary_dir = ' ${{CMAKE_BINARY_DIR}}/{0}'.format( subdirectories_to_project_name[subdirectory]) root_cmake.write('add_subdirectory({0}{1})\n'.format( set_unix_slash(subdirectory), binary_dir)) root_cmake.write('\n')
def write_flags(self, context, cmake_file): """ Get and write Preprocessor Macros definitions :param context: converter Context :type context: Context :param cmake_file: CMakeLists.txt IO wrapper :type cmake_file: _io.TextIOWrapper """ is_msvc = False for setting in context.settings: if cl_flags in context.settings[setting]: if context.settings[setting][cl_flags]: is_msvc = True break is_ifort = False for setting in context.settings: if ifort_cl_win in context.settings[setting]: if context.settings[setting][ifort_cl_win]: is_ifort = True break write_comment(cmake_file, 'Compile and link options') if is_msvc: self.write_compile_and_link_flags( context, cmake_file, os_check_str=None, compiler_check_str='MSVC', compiler_flags_key=cl_flags, linker_flags_key=ln_flags, ) if is_ifort: self.write_compile_and_link_flags( context, cmake_file, os_check_str='WIN32', compiler_check_str= '${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel"', compiler_flags_key=ifort_cl_win, linker_flags_key=ifort_ln_win) self.write_compile_and_link_flags( context, cmake_file, os_check_str='UNIX', compiler_check_str= '${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel"', compiler_flags_key=ifort_cl_unix, linker_flags_key=ifort_ln_unix)
def write_data(context, cmake_file): """ Write data defined in converter. :param context: converter context :type context: Context :param cmake_file: CMakeLists IO wrapper :type cmake_file: _io.TextIOWrapper """ context.files.write_cmake_project(context, cmake_file) # Add additional code or not if context.additional_code is not None: context.files.add_additional_code(context, context.additional_code, cmake_file) context.files.write_source_groups(context, cmake_file) if not context.has_only_headers: write_comment(cmake_file, 'Target') context.flags.write_target_artifact(context, cmake_file) context.flags.write_use_pch_function(context, cmake_file) context.dependencies.write_target_property_sheets( context, cmake_file) context.variables.write_target_outputs(context, cmake_file) context.dependencies.write_include_directories(context, cmake_file) context.flags.write_defines(context, cmake_file) context.flags.write_flags(context, cmake_file) context.dependencies.write_target_pre_build_events( context, cmake_file) context.dependencies.write_target_pre_link_events( context, cmake_file) context.dependencies.write_target_post_build_events( context, cmake_file) context.dependencies.write_custom_build_events_of_files( context, cmake_file) if (context.target_references or context.add_lib_deps or context.sln_deps or context.packages): write_comment(cmake_file, 'Dependencies') context.dependencies.write_target_references(context, cmake_file) context.dependencies.write_link_dependencies(context, cmake_file) context.dependencies.write_target_dependency_packages( context, cmake_file) else: Flags.write_target_headers_only_artifact(context, cmake_file)
def __write_target_build_events(context, cmake_file, comment, value_name, event_type): has_build_events = is_settings_has_data(context.sln_configurations_map, context.settings, value_name) if has_build_events: write_comment(cmake_file, comment) write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='add_custom_command_if(\n' ' TARGET ${{PROJECT_NAME}}\n' ' {0}\n' ' COMMANDS'.format(event_type), end_text=')', property_name=value_name, write_setting_property_func=Dependencies. write_target_build_event_of_setting) cmake_file.write('\n')
def __write_file_custom_build_events(context, cmake_file, comment, value_name, event_type): del event_type has_build_events = False for file in context.file_contexts: file_context = context.file_contexts[file] has_build_events = is_settings_has_data( context.sln_configurations_map, file_context.settings, value_name) if has_build_events: break if has_build_events: write_comment(cmake_file, comment) for file in context.file_contexts: file_context = context.file_contexts[file] outputs = '' description = '' for setting in file_context.settings: file_setting = file_context.settings[setting] if 'file_custom_build_events' in file_setting: outputs = file_setting['file_custom_build_events'][ 'outputs'] description = file_setting['file_custom_build_events'][ 'description'] text = write_property_of_settings( cmake_file, file_context.settings, context.sln_configurations_map, begin_text='add_custom_command_if(\n' ' OUTPUT "{0}"\n' ' COMMANDS'.format(outputs), end_text=' DEPENDS "{0}"\n' ' COMMENT "{1}"\n)'.format(file, description), property_name='file_custom_build_events', write_setting_property_func=Dependencies. write_file_build_event_of_setting) if text: cmake_file.write('\n')
def write_target_property_sheets(context, cmake_file): """ Write target property sheets of current context :param context: current context :type context: Context :param cmake_file: CMakeLists.txt IO wrapper :type cmake_file: _io.TextIOWrapper """ if is_settings_has_data(context.sln_configurations_map, context.settings, 'property_sheets'): write_comment(cmake_file, 'Includes for CMake from *.props') write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='', end_text='', property_name='property_sheets', write_setting_property_func=Dependencies.write_property_sheets) cmake_file.write('\n')
def write_defines(self, context, cmake_file): """ Routine that writes compile definitions into CMake file """ write_comment(cmake_file, 'Compile definitions') write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='target_compile_definitions(${PROJECT_NAME} PRIVATE', end_text=')', property_name=defines, separator=';\n', in_quotes=True) for file in context.file_contexts: write_property_of_settings( cmake_file, context.file_contexts[file].settings, context.sln_configurations_map, begin_text='set_source_files_properties({0} PROPERTIES'.format( file), end_text=')', property_name=defines, write_setting_property_func=self.__write_defines_for_files) cmake_file.write('\n')
def __write_global_compile_options(self, root_context, root_cmake, configuration_types_list): write_comment(root_cmake, 'Global compiler options') root_cmake.write('if(MSVC)\n') root_cmake.write( ' # remove default flags provided with CMake for MSVC\n') have_fortran = False for lang in sorted(root_context.solution_languages): if lang == 'Fortran': have_fortran = True continue self.__write_global_compile_options_language( root_cmake, configuration_types_list, lang) root_cmake.write('endif()\n\n') if have_fortran: root_cmake.write( 'if(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel")\n') root_cmake.write( ' # remove default flags provided with CMake for ifort\n') self.__write_global_compile_options_language( root_cmake, configuration_types_list, 'Fortran') root_cmake.write('endif()\n\n')
def __write_global_link_options(root_cmake, configuration_types_list): write_comment(root_cmake, 'Global linker options') root_cmake.write('if(MSVC)\n') root_cmake.write( ' # remove default flags provided with CMake for MSVC\n') root_cmake.write(' set(CMAKE_EXE_LINKER_FLAGS "")\n') root_cmake.write(' set(CMAKE_MODULE_LINKER_FLAGS "")\n') root_cmake.write(' set(CMAKE_SHARED_LINKER_FLAGS "")\n') root_cmake.write(' set(CMAKE_STATIC_LINKER_FLAGS "")\n') for configuration_type in configuration_types_list: ct_upper = configuration_type.upper() root_cmake.write( ' set(CMAKE_EXE_LINKER_FLAGS_{0} \"${{CMAKE_EXE_LINKER_FLAGS}}\")\n' .format(ct_upper)) root_cmake.write( ' set(CMAKE_MODULE_LINKER_FLAGS_{0} \"${{CMAKE_MODULE_LINKER_FLAGS}}\")\n' .format(ct_upper)) root_cmake.write( ' set(CMAKE_SHARED_LINKER_FLAGS_{0} \"${{CMAKE_SHARED_LINKER_FLAGS}}\")\n' .format(ct_upper)) root_cmake.write( ' set(CMAKE_STATIC_LINKER_FLAGS_{0} \"${{CMAKE_STATIC_LINKER_FLAGS}}\")\n' .format(ct_upper)) root_cmake.write('endif()\n\n')
def write_root_cmake_file(self, root_context, configuration_types_list, subdirectories_set, subdirectories_to_project_name): """ Routine that writes entry point of converted solution for CMake """ if root_context.dry: return root_cmake = get_cmake_lists(root_context, root_context.solution_path, 'r') root_cmake_projects_text = '' if root_cmake is not None: root_cmake_projects_text = root_cmake.read() root_cmake.close() root_cmake = get_cmake_lists(root_context, root_context.solution_path) root_cmake.write( 'cmake_minimum_required(VERSION 3.13.0 FATAL_ERROR)\n\n') if root_context.target_windows_version: root_cmake.write( 'set(CMAKE_SYSTEM_VERSION {} CACHE STRING "" FORCE)\n\n'. format(root_context.target_windows_version)) root_cmake.write('project({} {})\n\n'.format( os.path.splitext(os.path.basename(root_context.solution_path))[0], ' '.join(sorted(root_context.solution_languages)))) write_arch_types(root_cmake) self.__write_supported_architectures_check(root_context, root_cmake) self.__write_global_configuration_types(root_cmake, configuration_types_list) self.__write_global_compile_options(root_context, root_cmake, configuration_types_list) self.__write_global_link_options(root_cmake, configuration_types_list) write_use_package_stub(root_cmake) write_comment(root_cmake, 'Common utils') root_cmake.write('include(CMake/Utils.cmake)\n\n') self.copy_cmake_utils(root_context.solution_path) write_comment(root_cmake, 'Additional Global Settings(add specific info there)') root_cmake.write( 'include(CMake/GlobalSettingsInclude.cmake OPTIONAL)\n\n') write_comment(root_cmake, 'Use solution folders feature') root_cmake.write('set_property(GLOBAL PROPERTY USE_FOLDERS ON)\n\n') self.__write_subdirectories(root_cmake, subdirectories_set, subdirectories_to_project_name) if root_cmake_projects_text != '': root_cmake.write('\n' * 26) root_cmake.write(root_cmake_projects_text) root_cmake.close() warnings = '' if root_context.warnings_count > 0: warnings = ' ({} warnings)'.format(root_context.warnings_count) message( root_context, 'Conversion of {} finished{}'.format(root_context.solution_path, warnings), 'done')
def write_target_outputs(context, cmake_file): """ Add outputs for each artefacts CMake target :param context: related full context :type context: Context :param cmake_file: CMakeLists.txt IO wrapper :type cmake_file: _io.TextIOWrapper """ if not context.settings: return if context.root_namespace: cmake_file.write('set(ROOT_NAMESPACE {})\n\n'.format( context.root_namespace)) write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', end_text=')', property_name='VS_GLOBAL_KEYWORD', write_setting_property_func=ProjectVariables.write_target_property) if is_settings_has_data(context.sln_configurations_map, context.settings, 'TARGET_NAME'): write_comment(cmake_file, 'Target name') write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', end_text=')', property_name='TARGET_NAME', write_setting_property_func=ProjectVariables. write_target_property) if is_settings_has_data(context.sln_configurations_map, context.settings, 'OUTPUT_DIRECTORY'): write_comment(cmake_file, 'Output directory') write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', end_text=')', property_name='OUTPUT_DIRECTORY', write_setting_property_func=ProjectVariables. write_target_property) write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', end_text=')', property_name='ARCHIVE_OUTPUT_DIRECTORY', write_setting_property_func=ProjectVariables.write_target_property) write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', end_text=')', property_name='ARCHIVE_OUTPUT_NAME', write_setting_property_func=ProjectVariables.write_target_property) write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', end_text=')', property_name='PDB_OUTPUT_DIRECTORY', write_setting_property_func=ProjectVariables.write_target_property) # PDB_NAME doesn't support generator expressions yet (CMake 3.13) # write_property_of_settings( # cmake_file, context.settings, # context.sln_configurations_map, # begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', # end_text=')', # property_name='PDB_NAME', # write_setting_property_func=ProjectVariables.write_target_property # ) write_property_of_settings( cmake_file, context.settings, context.sln_configurations_map, begin_text='set_target_properties(${PROJECT_NAME} PROPERTIES', end_text=')', property_name='INTERPROCEDURAL_OPTIMIZATION', write_setting_property_func=ProjectVariables.write_target_property)