diff options
62 files changed, 1971 insertions, 492 deletions
diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake index fb55bfc..5b096ad 100644 --- a/CMakeCPack.cmake +++ b/CMakeCPack.cmake @@ -59,11 +59,43 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") if(${CPACK_SYSTEM_NAME} MATCHES Windows) if(CMAKE_CL_64) set(CPACK_SYSTEM_NAME win64-x64) + set(CPACK_IFW_TARGET_DIRECTORY "@RootDir@/Program Files/${CMAKE_PROJECT_NAME}") else() set(CPACK_SYSTEM_NAME win32-x86) endif() endif() + # default component for IFW + if(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME) + set(_CPACK_IFW_COMPONENT_NAME ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}) + else() + set(_CPACK_IFW_COMPONENT_NAME Unspecified) + endif() + string(TOUPPER ${_CPACK_IFW_COMPONENT_NAME} _CPACK_IFW_COMPONENT_UNAME) + + if(${CMAKE_SYSTEM_NAME} MATCHES Windows) + if(BUILD_QtDialog) + set(_CPACK_IFW_SHORTCUT_OPTIONAL "${_CPACK_IFW_SHORTCUT_OPTIONAL}component.addOperation(\"CreateShortcut\", \"@TargetDir@/bin/cmake-gui.exe\", \"@StartMenuDir@/CMake (cmake-gui).lnk\");\n") + endif() + if(SPHINX_HTML) + set(_CPACK_IFW_SHORTCUT_OPTIONAL "${_CPACK_IFW_SHORTCUT_OPTIONAL}component.addOperation(\"CreateShortcut\", \"@TargetDir@/doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/html/index.html\", \"@StartMenuDir@/CMake Documentation.lnk\");\n") + endif() + configure_file("${CMake_SOURCE_DIR}/Source/QtIFW/installscript.qs.in" + "${CMake_BINARY_DIR}/installscript.qs" @ONLY + ) + install(FILES "${CMake_SOURCE_DIR}/Source/QtIFW/cmake.org.html" + DESTINATION "." + ) + set(_CPACK_IFW_COMPONENT_SCRIPT "set(CPACK_IFW_COMPONENT_${_CPACK_IFW_COMPONENT_UNAME}_SCRIPT \"${CMake_BINARY_DIR}/installscript.qs\")") + endif() + + if(${CMAKE_SYSTEM_NAME} MATCHES Linux) + set(CPACK_IFW_TARGET_DIRECTORY "@HomeDir@/${CMAKE_PROJECT_NAME}") + set(CPACK_IFW_ADMIN_TARGET_DIRECTORY "@ApplicationsDir@/${CMAKE_PROJECT_NAME}") + endif() + + set(_CPACK_IFW_PACKAGE_VERSION ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}) + if(NOT DEFINED CPACK_PACKAGE_FILE_NAME) # if the CPACK_PACKAGE_FILE_NAME is not defined by the cache # default to source package - system, on cygwin system is not diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in index aba404f..135c07d 100644 --- a/CMakeCPackOptions.cmake.in +++ b/CMakeCPackOptions.cmake.in @@ -31,6 +31,20 @@ endif() # they might not if qt was not enabled for the build include("@QT_DIALOG_CPACK_OPTIONS_FILE@" OPTIONAL) +if(CPACK_GENERATOR MATCHES "IFW") + # Version with QtIFW limitations + set(CPACK_PACKAGE_VERSION "@_CPACK_IFW_PACKAGE_VERSION@") + # Enable install default component + set(CPACK_COMPONENTS_ALL "@_CPACK_IFW_COMPONENT_NAME@") + # Configuration + set(CPACK_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_DISPLAY_NAME "@CPACK_PACKAGE_NAME@") + set(CPACK_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_DESCRIPTION "@CPACK_PACKAGE_DESCRIPTION_SUMMARY@") + # IFW Configuration + set(CPACK_IFW_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_NAME "@CPACK_PACKAGE_NAME@") + set(CPACK_IFW_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_LICENSES "@CPACK_PACKAGE_NAME@ Copyright" "@CPACK_RESOURCE_FILE_LICENSE@") + @_CPACK_IFW_COMPONENT_SCRIPT@ +endif() + if(CPACK_GENERATOR MATCHES "CygwinSource") # when packaging source make sure the .build directory is not included set(CPACK_SOURCE_IGNORE_FILES diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index ecc9cc4..91fffe9 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -55,6 +55,7 @@ All Modules /module/CPackCygwin /module/CPackDeb /module/CPackDMG + /module/CPackIFW /module/CPackNSIS /module/CPackPackageMaker /module/CPackRPM diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index e4546c1..17dadc2 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -51,7 +51,6 @@ Properties on Directories /prop_dir/CACHE_VARIABLES /prop_dir/CLEAN_NO_CUSTOM /prop_dir/CMAKE_CONFIGURE_DEPENDS - /prop_dir/COMPILE_DEFINITIONS_CONFIG /prop_dir/COMPILE_DEFINITIONS /prop_dir/COMPILE_OPTIONS /prop_dir/DEFINITIONS @@ -101,7 +100,6 @@ Properties on Targets /prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MAX /prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MIN /prop_tgt/COMPATIBLE_INTERFACE_STRING - /prop_tgt/COMPILE_DEFINITIONS_CONFIG /prop_tgt/COMPILE_DEFINITIONS /prop_tgt/COMPILE_FEATURES /prop_tgt/COMPILE_FLAGS @@ -205,9 +203,7 @@ Properties on Targets /prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG /prop_tgt/PDB_OUTPUT_DIRECTORY /prop_tgt/POSITION_INDEPENDENT_CODE - /prop_tgt/POST_INSTALL_SCRIPT /prop_tgt/PREFIX - /prop_tgt/PRE_INSTALL_SCRIPT /prop_tgt/PRIVATE_HEADER /prop_tgt/PROJECT_LABEL /prop_tgt/PUBLIC_HEADER @@ -277,7 +273,6 @@ Properties on Source Files /prop_sf/ABSTRACT /prop_sf/AUTOUIC_OPTIONS /prop_sf/AUTORCC_OPTIONS - /prop_sf/COMPILE_DEFINITIONS_CONFIG /prop_sf/COMPILE_DEFINITIONS /prop_sf/COMPILE_FLAGS /prop_sf/EXTERNAL_OBJECT @@ -317,3 +312,32 @@ Properties on Installed Files /prop_inst/CPACK_NEVER_OVERWRITE.rst /prop_inst/CPACK_PERMANENT.rst + + +Deprecated Properties on Directories +===================================== + +.. toctree:: + :maxdepth: 1 + + /prop_dir/COMPILE_DEFINITIONS_CONFIG + + +Deprecated Properties on Targets +================================ + +.. toctree:: + :maxdepth: 1 + + /prop_tgt/COMPILE_DEFINITIONS_CONFIG + /prop_tgt/POST_INSTALL_SCRIPT + /prop_tgt/PRE_INSTALL_SCRIPT + + +Deprecated Properties on Source Files +===================================== + +.. toctree:: + :maxdepth: 1 + + /prop_sf/COMPILE_DEFINITIONS_CONFIG diff --git a/Help/module/CPackIFW.rst b/Help/module/CPackIFW.rst new file mode 100644 index 0000000..ea05796 --- /dev/null +++ b/Help/module/CPackIFW.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CPackIFW.cmake diff --git a/Help/prop_dir/COMPILE_DEFINITIONS_CONFIG.rst b/Help/prop_dir/COMPILE_DEFINITIONS_CONFIG.rst index c22606b..a6af45f 100644 --- a/Help/prop_dir/COMPILE_DEFINITIONS_CONFIG.rst +++ b/Help/prop_dir/COMPILE_DEFINITIONS_CONFIG.rst @@ -1,6 +1,8 @@ COMPILE_DEFINITIONS_<CONFIG> ---------------------------- +Ignored. See CMake Policy :policy:`CMP0043`. + Per-configuration preprocessor definitions in a directory. This is the configuration-specific version of :prop_dir:`COMPILE_DEFINITIONS` diff --git a/Help/prop_sf/COMPILE_DEFINITIONS_CONFIG.rst b/Help/prop_sf/COMPILE_DEFINITIONS_CONFIG.rst index e695f38..8487076 100644 --- a/Help/prop_sf/COMPILE_DEFINITIONS_CONFIG.rst +++ b/Help/prop_sf/COMPILE_DEFINITIONS_CONFIG.rst @@ -1,6 +1,8 @@ COMPILE_DEFINITIONS_<CONFIG> ---------------------------- +Ignored. See CMake Policy :policy:`CMP0043`. + Per-configuration preprocessor definitions on a source file. This is the configuration-specific version of COMPILE_DEFINITIONS. diff --git a/Help/prop_tgt/COMPILE_DEFINITIONS_CONFIG.rst b/Help/prop_tgt/COMPILE_DEFINITIONS_CONFIG.rst index e359d2c..84bd5e4 100644 --- a/Help/prop_tgt/COMPILE_DEFINITIONS_CONFIG.rst +++ b/Help/prop_tgt/COMPILE_DEFINITIONS_CONFIG.rst @@ -1,6 +1,8 @@ COMPILE_DEFINITIONS_<CONFIG> ---------------------------- +Ignored. See CMake Policy :policy:`CMP0043`. + Per-configuration preprocessor definitions on a target. This is the configuration-specific version of :prop_tgt:`COMPILE_DEFINITIONS` diff --git a/Help/release/dev/cpack-ifw-generator.rst b/Help/release/dev/cpack-ifw-generator.rst new file mode 100644 index 0000000..f667136 --- /dev/null +++ b/Help/release/dev/cpack-ifw-generator.rst @@ -0,0 +1,5 @@ +cpack-ifw-generator +------------------- + +* :manual:`cpack(1)` gained an ``IFW`` generator to package using + Qt Framework Installer tools. See the :module:`CPackIFW` module. diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake index cd0f8b8..0ab3af6 100644 --- a/Modules/CMakeDetermineCompiler.cmake +++ b/Modules/CMakeDetermineCompiler.cmake @@ -65,7 +65,7 @@ macro(_cmake_find_compiler lang) endif() find_program(CMAKE_${lang}_COMPILER NAMES ${CMAKE_${lang}_COMPILER_LIST} DOC "${lang} compiler") if(CMAKE_${lang}_COMPILER_INIT AND NOT CMAKE_${lang}_COMPILER) - set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER_INIT}" CACHE FILEPATH "${lang} compiler" FORCE) + set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${CMAKE_${lang}_COMPILER_INIT}") endif() unset(_${lang}_COMPILER_HINTS) unset(_languages) diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 89547af..b58f944 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -435,6 +435,7 @@ if(NOT CPACK_GENERATOR) option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF) option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF) endif() + option(CPACK_BINARY_IFW "Enable to build IFW packages" OFF) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_BUNDLE Bundle) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_DRAGNDROP DragNDrop) @@ -450,6 +451,7 @@ if(NOT CPACK_GENERATOR) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_TZ TZ) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_WIX WIX) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_ZIP ZIP) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_IFW IFW) endif() diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake index 1433d9e..5524a3f 100644 --- a/Modules/CPackComponent.cmake +++ b/Modules/CPackComponent.cmake @@ -458,6 +458,9 @@ macro(cpack_add_component_group grpname) cpack_append_string_variable_set_command( CPACK_COMPONENT_GROUP_${CPACK_ADDGRP_UNAME}_DESCRIPTION CPACK_ADDGRP_STR) + cpack_append_string_variable_set_command( + CPACK_COMPONENT_GROUP_${CPACK_ADDGRP_UNAME}_PARENT_GROUP + CPACK_ADDGRP_STR) cpack_append_option_set_command( CPACK_COMPONENT_GROUP_${CPACK_ADDGRP_UNAME}_EXPANDED CPACK_ADDGRP_STR) diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake new file mode 100644 index 0000000..f99488a --- /dev/null +++ b/Modules/CPackIFW.cmake @@ -0,0 +1,384 @@ +#.rst: +# CPackIFW +# -------- +# +# .. _QtIFW: http://qt-project.org/doc/qtinstallerframework/index.html +# +# This module looks for the location of the command line utilities supplied with +# the Qt Installer Framework (QtIFW_). +# +# The module also defines several commands to control the behavior of the +# CPack ``IFW`` generator. +# +# +# Overview +# ^^^^^^^^ +# +# CPack ``IFW`` generator helps you create online and offline +# binary cross-platform installers with a graphical user interface. +# +# CPack IFW generator prepare project installation and generate configuration +# and meta information for QtIFW_ tools. +# +# The QtIFW_ provides a set of tools and utilities to create +# installers for the supported desktop Qt platforms: Linux, Microsoft Windows, +# and Mac OS X. +# +# To use CPack ``IFW`` generator you must also install QtIFW_. +# +# Variables +# ^^^^^^^^^ +# +# Variables that Change Behavior +# """""""""""""""""""""""""""""" +# +# .. variable:: CPACK_IFW_TARGET_DIRECTORY +# +# Default target directory for installation. +# By default used "@ApplicationsDir@/:variable:`CPACK_PACKAGE_INSTALL_DIRECTORY`" +# +# You can use predefined variables. +# +# .. variable:: CPACK_IFW_ADMIN_TARGET_DIRECTORY +# +# Default target directory for installation with administrator rights. +# +# You can use predefined variables. +# +# .. variable:: CPACK_IFW_RESOLVE_DUPLICATE_NAMES +# +# Resolve duplicate names when installing components with groups. +# +# .. variable:: CPACK_IFW_PACKAGES_DIRECTORIES +# +# Additional prepared packages dirs that will be used to resolve +# dependent components. +# +# Advanced Variables +# """""""""""""""""" +# +# .. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE +# +# The path to "binarycreator" command line client. +# +# This variable is cached and can be configured user if need. +# +# .. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND +# +# True if the "binarycreator" command line client was found. +# +# .. variable:: CPACK_IFW_REPOGEN_EXECUTABLE +# +# The path to "repogen" command line client. +# +# This variable is cached and can be configured user if need. +# +# .. variable:: CPACK_IFW_REPOGEN_EXECUTABLE_FOUND +# +# True if the "repogen" command line client was found. +# +# Commands +# ^^^^^^^^^ +# +# The module defines the following commands: +# +# -------------------------------------------------------------------------- +# +# .. command:: cpack_ifw_configure_component +# +# Sets the arguments specific to the CPack IFW generator. +# +# :: +# +# cpack_ifw_configure_component(<compname> +# [VERSION <version>] +# [SCRIPT <script>] +# [NAME <name>] +# [PRIORITY <priority>] +# [LICENSES <display_name> <file_path> ...]) +# +# This command should be called after cpack_add_component command. +# +# ``VERSION`` is version of component. By default used :variable:`CPACK_PACKAGE_VERSION`. +# +# ``SCRIPT`` is relative or absolute path to operations script +# for this component. +# +# ``NAME`` is used to create domain-like identification for this component. +# By default used origin component name. +# +# ``PRIORITY`` is priority of the component in the tree. +# +# ``LICENSES`` pair of <display_name> and <file_path> of license text for this +# component. You can specify more then one license. +# +# -------------------------------------------------------------------------- +# +# .. command:: cpack_ifw_configure_component_group +# +# Sets the arguments specific to the CPack IFW generator. +# +# :: +# +# cpack_ifw_configure_component_group(<grpname> +# [VERSION <version>] +# [NAME <name>] +# [PRIORITY <priority>] +# [LICENSES <display_name> <file_path> ...]) +# +# This command should be called after cpack_add_component_group command. +# +# ``VERSION`` is version of component group. By default used :variable:`CPACK_PACKAGE_VERSION`. +# +# ``NAME`` is used to create domain-like identification for this component group. +# By default used origin component group name. +# +# ``PRIORITY`` is priority of the component group in the tree. +# +# ``LICENSES`` pair of <display_name> and <file_path> of license text for this +# component group. You can specify more then one license. +# +# Example usage +# ^^^^^^^^^^^^^ +# +# .. code-block:: cmake +# +# set(CPACK_PACKAGE_NAME "MyPackage") +# set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyPackage Installation Example") +# set(CPACK_PACKAGE_VERSION "1.0.0") +# +# include(CPack) +# include(CPackIFW) +# +# cpack_add_component(myapp +# DISPLAY_NAME "MyApp" +# DESCRIPTION "My Application") +# cpack_ifw_configure_component(myapp +# VERSION "1.2.3" +# SCRIPT "operations.qs") +# +# +# Online installer +# ^^^^^^^^^^^^^^^^ +# +# By defaul CPack IFW generator make offline installer. This means that all +# components will be packaged into a binary file. +# +# To make a component downloaded, you must set the ``DOWNLOADED`` option in +# :command:`cpack_add_component`. +# +# Then you would use the command :command:`cpack_configure_downloads`. +# If you set ``ALL`` option all components will be downloaded. +# +# CPack IFW generator create "repository" dir in current binary dir. You +# would copy content of this dir to specified ``site``. +# +# See Also +# ^^^^^^^^ +# +# Qt Installer Framework Manual: +# +# Index page +# http://qt-project.org/doc/qtinstallerframework/index.html +# +# Component Scripting +# http://qt-project.org/doc/qtinstallerframework/scripting.html +# +# Predefined Variables +# http://qt-project.org/doc/qtinstallerframework/scripting.html#predefined-variables +# +# Download Qt Installer Framework for you platform from Qt Project site: +# http://download.qt-project.org/official_releases/qt-installer-framework/ +# + +#============================================================================= +# Copyright 2014 Kitware, Inc. +# Copyright 2014 Konstantin Podsvirov <konstantin@podsvirov.pro> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +#============================================================================= +# Search Qt Installer Framework tools +#============================================================================= + +# Default path + +if(WIN32) + set(_CPACK_IFW_PATHS + "$ENV{HOMEDRIVE}/Qt" + "C:/Qt" + ) +else() + set(_CPACK_IFW_PATHS + "$ENV{HOME}/Qt" + "/opt/Qt" + ) +endif() + +set(_CPACK_IFW_SUFFIXES + "QtIFW-1.7.0/bin" + "QtIFW-1.6.0/bin" + "QtIFW-1.5.0/bin" + "QtIFW-1.4.0/bin" + "QtIFW-1.3.0/bin" +) + +# Look for 'binarycreator' + +if(NOT CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND) + +find_program(CPACK_IFW_BINARYCREATOR_EXECUTABLE + NAMES binarycreator + PATHS ${_CPACK_IFW_PATHS} + PATH_SUFFIXES ${_CPACK_IFW_SUFFIXES} + DOC "QtIFW binarycreator command line client" + ) +mark_as_advanced(CPACK_IFW_BINARYCREATOR_EXECUTABLE) + +if(EXISTS ${CPACK_IFW_BINARYCREATOR_EXECUTABLE}) + set(CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND 1) +endif() + +endif() # NOT CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND + +# Look for 'repogen' + +if(NOT CPACK_IFW_REPOGEN_EXECUTABLE_FOUND) + +find_program(CPACK_IFW_REPOGEN_EXECUTABLE + NAMES repogen + PATHS ${_CPACK_IFW_PATHS} + PATH_SUFFIXES ${_CPACK_IFW_SUFFIXES} + DOC "QtIFW repogen command line client" + ) +mark_as_advanced(CPACK_IFW_REPOGEN_EXECUTABLE) + +if(EXISTS ${CPACK_IFW_REPOGEN_EXECUTABLE}) + set(CPACK_IFW_REPOGEN_EXECUTABLE_FOUND 1) +endif() + +endif() # NOT CPACK_IFW_REPOGEN_EXECUTABLE_FOUND + +# +## Next code is included only once +# + +if(NOT CPackIFW_CMake_INCLUDED) +set(CPackIFW_CMake_INCLUDED 1) + +#============================================================================= +# Macro definition +#============================================================================= + +# Macro definition based on CPackComponent + +if(NOT CPackComponent_CMake_INCLUDED) + include(CPackComponent) +endif() + +if(NOT __CMAKE_PARSE_ARGUMENTS_INCLUDED) + include(CMakeParseArguments) +endif() + +# Resolve full path to lisense file +macro(_cpack_ifw_resolve_lisenses _variable) + if(${_variable}) + set(_ifw_license_file FALSE) + set(_ifw_licenses_fix) + foreach(_ifw_licenses_arg ${${_variable}}) + if(_ifw_license_file) + get_filename_component(_ifw_licenses_arg "${_ifw_licenses_arg}" ABSOLUTE) + set(_ifw_license_file FALSE) + else() + set(_ifw_license_file TRUE) + endif() + list(APPEND _ifw_licenses_fix "${_ifw_licenses_arg}") + endforeach(_ifw_licenses_arg) + set(${_variable} "${_ifw_licenses_fix}") + endif() +endmacro() + +# Macro for configure component +macro(cpack_ifw_configure_component compname) + + string(TOUPPER ${compname} _CPACK_IFWCOMP_UNAME) + + set(_IFW_OPT) + set(_IFW_ARGS VERSION SCRIPT NAME PRIORITY) + set(_IFW_MULTI_ARGS DEPENDS LICENSES) + cmake_parse_arguments(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN}) + + # Resolve full filename for script file + set(_IFW_SCRIPT_MACRO CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_SCRIPT) + set(_IFW_SCRIPT_FILE ${${_IFW_SCRIPT_MACRO}}) + if(DEFINED ${_IFW_SCRIPT_MACRO}) + get_filename_component(${_IFW_SCRIPT_MACRO} ${_IFW_SCRIPT_FILE} ABSOLUTE) + set(_IFW_SCRIPT_FILE ${${_IFW_SCRIPT_MACRO}}) + if(NOT EXISTS ${_IFW_SCRIPT_FILE}) + message(WARNING "CPack IFW: script file \"${_IFW_SCRIPT_FILE}\" for component \"${compname}\" is not exists" ) + set(${_IFW_SCRIPT_MACRO}) + endif() + endif() + + _cpack_ifw_resolve_lisenses(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_LICENSES) + + set(_CPACK_IFWCOMP_STR "\n# Configuration for IFW component \"${compname}\"\n") + + foreach(_IFW_ARG_NAME ${_IFW_ARGS}) + cpack_append_string_variable_set_command( + CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_${_IFW_ARG_NAME} + _CPACK_IFWCOMP_STR) + endforeach() + + foreach(_IFW_ARG_NAME ${_IFW_MULTI_ARGS}) + cpack_append_variable_set_command( + CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_${_IFW_ARG_NAME} + _CPACK_IFWCOMP_STR) + endforeach() + + if(CPack_CMake_INCLUDED) + file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}" "${_CPACK_IFWCOMP_STR}") + endif() + +endmacro() + +# Macro for configure group +macro(cpack_ifw_configure_component_group grpname) + + string(TOUPPER ${grpname} _CPACK_IFWGRP_UNAME) + + set(_IFW_OPT) + set(_IFW_ARGS VERSION NAME PRIORITY) + set(_IFW_MULTI_ARGS LICENSES) + cmake_parse_arguments(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN}) + + _cpack_ifw_resolve_lisenses(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_LICENSES) + + set(_CPACK_IFWGRP_STR "\n# Configuration for IFW component group \"${grpname}\"\n") + + foreach(_IFW_ARG_NAME ${_IFW_ARGS}) + cpack_append_string_variable_set_command( + CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_${_IFW_ARG_NAME} + _CPACK_IFWGRP_STR) + endforeach() + + foreach(_IFW_ARG_NAME ${_IFW_MULTI_ARGS}) + cpack_append_variable_set_command( + CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_${_IFW_ARG_NAME} + _CPACK_IFWGRP_STR) + endforeach() + + if(CPack_CMake_INCLUDED) + file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}" "${_CPACK_IFWGRP_STR}") + endif() +endmacro() + +endif() # NOT CPackIFW_CMake_INCLUDED diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake index f6c8b3a..65458b7 100644 --- a/Modules/FindImageMagick.cmake +++ b/Modules/FindImageMagick.cmake @@ -115,7 +115,19 @@ function(FIND_IMAGEMAGICK_API component header) "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include" PATH_SUFFIXES ImageMagick ImageMagick-6 - DOC "Path to the ImageMagick include dir." + DOC "Path to the ImageMagick arch-independent include dir." + ) + find_path(ImageMagick_${component}_ARCH_INCLUDE_DIR + NAMES magick/magick-baseconfig.h + HINTS + ${PC_${component}_INCLUDEDIR} + ${PC_${component}_INCLUDE_DIRS} + PATHS + ${ImageMagick_INCLUDE_DIRS} + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include" + PATH_SUFFIXES + ImageMagick ImageMagick-6 + DOC "Path to the ImageMagick arch-specific include dir." ) find_library(ImageMagick_${component}_LIBRARY NAMES ${ARGN} @@ -127,12 +139,24 @@ function(FIND_IMAGEMAGICK_API component header) DOC "Path to the ImageMagick Magick++ library." ) + # old version have only indep dir if(ImageMagick_${component}_INCLUDE_DIR AND ImageMagick_${component}_LIBRARY) set(ImageMagick_${component}_FOUND TRUE PARENT_SCOPE) - list(APPEND ImageMagick_INCLUDE_DIRS + # Construct per-component include directories. + set(ImageMagick_${component}_INCLUDE_DIRS ${ImageMagick_${component}_INCLUDE_DIR} ) + if(ImageMagick_${component}_ARCH_INCLUDE_DIR) + list(APPEND ImageMagick_${component}_INCLUDE_DIRS + ${ImageMagick_${component}_ARCH_INCLUDE_DIR}) + endif() + list(REMOVE_DUPLICATES ImageMagick_${component}_INCLUDE_DIRS) + set(ImageMagick_${component}_INCLUDE_DIRS + ${ImageMagick_${component}_INCLUDE_DIRS} PARENT_SCOPE) + + # Add the per-component include directories to the full include dirs. + list(APPEND ImageMagick_INCLUDE_DIRS ${ImageMagick_${component}_INCLUDE_DIRS}) list(REMOVE_DUPLICATES ImageMagick_INCLUDE_DIRS) set(ImageMagick_INCLUDE_DIRS ${ImageMagick_INCLUDE_DIRS} PARENT_SCOPE) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 3838cb0..c394946 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -577,6 +577,7 @@ set(CPACK_SRCS CPack/cmCPackGenerator.cxx CPack/cmCPackLog.cxx CPack/cmCPackNSISGenerator.cxx + CPack/cmCPackIFWGenerator.cxx CPack/cmCPackSTGZGenerator.cxx CPack/cmCPackTGZGenerator.cxx CPack/cmCPackTarBZip2Generator.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c034126..94f9919 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 0) -set(CMake_VERSION_PATCH 20140721) +set(CMake_VERSION_PATCH 20140729) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 9faf2b0..788e785 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -19,6 +19,7 @@ #include "cmCPackZIPGenerator.h" #include "cmCPackSTGZGenerator.h" #include "cmCPackNSISGenerator.h" +#include "cmCPackIFWGenerator.h" #ifdef __APPLE__ # include "cmCPackDragNDropGenerator.h" @@ -68,6 +69,11 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("NSIS64", "Null Soft Installer (64-bit)", cmCPackNSISGenerator::CreateGenerator64); } + if (cmCPackIFWGenerator::CanGenerate()) + { + this->RegisterGenerator("IFW", "Qt Installer Framework", + cmCPackIFWGenerator::CreateGenerator); + } #ifdef __CYGWIN__ if (cmCPackCygwinBinaryGenerator::CanGenerate()) { diff --git a/Source/CPack/cmCPackIFWGenerator.cxx b/Source/CPack/cmCPackIFWGenerator.cxx new file mode 100644 index 0000000..51c0f2e --- /dev/null +++ b/Source/CPack/cmCPackIFWGenerator.cxx @@ -0,0 +1,849 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmCPackIFWGenerator.h" + +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmSystemTools.h" +#include "cmMakefile.h" +#include "cmGeneratedFileStream.h" +#include "cmCPackLog.h" +#include "cmCPackComponentGroup.h" +#include "cmTimestamp.h" + +#include <cmsys/SystemTools.hxx> +#include <cmsys/Glob.hxx> +#include <cmsys/Directory.hxx> +#include <cmsys/RegularExpression.hxx> +#include <cmXMLSafe.h> + +//---------------------------------------------------------------------- +cmCPackIFWGenerator::cmCPackIFWGenerator() +{ +} + +//---------------------------------------------------------------------- +cmCPackIFWGenerator::~cmCPackIFWGenerator() +{ +} + +//---------------------------------------------------------------------- +int cmCPackIFWGenerator::PackageFiles() +{ + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl); + + if (!IfwCreateConfigFile()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPack error: Could not create IFW \"config.xml\" file." + << std::endl); + return false; + } + + if (Components.empty() && !IfwCreatePackageFile()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPack error: Could not create IFW " + "\"root/meta/package.xml\" file." + << std::endl); + return false; + } + + std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + std::string ifwTmpFile = ifwTLD; + ifwTmpFile += "/IFWOutput.log"; + + std::set<std::string> ifwDependsComponents; + std::string ifwBinaryComponents; + std::string ifwDownloadedComponents; + + // Create groups meta information + std::map<std::string, cmCPackComponentGroup>::iterator groupIt; + for(groupIt = this->ComponentGroups.begin(); + groupIt != this->ComponentGroups.end(); + ++groupIt + ) + { + std::string macroPrefix = "CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(groupIt->second.Name); + + std::string groupId = IfwGetGroupId(&groupIt->second); + + if(!ifwBinaryComponents.empty()) ifwBinaryComponents += ","; + ifwBinaryComponents += groupId; + + std::string pkgMetaDir = this->toplevel + "/packages/" + + groupId + + "/meta"; + + std::string pkgXmlFileName = pkgMetaDir + + "/package.xml"; + + cmGeneratedFileStream pkgXml(pkgXmlFileName.data()); + pkgXml << "<?xml version=\"1.0\"?>" << std::endl; + pkgXml << "<Package>" << std::endl; + pkgXml << " <DisplayName>" << groupIt->second.DisplayName + << "</DisplayName>" << std::endl; + pkgXml << " <Description>" << groupIt->second.Description + << "</Description>" << std::endl; + pkgXml << " <Name>" << groupId << "</Name>" << std::endl; + + // Version + const char* ifwPackageVersion = this->GetOption("CPACK_PACKAGE_VERSION"); + const char* ifwGroupVersion = this->GetOption(macroPrefix + "_VERSION"); + pkgXml << " <Version>" + << (ifwGroupVersion ? ifwGroupVersion : ifwPackageVersion) + << "</Version>" << std::endl; + pkgXml << " <ReleaseDate>" << IfwCreateCurrentDate() + << "</ReleaseDate>" << std::endl; + + // Licenses + std::vector<std::string> licenses; + if(IfwParseLicenses(licenses, macroPrefix + "_LICENSES", pkgMetaDir)) + { + pkgXml << " <Licenses>" << std::endl; + for(size_t i = 0; i < licenses.size(); i += 2) + { + pkgXml << " <License " + << "name=\"" << licenses[i] << "\" " + << "file=\"" << licenses[i + 1] << "\" " + << "/>" <<std::endl; + } + pkgXml << " </Licenses>" << std::endl; + } + + // Priority + if(const char* ifwGroupPriority = + this->GetOption(macroPrefix + "_PRIORITY")) + { + pkgXml << " <SortingPriority>" << ifwGroupPriority + << "</SortingPriority>" << std::endl; + } + pkgXml << "</Package>" << std::endl; + } + + // Create components meta information + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt = this->Components.begin(); + compIt != this->Components.end(); + ++compIt) + { + // Component id + std::string ifwCompId = IfwGetComponentId(&compIt->second); + + std::string pkgMetaDir = this->toplevel + "/" + + GetComponentInstallDirNamePrefix(compIt->second.Name) + + ifwCompId + "/meta"; + std::string pkgXmlFileName = pkgMetaDir + "/package.xml"; + cmGeneratedFileStream pkgXml(pkgXmlFileName.data()); + + // Check IFW version for component + std::string macroPrefix = "CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(compIt->second.Name); + + pkgXml << "<?xml version=\"1.0\"?>" << std::endl; + pkgXml << "<Package>" << std::endl; + pkgXml << " <DisplayName>" << compIt->second.DisplayName + << "</DisplayName>" << std::endl; + pkgXml << " <Description>" << compIt->second.Description + << "</Description>" << std::endl; + pkgXml << " <Name>" << ifwCompId << "</Name>" << std::endl; + + // Version + const char* ifwPackageVersion = this->GetOption("CPACK_PACKAGE_VERSION"); + const char* ifwCompVersion = + this->GetOption(macroPrefix + "_VERSION"); + pkgXml << " <Version>" + << (ifwCompVersion ? ifwCompVersion : ifwPackageVersion) + << "</Version>" << std::endl; + + pkgXml << " <ReleaseDate>" << IfwCreateCurrentDate() + << "</ReleaseDate>" << std::endl; + + // Script + const char* ifwCompScript = + this->GetOption(macroPrefix + "_SCRIPT"); + if (ifwCompScript) + { + // Copy file + std::string ifwCompScriptFile = pkgMetaDir + "/operations.qs"; + cmsys::SystemTools::CopyFileIfDifferent(ifwCompScript, + ifwCompScriptFile.data()); + pkgXml << " <Script>" << "operations.qs" << "</Script>" << std::endl; + } + + // Check dependencies + std::set<std::string> compDepSet; + // CMake dependencies + if (!compIt->second.Dependencies.empty()) + { + std::vector<cmCPackComponent *>::iterator depCompIt; + for(depCompIt = compIt->second.Dependencies.begin(); + depCompIt != compIt->second.Dependencies.end(); + ++depCompIt) + { + compDepSet.insert(IfwGetComponentId(*depCompIt)); + } + } + // QtIFW dependencies + if(const char *ifwCompDepsStr = this->GetOption(macroPrefix + "_DEPENDS")) + { + std::vector<std::string> ifwCompDepsVector; + cmSystemTools::ExpandListArgument(ifwCompDepsStr, + ifwCompDepsVector); + for(std::vector<std::string>::iterator + depCompIt = ifwCompDepsVector.begin(); + depCompIt != ifwCompDepsVector.end(); ++depCompIt) + { + compDepSet.insert(*depCompIt); + ifwDependsComponents.insert(*depCompIt); + } + } + + // Write dependencies + if (!compDepSet.empty()) + { + pkgXml << " <Dependencies>"; + std::set<std::string>::iterator it = compDepSet.begin(); + pkgXml << *it; + ++it; + while(it != compDepSet.end()) + { + pkgXml << "," << *it; + ++it; + } + pkgXml << "</Dependencies>" << std::endl; + } + + // Licenses + std::vector<std::string> licenses; + if(IfwParseLicenses(licenses, macroPrefix + "_LICENSES", pkgMetaDir)) + { + pkgXml << " <Licenses>" << std::endl; + for(size_t i = 0; i < licenses.size(); i += 2) + { + pkgXml << " <License " + << "name=\"" << licenses[i] << "\" " + << "file=\"" << licenses[i + 1] << "\" " + << "/>" <<std::endl; + } + pkgXml << " </Licenses>" << std::endl; + } + + // TODO: Check how enable virtual component (now it's allways disabled) + if (compIt->second.IsRequired) { + pkgXml << " <ForcedInstallation>true</ForcedInstallation>" + << std::endl; + } else if (compIt->second.IsDisabledByDefault) { + pkgXml << " <Default>false</Default>" << std::endl; + } else if (compIt->second.IsHidden) { + pkgXml << " <Virtual>true</Virtual>" << std::endl; + } else { + pkgXml << " <Default>true</Default>" << std::endl; + } + + // Priority + if(const char* ifwCompPriority = + this->GetOption(macroPrefix + "_PRIORITY")) + { + pkgXml << " <SortingPriority>" << ifwCompPriority + << "</SortingPriority>" << std::endl; + } + + pkgXml << "</Package>" << std::endl; + + // Downloaded + if (compIt->second.IsDownloaded) + { + if (!ifwDownloadedComponents.empty()) ifwDownloadedComponents += ","; + ifwDownloadedComponents += ifwCompId; + } + else + { + if (!ifwBinaryComponents.empty()) ifwBinaryComponents += ","; + ifwBinaryComponents += ifwCompId; + } + } + + // Run repogen + if (!ifwDownloadSite.empty()) + { + std::string ifwCmd = ifwRepoGen; + ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + ifwCmd += " -p " + this->toplevel + "/packages"; + + if(!ifwPkgsDirsVector.empty()) + { + for(std::vector<std::string>::iterator it = ifwPkgsDirsVector.begin(); + it != ifwPkgsDirsVector.end(); ++it) + { + ifwCmd += " -p " + *it; + } + } + + if (!ifwOnlineOnly && !ifwDownloadedComponents.empty()) { + ifwCmd += " -i " + ifwDownloadedComponents; + } + ifwCmd += " " + this->toplevel + "/repository"; + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd + << std::endl); + std::string output; + int retVal = 1; + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "- Generate repository" << std::endl); + bool res = cmSystemTools::RunSingleCommand( + ifwCmd.c_str(), &output, &retVal, 0, this->GeneratorVerbose, 0); + if ( !res || retVal ) + { + cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + ofs << "# Run command: " << ifwCmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); + return 0; + } + } + + // Run binary creator + { + std::string ifwCmd = ifwBinCreator; + ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + ifwCmd += " -p " + this->toplevel + "/packages"; + + if(!ifwPkgsDirsVector.empty()) + { + for(std::vector<std::string>::iterator it = ifwPkgsDirsVector.begin(); + it != ifwPkgsDirsVector.end(); ++it) + { + ifwCmd += " -p " + *it; + } + } + + if (ifwOnlineOnly) + { + ifwCmd += " --online-only"; + } + else if (!ifwDownloadedComponents.empty() && !ifwDownloadSite.empty()) + { + ifwCmd += " -e " + ifwDownloadedComponents; + } + else if (!ifwDependsComponents.empty()) + { + ifwCmd += " -i "; + std::set<std::string>::iterator it = ifwDependsComponents.begin(); + ifwCmd += *it; + ++it; + while(it != ifwDependsComponents.end()) + { + ifwCmd += "," + (*it); + ++it; + } + + ifwCmd += "," + ifwBinaryComponents; + } + // TODO: set correct name for multipackages + if (this->packageFileNames.size() > 0) + { + ifwCmd += " " + packageFileNames[0]; + } + else + { + ifwCmd += " installer"; + } + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd + << std::endl); + std::string output; + int retVal = 1; + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl); + bool res = cmSystemTools::RunSingleCommand( + ifwCmd.c_str(), &output, &retVal, 0, this->GeneratorVerbose, 0); + if ( !res || retVal ) + { + cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + ofs << "# Run command: " << ifwCmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------- +const char *cmCPackIFWGenerator::GetPackagingInstallPrefix() +{ + const char *defPrefix = cmCPackGenerator::GetPackagingInstallPrefix(); + + std::string tmpPref = defPrefix ? defPrefix : ""; + + if(this->Components.empty()) + { + tmpPref += "packages/root/data"; + } + + this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str()); + + return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX"); +} + +//---------------------------------------------------------------------- +const char *cmCPackIFWGenerator::GetOutputExtension() +{ + const char *suffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX"); + return suffix ? suffix : ""; +} + +//---------------------------------------------------------------------- +std::string cmCPackIFWGenerator::IfwGetGroupId(cmCPackComponentGroup *group) +{ + std::string ifwGroupId; + std::string ifwGroupName; + std::list<cmCPackComponentGroup*> groups; + while(group) + { + groups.push_front(group); + group = group->ParentGroup; + } + std::list<cmCPackComponentGroup*>::iterator it = groups.begin(); + if(it != groups.end()) + { + ifwGroupId = IfwGetGroupName(*it); + ++it; + } + while(it != groups.end()) + { + ifwGroupName = IfwGetGroupName(*it); + + if(ifwResolveDuplicateNames) + { + if(ifwGroupName.substr(0, ifwGroupId.size()) == ifwGroupId) + { + ifwGroupId = ifwGroupName; + ++it; + continue; + } + } + + ifwGroupId += "." + ifwGroupName; + + ++it; + } + + return ifwGroupId; +} + +//---------------------------------------------------------------------- +std::string cmCPackIFWGenerator::IfwGetComponentId(cmCPackComponent *component) +{ + std::string ifwCompId; + if(component) { + ifwCompId = IfwGetGroupId(component->Group); + if(!ifwCompId.empty()) ifwCompId += "."; + std::string ifwCompName = IfwGetComponentName(component); + if(ifwResolveDuplicateNames && + (ifwCompName.substr(0, ifwCompId.size()) == ifwCompId)) + { + ifwCompId = ifwCompName; + } + else + { + ifwCompId += ifwCompName; + } + } + return ifwCompId; +} + +//---------------------------------------------------------------------- +std::string cmCPackIFWGenerator::IfwGetGroupName(cmCPackComponentGroup *group) +{ + std::string ifwGroupName = group->Name; + if(const char* name = + this->GetOption("CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(group->Name) + "_NAME")) + { + ifwGroupName = name; + } + return ifwGroupName; +} + +//---------------------------------------------------------------------- +std::string +cmCPackIFWGenerator::IfwGetComponentName(cmCPackComponent *component) +{ + return IfwGetComponentName(component->Name); +} + +//---------------------------------------------------------------------- +std::string +cmCPackIFWGenerator::IfwGetComponentName(const std::string &componentName) +{ + std::string ifwCompName = componentName; + if(const char* name = + this->GetOption("CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(componentName) + "_NAME")) + { + ifwCompName = name; + } + return ifwCompName; +} + +//---------------------------------------------------------------------- +int cmCPackIFWGenerator::InitializeInternal() +{ + // Search Qt Installer Framework tools + + if(!this->IsOn("CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND") || + !this->IsOn("CPACK_IFW_REPOGEN_EXECUTABLE_FOUND")) + { + this->ReadListFile("CPackIFW.cmake"); + } + + // Look 'binarycreator' executable (needs) + + if(this->IsOn("CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND")) + { + const char *ifwBinCreatorStr = + this->GetOption("CPACK_IFW_BINARYCREATOR_EXECUTABLE"); + ifwBinCreator = ifwBinCreatorStr ? ifwBinCreatorStr : ""; + } + else + { + ifwBinCreator = ""; + } + + if (ifwBinCreator.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find QtIFW compiler \"binarycreator\": " + "likely it is not installed, or not in your PATH" + << std::endl); + return 0; + } + + // Look 'repogen' executable (optional) + + if(this->IsOn("CPACK_IFW_REPOGEN_EXECUTABLE_FOUND")) + { + const char *ifwRepoGenStr = + this->GetOption("CPACK_IFW_REPOGEN_EXECUTABLE"); + ifwRepoGen = ifwRepoGenStr ? ifwRepoGenStr : ""; + } + else + { + ifwRepoGen = ""; + } + + // // Variables that Change Behavior + + // Resolve duplicate names + ifwResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES"); + + // Additional packages dirs + ifwPkgsDirsVector.clear(); + if(const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) + { + cmSystemTools::ExpandListArgument(dirs, + ifwPkgsDirsVector); + } + + // Remote repository + + if (const char *site = this->GetOption("CPACK_DOWNLOAD_SITE")) + { + ifwDownloadSite = site; + } + + ifwOnlineOnly = this->IsOn("CPACK_DOWNLOAD_ALL") ? true : false; + + if (!ifwDownloadSite.empty() && ifwRepoGen.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find QtIFW repository generator \"repogen\": " + "likely it is not installed, or not in your PATH" + << std::endl); + return 0; + } + + return this->Superclass::InitializeInternal(); +} + +//---------------------------------------------------------------------- +std::string +cmCPackIFWGenerator::GetComponentInstallDirNamePrefix( + const std::string& /*componentName*/) +{ + return "packages/"; +} + +//---------------------------------------------------------------------- +std::string +cmCPackIFWGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + std::map<std::string, cmCPackComponent>::iterator + compIt = this->Components.find(componentName); + + cmCPackComponent *comp = + compIt != this->Components.end() ? &compIt->second : 0; + + const std::string prefix = GetComponentInstallDirNamePrefix(componentName); + const std::string suffix = "/data"; + + if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) { + return prefix + IfwGetComponentId(comp) + suffix; + } + + if (componentPackageMethod == ONE_PACKAGE) { + return std::string(prefix + "ALL_COMPONENTS_IN_ONE" + suffix); + } + + return prefix + IfwGetComponentId(comp) + suffix; +} + +//---------------------------------------------------------------------- +bool cmCPackIFWGenerator::GetListOfSubdirectories( + const char* topdir, std::vector<std::string>& dirs) +{ + cmsys::Directory dir; + dir.Load(topdir); + size_t fileNum; + for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) + { + if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") && + strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),"..")) + { + cmsys_stl::string fullPath = topdir; + fullPath += "/"; + fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); + if(cmsys::SystemTools::FileIsDirectory(fullPath.c_str()) && + !cmsys::SystemTools::FileIsSymlink(fullPath.c_str())) + { + if (!this->GetListOfSubdirectories(fullPath.c_str(), dirs)) + { + return false; + } + } + } + } + dirs.push_back(topdir); + return true; +} + +//---------------------------------------------------------------------- +enum cmCPackGenerator::CPackSetDestdirSupport +cmCPackIFWGenerator::SupportsSetDestdir() const +{ + return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED; +} + +//---------------------------------------------------------------------- +bool cmCPackIFWGenerator::SupportsAbsoluteDestination() const +{ + return false; +} + +//---------------------------------------------------------------------- +bool cmCPackIFWGenerator::SupportsComponentInstallation() const +{ + return true; +} + +//---------------------------------------------------------------------- +int cmCPackIFWGenerator::IfwCreateConfigFile() +{ + cmGeneratedFileStream cfg((this->toplevel + "/config/config.xml").data()); + + std::string ifwPkgName; + if (const char *name = this->GetOption("CPACK_PACKAGE_NAME")) + { + ifwPkgName = name; + } + else + { + ifwPkgName = "Your package"; + } + + std::string ifwPkgDescription; + if (const char *name = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) + { + ifwPkgDescription = name; + } + else + { + ifwPkgDescription = "Your package description"; + } + + std::string ifwPkgVersion; + if (const char *version = this->GetOption("CPACK_PACKAGE_VERSION")) + { + ifwPkgVersion = version; + } + else + { + ifwPkgVersion = "1.0.0"; + } + + const char *ifwPkgInstDir = + this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY"); + const char *ifwTargetDir = + this->GetOption("CPACK_IFW_TARGET_DIRECTORY"); + const char *ifwAdminTargetDir = + this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY"); + + cfg << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl; + cfg << "<Installer>" << std::endl; + cfg << " <Name>" << cmXMLSafe(ifwPkgName).str() << "</Name>" << std::endl; + cfg << " <Version>" << ifwPkgVersion << "</Version>" << std::endl; + cfg << " <Title>" << cmXMLSafe(ifwPkgDescription).str() << "</Title>" + << std::endl; + + // Default target directory for installation + if (ifwTargetDir) + { + cfg << " <TargetDir>" << ifwTargetDir << "</TargetDir>" << std::endl; + } + else if (ifwPkgInstDir) + { + cfg << " <TargetDir>@ApplicationsDir@/" << ifwPkgInstDir + << "</TargetDir>" << std::endl; + } + else + { + cfg << " <TargetDir>@RootDir@/usr/local</TargetDir>" << std::endl; + } + + // Default target directory for installation with administrator rights + if (ifwAdminTargetDir) + { + cfg << " <AdminTargetDir>" << ifwAdminTargetDir + << "</AdminTargetDir>" << std::endl; + } + + if (!ifwDownloadSite.empty()) + { + cfg << " <RemoteRepositories>" << std::endl; + cfg << " <Repository>" << std::endl; + cfg << " <Url>" << ifwDownloadSite << "</Url>" << std::endl; + // These properties can now be set from "cpack_configure_downloads" + // <Enabled>1</Enabled> + // <Username>user</Username> + // <Password>password</Password> + // <DisplayName>Example repository</DisplayName> + cfg << " </Repository>" << std::endl; + cfg << " </RemoteRepositories>" << std::endl; + } + + // CPack IFW default policy + cfg << " <!-- CPack IFW default policy -->" << std::endl; + cfg << " <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>" + << std::endl; + cfg << " <AllowSpaceInPath>true</AllowSpaceInPath>" << std::endl; + + cfg << "</Installer>" << std::endl; + + return 1; +} + +//---------------------------------------------------------------------- +// Create default package file +int cmCPackIFWGenerator::IfwCreatePackageFile() +{ + std::string ifwPkgName; + if (const char *name = this->GetOption("CPACK_PACKAGE_NAME")) + { + ifwPkgName = name; + } + else + { + ifwPkgName = "Your package"; + } + + std::string ifwPkgDescription; + if (const char *name = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) + { + ifwPkgDescription = name; + } + else + { + ifwPkgDescription = "Your package description"; + } + + cmGeneratedFileStream + pkgXml((this->toplevel + "/packages/root/meta/package.xml").data()); + pkgXml << "<?xml version=\"1.0\"?>" << std::endl; + pkgXml << "<Package>" << std::endl; + + pkgXml << " <DisplayName>" << ifwPkgName << "</DisplayName>" << std::endl; + pkgXml << " <Description>" << ifwPkgDescription + << "</Description>" << std::endl; + pkgXml << " <Name>" << "root" << "</Name>" << std::endl; + pkgXml << " <Version>" << this->GetOption("CPACK_PACKAGE_VERSION") + << "</Version>" << std::endl; + pkgXml << " <ReleaseDate>" << IfwCreateCurrentDate() << "</ReleaseDate>" + << std::endl; + + pkgXml << " <ForcedInstallation>true</ForcedInstallation>" << std::endl; + pkgXml << " <Default>true</Default>" << std::endl; + + pkgXml << "</Package>" << std::endl; + + return 1; +} + +//---------------------------------------------------------------------- +std::string cmCPackIFWGenerator::IfwCreateCurrentDate() +{ + cmTimestamp timestamp; + return timestamp.CurrentTime("%Y-%m-%d", false); +} + +//---------------------------------------------------------------------- +bool cmCPackIFWGenerator::IfwParseLicenses(std::vector<std::string> &licenses, + const std::string &variable, + const std::string &metaDir) +{ + if (const char *option = this->GetOption(variable)) + { + if(!licenses.empty()) licenses.clear(); + cmSystemTools::ExpandListArgument( option, licenses ); + } + else + { + return false; + } + + if ( licenses.size() % 2 != 0 ) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, variable + << " should contain pairs of <display_name> and <file_path>." + << std::endl); + return false; + } + + for(size_t i = 1; i < licenses.size(); i += 2) + { + std::string name = cmSystemTools::GetFilenameName(licenses[i]); + std::string path = metaDir + "/" + name; + cmsys::SystemTools::CopyFileIfDifferent(licenses[i].data(), path.data()); + licenses[i] = name; + } + + return licenses.size() > 1; +} diff --git a/Source/CPack/cmCPackIFWGenerator.h b/Source/CPack/cmCPackIFWGenerator.h new file mode 100644 index 0000000..d70e52d --- /dev/null +++ b/Source/CPack/cmCPackIFWGenerator.h @@ -0,0 +1,82 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmCPackIFWGenerator_h +#define cmCPackIFWGenerator_h + + +#include "cmCPackGenerator.h" +#include <set> + +/** \class cmCPackIFWGenerator + * \brief A generator for Qt Installer Framework tools + * + * http://qt-project.org/doc/qtinstallerframework/index.html + */ +class cmCPackIFWGenerator : public cmCPackGenerator +{ +public: + cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator); + + /** + * Construct generator + */ + cmCPackIFWGenerator(); + virtual ~cmCPackIFWGenerator(); + +protected: + virtual int InitializeInternal(); + virtual int PackageFiles(); + virtual const char* GetPackagingInstallPrefix(); + + virtual const char* GetOutputExtension(); + + std::string IfwGetGroupId(cmCPackComponentGroup *group); + std::string IfwGetComponentId(cmCPackComponent *component); + + std::string IfwGetGroupName(cmCPackComponentGroup *group); + + std::string IfwGetComponentName(cmCPackComponent *component); + std::string IfwGetComponentName(const std::string &componentName); + + virtual std::string GetComponentInstallDirNamePrefix( + const std::string& componentName); + + virtual std::string GetComponentInstallDirNameSuffix( + const std::string& componentName); + + bool GetListOfSubdirectories(const char* dir, + std::vector<std::string>& dirs); + + enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const; + virtual bool SupportsAbsoluteDestination() const; + virtual bool SupportsComponentInstallation() const; + +private: + int IfwCreateConfigFile(); + int IfwCreatePackageFile(); + std::string IfwCreateCurrentDate(); + bool IfwParseLicenses(std::vector<std::string> &licenses, + const std::string &variable, + const std::string &metaDir); + + std::string ifwRepoGen; + std::string ifwBinCreator; + + std::string ifwDownloadSite; + + bool ifwOnlineOnly; + bool ifwResolveDuplicateNames; + std::vector<std::string> ifwPkgsDirsVector; +}; + +#endif diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index ed57949..ced7982 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -1127,7 +1127,13 @@ cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, } else { - this->AppendMemTesterOutput(res, test); + std::vector<std::string> files; + this->TestOutputFileNames(test, files); + for(std::vector<std::string>::iterator i = files.begin(); + i != files.end(); ++i) + { + this->AppendMemTesterOutput(res, *i); + } } } @@ -1141,11 +1147,13 @@ cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res, cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "PostProcessBoundsCheckerTest for : " << res.Name << std::endl); - std::string ofile = this->TestOutputFileName(test); - if ( ofile.empty() ) + std::vector<std::string> files; + this->TestOutputFileNames(test, files); + if ( files.size() == 0 ) { return; } + std::string ofile = files[0]; // put a scope around this to close ifs so the file can be removed { cmsys::ifstream ifs(ofile.c_str()); @@ -1175,9 +1183,8 @@ cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res, void cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res, - int test) + std::string const& ofile) { - std::string ofile = this->TestOutputFileName(test); if ( ofile.empty() ) { return; @@ -1205,8 +1212,9 @@ cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res, } } -std::string -cmCTestMemCheckHandler::TestOutputFileName(int test) +void cmCTestMemCheckHandler::TestOutputFileNames(int test, + std::vector<std::string>& + files) { std::string index; cmOStringStream stream; @@ -1229,7 +1237,8 @@ cmCTestMemCheckHandler::TestOutputFileName(int test) } else { - ofile = g.GetFiles()[0]; + files = g.GetFiles(); + return; } } else if ( !cmSystemTools::FileExists(ofile.c_str()) ) @@ -1239,5 +1248,5 @@ cmCTestMemCheckHandler::TestOutputFileName(int test) cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); ofile = ""; } - return ofile; + files.push_back(ofile); } diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 2630fde..2195dab 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -145,10 +145,10 @@ private: ///! append MemoryTesterOutputFile to the test log void AppendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res, - int test); + std::string const& filename); ///! generate the output filename for the given test index - std::string TestOutputFileName(int test); + void TestOutputFileNames(int test, std::vector<std::string>& files); }; #endif diff --git a/Source/QtIFW/cmake.org.html b/Source/QtIFW/cmake.org.html new file mode 100644 index 0000000..cf5649d --- /dev/null +++ b/Source/QtIFW/cmake.org.html @@ -0,0 +1,7 @@ +<html> +<head> +<meta http-equiv="Refresh" content="0; url=http://cmake.org/" /> +</head> +<body> +</body> +</html> diff --git a/Source/QtIFW/installscript.qs.in b/Source/QtIFW/installscript.qs.in new file mode 100644 index 0000000..5491611 --- /dev/null +++ b/Source/QtIFW/installscript.qs.in @@ -0,0 +1,24 @@ +function Component() +{ + // default constructor +} + +Component.prototype.createOperations = function() +{ + // call default implementation to actually install applications! + component.createOperations(); + + // Create shortcut + if (installer.value("os") === "win") { + +@_CPACK_IFW_SHORTCUT_OPTIONAL@ + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/cmake.org.html", + installer.value("StartMenuDir") + "/CMake Web Site.lnk"); + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/uninstall.exe", + installer.value("StartMenuDir") + "/Uninstall.lnk"); + } +} diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 50a395e..134f45b 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -58,12 +58,7 @@ bool cmDepends::Write(std::ostream &makeDepends, // Get the source and object file. std::string const& src = *si++; if(si == pairs.end()) { break; } - std::string obj = *si++; - - // Make sure the object file is relative to the top of the build tree. - obj = this->LocalGenerator->Convert(obj, - cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); + std::string const& obj = *si++; dependencies[obj].insert(src); } for(std::map<std::string, std::set<std::string> >::const_iterator diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index d26d3a9..a1fc268 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -269,14 +269,20 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // written by the original local generator for this directory // convert the dependencies to paths relative to the home output // directory. We must do the same here. - internalDepends << obj << std::endl; + std::string obj_i = + this->LocalGenerator->Convert(obj, cmLocalGenerator::HOME_OUTPUT); + std::string obj_m = + this->LocalGenerator->ConvertToOutputFormat(obj_i, + cmLocalGenerator::MAKERULE); + internalDepends << obj_i << std::endl; + for(std::set<std::string>::const_iterator i=dependencies.begin(); i != dependencies.end(); ++i) { - makeDepends << obj << ": " << + makeDepends << obj_m << ": " << this->LocalGenerator->Convert(*i, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << std::endl; internalDepends << " " << *i << std::endl; } diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index f06971d..8fc8347 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -443,15 +443,20 @@ cmDependsFortran const char* src = info.Source.c_str(); // Write the include dependencies to the output stream. - internalDepends << obj << std::endl; + std::string obj_i = + this->LocalGenerator->Convert(obj, cmLocalGenerator::HOME_OUTPUT); + std::string obj_m = + this->LocalGenerator->ConvertToOutputFormat(obj_i, + cmLocalGenerator::MAKERULE); + internalDepends << obj_i << std::endl; internalDepends << " " << src << std::endl; for(std::set<std::string>::const_iterator i = info.Includes.begin(); i != info.Includes.end(); ++i) { - makeDepends << obj << ": " << + makeDepends << obj_m << ": " << this->LocalGenerator->Convert(*i, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << std::endl; internalDepends << " " << *i << std::endl; } @@ -482,10 +487,10 @@ cmDependsFortran proxy += ".mod.proxy"; proxy = this->LocalGenerator->Convert(proxy, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); + cmLocalGenerator::MAKERULE); // since we require some things add them to our list of requirements - makeDepends << obj << ".requires: " << proxy << std::endl; + makeDepends << obj_m << ".requires: " << proxy << std::endl; } // The object file should depend on timestamped files for the @@ -499,8 +504,8 @@ cmDependsFortran std::string stampFile = this->LocalGenerator->Convert(required->second, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << obj << ": " << stampFile << "\n"; + cmLocalGenerator::MAKERULE); + makeDepends << obj_m << ": " << stampFile << "\n"; } else { @@ -512,8 +517,8 @@ cmDependsFortran module = this->LocalGenerator->Convert(module, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << obj << ": " << module << "\n"; + cmLocalGenerator::MAKERULE); + makeDepends << obj_m << ": " << module << "\n"; } } } @@ -528,8 +533,8 @@ cmDependsFortran proxy += ".mod.proxy"; proxy = this->LocalGenerator->Convert(proxy, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << proxy << ": " << obj << ".provides" << std::endl; + cmLocalGenerator::MAKERULE); + makeDepends << proxy << ": " << obj_m << ".provides" << std::endl; } // If any modules are provided then they must be converted to stamp files. @@ -537,7 +542,7 @@ cmDependsFortran { // Create a target to copy the module after the object file // changes. - makeDepends << obj << ".provides.build:\n"; + makeDepends << obj_m << ".provides.build:\n"; for(std::set<std::string>::const_iterator i = info.Provides.begin(); i != info.Provides.end(); ++i) { @@ -575,7 +580,7 @@ cmDependsFortran } // After copying the modules update the timestamp file so that // copying will not be done again until the source rebuilds. - makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj + makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj_m << ".provides.build\n"; // Make sure the module timestamp rule is evaluated by the time @@ -584,8 +589,8 @@ cmDependsFortran driver += "/build"; driver = this->LocalGenerator->Convert(driver, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << driver << ": " << obj << ".provides.build\n"; + cmLocalGenerator::MAKERULE); + makeDepends << driver << ": " << obj_m << ".provides.build\n"; } return true; diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 2b4d955..7fc1464 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -97,6 +97,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Quiet = quiet; context.HadError = false; context.HadContextSensitiveCondition = false; + context.HadHeadSensitiveCondition = false; context.HeadTarget = headTarget; context.EvaluateForBuildsystem = this->EvaluateForBuildsystem; context.CurrentTarget = currentTarget ? currentTarget : headTarget; @@ -124,6 +125,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( if (!context.HadError) { this->HadContextSensitiveCondition = context.HadContextSensitiveCondition; + this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition; } this->DependTargets = context.DependTargets; @@ -137,6 +139,7 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( const std::string& input) : Backtrace(backtrace), Input(input), HadContextSensitiveCondition(false), + HadHeadSensitiveCondition(false), EvaluateForBuildsystem(false) { cmGeneratorExpressionLexer l; diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 324d23c..b952520 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -111,6 +111,10 @@ public: { return this->HadContextSensitiveCondition; } + bool GetHadHeadSensitiveCondition() const + { + return this->HadHeadSensitiveCondition; + } void SetEvaluateForBuildsystem(bool eval) { @@ -141,6 +145,7 @@ private: MaxLanguageStandard; mutable std::string Output; mutable bool HadContextSensitiveCondition; + mutable bool HadHeadSensitiveCondition; bool EvaluateForBuildsystem; }; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 28879f1..7a53d65 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -840,6 +840,10 @@ getLinkedTargetsContent( { context->HadContextSensitiveCondition = true; } + if (cge->GetHadHeadSensitiveCondition()) + { + context->HadHeadSensitiveCondition = true; + } } linkedTargetsContent = cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent); @@ -871,6 +875,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmTarget const* target = context->HeadTarget; std::string propertyName = *parameters.begin(); + if (parameters.size() == 1) + { + context->HadHeadSensitiveCondition = true; + } if (!target && parameters.size() == 1) { reportError(context, content->GetOriginalExpression(), @@ -1190,6 +1198,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { context->HadContextSensitiveCondition = true; } + if (cge->GetHadHeadSensitiveCondition()) + { + context->HadHeadSensitiveCondition = true; + } if (!linkedTargetsContent.empty()) { result += (result.empty() ? "" : ";") + linkedTargetsContent; @@ -1313,6 +1325,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode "not be used with add_custom_command or add_custom_target."); return std::string(); } + context->HadHeadSensitiveCondition = true; typedef std::map<std::string, std::vector<std::string> > LangMap; static LangMap availableFeatures; @@ -1446,6 +1459,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode } context->HadContextSensitiveCondition = true; + context->HadHeadSensitiveCondition = true; for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i) { diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 0ffb860..8a529e8 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -41,6 +41,7 @@ struct cmGeneratorExpressionContext bool Quiet; bool HadError; bool HadContextSensitiveCondition; + bool HadHeadSensitiveCondition; bool EvaluateForBuildsystem; }; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 6d737b1..249373c 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -148,8 +148,6 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang, { return; } - std::string doc = lang; - doc += " compiler."; const char* cname = this->GetCMakeInstance()-> GetCacheManager()->GetCacheValue(langComp); std::string changeVars; @@ -186,8 +184,6 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang, changeVars.c_str()); } } - mf->AddCacheDefinition(langComp, path.c_str(), - doc.c_str(), cmCacheManager::FILEPATH); } void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen) @@ -1153,7 +1149,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const return false; } -void cmGlobalGenerator::Generate() +void cmGlobalGenerator::DoGenerate() { // Some generators track files replaced during the Generate. // Start with an empty vector: @@ -1162,6 +1158,11 @@ void cmGlobalGenerator::Generate() // clear targets to issue warning CMP0042 for this->CMP0042WarnTargets.clear(); + this->Generate(); +} + +void cmGlobalGenerator::Generate() +{ // Check whether this generator is allowed to run. if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index ee3f269..6b608bb 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -80,7 +80,7 @@ public: * basically creates a series of LocalGenerators for each directory and * requests that they Generate. */ - virtual void Generate(); + void DoGenerate(); /** * Set/Get and Clear the enabled languages. @@ -338,6 +338,8 @@ public: bool GenerateCPackPropertiesFile(); protected: + virtual void Generate(); + typedef std::vector<cmLocalGenerator*> GeneratorVector; // for a project collect all its targets by following depend // information, and also collect all the targets diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index ff110d7..4cbbeea 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -182,9 +182,6 @@ public: /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation() static void GetDocumentation(cmDocumentationEntry& entry); - /// Overloaded methods. @see cmGlobalGenerator::Generate() - virtual void Generate(); - /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage() virtual void EnableLanguage(std::vector<std::string>const& languages, cmMakefile* mf, @@ -302,6 +299,9 @@ public: virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; protected: + /// Overloaded methods. @see cmGlobalGenerator::Generate() + virtual void Generate(); + /// Overloaded methods. /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const { return true; } diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 8dae81b..3478534 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -530,7 +530,7 @@ cmGlobalUnixMakefileGenerator3 // Begin the directory-level rules section. std::string dir = lg->GetMakefile()->GetStartOutputDirectory(); dir = lg->Convert(dir, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); + cmLocalGenerator::MAKERULE); lg->WriteDivider(ruleFileStream); ruleFileStream << "# Directory level rules for directory " diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index cb639dd..9f154e9 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -47,8 +47,6 @@ public: ///! create the correct local generator virtual cmLocalGenerator *CreateLocalGenerator(); - virtual void Generate(); - /** * Try to determine system infomation such as shared library * extension, pthreads, byte order etc. @@ -93,6 +91,8 @@ public: virtual void FindMakeProgram(cmMakefile*); protected: + virtual void Generate(); + virtual const char* GetIDEVersion() { return "10.0"; } std::string const& GetMSBuildCommand(); diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index b2fd28f..57c2660 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -64,13 +64,6 @@ public: ); /** - * Generate the all required files for building this project/tree. This - * basically creates a series of LocalGenerators for each directory and - * requests that they Generate. - */ - virtual void Generate(); - - /** * Generate the DSW workspace file. */ virtual void OutputDSWFile(); @@ -94,6 +87,7 @@ public: virtual bool IsForVS6() const { return true; } protected: + virtual void Generate(); virtual const char* GetIDEVersion() { return "6.0"; } private: virtual std::string GetVSMakeProgram() { return this->GetMSDevCommand(); } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 602d678..3d79357 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -773,7 +773,6 @@ void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout, const char* typeGuid, const std::set<std::string>&) { - std::string d = cmSystemTools::ConvertToOutputPath(location); fout << "Project(" << "\"{" << (typeGuid ? typeGuid : this->ExternalProjectType(location)) diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index bd84433..390b97c 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -72,13 +72,6 @@ public: ); /** - * Generate the all required files for building this project/tree. This - * basically creates a series of LocalGenerators for each directory and - * requests that they Generate. - */ - virtual void Generate(); - - /** * Generate the DSW workspace file. */ virtual void OutputSLNFile(); @@ -113,6 +106,7 @@ public: virtual std::string Encoding(); protected: + virtual void Generate(); virtual const char* GetIDEVersion() { return "7.0"; } std::string const& GetDevEnvCommand(); diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index aea2f01..d7e1f3a 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -45,7 +45,6 @@ public: * target. */ virtual void Configure(); - virtual void Generate(); /** * Where does this version of Visual Studio look for macros for the @@ -69,6 +68,7 @@ public: return !this->WindowsCEVersion.empty(); } protected: + virtual void Generate(); virtual const char* GetIDEVersion() { return "8.0"; } virtual std::string FindDevEnvCommand(); diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 05dbb11..356f4d4 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -27,11 +27,6 @@ public: virtual ~cmGlobalVisualStudioGenerator(); /** - * Basic generate implementation for all VS generators. - */ - virtual void Generate(); - - /** * Configure CMake's Visual Studio macros file into the user's Visual * Studio macros directory. */ @@ -90,6 +85,8 @@ public: void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; protected: + virtual void Generate(); + // Does this VS version link targets to each other if there are // dependencies in the SLN file? This was done for VS versions // below 8. diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index ae23e3b..fcdd349 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -64,13 +64,6 @@ public: std::vector<std::string> const& makeOptions = std::vector<std::string>() ); - /** - * Generate the all required files for building this project/tree. This - * basically creates a series of LocalGenerators for each directory and - * requests that they Generate. - */ - virtual void Generate(); - /** Append the subdirectory for the given configuration. */ virtual void AppendDirectoryForConfig(const std::string& prefix, const std::string& config, @@ -91,6 +84,8 @@ public: virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); void AppendFlag(std::string& flags, std::string const& flag); +protected: + virtual void Generate(); private: cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg); diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 1f3c066..dfbece7 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -152,18 +152,7 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry, } else if(entry->special & cmIDEFlagTable::SemicolonAppendable) { - std::map<std::string,std::string>::iterator itr; - itr = this->FlagMap.find(entry->IDEName); - if(itr != this->FlagMap.end()) - { - // Append to old value (if present) with semicolons; - itr->second += ";"; - itr->second += new_value; - } - else - { - this->FlagMap[entry->IDEName] = new_value; - } + this->FlagMap[entry->IDEName].push_back(new_value); } else { @@ -200,6 +189,13 @@ void cmIDEOptions::AddFlag(const char* flag, const char* value) } //---------------------------------------------------------------------------- +void cmIDEOptions::AddFlag(const char* flag, + std::vector<std::string> const& value) +{ + this->FlagMap[flag] = value; +} + +//---------------------------------------------------------------------------- void cmIDEOptions::RemoveFlag(const char* flag) { this->FlagMap.erase(flag); @@ -208,10 +204,11 @@ void cmIDEOptions::RemoveFlag(const char* flag) //---------------------------------------------------------------------------- const char* cmIDEOptions::GetFlag(const char* flag) { - std::map<std::string, std::string>::iterator i = this->FlagMap.find(flag); - if(i != this->FlagMap.end()) + // This method works only for single-valued flags! + std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(flag); + if(i != this->FlagMap.end() && i->second.size() == 1) { - return i->second.c_str(); + return i->second[0].c_str(); } return 0; } diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index e7749ec..313c003 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -29,6 +29,7 @@ public: void AddDefines(const char* defines); void AddDefines(const std::vector<std::string> &defines); void AddFlag(const char* flag, const char* value); + void AddFlag(const char* flag, std::vector<std::string> const& value); void RemoveFlag(const char* flag); const char* GetFlag(const char* flag); @@ -40,7 +41,23 @@ protected: // Then parse the command line flags specified in CMAKE_CXX_FLAGS // and CMAKE_C_FLAGS // and overwrite or add new values to this map - std::map<std::string, std::string> FlagMap; + class FlagValue: public std::vector<std::string> + { + typedef std::vector<std::string> derived; + public: + FlagValue& operator=(std::string const& r) + { + this->resize(1); + this->operator[](0) = r; + return *this; + } + FlagValue& operator=(std::vector<std::string> const& r) + { + this->derived::operator=(r); + return *this; + } + }; + std::map<std::string, FlagValue > FlagMap; // Preprocessor definitions. std::vector<std::string> Defines; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 5380d06..4bd9191 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -681,7 +681,7 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang, objVector.push_back(ofname); this->AddCustomCommandToCreateObject(ofname.c_str(), llang, *(*i), target); - objs += this->Convert(ofname,START_OUTPUT,MAKEFILE); + objs += this->Convert(ofname,START_OUTPUT,SHELL); objs += " "; } } @@ -2755,7 +2755,7 @@ std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source, { std::string result = source; // Convert it to an output path. - if (output == MAKEFILE) + if (output == MAKERULE) { result = cmSystemTools::ConvertToOutputPath(result.c_str()); } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index ad73073..b25b9ab 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -106,7 +106,7 @@ public: * path setting */ enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT }; - enum OutputFormat { UNCHANGED, MAKEFILE, SHELL, WATCOMQUOTE, RESPONSE }; + enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE }; std::string ConvertToOutputFormat(const std::string& source, OutputFormat output); std::string Convert(const std::string& remote, RelativeRoot local, diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 94e45e5..23513fa 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -630,7 +630,7 @@ cmLocalUnixMakefileGenerator3 // Construct the left hand side of the rule. replace = target; - std::string tgt = this->Convert(replace,HOME_OUTPUT,MAKEFILE); + std::string tgt = this->Convert(replace,HOME_OUTPUT,MAKERULE); const char* space = ""; if(tgt.size() == 1) { @@ -663,7 +663,7 @@ cmLocalUnixMakefileGenerator3 dep != depends.end(); ++dep) { replace = *dep; - replace = this->Convert(replace,HOME_OUTPUT,MAKEFILE); + replace = this->Convert(replace,HOME_OUTPUT,MAKERULE); os << cmMakeSafe(tgt) << space << ": " << cmMakeSafe(replace) << "\n"; } } diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index e0fe0fd..3ed4a48 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1013,7 +1013,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, if(!this->ModuleDefinitionFile.empty()) { std::string defFile = - this->ConvertToXMLOutputPath(this->ModuleDefinitionFile.c_str()); + this->ConvertToOptionallyRelativeOutputPath(this->ModuleDefinitionFile); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); } switch(target.GetType()) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 403f6e6..758c8e4 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -218,7 +218,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(dependFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; if(!this->NoRuleMessages) @@ -229,7 +229,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(this->ProgressFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; } @@ -262,7 +262,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(this->FlagFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; } diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 6b039bb..617214f 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -54,7 +54,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(this->ProgressFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; } diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index cc6932d..d4d565c 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1000,6 +1000,7 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, this->WriteOldMocDefinitionsFile(targetDirectory); + delete gg->GetCurrentLocalGenerator(); delete gg; gg = NULL; makefile = NULL; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 444e143..fbb4416 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1701,6 +1701,8 @@ bool extract_tar(const char* outFileName, bool verbose, { cmSystemTools::Error("Problem with archive_read_open_file(): ", archive_error_string(a)); + archive_write_free(ext); + archive_read_close(a); return false; } for (;;) @@ -1776,6 +1778,7 @@ bool extract_tar(const char* outFileName, bool verbose, } } } + archive_write_free(ext); archive_read_close(a); archive_read_finish(a); return r == ARCHIVE_EOF || r == ARCHIVE_OK; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 07f08de..ca24d2d 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -88,11 +88,6 @@ struct cmTarget::CompileInfo std::string CompilePdbDir; }; -struct TargetConfigPair : public std::pair<cmTarget const* , std::string> { - TargetConfigPair(cmTarget const* tgt, const std::string &config) - : std::pair<cmTarget const* , std::string>(tgt, config) {} -}; - //---------------------------------------------------------------------------- class cmTargetInternals { @@ -119,10 +114,12 @@ public: { OptionalLinkInterface(): LibrariesDone(false), AllDone(false), - Exists(false), ExplicitLibraries(0) {} + Exists(false), HadHeadSensitiveCondition(false), + ExplicitLibraries(0) {} bool LibrariesDone; bool AllDone; bool Exists; + bool HadHeadSensitiveCondition; const char* ExplicitLibraries; }; void ComputeLinkInterface(cmTarget const* thisTarget, @@ -135,17 +132,14 @@ public: cmTarget const* head, bool usage_requirements_only); - typedef std::map<TargetConfigPair, OptionalLinkInterface> + struct HeadToLinkInterfaceMap: + public std::map<cmTarget const*, OptionalLinkInterface> {}; + typedef std::map<std::string, HeadToLinkInterfaceMap> LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap; bool PolicyWarnedCMP0022; - typedef std::map<TargetConfigPair, OptionalLinkInterface> - ImportLinkInterfaceMapType; - ImportLinkInterfaceMapType ImportLinkInterfaceMap; - ImportLinkInterfaceMapType ImportLinkInterfaceUsageRequirementsOnlyMap; - typedef std::map<std::string, cmTarget::OutputInfo> OutputInfoMapType; OutputInfoMapType OutputInfoMap; @@ -159,12 +153,25 @@ public: struct OptionalLinkImplementation: public cmTarget::LinkImplementation { OptionalLinkImplementation(): - LibrariesDone(false), LanguagesDone(false) {} + LibrariesDone(false), LanguagesDone(false), + HadHeadSensitiveCondition(false) {} bool LibrariesDone; bool LanguagesDone; + bool HadHeadSensitiveCondition; }; - typedef std::map<TargetConfigPair, - OptionalLinkImplementation> LinkImplMapType; + void ComputeLinkImplementationLibraries(cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl, + cmTarget const* head) const; + void ComputeLinkImplementationLanguages(cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl + ) const; + + struct HeadToLinkImplementationMap: + public std::map<cmTarget const*, OptionalLinkImplementation> {}; + typedef std::map<std::string, + HeadToLinkImplementationMap> LinkImplMapType; LinkImplMapType LinkImplMap; typedef std::map<std::string, cmTarget::LinkClosure> LinkClosureMapType; @@ -196,11 +203,9 @@ public: public: TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, cmLinkImplItem const& item = NoLinkImplItem) - : ge(cge), Cached(false), LinkImplItem(item) + : ge(cge), LinkImplItem(item) {} const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; - std::vector<std::string> CachedEntries; - bool Cached; cmLinkImplItem const& LinkImplItem; }; std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; @@ -213,23 +218,6 @@ public: void AddInterfaceEntries( cmTarget const* thisTarget, std::string const& config, std::string const& prop, std::vector<TargetPropertyEntry*>& entries); - - std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceIncludeDirectoriesEntries; - std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceCompileOptionsEntries; - std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceCompileDefinitionsEntries; - std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceSourcesEntries; - std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceCompileFeaturesEntries; - - std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone; - std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone; - std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone; - std::map<std::string, bool> CacheLinkInterfaceSourcesDone; - std::map<std::string, bool> CacheLinkInterfaceCompileFeaturesDone; }; cmLinkImplItem cmTargetInternals::TargetPropertyEntry::NoLinkImplItem; @@ -249,26 +237,8 @@ static void deleteAndClear( } //---------------------------------------------------------------------------- -static void deleteAndClear( - std::map<std::string, - std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries) -{ - for (std::map<std::string, - std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator - it = entries.begin(), end = entries.end(); it != end; ++it) - { - deleteAndClear(it->second); - } -} - -//---------------------------------------------------------------------------- cmTargetInternals::~cmTargetInternals() { - deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries); - deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries); - deleteAndClear(this->CachedLinkInterfaceCompileFeaturesEntries); - deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries); - deleteAndClear(this->CachedLinkInterfaceSourcesEntries); } //---------------------------------------------------------------------------- @@ -565,8 +535,6 @@ void cmTarget::ClearLinkMaps() this->Internal->LinkImplMap.clear(); this->Internal->LinkInterfaceMap.clear(); this->Internal->LinkInterfaceUsageRequirementsOnlyMap.clear(); - this->Internal->ImportLinkInterfaceMap.clear(); - this->Internal->ImportLinkInterfaceUsageRequirementsOnlyMap.clear(); this->Internal->LinkClosureMap.clear(); for (cmTargetLinkInformationMap::const_iterator it = this->LinkInformation.begin(); @@ -670,49 +638,37 @@ static bool processSources(cmTarget const* tgt, for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) { - bool cacheSources = false; - std::vector<std::string> entrySources = (*it)->CachedEntries; - if(entrySources.empty()) + std::vector<std::string> entrySources; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + tgt, + dagChecker), + entrySources); + + if ((*it)->ge->GetHadContextSensitiveCondition()) { - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - tgt, - tgt, - dagChecker), - entrySources); + contextDependent = true; + } - if ((*it)->ge->GetHadContextSensitiveCondition()) - { - contextDependent = true; - } - else if (mf->IsGeneratingBuildSystem()) - { - cacheSources = true; - } + for(std::vector<std::string>::iterator i = entrySources.begin(); + i != entrySources.end(); ++i) + { + std::string& src = *i; - for(std::vector<std::string>::iterator i = entrySources.begin(); - i != entrySources.end(); ++i) + cmSourceFile* sf = mf->GetOrCreateSource(src); + std::string e; + src = sf->GetFullPath(&e); + if(src.empty()) { - std::string& src = *i; - - cmSourceFile* sf = mf->GetOrCreateSource(src); - std::string e; - src = sf->GetFullPath(&e); - if(src.empty()) + if(!e.empty()) { - if(!e.empty()) - { - cmake* cm = mf->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e, - tgt->GetBacktrace()); - } - return contextDependent; + cmake* cm = mf->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, e, + tgt->GetBacktrace()); } - } - if (cacheSources) - { - (*it)->CachedEntries = entrySources; + return contextDependent; } } std::string usedSources; @@ -810,16 +766,16 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, config, debugSources); - if (!this->Internal->CacheLinkInterfaceSourcesDone[config]) - { - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_SOURCES", - this->Internal->CachedLinkInterfaceSourcesEntries[config]); - } + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceSourcesEntries; - std::vector<std::string>::size_type numFilesBefore = files.size(); - bool contextDependentInterfaceSources = processSources(this, - this->Internal->CachedLinkInterfaceSourcesEntries[config], + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_SOURCES", + linkInterfaceSourcesEntries); + + std::vector<std::string>::size_type numFilesBefore = files.size(); + bool contextDependentInterfaceSources = processSources(this, + linkInterfaceSourcesEntries, files, uniqueSrcs, &dagChecker, @@ -832,14 +788,7 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, this->LinkImplementationLanguageIsContextDependent = false; } - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal->CachedLinkInterfaceSourcesEntries); - } - else - { - this->Internal->CacheLinkInterfaceSourcesDone[config] = true; - } + deleteAndClear(linkInterfaceSourcesEntries); } //---------------------------------------------------------------------------- @@ -2045,27 +1994,14 @@ static void processIncludeDirectories(cmTarget const* tgt, std::string const& targetName = item; bool const fromImported = item.Target && item.Target->IsImported(); bool const checkCMP0027 = item.FromGenex; - bool testIsOff = true; - bool cacheIncludes = false; - std::vector<std::string>& entryIncludes = (*it)->CachedEntries; - if(!entryIncludes.empty()) - { - testIsOff = false; - } - else - { - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - tgt, - dagChecker), - entryIncludes); - if (mf->IsGeneratingBuildSystem() - && !(*it)->ge->GetHadContextSensitiveCondition()) - { - cacheIncludes = true; - } - } + std::vector<std::string> entryIncludes; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + dagChecker), + entryIncludes); + std::string usedIncludes; for(std::vector<std::string>::iterator li = entryIncludes.begin(); li != entryIncludes.end(); ++li) @@ -2147,7 +2083,7 @@ static void processIncludeDirectories(cmTarget const* tgt, } } - if (testIsOff && !cmSystemTools::IsOff(li->c_str())) + if (!cmSystemTools::IsOff(li->c_str())) { cmSystemTools::ConvertToUnixSlashes(*li); } @@ -2162,10 +2098,6 @@ static void processIncludeDirectories(cmTarget const* tgt, } } } - if (cacheIncludes) - { - (*it)->CachedEntries = entryIncludes; - } if (!usedIncludes.empty()) { mf->GetCMakeInstance()->IssueMessage(cmake::LOG, @@ -2213,58 +2145,47 @@ cmTarget::GetIncludeDirectories(const std::string& config) const config, debugIncludes); - if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[config]) - { - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_INCLUDE_DIRECTORIES", - this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries[config]); + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceIncludeDirectoriesEntries; + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_INCLUDE_DIRECTORIES", + linkInterfaceIncludeDirectoriesEntries); - if(this->Makefile->IsOn("APPLE")) + if(this->Makefile->IsOn("APPLE")) + { + LinkImplementation const* impl = this->GetLinkImplementation(config); + for(std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) { - LinkImplementation const* impl = this->GetLinkImplementation(config); - for(std::vector<cmLinkImplItem>::const_iterator - it = impl->Libraries.begin(); - it != impl->Libraries.end(); ++it) - { - std::string libDir = cmSystemTools::CollapseFullPath(it->c_str()); + std::string libDir = cmSystemTools::CollapseFullPath(it->c_str()); - static cmsys::RegularExpression - frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); - if(!frameworkCheck.find(libDir)) - { - continue; - } + static cmsys::RegularExpression + frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); + if(!frameworkCheck.find(libDir)) + { + continue; + } - libDir = frameworkCheck.match(1); + libDir = frameworkCheck.match(1); - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(libDir.c_str()); - this->Internal - ->CachedLinkInterfaceIncludeDirectoriesEntries[config] - .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); - } + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(libDir.c_str()); + linkInterfaceIncludeDirectoriesEntries + .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); } } processIncludeDirectories(this, - this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries[config], + linkInterfaceIncludeDirectoriesEntries, includes, uniqueIncludes, &dagChecker, config, debugIncludes); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear( - this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries); - } - else - { - this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[config] - = true; - } + deleteAndClear(linkInterfaceIncludeDirectoriesEntries); return includes; } @@ -2282,33 +2203,16 @@ static void processCompileOptionsInternal(cmTarget const* tgt, for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) { - std::vector<std::string>& entriesRef = (*it)->CachedEntries; - std::vector<std::string> localEntries; - std::vector<std::string>* entryOptions = &entriesRef; - if(!(*it)->Cached) - { - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - tgt, - dagChecker), - localEntries); - if (mf->IsGeneratingBuildSystem() - && !(*it)->ge->GetHadContextSensitiveCondition()) - { - // Cache the result. - *entryOptions = localEntries; - (*it)->Cached = true; - } - else - { - // Use the context-sensitive results here. - entryOptions = &localEntries; - } - } + std::vector<std::string> entryOptions; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + dagChecker), + entryOptions); std::string usedOptions; for(std::vector<std::string>::iterator - li = entryOptions->begin(); li != entryOptions->end(); ++li) + li = entryOptions.begin(); li != entryOptions.end(); ++li) { std::string const& opt = *li; @@ -2405,29 +2309,22 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result, config, debugOptions); - if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[config]) - { - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_COMPILE_OPTIONS", - this->Internal->CachedLinkInterfaceCompileOptionsEntries[config]); - } + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceCompileOptionsEntries; + + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_OPTIONS", + linkInterfaceCompileOptionsEntries); processCompileOptions(this, - this->Internal->CachedLinkInterfaceCompileOptionsEntries[config], + linkInterfaceCompileOptionsEntries, result, uniqueOptions, &dagChecker, config, debugOptions); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries); - } - else - { - this->Internal->CacheLinkInterfaceCompileOptionsDone[config] = true; - } + deleteAndClear(linkInterfaceCompileOptionsEntries); } //---------------------------------------------------------------------------- @@ -2479,66 +2376,54 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list, config, debugDefines); - if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[config]) + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceCompileDefinitionsEntries; + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_DEFINITIONS", + linkInterfaceCompileDefinitionsEntries); + if (!config.empty()) { - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_COMPILE_DEFINITIONS", - this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[config]); - if (!config.empty()) + std::string configPropName = "COMPILE_DEFINITIONS_" + + cmSystemTools::UpperCase(config); + const char *configProp = this->GetProperty(configPropName); + if (configProp) { - std::string configPropName = "COMPILE_DEFINITIONS_" - + cmSystemTools::UpperCase(config); - const char *configProp = this->GetProperty(configPropName); - if (configProp) + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) { - switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) + case cmPolicies::WARN: { - case cmPolicies::WARN: - { - cmOStringStream e; - e << this->Makefile->GetCMakeInstance()->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0043); - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - e.str()); - } - case cmPolicies::OLD: - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(configProp); - this->Internal - ->CachedLinkInterfaceCompileDefinitionsEntries[config] - .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); - } - break; - case cmPolicies::NEW: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - break; + cmOStringStream e; + e << this->Makefile->GetCMakeInstance()->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0043); + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + e.str()); + } + case cmPolicies::OLD: + { + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(configProp); + linkInterfaceCompileDefinitionsEntries + .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); } + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + break; } } - } processCompileDefinitions(this, - this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[config], + linkInterfaceCompileDefinitionsEntries, list, uniqueOptions, &dagChecker, config, debugDefines); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal - ->CachedLinkInterfaceCompileDefinitionsEntries); - } - else - { - this->Internal->CacheLinkInterfaceCompileDefinitionsDone[config] - = true; - } + deleteAndClear(linkInterfaceCompileDefinitionsEntries); } //---------------------------------------------------------------------------- @@ -2590,29 +2475,21 @@ void cmTarget::GetCompileFeatures(std::vector<std::string> &result, config, debugFeatures); - if (!this->Internal->CacheLinkInterfaceCompileFeaturesDone[config]) - { - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_COMPILE_FEATURES", - this->Internal->CachedLinkInterfaceCompileFeaturesEntries[config]); - } + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceCompileFeaturesEntries; + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_FEATURES", + linkInterfaceCompileFeaturesEntries); processCompileFeatures(this, - this->Internal->CachedLinkInterfaceCompileFeaturesEntries[config], + linkInterfaceCompileFeaturesEntries, result, uniqueFeatures, &dagChecker, config, debugFeatures); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal->CachedLinkInterfaceCompileFeaturesEntries); - } - else - { - this->Internal->CacheLinkInterfaceCompileFeaturesDone[config] = true; - } + deleteAndClear(linkInterfaceCompileFeaturesEntries); } //---------------------------------------------------------------------------- @@ -3562,7 +3439,8 @@ void cmTarget::ExpandLinkItems(std::string const& prop, std::string const& config, cmTarget const* headTarget, bool usage_requirements_only, - std::vector<cmLinkItem>& items) const + std::vector<cmLinkItem>& items, + bool& hadHeadSensitiveCondition) const { cmGeneratorExpression ge; cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0); @@ -3573,13 +3451,15 @@ void cmTarget::ExpandLinkItems(std::string const& prop, dagChecker.SetTransitivePropertiesOnly(); } std::vector<std::string> libs; - cmSystemTools::ExpandListArgument(ge.Parse(value)->Evaluate( + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + cmSystemTools::ExpandListArgument(cge->Evaluate( this->Makefile, config, false, headTarget, this, &dagChecker), libs); this->LookupLinkItems(libs, items); + hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); } //---------------------------------------------------------------------------- @@ -5881,10 +5761,18 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface( } // Lookup any existing link interface for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkInterfaceMap& hm = + this->Internal->LinkInterfaceMap[CONFIG]; + + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } - cmTargetInternals::OptionalLinkInterface& - iface = this->Internal->LinkInterfaceMap[key]; + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; if(!iface.LibrariesDone) { iface.LibrariesDone = true; @@ -5924,13 +5812,20 @@ cmTarget::GetLinkInterfaceLibraries(const std::string& config, } // Lookup any existing link interface for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); - cmTargetInternals::LinkInterfaceMapType& lim = + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkInterfaceMap& hm = (usage_requirements_only ? - this->Internal->LinkInterfaceUsageRequirementsOnlyMap : - this->Internal->LinkInterfaceMap); + this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : + this->Internal->LinkInterfaceMap[CONFIG]); - cmTargetInternals::OptionalLinkInterface& iface = lim[key]; + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; if(!iface.LibrariesDone) { iface.LibrariesDone = true; @@ -5953,13 +5848,20 @@ cmTarget::GetImportLinkInterface(const std::string& config, return 0; } - TargetConfigPair key(headTarget, cmSystemTools::UpperCase(config)); - cmTargetInternals::ImportLinkInterfaceMapType& lim = + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkInterfaceMap& hm = (usage_requirements_only ? - this->Internal->ImportLinkInterfaceUsageRequirementsOnlyMap : - this->Internal->ImportLinkInterfaceMap); + this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : + this->Internal->LinkInterfaceMap[CONFIG]); - cmTargetInternals::OptionalLinkInterface& iface = lim[key]; + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + + cmTargetInternals::OptionalLinkInterface& iface = hm[headTarget]; if(!iface.AllDone) { iface.AllDone = true; @@ -5967,7 +5869,8 @@ cmTarget::GetImportLinkInterface(const std::string& config, cmSystemTools::ExpandListArgument(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, - iface.Libraries); + iface.Libraries, + iface.HadHeadSensitiveCondition); std::vector<std::string> deps; cmSystemTools::ExpandListArgument(info->SharedDeps, deps); this->LookupLinkItems(deps, iface.SharedDeps); @@ -6151,7 +6054,8 @@ cmTargetInternals::ComputeLinkInterfaceLibraries( // The interface libraries have been explicitly set. thisTarget->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget, usage_requirements_only, - iface.Libraries); + iface.Libraries, + iface.HadHeadSensitiveCondition); } else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) @@ -6174,9 +6078,10 @@ cmTargetInternals::ComputeLinkInterfaceLibraries( static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; if(const char* newExplicitLibraries = thisTarget->GetProperty(newProp)) { + bool hadHeadSensitiveConditionDummy = false; thisTarget->ExpandLinkItems(newProp, newExplicitLibraries, config, headTarget, usage_requirements_only, - ifaceLibs); + ifaceLibs, hadHeadSensitiveConditionDummy); } if (ifaceLibs != iface.Libraries) { @@ -6361,18 +6266,19 @@ cmTarget::GetLinkImplementation(const std::string& config) const } // Populate the link implementation for this configuration. - TargetConfigPair key(this, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); cmTargetInternals::OptionalLinkImplementation& - impl = this->Internal->LinkImplMap[key]; + impl = this->Internal->LinkImplMap[CONFIG][this]; if(!impl.LibrariesDone) { impl.LibrariesDone = true; - this->ComputeLinkImplementationLibraries(config, impl, this); + this->Internal + ->ComputeLinkImplementationLibraries(this, config, impl, this); } if(!impl.LanguagesDone) { impl.LanguagesDone = true; - this->ComputeLinkImplementationLanguages(config, impl); + this->Internal->ComputeLinkImplementationLanguages(this, config, impl); } return &impl; } @@ -6396,57 +6302,73 @@ cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, } // Populate the link implementation libraries for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); - cmTargetInternals::OptionalLinkImplementation& - impl = this->Internal->LinkImplMap[key]; + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkImplementationMap& hm = + this->Internal->LinkImplMap[CONFIG]; + + // If the link implementation does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + + cmTargetInternals::OptionalLinkImplementation& impl = hm[head]; if(!impl.LibrariesDone) { impl.LibrariesDone = true; - this->ComputeLinkImplementationLibraries(config, impl, head); + this->Internal + ->ComputeLinkImplementationLibraries(this, config, impl, head); } return &impl; } //---------------------------------------------------------------------------- void -cmTarget::ComputeLinkImplementationLibraries(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const +cmTargetInternals::ComputeLinkImplementationLibraries( + cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl, + cmTarget const* head) const { // Collect libraries directly linked in this configuration. for (std::vector<cmValueWithOrigin>::const_iterator - le = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); + le = this->LinkImplementationPropertyEntries.begin(), + end = this->LinkImplementationPropertyEntries.end(); le != end; ++le) { std::vector<std::string> llibs; cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), + thisTarget->GetName(), "LINK_LIBRARIES", 0, 0); cmGeneratorExpression ge(&le->Backtrace); cmsys::auto_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(le->Value); std::string const evaluated = - cge->Evaluate(this->Makefile, config, false, head, &dagChecker); + cge->Evaluate(thisTarget->Makefile, config, false, head, &dagChecker); cmSystemTools::ExpandListArgument(evaluated, llibs); + if(cge->GetHadHeadSensitiveCondition()) + { + impl.HadHeadSensitiveCondition = true; + } for(std::vector<std::string>::const_iterator li = llibs.begin(); li != llibs.end(); ++li) { // Skip entries that resolve to the target itself or are empty. - std::string name = this->CheckCMP0004(*li); - if(name == this->GetName() || name.empty()) + std::string name = thisTarget->CheckCMP0004(*li); + if(name == thisTarget->GetName() || name.empty()) { - if(name == this->GetName()) + if(name == thisTarget->GetName()) { bool noMessage = false; cmake::MessageType messageType = cmake::FATAL_ERROR; cmOStringStream e; - switch(this->GetPolicyStatusCMP0038()) + switch(thisTarget->GetPolicyStatusCMP0038()) { case cmPolicies::WARN: { - e << (this->Makefile->GetPolicies() + e << (thisTarget->Makefile->GetPolicies() ->GetPolicyWarning(cmPolicies::CMP0038)) << "\n"; messageType = cmake::AUTHOR_WARNING; } @@ -6462,9 +6384,9 @@ cmTarget::ComputeLinkImplementationLibraries(const std::string& config, if(!noMessage) { - e << "Target \"" << this->GetName() << "\" links to itself."; - this->Makefile->GetCMakeInstance()->IssueMessage( - messageType, e.str(), this->GetBacktrace()); + e << "Target \"" << thisTarget->GetName() << "\" links to itself."; + thisTarget->Makefile->GetCMakeInstance()->IssueMessage( + messageType, e.str(), thisTarget->GetBacktrace()); if (messageType == cmake::FATAL_ERROR) { return; @@ -6476,7 +6398,7 @@ cmTarget::ComputeLinkImplementationLibraries(const std::string& config, // The entry is meant for this configuration. impl.Libraries.push_back( - cmLinkImplItem(name, this->FindTargetToLink(name), + cmLinkImplItem(name, thisTarget->FindTargetToLink(name), le->Backtrace, evaluated != le->Value)); } @@ -6484,42 +6406,45 @@ cmTarget::ComputeLinkImplementationLibraries(const std::string& config, for (std::set<std::string>::const_iterator it = seenProps.begin(); it != seenProps.end(); ++it) { - if (!this->GetProperty(*it)) + if (!thisTarget->GetProperty(*it)) { - this->LinkImplicitNullProperties.insert(*it); + thisTarget->LinkImplicitNullProperties.insert(*it); } } - cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards); + cge->GetMaxLanguageStandard(thisTarget, thisTarget->MaxLanguageStandards); } - cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); - LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries(); + cmTarget::LinkLibraryType linkType = thisTarget->ComputeLinkType(config); + cmTarget::LinkLibraryVectorType const& oldllibs = + thisTarget->GetOriginalLinkLibraries(); for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin(); li != oldllibs.end(); ++li) { if(li->second != cmTarget::GENERAL && li->second != linkType) { - std::string name = this->CheckCMP0004(li->first); - if(name == this->GetName() || name.empty()) + std::string name = thisTarget->CheckCMP0004(li->first); + if(name == thisTarget->GetName() || name.empty()) { continue; } // Support OLD behavior for CMP0003. impl.WrongConfigLibraries.push_back( - cmLinkItem(name, this->FindTargetToLink(name))); + cmLinkItem(name, thisTarget->FindTargetToLink(name))); } } } //---------------------------------------------------------------------------- void -cmTarget::ComputeLinkImplementationLanguages(const std::string& config, - LinkImplementation& impl) const +cmTargetInternals::ComputeLinkImplementationLanguages( + cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl) const { // This target needs runtime libraries for its source languages. std::set<std::string> languages; // Get languages used in our source files. - this->GetLanguages(languages, config); + thisTarget->GetLanguages(languages, config); // Copy the set of langauges to the link implementation. for(std::set<std::string>::iterator li = languages.begin(); li != languages.end(); ++li) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b4c8a0f..333e2ae 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -797,17 +797,13 @@ private: LinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(const std::string& config, cmTarget const* head) const; - void ComputeLinkImplementationLibraries(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const; - void ComputeLinkImplementationLanguages(const std::string& config, - LinkImplementation& impl) const; void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, cmTarget const* headTarget, bool usage_requirements_only, - std::vector<cmLinkItem>& items) const; + std::vector<cmLinkItem>& items, + bool& hadHeadSensitiveCondition) const; void LookupLinkItems(std::vector<std::string> const& names, std::vector<cmLinkItem>& items) const; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 15439f6..5674317 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -343,19 +343,20 @@ void cmVisualStudio10TargetGenerator::Generate() } this->WriteString("<Platform>", 2); - (*this->BuildFileStream) << this->Platform << "</Platform>\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform) + << "</Platform>\n"; const char* projLabel = this->Target->GetProperty("PROJECT_LABEL"); if(!projLabel) { projLabel = this->Name.c_str(); } this->WriteString("<ProjectName>", 2); - (*this->BuildFileStream) << projLabel << "</ProjectName>\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n"; if(const char* targetFrameworkVersion = this->Target->GetProperty( "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { this->WriteString("<TargetFrameworkVersion>", 2); - (*this->BuildFileStream) << targetFrameworkVersion + (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion) << "</TargetFrameworkVersion>\n"; } this->WriteString("</PropertyGroup>\n", 1); @@ -507,7 +508,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() this->WriteString("<Configuration>", 3); (*this->BuildFileStream ) << *i << "</Configuration>\n"; this->WriteString("<Platform>", 3); - (*this->BuildFileStream) << this->Platform << "</Platform>\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform) + << "</Platform>\n"; this->WriteString("</ProjectConfiguration>\n", 2); } this->WriteString("</ItemGroup>\n", 1); @@ -700,7 +702,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, (*this->BuildFileStream ) << script << "</Command>\n"; this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3); - (*this->BuildFileStream ) << source->GetFullPath(); + (*this->BuildFileStream ) << cmVS10EscapeXML(source->GetFullPath()); for(std::vector<std::string>::const_iterator d = ccg.GetDepends().begin(); d != ccg.GetDepends().end(); @@ -710,7 +712,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, if(this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(), dep)) { this->ConvertToWindowsSlash(dep); - (*this->BuildFileStream ) << ";" << dep; + (*this->BuildFileStream ) << ";" << cmVS10EscapeXML(dep); } } (*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n"; @@ -723,7 +725,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, { std::string out = *o; this->ConvertToWindowsSlash(out); - (*this->BuildFileStream ) << sep << out; + (*this->BuildFileStream ) << sep << cmVS10EscapeXML(out); sep = ";"; } (*this->BuildFileStream ) << "</Outputs>\n"; @@ -824,7 +826,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::string obj = (*oi)->GetFullPath(); this->WriteString("<EmbeddedResource Include=\"", 2); this->ConvertToWindowsSlash(obj); - (*this->BuildFileStream ) << obj << "\">\n"; + (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n"; this->WriteString("<Filter>Resource Files</Filter>\n", 3); this->WriteString("</EmbeddedResource>\n", 2); } @@ -843,7 +845,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::string obj = *oi; this->WriteString("<Object Include=\"", 2); this->ConvertToWindowsSlash(obj); - (*this->BuildFileStream ) << obj << "\">\n"; + (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n"; this->WriteString("<Filter>Object Libraries</Filter>\n", 3); this->WriteString("</Object>\n", 2); } @@ -978,7 +980,7 @@ WriteGroupSources(const char* name, std::string path = this->ConvertPath(source, s->RelativePath); this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << name << " Include=\"" - << path; + << cmVS10EscapeXML(path); if(strlen(filter)) { (*this->BuildFileStream) << "\">\n"; @@ -1033,7 +1035,8 @@ void cmVisualStudio10TargetGenerator::WriteSource( } this->ConvertToWindowsSlash(sourceFile); this->WriteString("<", 2); - (*this->BuildFileStream ) << tool << " Include=\"" << sourceFile << "\""; + (*this->BuildFileStream ) << tool << " Include=\"" + << cmVS10EscapeXML(sourceFile) << "\""; if(sf->GetExtension() == "h" && this->IsResxHeader(sf->GetFullPath())) @@ -1165,7 +1168,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() std::string obj = *oi; this->WriteString("<Object Include=\"", 2); this->ConvertToWindowsSlash(obj); - (*this->BuildFileStream ) << obj << "\" />\n"; + (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\" />\n"; } this->WriteString("</ItemGroup>\n", 1); @@ -1735,6 +1738,9 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) } // Replace spaces in libs with ; cmSystemTools::ReplaceString(libs, " ", ";"); + std::vector<std::string> libVec; + cmSystemTools::ExpandListArgument(libs, libVec); + cmComputeLinkInformation* pcli = this->Target->GetLinkInformation(config.c_str()); if(!pcli) @@ -1746,28 +1752,21 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) } // add the libraries for the target to libs string cmComputeLinkInformation& cli = *pcli; - this->AddLibraries(cli, libs); - linkOptions.AddFlag("AdditionalDependencies", libs.c_str()); + this->AddLibraries(cli, libVec); + linkOptions.AddFlag("AdditionalDependencies", libVec); std::vector<std::string> const& ldirs = cli.GetDirectories(); - const char* sep = ""; - std::string linkDirs; + std::vector<std::string> linkDirs; for(std::vector<std::string>::const_iterator d = ldirs.begin(); d != ldirs.end(); ++d) { // first just full path - linkDirs += sep; - linkDirs += *d; - sep = ";"; - linkDirs += sep; + linkDirs.push_back(*d); // next path with configuration type Debug, Release, etc - linkDirs += *d; - linkDirs += "/$(Configuration)"; - linkDirs += sep; + linkDirs.push_back(*d + "/$(Configuration)"); } - linkDirs += "%(AdditionalLibraryDirectories)"; - linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs.c_str()); - linkOptions.AddFlag("AdditionalDependencies", libs.c_str()); + linkDirs.push_back("%(AdditionalLibraryDirectories)"); + linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs); std::string targetName; std::string targetNameSO; @@ -1867,11 +1866,10 @@ cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config) void cmVisualStudio10TargetGenerator::AddLibraries( cmComputeLinkInformation& cli, - std::string& libstring) + std::vector<std::string>& libVec) { typedef cmComputeLinkInformation::ItemVector ItemVector; ItemVector libs = cli.GetItems(); - const char* sep = ";"; for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) { if(l->IsPath) @@ -1881,14 +1879,12 @@ void cmVisualStudio10TargetGenerator::AddLibraries( cmLocalGenerator::START_OUTPUT, cmLocalGenerator::UNCHANGED); this->ConvertToWindowsSlash(path); - libstring += sep; - libstring += path; + libVec.push_back(path); } else if (!l->Target || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY) { - libstring += sep; - libstring += l->Value; + libVec.push_back(l->Value); } } } @@ -2051,7 +2047,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() path += dt->GetName(); path += ".vcxproj"; } - (*this->BuildFileStream) << path << "\">\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n"; this->WriteString("<Project>", 3); (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str()) diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 6c92b57..7a329cb 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -90,7 +90,8 @@ private: void WriteGroups(); void WriteProjectReferences(); bool OutputSourceSpecificFlags(cmSourceFile const* source); - void AddLibraries(cmComputeLinkInformation& cli, std::string& libstring); + void AddLibraries(cmComputeLinkInformation& cli, + std::vector<std::string>& libVec); void WriteLibOptions(std::string const& config); void WriteEvents(std::string const& configName); void WriteEvent(const char* name, diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 2cbf5db..b14fc45 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -3,9 +3,9 @@ #include <cmsys/System.h> #include "cmVisualStudio10TargetGenerator.h" -inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s) +static +std::string cmVisualStudio10GeneratorOptionsEscapeForXML(std::string ret) { - std::string ret = s; cmSystemTools::ReplaceString(ret, ";", "%3B"); cmSystemTools::ReplaceString(ret, "&", "&"); cmSystemTools::ReplaceString(ret, "<", "<"); @@ -13,9 +13,9 @@ inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s) return ret; } -inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s) +static +std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret) { - std::string ret = s; cmSystemTools::ReplaceString(ret, "&", "&"); cmSystemTools::ReplaceString(ret, "\"", """); cmSystemTools::ReplaceString(ret, "<", "<"); @@ -269,7 +269,7 @@ cmVisualStudioGeneratorOptions // Escape this flag for the IDE. if(this->Version >= cmLocalVisualStudioGenerator::VS10) { - define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str()); + define = cmVisualStudio10GeneratorOptionsEscapeForXML(define); if(lang == "RC") { @@ -278,7 +278,7 @@ cmVisualStudioGeneratorOptions } else { - define = cmVisualStudioGeneratorOptionsEscapeForXML(define.c_str()); + define = cmVisualStudioGeneratorOptionsEscapeForXML(define); } // Store the flag in the project file. fout << sep << define; @@ -301,7 +301,7 @@ cmVisualStudioGeneratorOptions { if(this->Version >= cmLocalVisualStudioGenerator::VS10) { - for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin(); + for(std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin(); m != this->FlagMap.end(); ++m) { fout << indent; @@ -317,20 +317,34 @@ cmVisualStudioGeneratorOptions { fout << "<" << m->first << ">"; } - fout << m->second; + const char* sep = ""; + for(std::vector<std::string>::iterator i = m->second.begin(); + i != m->second.end(); ++i) + { + fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i); + sep = ";"; + } if (m->first == "AdditionalIncludeDirectories") { - fout << ";%(AdditionalIncludeDirectories)"; + fout << sep << "%(AdditionalIncludeDirectories)"; } fout << "</" << m->first << ">\n"; } } else { - for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin(); + for(std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin(); m != this->FlagMap.end(); ++m) { - fout << indent << m->first << "=\"" << m->second << "\"\n"; + fout << indent << m->first << "=\""; + const char* sep = ""; + for(std::vector<std::string>::iterator i = m->second.begin(); + i != m->second.end(); ++i) + { + fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i); + sep = ";"; + } + fout << "\"\n"; } } } @@ -359,14 +373,13 @@ cmVisualStudioGeneratorOptions { fout << "<AdditionalOptions>"; } - fout << this->FlagString.c_str() + fout << cmVisualStudio10GeneratorOptionsEscapeForXML(this->FlagString) << " %(AdditionalOptions)</AdditionalOptions>\n"; } else { fout << prefix << "AdditionalOptions=\""; - fout << - cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString.c_str()); + fout << cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString); fout << "\"" << suffix; } } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a051c87..5aa1ab0 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1715,7 +1715,7 @@ int cmake::Generate() { return -1; } - this->GlobalGenerator->Generate(); + this->GlobalGenerator->DoGenerate(); if ( !this->GraphVizFile.empty() ) { std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl; diff --git a/Tests/CTestTestMemcheck/CMakeLists.txt b/Tests/CTestTestMemcheck/CMakeLists.txt index d16d432..3ad0b26 100644 --- a/Tests/CTestTestMemcheck/CMakeLists.txt +++ b/Tests/CTestTestMemcheck/CMakeLists.txt @@ -121,7 +121,7 @@ set(CTEST_EXTRA_CODE) # add LeakSanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE @@ -136,7 +136,7 @@ set_tests_properties(CTestTestMemcheckDummyLeakSanitizer PROPERTIES ".*Memory checking results:.*Direct leak - 2.*Indirect leak - 1.*") # add AddressSanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE @@ -225,7 +225,7 @@ set_tests_properties(CTestTestMemcheckDummyValgrindIgnoreMemcheck PASS_REGULAR_EXPRESSION "\n2/2 Test #2: RunCMakeAgain .*${ctest_and_tool_outputs}$") set_tests_properties(CTestTestMemcheckDummyBC PROPERTIES - PASS_REGULAR_EXPRESSION "\n1/1 MemCheck #1: RunCMake \\.+ Passed +[0-9]+.[0-9]+ sec\n\n100% tests passed, 0 tests failed out of 1\n(.*\n)?Error parsing XML in stream at line 1: no element found\n") + PASS_REGULAR_EXPRESSION "\n1/1 MemCheck #1: RunCMake \\.+ Passed +[0-9]+.[0-9]+ sec\n${guard_malloc_lines}\n100% tests passed, 0 tests failed out of 1\n(.*\n)?Error parsing XML in stream at line 1: no element found\n") set_tests_properties(CTestTestMemcheckDummyValgrindInvalidSupFile PROPERTIES PASS_REGULAR_EXPRESSION "\nCannot find memory checker suppression file: ${CTEST_ESCAPED_REALPATH_CMAKE_CURRENT_BINARY_DIR}/does-not-exist\n") diff --git a/Tests/CTestTestMemcheck/testAddressSanitizer.cmake b/Tests/CTestTestMemcheck/testAddressSanitizer.cmake index a359e28..a073151 100644 --- a/Tests/CTestTestMemcheck/testAddressSanitizer.cmake +++ b/Tests/CTestTestMemcheck/testAddressSanitizer.cmake @@ -5,6 +5,10 @@ message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]") string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}") message("LOG_FILE=[${LOG_FILE}]") +# if we are not asked to simulate address sanitizer don't do it +if(NOT "$ENV{ASAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") + return() +endif() # clear the log file file(REMOVE "${LOG_FILE}.2343") diff --git a/Tests/CTestTestMemcheck/testLeakSanitizer.cmake b/Tests/CTestTestMemcheck/testLeakSanitizer.cmake index ca0a264..02030be 100644 --- a/Tests/CTestTestMemcheck/testLeakSanitizer.cmake +++ b/Tests/CTestTestMemcheck/testLeakSanitizer.cmake @@ -4,9 +4,14 @@ message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]") string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}") message("LOG_FILE=[${LOG_FILE}]") +# if we are not asked to simulate leak sanitizer don't do it +if(NOT "$ENV{ASAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") + return() +endif() # clear the log file file(REMOVE "${LOG_FILE}.2343") +file(REMOVE "${LOG_FILE}.2344") # create an error of each type of thread santizer # these names come from tsan_report.cc in llvm @@ -20,6 +25,12 @@ Direct leak of 4360 byte(s) in 1 object(s) allocated from: #1 0x4823b4 in main /home/kitware/msan/memcheck.cxx:12 #2 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 +SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +") +file(APPEND "${LOG_FILE}.2342" +"================================================================= +==25308==ERROR: LeakSanitizer: detected memory leaks + Direct leak of 76 byte(s) in 1 object(s) allocated from: #0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669) #1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4 diff --git a/Tests/Complex/CMakeLists.txt b/Tests/Complex/CMakeLists.txt index 222250c..5e5eead 100644 --- a/Tests/Complex/CMakeLists.txt +++ b/Tests/Complex/CMakeLists.txt @@ -14,6 +14,21 @@ if(POLICY CMP0003) endif() endif() +# It is not recommended to set a policy to OLD, but this test +# covers the OLD behavior of some policies. +foreach(p + CMP0029 + CMP0032 + CMP0033 + CMP0034 + CMP0043 + CMP0050 + ) + if(POLICY ${p}) + cmake_policy(SET ${p} OLD) + endif() +endforeach() + # Test building without per-rule echo lines in Makefiles. set_property(GLOBAL PROPERTY RULE_MESSAGES OFF) diff --git a/Tests/ComplexOneConfig/CMakeLists.txt b/Tests/ComplexOneConfig/CMakeLists.txt index 3f17dcc..3b73e70 100644 --- a/Tests/ComplexOneConfig/CMakeLists.txt +++ b/Tests/ComplexOneConfig/CMakeLists.txt @@ -14,6 +14,21 @@ if(POLICY CMP0003) endif() endif() +# It is not recommended to set a policy to OLD, but this test +# covers the OLD behavior of some policies. +foreach(p + CMP0029 + CMP0032 + CMP0033 + CMP0034 + CMP0043 + CMP0050 + ) + if(POLICY ${p}) + cmake_policy(SET ${p} OLD) + endif() +endforeach() + # Test building without per-rule echo lines in Makefiles. set_property(GLOBAL PROPERTY RULE_MESSAGES OFF) |