diff --git a/CMake/cotire.cmake b/CMake/cotire.cmake index 972685b..8525526 100644 --- a/CMake/cotire.cmake +++ b/CMake/cotire.cmake @@ -37,7 +37,7 @@ set(__COTIRE_INCLUDED TRUE) cmake_minimum_required(VERSION 2.8.6) set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") -set (COTIRE_CMAKE_MODULE_VERSION "1.0.9") +set (COTIRE_CMAKE_MODULE_VERSION "1.1.0") include(CMakeParseArguments) @@ -210,8 +210,8 @@ function (cotrie_resolve_config_properites _configurations _propertiesVar) foreach (_property ${ARGN}) if ("${_property}" MATCHES "") foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _config) - string (REPLACE "" "${_config}" _configProperty "${_property}") + string (TOUPPER "${_config}" _upperConfig) + string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") list (APPEND _properties ${_configProperty}) endforeach() else() @@ -282,14 +282,14 @@ function (cotire_filter_compile_flags _flagFilter _matchedOptionsVar _unmatchedO endfunction() function (cotire_get_target_compile_flags _config _language _directory _target _flagsVar) - string (TOUPPER "${_config}" _config) + string (TOUPPER "${_config}" _upperConfig) # collect options from CMake language variables set (_compileFlags "") if (CMAKE_${_language}_FLAGS) set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") endif() - if (CMAKE_${_language}_FLAGS_${_config}) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_config}}") + if (CMAKE_${_language}_FLAGS_${_upperConfig}) + set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") endif() if (_target) # add option from CMake target type variable @@ -326,7 +326,7 @@ function (cotire_get_target_compile_flags _config _language _directory _target _ endif() # platform specific flags if (APPLE) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_config}) + get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) if (NOT _architectures) get_target_property(_architectures ${_target} OSX_ARCHITECTURES) endif() @@ -418,7 +418,7 @@ function (cotire_get_target_export_symbol _target _exportSymbolVar) endfunction() function (cotire_get_target_compile_definitions _config _language _directory _target _definitionsVar) - string (TOUPPER "${_config}" _config) + string (TOUPPER "${_config}" _upperConfig) set (_configDefinitions "") # CMAKE_INTDIR for multi-configuration build systems if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") @@ -434,7 +434,7 @@ function (cotire_get_target_compile_definitions _config _language _directory _ta if (_definitions) list (APPEND _configDefinitions ${_definitions}) endif() - get_directory_property(_definitions DIRECTORY "${_directory}" COMPILE_DEFINITIONS_${_config}) + get_directory_property(_definitions DIRECTORY "${_directory}" COMPILE_DEFINITIONS_${_upperConfig}) if (_definitions) list (APPEND _configDefinitions ${_definitions}) endif() @@ -443,7 +443,7 @@ function (cotire_get_target_compile_definitions _config _language _directory _ta if (_definitions) list (APPEND _configDefinitions ${_definitions}) endif() - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_config}) + get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) if (_definitions) list (APPEND _configDefinitions ${_definitions}) endif() @@ -515,12 +515,12 @@ endfunction() function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) set (_compileDefinitions "") if (NOT CMAKE_SCRIPT_MODE_FILE) - string (TOUPPER "${_config}" _config) + string (TOUPPER "${_config}" _upperConfig) get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) if (_definitions) list (APPEND _compileDefinitions ${_definitions}) endif() - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_config}) + get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) if (_definitions) list (APPEND _compileDefinitions ${_definitions}) endif() @@ -724,10 +724,10 @@ endmacro() macro (cotire_parse_line _line _headerFileVar _headerDepthVar) if (MSVC) # cl.exe /showIncludes output looks different depending on the language pack used, e.g.: - # English: "Note: including file:" - # German: "Hinweis: Einlesen der Datei:" + # English: "Note: including file: C:\directory\file" + # German: "Hinweis: Einlesen der Datei: C:\directory\file" # We use a very general regular expression, relying on the presence of the : character - if ("${_line}" MATCHES "^[^:]+:[^:]+:( +)(.*)$") + if ("${_line}" MATCHES "( +)([^:]+:[^:]+)$") # Visual Studio compiler output string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) @@ -882,7 +882,10 @@ function (cotire_scan_includes _includesVar) if (COTIRE_VERBOSE) message (STATUS "execute_process: ${_cmd}") endif() - if (WIN32) + if ("${_option_COMPILER_ID}" STREQUAL "MSVC") + if (COTIRE_DEBUG) + message (STATUS "clearing VS_UNICODE_OUTPUT") + endif() # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared unset (ENV{VS_UNICODE_OUTPUT}) endif() @@ -918,11 +921,12 @@ macro (cotire_comment_str _language _commentText _commentVar) endmacro() function (cotire_write_file _language _file _contents _force) - cotire_comment_str("${_language}" "cotire.cmake ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) cotire_comment_str("${_language}" "${_file}" _header2) set (_contents "${_header1}\n${_header2}\n${_contents}") if (COTIRE_DEBUG) - message ("${_contents}") + message (STATUS "${_contents}") endif() if (_force OR NOT EXISTS "${_file}") file (WRITE "${_file}" "${_contents}") @@ -1226,7 +1230,10 @@ function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) if (COTIRE_VERBOSE) message (STATUS "execute_process: ${_cmd}") endif() - if (WIN32) + if ("${_option_COMPILER_ID}" STREQUAL "MSVC") + if (COTIRE_DEBUG) + message (STATUS "clearing VS_UNICODE_OUTPUT") + endif() # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared unset (ENV{VS_UNICODE_OUTPUT}) endif() @@ -1440,7 +1447,8 @@ endfunction() function (cotire_generate_target_script _language _configurations _target _targetScriptVar) set (COTIRE_TARGET_SOURCES ${ARGN}) - set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_cotire.cmake") + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS) cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS) # set up variables to be configured @@ -1455,29 +1463,18 @@ function (cotire_generate_target_script _language _configurations _target _targe get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${COTIRE_TARGET_SOURCES}) cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${COTIRE_TARGET_SOURCES}) - if (CMAKE_CONFIGURATION_TYPES) - set (COTIRE_TARGET_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}") - foreach (_config ${CMAKE_CONFIGURATION_TYPES}) - cotire_get_target_include_directories( - "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_config}) - cotire_get_target_compile_definitions( - "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_config}) - cotire_get_target_compiler_flags( - "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_config}) - cotire_get_source_files_compile_definitions( - "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_config} ${COTIRE_TARGET_SOURCES}) - endforeach() - else() - set (COTIRE_TARGET_CONFIGURATION_TYPES "") + set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") + foreach (_config ${_configurations}) + string (TOUPPER "${_config}" _upperConfig) cotire_get_target_include_directories( - "${CMAKE_BUILD_TYPE}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES) + "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}) cotire_get_target_compile_definitions( - "${CMAKE_BUILD_TYPE}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS) + "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) cotire_get_target_compiler_flags( - "${CMAKE_BUILD_TYPE}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS) + "${_config}" "${_language}" "${CMAKE_CURRENT_SOURCE_DIR}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) cotire_get_source_files_compile_definitions( - "${CMAKE_BUILD_TYPE}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS ${COTIRE_TARGET_SOURCES}) - endif() + "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${COTIRE_TARGET_SOURCES}) + endforeach() get_cmake_property(_vars VARIABLES) string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") # remove COTIRE_VERBOSE which is passed as a CMake define on command line @@ -2137,8 +2134,10 @@ function (cotire_target _target) if (NOT _option_CONFIGURATIONS) if (CMAKE_CONFIGURATION_TYPES) set (_option_CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES}) - else() + elseif (CMAKE_BUILD_TYPE) set (_option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}") + else() + set (_option_CONFIGURATIONS "None") endif() endif() # trivial checks @@ -2150,9 +2149,16 @@ function (cotire_target _target) # check if target needs to be cotired for build type # when using configuration types, the test is performed at build time cotire_init_cotire_target_properties(${_target}) - if (NOT CMAKE_CONFIGURATION_TYPES AND CMAKE_BUILD_TYPE AND _option_CONFIGURATIONS) - list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) + if (NOT CMAKE_CONFIGURATION_TYPES) + if (CMAKE_BUILD_TYPE) + list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) + else() + list (FIND _option_CONFIGURATIONS "None" _index) + endif() if (_index EQUAL -1) + if (COTIRE_DEBUG) + message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") + endif() return() endif() endif() @@ -2282,7 +2288,7 @@ if (CMAKE_SCRIPT_MODE_FILE) endforeach() if (COTIRE_DEBUG) - message ("${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") + message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") endif() # include target script if available @@ -2298,36 +2304,31 @@ if (CMAKE_SCRIPT_MODE_FILE) endif() endif() - if (COTIRE_TARGET_CONFIGURATION_TYPES) - set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${COTIRE_BUILD_TYPE}}) - set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${COTIRE_BUILD_TYPE}}) - set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${COTIRE_BUILD_TYPE}}) - if (NOT COTIRE_BUILD_TYPE) - # init COTIRE_BUILD_TYPE to first configuration type if not set explicitly - list (GET CMAKE_CONFIGURATION_TYPES 0 COTIRE_BUILD_TYPE) - endif() - # check if target has been cotired for actual build type COTIRE_BUILD_TYPE - list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) - if (_index GREATER -1) - set (_sources ${COTIRE_TARGET_SOURCES}) - set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${COTIRE_BUILD_TYPE}}) - else() - set (_sources "") - set (_sourcesDefinitions "") - endif() - else() - set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES}) - set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS}) - set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS}) + if (NOT COTIRE_BUILD_TYPE) + set (COTIRE_BUILD_TYPE "None") + endif() + string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) + set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) + set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) + set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) + # check if target has been cotired for actual build type COTIRE_BUILD_TYPE + list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) + if (_index GREATER -1) set (_sources ${COTIRE_TARGET_SOURCES}) - set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS}) + set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) + else() + if (COTIRE_DEBUG) + message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") + endif() + set (_sources "") + set (_sourcesDefinitions "") endif() set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) - if (${COTIRE_ARGV1} STREQUAL "unity") + if ("${COTIRE_ARGV1}" STREQUAL "unity") cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) cotire_generate_unity_source( @@ -2340,7 +2341,7 @@ if (CMAKE_SCRIPT_MODE_FILE) SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} SOURCES_POST_UNDEFS ${_sourcesPostUndefs}) - elseif (${COTIRE_ARGV1} STREQUAL "prefix") + elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") set (_files "") foreach (_index RANGE 4 ${COTIRE_ARGC}) @@ -2364,7 +2365,7 @@ if (CMAKE_SCRIPT_MODE_FILE) COMPILE_DEFINITIONS ${_compileDefinitions} COMPILE_FLAGS ${_compileFlags}) - elseif (${COTIRE_ARGV1} STREQUAL "precompile") + elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") set (_files "") foreach (_index RANGE 5 ${COTIRE_ARGC}) @@ -2384,7 +2385,7 @@ if (CMAKE_SCRIPT_MODE_FILE) COMPILE_DEFINITIONS ${_compileDefinitions} COMPILE_FLAGS ${_compileFlags}) - elseif (${COTIRE_ARGV1} STREQUAL "combine") + elseif ("${COTIRE_ARGV1}" STREQUAL "combine") set (_files "") foreach (_index RANGE 2 ${COTIRE_ARGC}) @@ -2394,12 +2395,12 @@ if (CMAKE_SCRIPT_MODE_FILE) endforeach() cotire_generate_unity_source(${_files}) - elseif (${COTIRE_ARGV1} STREQUAL "cleanup") + elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") else() - message (FATAL_ERROR "Unknown command ${COTIRE_ARGV1}.") + message (FATAL_ERROR "Unknown cotire command \"${COTIRE_ARGV1}\".") endif() else() diff --git a/HISTORY.md b/HISTORY.md index ba7d2a4..12f8fe2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,10 @@ +## 1.1.0 (2012-04-19) + +* tested with CMake 2.8.8. +* added example to manual that shows how to apply cotire to CMake object library targets. +* fixed multiple bugs with handling of CMake single build type and multiple configuration builds. +* added more robust parsing of localized MSVC `/showIncludes` output. + ## 1.0.9 (2012-04-09) * add support for compiler wrappers like ccache. diff --git a/MANUAL.md b/MANUAL.md index 9e479d5..9e9192e 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -269,7 +269,7 @@ directories. A target inherits the property value from its enclosing directory. ### disabling precompiled headers for small targets The cache variable `COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES` can be set to the minimum number of -source files required to enable the use of precompiled header. It defaults to 3. +source files required to enable the use of a precompiled header. It defaults to 3. ### configuring the generation of the prefix header @@ -382,6 +382,27 @@ enabled in the following way upon configuring the project: $ export CXX="/usr/local/bin/ccache /usr/bin/g++" $ cmake .. +### applying cotire to object library targets + +CMake 2.8.8 introduced a new type of library target called [object library][objlib]. An object +library is a convenience target that compiles multiple source files but does not create a linked +target library for them, e.g.: + + add_library(myLib OBJECT lib1.cpp lib2.cpp lib3.cpp) + add_executable(exeA $ mainA.cpp) + add_executable(exeB $ mainB.cpp) + +The `cotire` function can be applied to an object library target in a familiar fashion: + + add_library(myLib OBJECT lib1.cpp lib2.cpp lib3.cpp) + cotire(myLib) + # use unity object library for executables + add_executable(exeA $ mainA.cpp) + add_executable(exeB $ mainB.cpp) + +Because object library targets do not support `PRE_BUILD` actions, precompiled header usage cannot +be enabled for them for Xcode projects generated with CMake. Unity builds work as expected, though. + cotire usage restrictions ------------------------- @@ -415,4 +436,5 @@ To get a workable build system, set the `COTIRE_EXCLUDED` property on .m and .mm [EoUB]:http://leewinder.co.uk/blog/?p=394 [pch]:http://en.wikipedia.org/wiki/Precompiled_header [scu]:http://en.wikipedia.org/wiki/Single_Compilation_Unit +[objlib]:http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_library [pfh]:http://en.wikipedia.org/wiki/Prefix_header