diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in index 3a72eaa5c..47dad49c2 100644 --- a/CMakeCPackOptions.cmake.in +++ b/CMakeCPackOptions.cmake.in @@ -51,3 +51,27 @@ if("${CPACK_GENERATOR}" STREQUAL "PackageMaker") set(CPACK_PACKAGE_DEFAULT_LOCATION "/usr") endif() endif() + +if("${CPACK_GENERATOR}" STREQUAL "WIX") + # Reset CPACK_PACKAGE_VERSION to deal with WiX restriction. + # But the file names still use the full CMake_VERSION value: + set(CPACK_PACKAGE_FILE_NAME + "${CPACK_PACKAGE_NAME}-@CMake_VERSION@-${CPACK_SYSTEM_NAME}") + set(CPACK_SOURCE_PACKAGE_FILE_NAME + "${CPACK_PACKAGE_NAME}-@CMake_VERSION@-Source") + + if(NOT CPACK_WIX_SIZEOF_VOID_P) + set(CPACK_WIX_SIZEOF_VOID_P "@CMAKE_SIZEOF_VOID_P@") + endif() + + set(CPACK_PACKAGE_VERSION + "@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@.@CMake_VERSION_PATCH@") + # WIX installers require at most a 4 component version number, where + # each component is an integer between 0 and 65534 inclusive + set(tweak "@CMake_VERSION_TWEAK@") + if(tweak MATCHES "^[0-9]+$") + if(tweak GREATER 0 AND tweak LESS 65535) + set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}.${tweak}") + endif() + endif() +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index a67fb6e62..e84f8980e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,8 +234,6 @@ macro (CMAKE_BUILD_UTILITIES) set(kwsys_folder "Utilities/KWSys") CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}") CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}_c "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}EncodeExecutable "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}ProcessFwd9x "${kwsys_folder}") if(BUILD_TESTING) CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestDynload "${kwsys_folder}") CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestProcess "${kwsys_folder}") @@ -590,10 +588,10 @@ if(NOT CMake_VERSION_IS_RELEASE) NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 4.2) set(C_FLAGS_LIST -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security - -Wmissing-format-attribute -fno-common + -Wmissing-format-attribute -fno-common -Wundef ) set(CXX_FLAGS_LIST -Wnon-virtual-dtor -Wcast-align -Wchar-subscripts -Wall -W - -Wshadow -Wpointer-arith -Wformat-security + -Wshadow -Wpointer-arith -Wformat-security -Wundef ) foreach(FLAG_LANG C CXX) diff --git a/ChangeLog.manual b/ChangeLog.manual index aa5534812..90c91629e 100644 --- a/ChangeLog.manual +++ b/ChangeLog.manual @@ -1,3 +1,17 @@ +Changes in CMake 2.8.10.2 (since 2.8.10.1) +---------------------------------------------- +Alex Neundorf (1): + Automoc: fix regression #13667, broken build in phonon + +Brad King (1): + Initialize IMPORTED GLOBAL targets on reconfigure (#13702) + +David Cole (1): + CMake: Fix infinite loop untarring corrupt tar file + +Rolf Eike Beer (1): + FindGettext: fix overwriting result with empty variable (#13691) + Changes in CMake 2.8.10.1 (since 2.8.10) ---------------------------------------------- Brad King (5): diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index d74dcdcee..c41adc956 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -50,6 +50,7 @@ endif() set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "@CMAKE_C_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") @SET_CMAKE_CMCLDEPS_EXECUTABLE@ @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 8c5d84e6c..9287b8194 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -51,6 +51,7 @@ endif() set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") @SET_CMAKE_CMCLDEPS_EXECUTABLE@ @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 75247d955..25d6bbea7 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -72,19 +72,9 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) # Parse implicit linker information for this language, if available. set(implicit_dirs "") set(implicit_libs "") - set(MULTI_ARCH FALSE) - if(DEFINED CMAKE_OSX_ARCHITECTURES) - if( "${CMAKE_OSX_ARCHITECTURES}" MATCHES ";" ) - set(MULTI_ARCH TRUE) - endif() - endif() - if(CMAKE_${lang}_VERBOSE_FLAG - # Implicit link information cannot be used explicitly for - # multiple OS X architectures, so we skip it. - AND NOT MULTI_ARCH - # Skip this with Xcode for now. - AND NOT "${CMAKE_GENERATOR}" MATCHES Xcode) - CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs log + set(implicit_fwks "") + if(CMAKE_${lang}_VERBOSE_FLAG) + CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs implicit_fwks log "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Parsed ${lang} implicit link information from above output:\n${log}\n\n") @@ -112,8 +102,17 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) message(STATUS "${_desc}") endif() + # Implicit link libraries cannot be used explicitly for multiple + # OS X architectures, so we skip it. + if(DEFINED CMAKE_OSX_ARCHITECTURES) + if("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";") + set(implicit_libs "") + endif() + endif() + set(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE) set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE) + set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE) # Detect library architecture directory name. if(CMAKE_LIBRARY_ARCHITECTURE_REGEX) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 906a5e7ba..609f35bf7 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -107,11 +107,14 @@ Id flags: ${testflags} ") # Compile the compiler identification source. - if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([0-9]+)( .NET)?( 200[358])? *((Win64|IA64|ARM))?") + if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([0-9]+)") set(vs_version ${CMAKE_MATCH_1}) - set(vs_arch ${CMAKE_MATCH_4}) + set(id_arch ${CMAKE_VS_PLATFORM_NAME}) set(id_lang "${lang}") set(id_cl cl.exe) + if(NOT id_arch) + set(id_arch Win32) + endif() if(NOT "${vs_version}" VERSION_LESS 10) set(v 10) set(ext vcxproj) @@ -123,25 +126,26 @@ Id flags: ${testflags} set(v 6) set(ext dsp) endif() - if("${vs_arch}" STREQUAL "Win64") - set(id_machine_7 17) + if("${id_arch}" STREQUAL "x64") set(id_machine_10 MachineX64) - set(id_arch x64) - elseif("${vs_arch}" STREQUAL "IA64") - set(id_machine_7 5) + elseif("${id_arch}" STREQUAL "Itanium") set(id_machine_10 MachineIA64) set(id_arch ia64) else() set(id_machine_6 x86) - set(id_machine_7 1) set(id_machine_10 MachineX86) - set(id_arch Win32) endif() if(CMAKE_VS_PLATFORM_TOOLSET) set(id_toolset "${CMAKE_VS_PLATFORM_TOOLSET}") else() set(id_toolset "") endif() + if(CMAKE_VS_WINCE_VERSION) + set(id_entrypoint "mainACRTStartup") + set(id_subsystem 9) + else() + set(id_subsystem 1) + endif() if("${CMAKE_MAKE_PROGRAM}" MATCHES "[Mm][Ss][Bb][Uu][Ii][Ll][Dd]") set(build /p:Configuration=Debug /p:Platform=@id_arch@ /p:VisualStudioVersion=${vs_version}.0) elseif("${CMAKE_MAKE_PROGRAM}" MATCHES "[Mm][Ss][Dd][Ee][Vv]") diff --git a/Modules/CMakeDetermineJavaCompiler.cmake b/Modules/CMakeDetermineJavaCompiler.cmake index c4217f552..ae9f5fcaf 100644 --- a/Modules/CMakeDetermineJavaCompiler.cmake +++ b/Modules/CMakeDetermineJavaCompiler.cmake @@ -63,6 +63,8 @@ if(NOT CMAKE_Java_COMPILER) /usr/java/j2sdk1.4.2_09/bin /usr/lib/j2sdk1.5-sun/bin /opt/sun-jdk-1.5.0.04/bin + /usr/local/jdk-1.7.0/bin + /usr/local/jdk-1.6.0/bin ) # if no compiler has been specified yet, then look for one if(CMAKE_Java_COMPILER_INIT) diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index cd3344756..c7f9c32a7 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -106,6 +106,12 @@ if(CMAKE_SYSTEM_NAME) set(CMAKE_CROSSCOMPILING TRUE) endif() set(PRESET_CMAKE_SYSTEM_NAME TRUE) +elseif(CMAKE_VS_WINCE_VERSION) + set(CMAKE_SYSTEM_NAME "WindowsCE") + set(CMAKE_SYSTEM_VERSION "${CMAKE_VS_WINCE_VERSION}") + set(CMAKE_SYSTEM_PROCESSOR "${MSVC_C_ARCHITECTURE_ID}") + set(CMAKE_CROSSCOMPILING TRUE) + set(PRESET_CMAKE_SYSTEM_NAME TRUE) else() set(CMAKE_SYSTEM_NAME "${CMAKE_HOST_SYSTEM_NAME}") set(CMAKE_SYSTEM_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 55f827773..d193881d9 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -52,3 +52,4 @@ endif() set(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES "@CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index 4d25de0ba..f84852aeb 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -74,12 +74,8 @@ PRINT *, 'INFO:platform[IRIX]' #elif defined(__hpux) || defined(__hpux__) PRINT *, 'INFO:platform[HP-UX]' -#elif defined(__HAIKU) || defined(__HAIKU__) || defined(_HAIKU) +#elif defined(__HAIKU__) PRINT *, 'INFO:platform[Haiku]' -# if 0 -! Haiku also defines __BEOS__ so we must -! put it prior to the check for __BEOS__ -# endif #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) PRINT *, 'INFO:platform[BeOS]' #elif defined(__QNX__) || defined(__QNXNTO__) diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake index 96ecb4270..a92ce7cc9 100644 --- a/Modules/CMakePackageConfigHelpers.cmake +++ b/Modules/CMakePackageConfigHelpers.cmake @@ -188,8 +188,13 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile) endif() endforeach() + get_filename_component(inputFileName "${_inputFile}" NAME) + set(PACKAGE_INIT " ####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### +####### Any changes to this file will be overwritten by the next CMake run #### +####### The input file was ${inputFileName} ######## + get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_RELATIVE_PATH}\" ABSOLUTE) ") diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index ecb20dc6b..234fb7fa1 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -16,9 +16,10 @@ # This is used internally by CMake and should not be included by user # code. -function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) +function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj_regex) set(implicit_libs_tmp "") set(implicit_dirs_tmp) + set(implicit_fwks_tmp) set(log "") # Parse implicit linker arguments. @@ -36,6 +37,16 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) set(cmd) if("${line}" MATCHES "${linker_regex}" AND NOT "${line}" MATCHES "${linker_exclude_regex}") + if(XCODE) + # Xcode unconditionally adds a path under the project build tree and + # on older versions it is not reported with proper quotes. Remove it. + string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" _dir_regex "${CMAKE_BINARY_DIR}") + string(REGEX REPLACE " -[FL]${_dir_regex}/([^ ]| [^-])+( |$)" " " xline "${line}") + if(NOT "x${xline}" STREQUAL "x${line}") + set(log "${log} reduced line: [${line}]\n to: [${xline}]\n") + set(line "${xline}") + endif() + endif() if(UNIX) separate_arguments(args UNIX_COMMAND "${line}") else() @@ -97,6 +108,18 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) endif() endforeach() + # Look for library search paths reported by linker. + if("${output_lines}" MATCHES ";Library search paths:((;\t[^;]+)+)") + string(REPLACE ";\t" ";" implicit_dirs_match "${CMAKE_MATCH_1}") + set(log "${log} Library search paths: [${implicit_dirs_match}]\n") + list(APPEND implicit_dirs_tmp ${implicit_dirs_match}) + endif() + if("${output_lines}" MATCHES ";Framework search paths:((;\t[^;]+)+)") + string(REPLACE ";\t" ";" implicit_fwks_match "${CMAKE_MATCH_1}") + set(log "${log} Framework search paths: [${implicit_fwks_match}]\n") + list(APPEND implicit_fwks_tmp ${implicit_fwks_match}) + endif() + # Cleanup list of libraries and flags. # We remove items that are not language-specific. set(implicit_libs "") @@ -108,21 +131,33 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) endif() endforeach() - # Cleanup list of directories. - set(implicit_dirs "") - foreach(d IN LISTS implicit_dirs_tmp) - get_filename_component(dir "${d}" ABSOLUTE) - list(APPEND implicit_dirs "${dir}") - set(log "${log} collapse dir [${d}] ==> [${dir}]\n") + # Cleanup list of library and framework directories. + set(desc_dirs "library") + set(desc_fwks "framework") + foreach(t dirs fwks) + set(implicit_${t} "") + foreach(d IN LISTS implicit_${t}_tmp) + get_filename_component(dir "${d}" ABSOLUTE) + string(FIND "${dir}" "${CMAKE_FILES_DIRECTORY}/" pos) + if(NOT pos LESS 0) + set(msg ", skipping non-system directory") + else() + set(msg "") + list(APPEND implicit_${t} "${dir}") + endif() + set(log "${log} collapse ${desc_${t}} dir [${d}] ==> [${dir}]${msg}\n") + endforeach() + list(REMOVE_DUPLICATES implicit_${t}) endforeach() - list(REMOVE_DUPLICATES implicit_dirs) # Log results. set(log "${log} implicit libs: [${implicit_libs}]\n") set(log "${log} implicit dirs: [${implicit_dirs}]\n") + set(log "${log} implicit fwks: [${implicit_fwks}]\n") # Return results. set(${lib_var} "${implicit_libs}" PARENT_SCOPE) set(${dir_var} "${implicit_dirs}" PARENT_SCOPE) + set(${fwk_var} "${implicit_fwks}" PARENT_SCOPE) set(${log_var} "${log}" PARENT_SCOPE) endfunction() diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index c37341411..69171c2a3 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -35,11 +35,8 @@ #elif defined(__hpux) || defined(__hpux__) # define PLATFORM_ID "HP-UX" -#elif defined(__HAIKU) || defined(__HAIKU__) || defined(_HAIKU) +#elif defined(__HAIKU__) # define PLATFORM_ID "Haiku" -/* Haiku also defines __BEOS__ so we must - put it prior to the check for __BEOS__ -*/ #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) # define PLATFORM_ID "BeOS" diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 6886ed9fd..42d3c0c39 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -438,6 +438,7 @@ if(NOT CPACK_GENERATOR) endif() else() option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON) + option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF) option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF) endif() @@ -453,6 +454,7 @@ if(NOT CPACK_GENERATOR) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_TGZ TGZ) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_TBZ2 TBZ2) 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) endif() @@ -483,7 +485,7 @@ endif() mark_as_advanced(CPACK_BINARY_CYGWIN CPACK_BINARY_PACKAGEMAKER CPACK_BINARY_OSXX11 CPACK_BINARY_STGZ CPACK_BINARY_TGZ CPACK_BINARY_TBZ2 CPACK_BINARY_DEB CPACK_BINARY_RPM CPACK_BINARY_TZ - CPACK_BINARY_NSIS CPACK_BINARY_ZIP CPACK_BINARY_BUNDLE + CPACK_BINARY_NSIS CPACK_BINARY_WIX CPACK_BINARY_ZIP CPACK_BINARY_BUNDLE CPACK_SOURCE_CYGWIN CPACK_SOURCE_TBZ2 CPACK_SOURCE_TGZ CPACK_SOURCE_TZ CPACK_SOURCE_ZIP CPACK_BINARY_DRAGNDROP) @@ -522,6 +524,9 @@ cpack_set_if_not_set(CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") cpack_set_if_not_set(CPACK_NSIS_INSTALLER_ICON_CODE "") cpack_set_if_not_set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") +# WiX specific variables +cpack_set_if_not_set(CPACK_WIX_SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P}") + if(DEFINED CPACK_COMPONENTS_ALL) if(CPACK_MONOLITHIC_INSTALL) message("CPack warning: both CPACK_COMPONENTS_ALL and CPACK_MONOLITHIC_INSTALL have been set.\nDefaulting to a monolithic installation.") diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake new file mode 100644 index 000000000..0c0a8f19f --- /dev/null +++ b/Modules/CPackWIX.cmake @@ -0,0 +1,109 @@ +##section Variables specific to CPack WiX generator +##end +##module +# - CPack WiX generator specific options +# +# The following variables are specific to the installers built +# on Windows using WiX. +##end +##variable +# CPACK_WIX_UPGRADE_GUID - Upgrade GUID (Product/@UpgradeCode) +# +# Will be automatically generated unless explicitly provided. +# +# It should be explicitly set to a constant generated +# gloabally unique identifier (GUID) to allow your installers +# to replace existing installations that use the same GUID. +# +# You may for example explicitly set this variable in +# your CMakeLists.txt to the value that has been generated per default. +# You should not use GUIDs that you did not generate yourself or which may +# belong to other projects. +# +# A GUID shall have the following fixed length syntax: +# XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +# (each X represents an uppercase hexadecimal digit) +##end +##variable +# CPACK_WIX_PRODUCT_GUID - Product GUID (Product/@Id) +# +# Will be automatically generated unless explicitly provided. +# +# If explicitly provided this will set the Product Id of your installer. +# +# The installer will abort if it detects a pre-existing installation that uses +# the same GUID. +# +# The GUID shall use the syntax described for CPACK_WIX_UPGRADE_GUID. +##end +##variable +# CPACK_WIX_LICENSE_RTF - RTF License File +# +# If CPACK_RESOURCE_FILE_LICENSE has an .rtf extension +# it is used as-is. +# +# If CPACK_RESOURCE_FILE_LICENSE has an .txt extension +# it is implicitly converted to RTF by the WiX Generator. +# +# With CPACK_WIX_LICENSE_RTF you can override the license file used +# by the WiX Generator in case CPACK_RESOURCE_FILE_LICENSE +# is in an unsupported format or the .txt -> .rtf +# conversion does not work as expected. +# +##end +# +##variable +# CPACK_WIX_PRODUCT_ICON - The Icon shown next to the program name in Add/Remove programs. +# +# If set, this icon is used in place of the default icon. +# +##end +# +##variable +# CPACK_WIX_UI_BANNER - The bitmap will appear at the top of all installer pages other than the welcome and completion dialogs. +# +# If set, this image will replace the default banner image. +# +# This image must be 493 by 58 pixels. +# +##end +# +##variable +# CPACK_WIX_UI_DIALOG - Background bitmap used on the welcome and completion dialogs. +# +# If this variable is set, the installer will replace the default dialog image. +# +# This image must be 493 by 312 pixels. +# +##end + +#============================================================================= +# Copyright 2012 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. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if(NOT CPACK_WIX_ROOT) + file(TO_CMAKE_PATH "$ENV{WIX}" CPACK_WIX_ROOT) +endif() + +find_program(CPACK_WIX_CANDLE_EXECUTABLE candle + PATHS "${CPACK_WIX_ROOT}/bin") + +if(NOT CPACK_WIX_CANDLE_EXECUTABLE) + message(FATAL_ERROR "Could not find the WiX candle executable.") +endif() + +find_program(CPACK_WIX_LIGHT_EXECUTABLE light + PATHS "${CPACK_WIX_ROOT}/bin") + +if(NOT CPACK_WIX_LIGHT_EXECUTABLE) + message(FATAL_ERROR "Could not find the WiX light executable.") +endif() diff --git a/Modules/CTestUseLaunchers.cmake b/Modules/CTestUseLaunchers.cmake index 6731d3754..24f5f2e16 100644 --- a/Modules/CTestUseLaunchers.cmake +++ b/Modules/CTestUseLaunchers.cmake @@ -35,7 +35,7 @@ if(NOT DEFINED CTEST_USE_LAUNCHERS AND DEFINED ENV{CTEST_USE_LAUNCHERS_DEFAULT}) CACHE INTERNAL "CTEST_USE_LAUNCHERS initial value from ENV") endif() -if(NOT "${CMAKE_GENERATOR}" MATCHES "Make") +if(NOT "${CMAKE_GENERATOR}" MATCHES "Make|Ninja") set(CTEST_USE_LAUNCHERS 0) endif() diff --git a/Modules/CheckForPthreads.c b/Modules/CheckForPthreads.c index 882dc21b7..7250fbff6 100644 --- a/Modules/CheckForPthreads.c +++ b/Modules/CheckForPthreads.c @@ -16,7 +16,7 @@ int main(int ac, char*av[]){ pthread_create(&tid[0], 0, runner, (void*)1); pthread_create(&tid[1], 0, runner, (void*)2); -#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__) // (no usleep on BeOS 5.) +#if defined(__BEOS__) && !defined(__ZETA__) // (no usleep on BeOS 5.) usleep(1); // for strange behavior on single-processor sun #endif diff --git a/Modules/CompilerId/VS-7.vcproj.in b/Modules/CompilerId/VS-7.vcproj.in index 71bf64de2..fa48cadb3 100644 --- a/Modules/CompilerId/VS-7.vcproj.in +++ b/Modules/CompilerId/VS-7.vcproj.in @@ -24,7 +24,6 @@ " + ) + set_property(TARGET Qt4::${_QT_MODULE} APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS + "$" + ) + endforeach() + endif() + endmacro() + + macro(_qt4_add_target_depends _QT_MODULE) + _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_INTERFACE_LIBRARIES ${ARGN}) + endmacro() + + macro(_qt4_add_target_private_depends _QT_MODULE) + _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_DEPENDENT_LIBRARIES ${ARGN}) + endmacro() + + # Set QT_xyz_LIBRARY variable and add # library include path to QT_INCLUDES _QT4_ADJUST_LIB_VARS(QtCore) + set_property(TARGET Qt4::QtCore APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + "${QT_MKSPECS_DIR}/default" + ${QT_INCLUDE_DIR} + ) foreach(QT_MODULE ${QT_MODULES}) _QT4_ADJUST_LIB_VARS(${QT_MODULE}) + _qt4_add_target_depends(${QT_MODULE} Core) endforeach() _QT4_ADJUST_LIB_VARS(QtAssistant) @@ -958,6 +1013,41 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) _QT4_ADJUST_LIB_VARS(QAxContainer) endif() + # Only public dependencies are listed here. + # Eg, QtDBus links to QtXml, but users of QtDBus do not need to + # link to QtXml because QtDBus only uses it internally, not in public + # headers. + # Everything depends on QtCore, but that is covered above already + _qt4_add_target_depends(Qt3Support Sql Gui Network) + if (TARGET Qt4::Qt3Support) + # An additional define is required for QT3_SUPPORT + set_property(TARGET Qt4::Qt3Support APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS QT3_SUPPORT) + endif() + _qt4_add_target_depends(QtDeclarative Script Gui) + _qt4_add_target_depends(QtDesigner Gui) + _qt4_add_target_depends(QtHelp Gui) + _qt4_add_target_depends(QtMultimedia Gui) + _qt4_add_target_depends(QtOpenGL Gui) + _qt4_add_target_depends(QtSvg Gui) + _qt4_add_target_depends(QtWebKit Gui Network) + + _qt4_add_target_private_depends(Qt3Support Xml) + _qt4_add_target_private_depends(QtSvg Xml) + _qt4_add_target_private_depends(QtDBus Xml) + _qt4_add_target_private_depends(QtUiTools Xml Gui) + _qt4_add_target_private_depends(QtHelp Sql Xml Network) + _qt4_add_target_private_depends(QtXmlPatterns Network) + _qt4_add_target_private_depends(QtScriptTools Gui) + _qt4_add_target_private_depends(QtWebKit XmlPatterns) + _qt4_add_target_private_depends(QtDeclarative XmlPatterns Svg Sql Gui) + _qt4_add_target_private_depends(QtMultimedia Gui) + _qt4_add_target_private_depends(QtOpenGL Gui) + _qt4_add_target_private_depends(QAxServer Gui) + _qt4_add_target_private_depends(QAxContainer Gui) + _qt4_add_target_private_depends(phonon Gui) + if(QT_QTDBUS_FOUND) + _qt4_add_target_private_depends(phonon DBus) + endif() ####################################### # @@ -982,13 +1072,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) endif() find_program(QT_MOC_EXECUTABLE - NAMES moc-qt4 moc + NAMES moc-qt4 moc moc4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) find_program(QT_UIC_EXECUTABLE - NAMES uic-qt4 uic + NAMES uic-qt4 uic uic4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) @@ -1018,13 +1108,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) ) find_program(QT_LUPDATE_EXECUTABLE - NAMES lupdate-qt4 lupdate + NAMES lupdate-qt4 lupdate lupdate4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) find_program(QT_LRELEASE_EXECUTABLE - NAMES lrelease-qt4 lrelease + NAMES lrelease-qt4 lrelease lrelease4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) @@ -1036,13 +1126,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) ) find_program(QT_DESIGNER_EXECUTABLE - NAMES designer-qt4 designer + NAMES designer-qt4 designer designer4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) find_program(QT_LINGUIST_EXECUTABLE - NAMES linguist-qt4 linguist + NAMES linguist-qt4 linguist linguist4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) @@ -1170,11 +1260,6 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) include("${_qt4_current_dir}/Qt4Macros.cmake") - # set version variables - string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" QT_VERSION_MAJOR "${QTVERSION}") - string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" QT_VERSION_MINOR "${QTVERSION}") - string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" QT_VERSION_PATCH "${QTVERSION}") - endif() #support old QT_MIN_VERSION if set, but not if version is supplied by find_package() diff --git a/Modules/FindSDL.cmake b/Modules/FindSDL.cmake index f2e9f25f5..fec142ed5 100644 --- a/Modules/FindSDL.cmake +++ b/Modules/FindSDL.cmake @@ -122,7 +122,7 @@ if(SDL_LIBRARY_TEMP) if(SDLMAIN_LIBRARY AND NOT SDL_BUILDING_LIBRARY) list(FIND SDL_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" _SDL_MAIN_INDEX) if(_SDL_MAIN_INDEX EQUAL -1) - list(APPEND SDL_LIBRARY_TEMP "${SDLMAIN_LIBRARY}") + set(SDL_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" ${SDL_LIBRARY_TEMP}) endif() unset(_SDL_MAIN_INDEX) endif() diff --git a/Modules/FindSDL_image.cmake b/Modules/FindSDL_image.cmake index 4cae03274..30d74acfb 100644 --- a/Modules/FindSDL_image.cmake +++ b/Modules/FindSDL_image.cmake @@ -40,7 +40,7 @@ find_path(SDL_IMAGE_INCLUDE_DIR SDL_image.h HINTS ENV SDLIMAGEDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_IMAGE_LIBRARY AND SDLIMAGE_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_IMAGE_LIBRARY HINTS ENV SDLIMAGEDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_IMAGE_INCLUDE_DIR AND EXISTS "${SDL_IMAGE_INCLUDE_DIR}/SDL_image.h") diff --git a/Modules/FindSDL_mixer.cmake b/Modules/FindSDL_mixer.cmake index 666fc6e0f..8ca7cc33c 100644 --- a/Modules/FindSDL_mixer.cmake +++ b/Modules/FindSDL_mixer.cmake @@ -40,7 +40,7 @@ find_path(SDL_MIXER_INCLUDE_DIR SDL_mixer.h HINTS ENV SDLMIXERDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_MIXER_LIBRARY AND SDLMIXER_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_MIXER_LIBRARY HINTS ENV SDLMIXERDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_MIXER_INCLUDE_DIR AND EXISTS "${SDL_MIXER_INCLUDE_DIR}/SDL_mixer.h") diff --git a/Modules/FindSDL_net.cmake b/Modules/FindSDL_net.cmake index d8f479f5b..ca707af8d 100644 --- a/Modules/FindSDL_net.cmake +++ b/Modules/FindSDL_net.cmake @@ -40,7 +40,7 @@ find_path(SDL_NET_INCLUDE_DIR SDL_net.h HINTS ENV SDLNETDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_NET_LIBRARY AND SDLNET_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_NET_LIBRARY HINTS ENV SDLNETDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_NET_INCLUDE_DIR AND EXISTS "${SDL_NET_INCLUDE_DIR}/SDL_net.h") diff --git a/Modules/FindSDL_sound.cmake b/Modules/FindSDL_sound.cmake index 5ff50be64..efd26580b 100644 --- a/Modules/FindSDL_sound.cmake +++ b/Modules/FindSDL_sound.cmake @@ -77,7 +77,7 @@ find_path(SDL_SOUND_INCLUDE_DIR SDL_sound.h HINTS ENV SDLSOUNDDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) find_library(SDL_SOUND_LIBRARY @@ -85,6 +85,7 @@ find_library(SDL_SOUND_LIBRARY HINTS ENV SDLSOUNDDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) diff --git a/Modules/FindSDL_ttf.cmake b/Modules/FindSDL_ttf.cmake index 2cc5ee232..bb0ca9147 100644 --- a/Modules/FindSDL_ttf.cmake +++ b/Modules/FindSDL_ttf.cmake @@ -40,7 +40,7 @@ find_path(SDL_TTF_INCLUDE_DIR SDL_ttf.h HINTS ENV SDLTTFDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_TTF_LIBRARY AND SDLTTF_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_TTF_LIBRARY HINTS ENV SDLTTFDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_TTF_INCLUDE_DIR AND EXISTS "${SDL_TTF_INCLUDE_DIR}/SDL_ttf.h") diff --git a/Modules/FindTCL.cmake b/Modules/FindTCL.cmake index 2f84ae091..f649ddc56 100644 --- a/Modules/FindTCL.cmake +++ b/Modules/FindTCL.cmake @@ -82,6 +82,10 @@ set(TCLTK_POSSIBLE_LIB_PATHS "${TK_LIBRARY_PATH}" "${TCL_TCLSH_PATH_PARENT}/lib" "${TK_WISH_PATH_PARENT}/lib" + /usr/local/lib/tcl/tcl8.5 + /usr/local/lib/tcl/tk8.5 + /usr/local/lib/tcl/tcl8.4 + /usr/local/lib/tcl/tk8.4 ) if(WIN32) @@ -168,6 +172,10 @@ set(TCLTK_POSSIBLE_INCLUDE_PATHS /usr/include/tcl8.3 /usr/include/tcl8.2 /usr/include/tcl8.0 + /usr/local/include/tcl8.5 + /usr/local/include/tk8.5 + /usr/local/include/tcl8.4 + /usr/local/include/tk8.4 ) if(WIN32) diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in index ffc425e67..59a444bde 100644 --- a/Modules/NSIS.template.in +++ b/Modules/NSIS.template.in @@ -37,6 +37,9 @@ ;Set compression SetCompressor @CPACK_NSIS_COMPRESSOR@ + ;Require administrator access + RequestExecutionLevel admin + @CPACK_NSIS_DEFINES@ !include Sections.nsh @@ -119,7 +122,7 @@ Var AR_RegFlags "exit_${SecName}:" !macroend -!macro RemoveSection SecName +!macro RemoveSection_CPack SecName ; This macro is used to call section's Remove_... macro ;from the uninstaller. ;Input: section index constant name specified in Section command. @@ -841,7 +844,7 @@ Section "Uninstall" DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" ; Removes all optional components - !insertmacro SectionList "RemoveSection" + !insertmacro SectionList "RemoveSection_CPack" !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP diff --git a/Modules/Platform/Darwin-Clang.cmake b/Modules/Platform/Darwin-Clang.cmake index de7a85636..528873cfd 100644 --- a/Modules/Platform/Darwin-Clang.cmake +++ b/Modules/Platform/Darwin-Clang.cmake @@ -19,6 +19,7 @@ endif() set(__DARWIN_COMPILER_CLANG 1) macro(__darwin_compiler_clang lang) + set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names") set(CMAKE_${lang}_SYSROOT_FLAG "-isysroot") diff --git a/Modules/Platform/Darwin-GNU.cmake b/Modules/Platform/Darwin-GNU.cmake index d9535039f..5fee7e3ae 100644 --- a/Modules/Platform/Darwin-GNU.cmake +++ b/Modules/Platform/Darwin-GNU.cmake @@ -19,6 +19,7 @@ endif() set(__DARWIN_COMPILER_GNU 1) macro(__darwin_compiler_gnu lang) + set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output # GNU does not have -shared on OS X set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names") diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index ed0b8af3f..2e6b71e36 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -256,6 +256,24 @@ set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK if(NOT DEFINED CMAKE_FIND_FRAMEWORK) set(CMAKE_FIND_FRAMEWORK FIRST) endif() + +# Older OS X linkers do not report their framework search path +# with -v but "man ld" documents the following locations. +set(CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + ${_CMAKE_OSX_SYSROOT_PATH}/Library/Frameworks + ${_CMAKE_OSX_SYSROOT_PATH}/System/Library/Frameworks + ) +if(_CMAKE_OSX_SYSROOT_PATH) + # Treat some paths as implicit so we do not override the SDK versions. + list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + /System/Library/Frameworks) +endif() +if("${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5") + # Older OS X tools had more implicit paths. + list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + ${_CMAKE_OSX_SYSROOT_PATH}/Network/Library/Frameworks) +endif() + # set up the default search directories for frameworks set(CMAKE_SYSTEM_FRAMEWORK_PATH ~/Library/Frameworks diff --git a/Modules/Platform/OpenBSD.cmake b/Modules/Platform/OpenBSD.cmake index df240e01b..53cabedde 100644 --- a/Modules/Platform/OpenBSD.cmake +++ b/Modules/Platform/OpenBSD.cmake @@ -16,3 +16,7 @@ if(NOT CMAKE_PLATFORM_RUNTIME_PATH) endif() set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_OPENBSD_VERSIONING 1) + +# OpenBSD policy requires that shared libraries be installed without +# executable permission. +set(CMAKE_INSTALL_SO_NO_EXE 1) diff --git a/Modules/Platform/Windows-Intel.cmake b/Modules/Platform/Windows-Intel.cmake index 58da8c56d..8a9d630f6 100644 --- a/Modules/Platform/Windows-Intel.cmake +++ b/Modules/Platform/Windows-Intel.cmake @@ -50,7 +50,7 @@ elseif(MSVC_CXX_ARCHITECTURE_ID) elseif(MSVC_Fortran_ARCHITECTURE_ID) set(_MACHINE_ARCH_FLAG "/machine:${MSVC_Fortran_ARCHITECTURE_ID}") endif() -set (CMAKE_EXE_LINKER_FLAGS_INIT "/STACK:10000000 /INCREMENTAL:YES ${_MACHINE_ARCH_FLAG}") +set (CMAKE_EXE_LINKER_FLAGS_INIT "/INCREMENTAL:YES ${_MACHINE_ARCH_FLAG}") set (CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT "/debug") set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO_INIT "/debug") diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 32dd54631..5cbf9ee6b 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -165,7 +165,7 @@ set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") # executable linker flags set (CMAKE_LINK_DEF_FILE_FLAG "/DEF:") -# set the stack size and the machine type +# set the machine type set(_MACHINE_ARCH_FLAG ${MSVC_C_ARCHITECTURE_ID}) if(NOT _MACHINE_ARCH_FLAG) set(_MACHINE_ARCH_FLAG ${MSVC_CXX_ARCHITECTURE_ID}) @@ -178,7 +178,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "WindowsCE") endif() endif() set (CMAKE_EXE_LINKER_FLAGS_INIT - "${CMAKE_EXE_LINKER_FLAGS_INIT} /STACK:10000000 /machine:${_MACHINE_ARCH_FLAG}") + "${CMAKE_EXE_LINKER_FLAGS_INIT} /machine:${_MACHINE_ARCH_FLAG}") # add /debug and /INCREMENTAL:YES to DEBUG and RELWITHDEBINFO also add pdbtype # on versions that support it diff --git a/Modules/UseQt4.cmake b/Modules/UseQt4.cmake index e8166f4fc..f05a3d5f3 100644 --- a/Modules/UseQt4.cmake +++ b/Modules/UseQt4.cmake @@ -25,7 +25,11 @@ if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS QT_NO_DEBUG) endif() -include_directories(${QT_INCLUDE_DIR}) +if(QT_INCLUDE_DIRS_NO_SYSTEM) + include_directories(${QT_INCLUDE_DIR}) +else(QT_INCLUDE_DIRS_NO_SYSTEM) + include_directories(SYSTEM ${QT_INCLUDE_DIR}) +endif(QT_INCLUDE_DIRS_NO_SYSTEM) set(QT_LIBRARIES "") set(QT_LIBRARIES_PLUGINS "") @@ -89,7 +93,11 @@ foreach(module QT3SUPPORT QTOPENGL QTASSISTANT QTDESIGNER QTMOTIF QTNSPLUGIN if(QT_USE_${module}) string(REPLACE "QT" "" qt_module_def "${module}") add_definitions(-DQT_${qt_module_def}_LIB) - include_directories(${QT_${module}_INCLUDE_DIR}) + if(QT_INCLUDE_DIRS_NO_SYSTEM) + include_directories(${QT_${module}_INCLUDE_DIR}) + else(QT_INCLUDE_DIRS_NO_SYSTEM) + include_directories(SYSTEM ${QT_${module}_INCLUDE_DIR}) + endif(QT_INCLUDE_DIRS_NO_SYSTEM) endif() set(QT_LIBRARIES ${QT_LIBRARIES} ${QT_${module}_LIBRARY}) set(QT_LIBRARIES_PLUGINS ${QT_LIBRARIES_PLUGINS} ${QT_${module}_PLUGINS}) diff --git a/Modules/WIX.template.in b/Modules/WIX.template.in new file mode 100644 index 000000000..0bc7e10ce --- /dev/null +++ b/Modules/WIX.template.in @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + ProductIcon.ico + + + + + + + + + + + + + + + + diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 66f7c42aa..7808f2326 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -355,6 +355,8 @@ if (WIN32) cmLocalVisualStudio7Generator.h cmLocalVisualStudioGenerator.cxx cmLocalVisualStudioGenerator.h + cmVisualStudioWCEPlatformParser.h + cmVisualStudioWCEPlatformParser.cxx cmWin32ProcessExecution.cxx cmWin32ProcessExecution.h ) @@ -499,6 +501,14 @@ if(UNIX) ) endif() +if(WIN32) + set(CPACK_SRCS ${CPACK_SRCS} + CPack/WiX/cmCPackWIXGenerator.cxx + CPack/WiX/cmWIXSourceWriter.cxx + CPack/WiX/cmWIXRichTextFormatWriter.cxx + ) +endif() + if(APPLE) set(CPACK_SRCS ${CPACK_SRCS} CPack/cmCPackBundleGenerator.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 60514b70e..f77d17c3f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121124) +set(CMake_VERSION_TWEAK 20130110) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx new file mode 100644 index 000000000..e8b0ea971 --- /dev/null +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -0,0 +1,571 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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 "cmCPackWIXGenerator.h" + +#include +#include +#include +#include + +#include "cmWIXSourceWriter.h" +#include "cmWIXRichTextFormatWriter.h" + +#include +#include + +#include // for GUID generation + +int cmCPackWIXGenerator::InitializeInternal() +{ + componentPackageMethod = ONE_PACKAGE; + + return this->Superclass::InitializeInternal(); +} + +bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command) +{ + std::string cpackTopLevel; + if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) + { + return false; + } + + std::string logFileName = cpackTopLevel + "/wix.log"; + + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "Running WiX command: " << command << std::endl); + + std::string output; + + int returnValue = 0; + bool status = cmSystemTools::RunSingleCommand(command.c_str(), &output, + &returnValue, 0, cmSystemTools::OUTPUT_NONE); + + std::ofstream logFile(logFileName.c_str(), std::ios::app); + logFile << command << std::endl; + logFile << output; + logFile.close(); + + if(!status || returnValue) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem running WiX candle. " + "Please check '" << logFileName << "' for errors." << std::endl); + + return false; + } + + return true; +} + +bool cmCPackWIXGenerator::RunCandleCommand( + const std::string& sourceFile, const std::string& objectFile) +{ + std::string executable; + if(!RequireOption("CPACK_WIX_CANDLE_EXECUTABLE", executable)) + { + return false; + } + + std::stringstream command; + command << QuotePath(executable); + command << " -nologo"; + command << " -arch " << GetArchitecture(); + command << " -out " << QuotePath(objectFile); + command << " " << QuotePath(sourceFile); + + return RunWiXCommand(command.str()); +} + +bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) +{ + std::string executable; + if(!RequireOption("CPACK_WIX_LIGHT_EXECUTABLE", executable)) + { + return false; + } + + std::stringstream command; + command << QuotePath(executable); + command << " -nologo"; + command << " -out " << QuotePath(packageFileNames.at(0)); + command << " -ext WixUIExtension"; + command << " " << objectFiles; + + return RunWiXCommand(command.str()); +} + +int cmCPackWIXGenerator::PackageFiles() +{ + if(!PackageFilesImpl() || cmSystemTools::GetErrorOccuredFlag()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Fatal WiX Generator Error" << std::endl); + return false; + } + + return true; +} + +bool cmCPackWIXGenerator::InitializeWiXConfiguration() +{ + if(!ReadListFile("CPackWIX.cmake")) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error while executing CPackWIX.cmake" << std::endl); + return false; + } + + if(GetOption("CPACK_WIX_PRODUCT_GUID") == 0) + { + std::string guid = GenerateGUID(); + SetOption("CPACK_WIX_PRODUCT_GUID", guid.c_str()); + + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "CPACK_WIX_PRODUCT_GUID implicitly set to " << guid << " . " + << std::endl); + } + + if(GetOption("CPACK_WIX_UPGRADE_GUID") == 0) + { + std::string guid = GenerateGUID(); + SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str()); + + cmCPackLogger(cmCPackLog::LOG_WARNING, + "CPACK_WIX_UPGRADE_GUID implicitly set to " << guid << " . " + "Please refer to the documentation on how and why " + "you might want to set this explicitly." << std::endl); + } + + std::string cpackTopLevel; + if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) + { + return false; + } + + if(GetOption("CPACK_WIX_LICENSE_RTF") == 0) + { + std::string licenseFilename = cpackTopLevel + "/License.rtf"; + SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str()); + + if(!CreateLicenseFile()) + { + return false; + } + } + + return true; +} + +bool cmCPackWIXGenerator::PackageFilesImpl() +{ + if(!InitializeWiXConfiguration()) + { + return false; + } + + if(!CreateWiXVariablesIncludeFile()) + { + return false; + } + + if(!CreateWiXSourceFiles()) + { + return false; + } + + std::stringstream objectFiles; + for(size_t i = 0; i < wixSources.size(); ++i) + { + const std::string& sourceFilename = wixSources[i]; + + std::string objectFilename = + cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj"; + + if(!RunCandleCommand(sourceFilename, objectFilename)) + { + return false; + } + + objectFiles << " " << QuotePath(objectFilename); + } + + return RunLightCommand(objectFiles.str()); +} + +bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() +{ + std::string cpackTopLevel; + if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) + { + return false; + } + + std::string includeFilename = + cpackTopLevel + "/cpack_variables.wxi"; + + cmWIXSourceWriter includeFile(Logger, includeFilename, true); + CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID"); + CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID"); + CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR"); + CopyDefinition(includeFile, "CPACK_PACKAGE_NAME"); + CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION"); + CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF"); + CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON"); + CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER"); + CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG"); + + return true; +} + +void cmCPackWIXGenerator::CopyDefinition( + cmWIXSourceWriter &source, const std::string &name) +{ + const char* value = GetOption(name.c_str()); + if(value) + { + AddDefinition(source, name, value); + } +} + +void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source, + const std::string& name, const std::string& value) +{ + std::stringstream tmp; + tmp << name << "=\"" << value << '"'; + + source.AddProcessingInstruction("define", + cmWIXSourceWriter::WindowsCodepageToUtf8(tmp.str())); +} + +bool cmCPackWIXGenerator::CreateWiXSourceFiles() +{ + std::string cpackTopLevel; + if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) + { + return false; + } + + std::string directoryDefinitionsFilename = + cpackTopLevel + "/directories.wxs"; + + wixSources.push_back(directoryDefinitionsFilename); + + cmWIXSourceWriter directoryDefinitions(Logger, directoryDefinitionsFilename); + directoryDefinitions.BeginElement("Fragment"); + + directoryDefinitions.BeginElement("Directory"); + directoryDefinitions.AddAttribute("Id", "TARGETDIR"); + directoryDefinitions.AddAttribute("Name", "SourceDir"); + + directoryDefinitions.BeginElement("Directory"); + if(GetArchitecture() == "x86") + { + directoryDefinitions.AddAttribute("Id", "ProgramFilesFolder"); + } + else + { + directoryDefinitions.AddAttribute("Id", "ProgramFiles64Folder"); + } + + std::vector install_root; + + std::string tmp; + if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", tmp)) + { + return false; + } + + cmSystemTools::SplitPath(tmp.c_str(), install_root); + + if(!install_root.empty() && install_root.back().empty()) + { + install_root.pop_back(); + } + + for(size_t i = 1; i < install_root.size(); ++i) + { + directoryDefinitions.BeginElement("Directory"); + + if(i == install_root.size() - 1) + { + directoryDefinitions.AddAttribute("Id", "INSTALL_ROOT"); + } + else + { + std::stringstream ss; + ss << "INSTALL_PREFIX_" << i; + directoryDefinitions.AddAttribute("Id", ss.str()); + } + + directoryDefinitions.AddAttribute("Name", install_root[i]); + } + + size_t directoryCounter = 0; + size_t fileCounter = 0; + + std::string fileDefinitionsFilename = + cpackTopLevel + "/files.wxs"; + + wixSources.push_back(fileDefinitionsFilename); + + cmWIXSourceWriter fileDefinitions(Logger, fileDefinitionsFilename); + fileDefinitions.BeginElement("Fragment"); + + std::string featureDefinitionsFilename = + cpackTopLevel +"/features.wxs"; + + wixSources.push_back(featureDefinitionsFilename); + + cmWIXSourceWriter featureDefinitions(Logger, featureDefinitionsFilename); + featureDefinitions.BeginElement("Fragment"); + + featureDefinitions.BeginElement("Feature"); + featureDefinitions.AddAttribute("Id", "ProductFeature"); + featureDefinitions.AddAttribute("Title", Name); + featureDefinitions.AddAttribute("Level", "1"); + featureDefinitions.EndElement(); + + featureDefinitions.BeginElement("FeatureRef"); + featureDefinitions.AddAttribute("Id", "ProductFeature"); + + AddDirectoryAndFileDefinitons( + toplevel, "INSTALL_ROOT", + directoryDefinitions, fileDefinitions, featureDefinitions, + directoryCounter, fileCounter); + + featureDefinitions.EndElement(); + featureDefinitions.EndElement(); + fileDefinitions.EndElement(); + + for(size_t i = 1; i < install_root.size(); ++i) + { + directoryDefinitions.EndElement(); + } + + directoryDefinitions.EndElement(); + directoryDefinitions.EndElement(); + directoryDefinitions.EndElement(); + + std::string wixTemplate = FindTemplate("WIX.template.in"); + if(wixTemplate.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Could not find CPack WiX template file WIX.template.in" << std::endl); + return false; + } + + std::string mainSourceFilePath = cpackTopLevel + "/main.wxs"; + + if(!ConfigureFile(wixTemplate.c_str(), mainSourceFilePath .c_str())) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Failed creating '" << mainSourceFilePath << + "'' from template." << std::endl); + + return false; + } + + wixSources.push_back(mainSourceFilePath); + + return true; +} + +bool cmCPackWIXGenerator::CreateLicenseFile() +{ + std::string licenseSourceFilename; + if(!RequireOption("CPACK_RESOURCE_FILE_LICENSE", licenseSourceFilename)) + { + return false; + } + + std::string licenseDestinationFilename; + if(!RequireOption("CPACK_WIX_LICENSE_RTF", licenseDestinationFilename)) + { + return false; + } + + std::string extension = GetRightmostExtension(licenseSourceFilename); + + if(extension == ".rtf") + { + cmSystemTools::CopyAFile( + licenseSourceFilename.c_str(), + licenseDestinationFilename.c_str()); + } + else if(extension == ".txt") + { + cmWIXRichTextFormatWriter rtfWriter(licenseDestinationFilename); + + std::ifstream licenseSource(licenseSourceFilename.c_str()); + + std::string line; + while(std::getline(licenseSource, line)) + { + rtfWriter.AddText(line); + rtfWriter.AddText("\n"); + } + } + else + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "unsupported WiX License file extension '" << + extension << "'" << std::endl); + + return false; + } + + return true; +} + +void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( + const std::string& topdir, + const std::string& directoryId, + cmWIXSourceWriter& directoryDefinitions, + cmWIXSourceWriter& fileDefinitions, + cmWIXSourceWriter& featureDefinitions, + size_t& directoryCounter, + size_t& fileCounter) +{ + cmsys::Directory dir; + dir.Load(topdir.c_str()); + + for(size_t i = 0; i < dir.GetNumberOfFiles(); ++i) + { + std::string fileName = dir.GetFile(static_cast(i)); + + if(fileName == "." || fileName == "..") + { + continue; + } + + std::string fullPath = topdir + "/" + fileName; + + if(cmSystemTools::FileIsDirectory(fullPath.c_str())) + { + std::stringstream tmp; + tmp << "DIR_ID_" << ++directoryCounter; + std::string subDirectoryId = tmp.str(); + + directoryDefinitions.BeginElement("Directory"); + directoryDefinitions.AddAttribute("Id", subDirectoryId); + directoryDefinitions.AddAttribute("Name", fileName); + + AddDirectoryAndFileDefinitons( + fullPath, subDirectoryId, + directoryDefinitions, + fileDefinitions, + featureDefinitions, + directoryCounter, + fileCounter); + + directoryDefinitions.EndElement(); + } + else + { + std::stringstream tmp; + tmp << "_ID_" << ++fileCounter; + std::string idSuffix = tmp.str(); + + std::string componentId = std::string("CMP") + idSuffix; + std::string fileId = std::string("FILE") + idSuffix; + + fileDefinitions.BeginElement("DirectoryRef"); + fileDefinitions.AddAttribute("Id", directoryId); + + fileDefinitions.BeginElement("Component"); + fileDefinitions.AddAttribute("Id", componentId); + fileDefinitions.AddAttribute("Guid", "*"); + + fileDefinitions.BeginElement("File"); + fileDefinitions.AddAttribute("Id", fileId); + fileDefinitions.AddAttribute("Source", fullPath); + fileDefinitions.AddAttribute("KeyPath", "yes"); + + fileDefinitions.EndElement(); + fileDefinitions.EndElement(); + fileDefinitions.EndElement(); + + featureDefinitions.BeginElement("ComponentRef"); + featureDefinitions.AddAttribute("Id", componentId); + featureDefinitions.EndElement(); + } + } +} + +bool cmCPackWIXGenerator::RequireOption( + const std::string& name, std::string &value) const +{ + const char* tmp = GetOption(name.c_str()); + if(tmp) + { + value = tmp; + + return true; + } + else + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Required variable " << name << " not set" << std::endl); + + return false; + } +} + +std::string cmCPackWIXGenerator::GetArchitecture() const +{ + std::string void_p_size; + RequireOption("CPACK_WIX_SIZEOF_VOID_P", void_p_size); + + if(void_p_size == "8") + { + return "x64"; + } + else + { + return "x86"; + } +} + +std::string cmCPackWIXGenerator::GenerateGUID() +{ + UUID guid; + UuidCreate(&guid); + + unsigned char *tmp = 0; + UuidToString(&guid, &tmp); + + std::string result(reinterpret_cast(tmp)); + RpcStringFree(&tmp); + + return cmSystemTools::UpperCase(result); +} + +std::string cmCPackWIXGenerator::QuotePath(const std::string& path) +{ + return std::string("\"") + path + '"'; +} + +std::string cmCPackWIXGenerator::GetRightmostExtension( + const std::string& filename) +{ + std::string extension; + + std::string::size_type i = filename.rfind("."); + if(i != std::string::npos) + { + extension = filename.substr(i); + } + + return cmSystemTools::LowerCase(extension); +} diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h new file mode 100644 index 000000000..0e95d70f6 --- /dev/null +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -0,0 +1,101 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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 cmCPackWIXGenerator_h +#define cmCPackWIXGenerator_h + +#include + +#include +#include + +class cmWIXSourceWriter; + +/** \class cmCPackWIXGenerator + * \brief A generator for WIX files + */ +class cmCPackWIXGenerator : public cmCPackGenerator +{ +public: + cmCPackTypeMacro(cmCPackWIXGenerator, cmCPackGenerator); + +protected: + virtual int InitializeInternal(); + + virtual int PackageFiles(); + + virtual const char* GetOutputExtension() + { + return ".msi"; + } + + virtual enum CPackSetDestdirSupport SupportsSetDestdir() const + { + return SETDESTDIR_UNSUPPORTED; + } + + virtual bool SupportsAbsoluteDestination() const + { + return false; + } + + virtual bool SupportsComponentInstallation() const + { + return false; + } + +private: + bool InitializeWiXConfiguration(); + + bool PackageFilesImpl(); + + bool CreateWiXVariablesIncludeFile(); + + void CopyDefinition( + cmWIXSourceWriter &source, const std::string &name); + + void AddDefinition(cmWIXSourceWriter& source, + const std::string& name, const std::string& value); + + bool CreateWiXSourceFiles(); + + bool CreateLicenseFile(); + + bool RunWiXCommand(const std::string& command); + + bool RunCandleCommand( + const std::string& sourceFile, const std::string& objectFile); + + bool RunLightCommand(const std::string& objectFiles); + + void AddDirectoryAndFileDefinitons(const std::string& topdir, + const std::string& directoryId, + cmWIXSourceWriter& directoryDefinitions, + cmWIXSourceWriter& fileDefinitions, + cmWIXSourceWriter& featureDefinitions, + size_t& directoryCounter, + size_t& fileCounter); + + bool RequireOption(const std::string& name, std::string& value) const; + + std::string GetArchitecture() const; + + static std::string GenerateGUID(); + + static std::string QuotePath(const std::string& path); + + static std::string GetRightmostExtension(const std::string& filename); + + std::vector wixSources; +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx new file mode 100644 index 000000000..774c22c76 --- /dev/null +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx @@ -0,0 +1,137 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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. +============================================================================*/ + +#include "cmWIXRichTextFormatWriter.h" + +#include + +cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( + const std::string& filename): + file(filename.c_str(), std::ios::binary) +{ + StartGroup(); + WriteHeader(); + WriteDocumentPrefix(); +} + +cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter() +{ + EndGroup(); + + /* I haven't seen this in the RTF spec but + * wordpad terminates its RTF like this */ + file << "\r\n"; + file.put(0); +} + +void cmWIXRichTextFormatWriter::AddText(const std::string& text) +{ + typedef unsigned char rtf_byte_t; + + for(size_t i = 0; i < text.size(); ++i) + { + rtf_byte_t c = rtf_byte_t(text[i]); + + switch(c) + { + case '\\': + file << "\\\\"; + break; + case '{': + file << "\\{"; + break; + case '}': + file << "\\}"; + break; + case '\n': + file << "\\par\r\n"; + break; + case '\r': + continue; + default: + { + if(c <= 0x7F) + { + file << c; + } + else + { + file << "[NON-ASCII-" << int(c) << "]"; + } + } + break; + } + } +} + +void cmWIXRichTextFormatWriter::WriteHeader() +{ + ControlWord("rtf1"); + ControlWord("ansi"); + ControlWord("ansicpg1252"); + ControlWord("deff0"); + ControlWord("deflang1031"); + + WriteFontTable(); + WriteGenerator(); +} + +void cmWIXRichTextFormatWriter::WriteFontTable() +{ + StartGroup(); + ControlWord("fonttbl"); + + StartGroup(); + ControlWord("f0"); + ControlWord("fswiss"); + ControlWord("fcharset0 Arial;"); + EndGroup(); + + EndGroup(); +} + +void cmWIXRichTextFormatWriter::WriteGenerator() +{ + StartGroup(); + NewControlWord("generator"); + file << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");"; + EndGroup(); +} + +void cmWIXRichTextFormatWriter::WriteDocumentPrefix() +{ + ControlWord("viewkind4"); + ControlWord("uc1"); + ControlWord("pard"); + ControlWord("f0"); + ControlWord("fs20"); +} + +void cmWIXRichTextFormatWriter::ControlWord(const std::string& keyword) +{ + file << "\\" << keyword; +} + +void cmWIXRichTextFormatWriter::NewControlWord(const std::string& keyword) +{ + file << "\\*\\" << keyword; +} + +void cmWIXRichTextFormatWriter::StartGroup() +{ + file.put('{'); +} + +void cmWIXRichTextFormatWriter::EndGroup() +{ + file.put('}'); +} diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h new file mode 100644 index 000000000..10b67c39f --- /dev/null +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h @@ -0,0 +1,46 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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 cmWIXRichTextFormatWriter_h +#define cmWIXRichTextFormatWriter_h + +#include + +/** \class cmWIXRichtTextFormatWriter + * \brief Helper class to generate Rich Text Format (RTF) documents + * from plain text (e.g. for license and welcome text) + */ +class cmWIXRichTextFormatWriter +{ +public: + cmWIXRichTextFormatWriter(const std::string& filename); + ~cmWIXRichTextFormatWriter(); + + void AddText(const std::string& text); + +private: + void WriteHeader(); + void WriteFontTable(); + void WriteGenerator(); + + void WriteDocumentPrefix(); + + void ControlWord(const std::string& keyword); + void NewControlWord(const std::string& keyword); + + void StartGroup(); + void EndGroup(); + + std::ofstream file; +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx new file mode 100644 index 000000000..af7ba807f --- /dev/null +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -0,0 +1,189 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 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. +============================================================================*/ + +#include "cmWIXSourceWriter.h" + +#include + +#include + +cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger, + const std::string& filename, + bool isIncludeFile): + Logger(logger), + file(filename.c_str()), + state(DEFAULT) +{ + WriteXMLDeclaration(); + + if(isIncludeFile) + { + BeginElement("Include"); + } + else + { + BeginElement("Wix"); + } + + AddAttribute("xmlns", "http://schemas.microsoft.com/wix/2006/wi"); +} + +cmWIXSourceWriter::~cmWIXSourceWriter() +{ + while(elements.size()) + { + EndElement(); + } +} + +void cmWIXSourceWriter::BeginElement(const std::string& name) +{ + if(state == BEGIN) + { + file << ">"; + } + + file << "\n"; + Indent(elements.size()); + file << "<" << name; + + elements.push_back(name); + state = BEGIN; +} + +void cmWIXSourceWriter::EndElement() +{ + if(elements.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "can not end WiX element with no open elements" << std::endl); + return; + } + + if(state == DEFAULT) + { + file << "\n"; + Indent(elements.size()-1); + file << ""; + } + else + { + file << "/>"; + } + + elements.pop_back(); + state = DEFAULT; +} + +void cmWIXSourceWriter::AddProcessingInstruction( + const std::string& target, const std::string& content) +{ + if(state == BEGIN) + { + file << ">"; + } + + file << "\n"; + Indent(elements.size()); + file << ""; + + state = DEFAULT; +} + +void cmWIXSourceWriter::AddAttribute( + const std::string& key, const std::string& value) +{ + std::string utf8 = WindowsCodepageToUtf8(value); + + file << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"'; +} + +std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value) +{ + if(value.empty()) + { + return std::string(); + } + + int characterCount = MultiByteToWideChar( + CP_ACP, 0, value.c_str(), static_cast(value.size()), 0, 0); + + if(characterCount == 0) + { + return std::string(); + } + + std::vector utf16(characterCount); + + MultiByteToWideChar( + CP_ACP, 0, value.c_str(), static_cast(value.size()), + &utf16[0], static_cast(utf16.size())); + + int utf8ByteCount = WideCharToMultiByte( + CP_UTF8, 0, &utf16[0], static_cast(utf16.size()), 0, 0, 0, 0); + + if(utf8ByteCount == 0) + { + return std::string(); + } + + std::vector utf8(utf8ByteCount); + + WideCharToMultiByte(CP_UTF8, 0, &utf16[0], static_cast(utf16.size()), + &utf8[0], static_cast(utf8.size()), 0, 0); + + return std::string(&utf8[0], utf8.size()); +} + + +void cmWIXSourceWriter::WriteXMLDeclaration() +{ + file << "" << std::endl; +} + +void cmWIXSourceWriter::Indent(size_t count) +{ + for(size_t i = 0; i < count; ++i) + { + file << " "; + } +} + +std::string cmWIXSourceWriter::EscapeAttributeValue( + const std::string& value) +{ + std::string result; + result.reserve(value.size()); + + char c = 0; + for(size_t i = 0 ; i < value.size(); ++i) + { + c = value[i]; + switch(c) + { + case '<': + result += "<"; + break; + case '&': + result +="&"; + break; + case '"': + result += """; + break; + default: + result += c; + break; + } + } + + return result; +} diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h new file mode 100644 index 000000000..1dafc1ff2 --- /dev/null +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -0,0 +1,67 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 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 cmWIXSourceWriter_h +#define cmWIXSourceWriter_h + +#include +#include +#include + +#include + +/** \class cmWIXSourceWriter + * \brief Helper class to generate XML WiX source files + */ +class cmWIXSourceWriter +{ +public: + cmWIXSourceWriter(cmCPackLog* logger, + const std::string& filename, bool isIncludeFile = false); + + ~cmWIXSourceWriter(); + + void BeginElement(const std::string& name); + + void EndElement(); + + void AddProcessingInstruction( + const std::string& target, const std::string& content); + + void AddAttribute( + const std::string& key, const std::string& value); + + static std::string WindowsCodepageToUtf8(const std::string& value); + +private: + enum State + { + DEFAULT, + BEGIN + }; + + void WriteXMLDeclaration(); + + void Indent(size_t count); + + static std::string EscapeAttributeValue(const std::string& value); + + cmCPackLog* Logger; + + std::ofstream file; + + State state; + + std::vector elements; +}; + +#endif diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 6317fa031..7cc152269 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -23,7 +23,6 @@ #include #include -#include // auto_ptr #include #if defined(__HAIKU__) @@ -696,7 +695,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cm.SetProgressCallback(cmCPackGeneratorProgress, this); cmGlobalGenerator gg; gg.SetCMakeInstance(&cm); - std::auto_ptr lg(gg.CreateLocalGenerator()); + cmsys::auto_ptr lg(gg.CreateLocalGenerator()); cmMakefile *mf = lg->GetMakefile(); std::string realInstallDirectory = tempInstallDirectory; if ( !installSubDirectory.empty() && installSubDirectory != "/" ) diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 37ff46041..b36c2a2f8 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -19,6 +19,7 @@ #include "cmCPackZIPGenerator.h" #include "cmCPackSTGZGenerator.h" #include "cmCPackNSISGenerator.h" + #ifdef __APPLE__ # include "cmCPackDragNDropGenerator.h" # include "cmCPackBundleGenerator.h" @@ -32,11 +33,14 @@ #endif #if !defined(_WIN32) \ - && !defined(__QNXNTO__) && !defined(__BEOS__) + && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__) # include "cmCPackDebGenerator.h" # include "cmCPackRPMGenerator.h" #endif +#ifdef _WIN32 +# include "WiX/cmCPackWIXGenerator.h" +#endif #include "cmCPackLog.h" @@ -61,6 +65,8 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() { this->RegisterGenerator("NSIS", "Null Soft Installer", cmCPackNSISGenerator::CreateGenerator); + this->RegisterGenerator("NSIS64", "Null Soft Installer (64-bit)", + cmCPackNSISGenerator::CreateGenerator64); } #ifdef __CYGWIN__ if (cmCPackCygwinBinaryGenerator::CanGenerate()) @@ -80,6 +86,13 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("ZIP", "ZIP file format", cmCPackZIPGenerator::CreateGenerator); } +#ifdef _WIN32 + if (cmCPackWIXGenerator::CanGenerate()) + { + this->RegisterGenerator("WIX", "MSI file format via WiX tools", + cmCPackWIXGenerator::CreateGenerator); + } +#endif if (cmCPackTarBZip2Generator::CanGenerate()) { this->RegisterGenerator("TBZ2", "Tar BZip2 compression", @@ -113,7 +126,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() } #endif #if !defined(_WIN32) \ - && !defined(__QNXNTO__) && !defined(__BEOS__) + && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__) if (cmCPackDebGenerator::CanGenerate()) { this->RegisterGenerator("DEB", "Debian packages", diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index fdbae3504..9f86ea272 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -33,8 +33,9 @@ #endif //---------------------------------------------------------------------- -cmCPackNSISGenerator::cmCPackNSISGenerator() +cmCPackNSISGenerator::cmCPackNSISGenerator(bool nsis64) { + Nsis64 = nsis64; } //---------------------------------------------------------------------- @@ -359,6 +360,21 @@ int cmCPackNSISGenerator::InitializeInternal() bool gotRegValue = false; #ifdef _WIN32 + if (Nsis64) + { + if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath, + cmsys::SystemTools::KeyWOW64_64) ) + { + gotRegValue = true; + } + if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath, + cmsys::SystemTools::KeyWOW64_64) ) + { + gotRegValue = true; + } + } if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue( "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath, cmsys::SystemTools::KeyWOW64_32) ) diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h index 82248546f..e46fbdab7 100644 --- a/Source/CPack/cmCPackNSISGenerator.h +++ b/Source/CPack/cmCPackNSISGenerator.h @@ -27,10 +27,13 @@ class cmCPackNSISGenerator : public cmCPackGenerator public: cmCPackTypeMacro(cmCPackNSISGenerator, cmCPackGenerator); + static cmCPackGenerator* CreateGenerator64() + { return new cmCPackNSISGenerator(true); } + /** * Construct generator */ - cmCPackNSISGenerator(); + cmCPackNSISGenerator(bool nsis64 = false); virtual ~cmCPackNSISGenerator(); protected: @@ -77,6 +80,8 @@ protected: /// Translations any newlines found in the string into \\r\\n, so that the /// resulting string can be used within NSIS. static std::string TranslateNewlines(std::string str); + + bool Nsis64; }; #endif diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index b6035854e..0ba732269 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -27,7 +27,6 @@ #include #include -#include // auto_ptr //---------------------------------------------------------------------------- static const char * cmDocumentationName[][3] = @@ -276,7 +275,7 @@ int main (int argc, char *argv[]) cminst.RemoveUnscriptableCommands(); cmGlobalGenerator cmgg; cmgg.SetCMakeInstance(&cminst); - std::auto_ptr cmlg(cmgg.CreateLocalGenerator()); + cmsys::auto_ptr cmlg(cmgg.CreateLocalGenerator()); cmMakefile* globalMF = cmlg->GetMakefile(); bool cpackConfigFileSpecified = true; diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 4d1e249e6..20aded2b5 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -1097,10 +1097,17 @@ int cmCTestCoverageHandler::HandleGCovCoverage( } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Unknown gcov output line: [" << line->c_str() << "]" << std::endl); - cont->Error ++; - //abort(); + // gcov 4.7 can have output lines saying "No executable lines" and + // "Removing 'filename.gcov'"... Don't log those as "errors." + if(*line != "No executable lines" && + !cmSystemTools::StringStartsWith(line->c_str(), "Removing ")) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output line: [" << line->c_str() << "]" + << std::endl); + cont->Error ++; + //abort(); + } } diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index ebef1ed9c..76ddeea01 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -248,7 +248,12 @@ bool cmCTestMultiProcessHandler::StartTest(int test) //--------------------------------------------------------- void cmCTestMultiProcessHandler::StartNextTests() { - size_t numToStart = this->ParallelLevel - this->RunningCount; + size_t numToStart = 0; + if(this->RunningCount < this->ParallelLevel) + { + numToStart = this->ParallelLevel - this->RunningCount; + } + if(numToStart == 0) { return; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index b796b8373..e7491bba3 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -32,7 +32,6 @@ #include #include -#include // auto_ptr #include //---------------------------------------------------------------------- @@ -1547,7 +1546,7 @@ void cmCTestTestHandler::GetListOfTests() cmake cm; cmGlobalGenerator gg; gg.SetCMakeInstance(&cm); - std::auto_ptr lg(gg.CreateLocalGenerator()); + cmsys::auto_ptr lg(gg.CreateLocalGenerator()); cmMakefile *mf = lg->GetMakefile(); mf->AddDefinition("CTEST_CONFIGURATION_TYPE", this->CTest->GetConfigType().c_str()); diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index c14456535..e5f27cb51 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -134,6 +134,10 @@ public: "They may contain custom commands generating such sources, but not " "PRE_BUILD, PRE_LINK, or POST_BUILD commands. " "Object libraries cannot be imported, exported, installed, or linked." + " " + "Some native build systems may not like targets that have only " + "object files, so consider adding at least one real source file " + "to any target that references $." ; } diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx index 9097a7482..e3a2ad4e5 100644 --- a/Source/cmBootstrapCommands.cxx +++ b/Source/cmBootstrapCommands.cxx @@ -89,6 +89,7 @@ #include "cmStringCommand.cxx" #include "cmSubdirCommand.cxx" #include "cmTargetLinkLibrariesCommand.cxx" +#include "cmTimestamp.cxx" #include "cmTryCompileCommand.cxx" #include "cmTryRunCommand.cxx" #include "cmUnsetCommand.cxx" diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index bb6f3f29d..322a6a26f 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -53,7 +53,7 @@ #include #include -#if defined(__BEOS__) && !defined(__HAIKU__) +#if defined(__BEOS__) #include /* disable_debugger() API. */ #endif diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx index 696a6a8c3..c5146c5d7 100644 --- a/Source/cmCommandArgumentParser.cxx +++ b/Source/cmCommandArgumentParser.cxx @@ -279,7 +279,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -701,7 +701,7 @@ while (YYID (0)) we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 49ed96795..227b22678 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -28,6 +28,9 @@ #include "cmRemoveDefinitionsCommand.cxx" #include "cmSourceGroupCommand.cxx" #include "cmSubdirDependsCommand.cxx" +#include "cmTargetCompileDefinitionsCommand.cxx" +#include "cmTargetIncludeDirectoriesCommand.cxx" +#include "cmTargetPropCommandBase.cxx" #include "cmUseMangledMesaCommand.cxx" #include "cmUtilitySourceCommand.cxx" #include "cmVariableRequiresCommand.cxx" @@ -66,6 +69,8 @@ void GetPredefinedCommands(std::list& commands.push_back(new cmRemoveDefinitionsCommand); commands.push_back(new cmSourceGroupCommand); commands.push_back(new cmSubdirDependsCommand); + commands.push_back(new cmTargetIncludeDirectoriesCommand); + commands.push_back(new cmTargetCompileDefinitionsCommand); commands.push_back(new cmUseMangledMesaCommand); commands.push_back(new cmUtilitySourceCommand); commands.push_back(new cmVariableRequiresCommand); diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 055aab032..dec2b54d1 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -172,10 +172,11 @@ satisfy dependencies. //---------------------------------------------------------------------------- cmComputeLinkDepends -::cmComputeLinkDepends(cmTarget* target, const char* config) +::cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget* head) { // Store context information. this->Target = target; + this->HeadTarget = head; this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); @@ -352,7 +353,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) { // Follow the target dependencies. if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config)) + entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) { // This target provides its own link interface information. this->AddLinkEntries(depender_index, iface->Libraries); @@ -444,7 +445,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) if(entry.Target) { if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config)) + entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) { // Follow public and private dependencies transitively. this->FollowSharedDeps(index, iface, true); @@ -533,7 +534,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries() { // Add direct link dependencies in this configuration. cmTarget::LinkImplementation const* impl = - this->Target->GetLinkImplementation(this->Config); + this->Target->GetLinkImplementation(this->Config, this->HeadTarget); this->AddLinkEntries(-1, impl->Libraries); for(std::vector::const_iterator wi = impl->WrongConfigLibraries.begin(); @@ -944,7 +945,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) if(cmTarget* target = this->EntryList[*ni].Target) { if(cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config)) + target->GetLinkInterface(this->Config, this->HeadTarget)) { if(iface->Multiplicity > count) { diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 80a04541f..1d5d1b920 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -32,7 +32,7 @@ class cmake; class cmComputeLinkDepends { public: - cmComputeLinkDepends(cmTarget* target, const char* config); + cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget *head); ~cmComputeLinkDepends(); // Basic information about each link item. @@ -59,6 +59,7 @@ private: // Context information. cmTarget* Target; + cmTarget* HeadTarget; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; cmGlobalGenerator* GlobalGenerator; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index d8ffb5e83..08cdcb5b8 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -239,10 +239,12 @@ because this need be done only for shared libraries without soname-s. //---------------------------------------------------------------------------- cmComputeLinkInformation -::cmComputeLinkInformation(cmTarget* target, const char* config) +::cmComputeLinkInformation(cmTarget* target, const char* config, + cmTarget *headTarget) { // Store context information. this->Target = target; + this->HeadTarget = headTarget; this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); @@ -265,7 +267,7 @@ cmComputeLinkInformation this->OrderDependentRPath = 0; // Get the language used for linking this target. - this->LinkLanguage = this->Target->GetLinkerLanguage(config); + this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget); if(!this->LinkLanguage) { // The Compute method will do nothing, so skip the rest of the @@ -503,7 +505,7 @@ bool cmComputeLinkInformation::Compute() } // Compute the ordered link line items. - cmComputeLinkDepends cld(this->Target, this->Config); + cmComputeLinkDepends cld(this->Target, this->Config, this->HeadTarget); cld.SetOldLinkDirMode(this->OldLinkDirMode); cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute(); @@ -569,7 +571,8 @@ bool cmComputeLinkInformation::Compute() void cmComputeLinkInformation::AddImplicitLinkInfo() { // The link closure lists all languages whose implicit info is needed. - cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config); + cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config, + this->HeadTarget); for(std::vector::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) { @@ -1376,10 +1379,31 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item) //---------------------------------------------------------------------------- void cmComputeLinkInformation::ComputeFrameworkInfo() { - // Avoid adding system framework paths. See "man ld" on OS X. - this->FrameworkPathsEmmitted.insert("/Library/Frameworks"); - this->FrameworkPathsEmmitted.insert("/Network/Library/Frameworks"); - this->FrameworkPathsEmmitted.insert("/System/Library/Frameworks"); + // Avoid adding implicit framework paths. + std::vector implicitDirVec; + + // Get platform-wide implicit directories. + if(const char* implicitLinks = this->Makefile->GetDefinition + ("CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES")) + { + cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec); + } + + // Get language-specific implicit directories. + std::string implicitDirVar = "CMAKE_"; + implicitDirVar += this->LinkLanguage; + implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"; + if(const char* implicitDirs = + this->Makefile->GetDefinition(implicitDirVar.c_str())) + { + cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec); + } + + for(std::vector::const_iterator i = implicitDirVec.begin(); + i != implicitDirVec.end(); ++i) + { + this->FrameworkPathsEmmitted.insert(*i); + } // Regular expression to extract a framework path and name. this->SplitFramework.compile("(.*)/(.*)\\.framework$"); diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index e0078af2a..1a76922a5 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -29,7 +29,8 @@ class cmOrderDirectories; class cmComputeLinkInformation { public: - cmComputeLinkInformation(cmTarget* target, const char* config); + cmComputeLinkInformation(cmTarget* target, const char* config, + cmTarget* headTarget); ~cmComputeLinkInformation(); bool Compute(); @@ -74,6 +75,7 @@ private: // Context information. cmTarget* Target; + cmTarget* HeadTarget; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; cmGlobalGenerator* GlobalGenerator; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index ab77c6bc9..8fd95b9cd 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -200,20 +200,48 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Get the depender. cmTarget* depender = this->Targets[depender_index]; - // Loop over all targets linked directly. + // Loop over all targets linked directly in all configs. + // We need to make targets depend on the union of all config-specific + // dependencies in all targets, because the generated build-systems can't + // deal with config-specific dependencies. { - cmTarget::LinkLibraryVectorType const& tlibs = - depender->GetOriginalLinkLibraries(); std::set emitted; + { + std::vector tlibs; + depender->GetDirectLinkLibraries(0, tlibs, depender); // A target should not depend on itself. emitted.insert(depender->GetName()); - for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin(); + for(std::vector::const_iterator lib = tlibs.begin(); lib != tlibs.end(); ++lib) { // Don't emit the same library twice for this target. - if(emitted.insert(lib->first).second) + if(emitted.insert(*lib).second) { - this->AddTargetDepend(depender_index, lib->first.c_str(), true); + this->AddTargetDepend(depender_index, lib->c_str(), true); + this->AddInterfaceDepends(depender_index, lib->c_str(), + true, emitted); + } + } + } + std::vector configs; + depender->GetMakefile()->GetConfigurations(configs); + for (std::vector::const_iterator it = configs.begin(); + it != configs.end(); ++it) + { + std::vector tlibs; + depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender); + // A target should not depend on itself. + emitted.insert(depender->GetName()); + for(std::vector::const_iterator lib = tlibs.begin(); + lib != tlibs.end(); ++lib) + { + // Don't emit the same library twice for this target. + if(emitted.insert(*lib).second) + { + this->AddTargetDepend(depender_index, lib->c_str(), true); + this->AddInterfaceDepends(depender_index, lib->c_str(), + true, emitted); + } } } } @@ -236,6 +264,64 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) } } +//---------------------------------------------------------------------------- +void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, + cmTarget* dependee, + const char *config, + std::set &emitted) +{ + cmTarget* depender = this->Targets[depender_index]; + if(cmTarget::LinkInterface const* iface = + dependee->GetLinkInterface(config, depender)) + { + for(std::vector::const_iterator + lib = iface->Libraries.begin(); + lib != iface->Libraries.end(); ++lib) + { + // Don't emit the same library twice for this target. + if(emitted.insert(*lib).second) + { + this->AddTargetDepend(depender_index, lib->c_str(), true); + } + } + } +} + +//---------------------------------------------------------------------------- +void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, + const char* dependee_name, + bool linking, + std::set &emitted) +{ + cmTarget* depender = this->Targets[depender_index]; + cmTarget* dependee = + depender->GetMakefile()->FindTargetToUse(dependee_name); + // Skip targets that will not really be linked. This is probably a + // name conflict between an external library and an executable + // within the project. + if(linking && dependee && + dependee->GetType() == cmTarget::EXECUTABLE && + !dependee->IsExecutableWithExports()) + { + dependee = 0; + } + + if(dependee) + { + this->AddInterfaceDepends(depender_index, dependee, 0, emitted); + std::vector configs; + depender->GetMakefile()->GetConfigurations(configs); + for (std::vector::const_iterator it = configs.begin(); + it != configs.end(); ++it) + { + // A target should not depend on itself. + emitted.insert(depender->GetName()); + this->AddInterfaceDepends(depender_index, dependee, + it->c_str(), emitted); + } + } +} + //---------------------------------------------------------------------------- void cmComputeTargetDepends::AddTargetDepend(int depender_index, const char* dependee_name, diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 67bce72d9..d6131cf1c 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -48,7 +48,11 @@ private: bool linking); void AddTargetDepend(int depender_index, cmTarget* dependee, bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); - + void AddInterfaceDepends(int depender_index, const char* dependee_name, + bool linking, std::set &emitted); + void AddInterfaceDepends(int depender_index, cmTarget* dependee, + const char *config, + std::set &emitted); cmGlobalGenerator* GlobalGenerator; bool DebugMode; bool NoCycles; diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 07df7d5e0..f2f77eea0 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -47,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const { return target->GetLocation(this->Config); } - return this->GE->Parse(argv0).Evaluate(this->Makefile, this->Config); + return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config); } //---------------------------------------------------------------------------- @@ -58,7 +58,7 @@ cmCustomCommandGenerator cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; for(unsigned int j=1;j < commandLine.size(); ++j) { - std::string arg = this->GE->Parse(commandLine[j]).Evaluate(this->Makefile, + std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile, this->Config); cmd += " "; if(this->OldStyle) diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index 445fd0e12..b8889ac20 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -26,6 +26,16 @@ "strings which contain a '>' for example.\n" \ " $ = A literal ','. Used to compare " \ "strings which contain a ',' for example.\n" \ + " $ = Marks ... as being the name of a " \ + "target. This is required if exporting targets to multiple " \ + "dependent export sets. The '...' must be a literal name of a " \ + "target- it may not contain generator expressions.\n" \ + " $ = content of \"...\" when the property " \ + "is exported using install(EXPORT), and empty otherwise.\n" \ + " $ = content of \"...\" when the property " \ + "is exported using export(), or when the target is used by another " \ + "target in the same buildsystem. Expands to the empty string " \ + "otherwise.\n" \ " $ = main file (.exe, .so.1.2, .a)\n" \ " $ = file used to link (.a, .lib, .so)\n" \ " $ = file with soname (.so.3)\n" \ diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index d855bd278..579f77f80 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -896,6 +896,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm) " script, it may get fatal error messages from the script.",false, "Variables That Change Behavior"); + cm->DefineProperty + ("CMAKE_DEBUG_TARGET_PROPERTIES", cmProperty::VARIABLE, + "Enables tracing output for target properties.", + "This variable can be populated with a list of properties to generate " + "debug output for when evaluating target properties. Currently it can " + "only be used when evaluating the INCLUDE_DIRECTORIES target property. " + "In that case, it outputs a backtrace for each include directory in " + "the build. Default is unset.",false,"Variables That Change Behavior"); cm->DefineProperty ("CMAKE_SUBLIMECLANG_DISABLED", cmProperty::VARIABLE, "Used by the Sublime Text 2 generator to disable SublimeClang in " @@ -1146,6 +1154,17 @@ void cmDocumentVariables::DefineVariables(cmake* cm) false, "Variables that Control the Build"); + cm->DefineProperty + ("CMAKE_BUILD_INTERFACE_INCLUDES", cmProperty::VARIABLE, + "Automatically add the current source- and build directories " + "to the INTERFACE_INCLUDE_DIRECTORIES.", + "If this variable is enabled, CMake automatically adds for each " + "target ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} " + "to the INTERFACE_INCLUDE_DIRECTORIES." + "By default CMAKE_BUILD_INTERFACE_INCLUDES is OFF.", + false, + "Variables that Control the Build"); + cm->DefineProperty ("CMAKE_INSTALL_RPATH", cmProperty::VARIABLE, "The rpath to use for installed targets.", @@ -1630,6 +1649,23 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "These paths are implicit linker search directories for the compiler's " "language. " "CMake automatically detects these directories for each language and " + "reports the results in this variable." + "\n" + "When a library in one of these directories is given by full path to " + "target_link_libraries() CMake will generate the -l form on " + "link lines to ensure the linker searches its implicit directories " + "for the library. " + "Note that some toolchains read implicit directories from an " + "environment variable such as LIBRARY_PATH so keep its value " + "consistent when operating in a given build tree.",false, + "Variables for Languages"); + + cm->DefineProperty + ("CMAKE__IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", cmProperty::VARIABLE, + "Implicit linker framework search path detected for language .", + "These paths are implicit linker framework search directories for " + "the compiler's language. " + "CMake automatically detects these directories for each language and " "reports the results in this variable.", false, "Variables for Languages"); diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index fb3f39fe6..9533319e9 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -22,15 +22,20 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator() //---------------------------------------------------------------------------- bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { - // Create all the imported targets. + std::vector allTargets; + { + std::string expectedTargets; + std::string sep; for(std::vector::const_iterator tei = this->Exports->begin(); tei != this->Exports->end(); ++tei) { + expectedTargets += sep + this->Namespace + (*tei)->GetName(); + sep = " "; cmTarget* te = *tei; if(this->ExportedTargets.insert(te).second) { - this->GenerateImportTargetCode(os, te); + allTargets.push_back(te); } else { @@ -44,6 +49,33 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) } } + this->GenerateExpectedTargetsCode(os, expectedTargets); + } + + std::vector missingTargets; + + // Create all the imported targets. + for(std::vector::const_iterator + tei = allTargets.begin(); + tei != allTargets.end(); ++tei) + { + cmTarget* te = *tei; + this->GenerateImportTargetCode(os, te); + + ImportPropertyMap properties; + + this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + + this->GenerateInterfaceProperties(te, os, properties); + } + + this->GenerateMissingTargetsCheckCode(os, missingTargets); + // Generate import file content for each configuration. for(std::vector::const_iterator ci = this->Configurations.begin(); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 8dffae43a..90c0c4111 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -124,6 +124,201 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, this->GenerateImportTargetsConfig(os, config, suffix); } +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + const char *outputName, + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector &missingTargets) +{ + const char *input = target->GetProperty(propName); + if (input) + { + if (!*input) + { + // Set to empty + properties[outputName] = ""; + return; + } + + std::string prepro = cmGeneratorExpression::Preprocess(input, + preprocessRule); + if (!prepro.empty()) + { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + missingTargets); + properties[outputName] = prepro; + } + } +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector &missingTargets) +{ + this->PopulateInterfaceProperty(propName, propName, target, preprocessRule, + properties, missingTargets); +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, + std::ostream& os, + const ImportPropertyMap &properties) +{ + if (!properties.empty()) + { + std::string targetName = this->Namespace; + targetName += target->GetName(); + os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n"; + for(ImportPropertyMap::const_iterator pi = properties.begin(); + pi != properties.end(); ++pi) + { + os << " " << pi->first << " \"" << pi->second << "\"\n"; + } + os << ")\n\n"; + } +} + +//---------------------------------------------------------------------------- +void +cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( + std::string &input, + cmTarget* target, + std::vector &missingTargets) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + + cmMakefile *mf = target->GetMakefile(); + std::string errorString; + + while((pos = input.find("$", nameStartPos); + std::string::size_type commaPos = input.find(",", nameStartPos); + std::string::size_type nextOpenPos = input.find("$<", nameStartPos); + if (commaPos == input.npos // Implied 'this' target + || closePos == input.npos // Imcomplete expression. + || closePos < commaPos // Implied 'this' target + || nextOpenPos < commaPos) // Non-literal + { + lastPos = nameStartPos; + continue; + } + + const std::string targetName = input.substr(nameStartPos, + commaPos - nameStartPos); + + pos = nameStartPos; // We're not going to replace the entire expression, + // but only the target parameter. + if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) + { + if(tgt->IsImported()) + { + pos += targetName.size(); + } + else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input.replace(pos, targetName.size(), + this->Namespace + targetName); + pos += this->Namespace.size() + targetName.size(); + } + else + { + std::string namespacedTarget; + this->HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input.replace(pos, targetName.size(), namespacedTarget); + pos += namespacedTarget.size(); + } + } + } + else + { + errorString = "$ requires " + "its first parameter to be a reachable target."; + } + lastPos = pos; + if (!errorString.empty()) + { + break; + } + } + if (!errorString.empty()) + { + mf->IssueMessage(cmake::FATAL_ERROR, errorString); + return; + } + + pos = 0; + lastPos = pos; + while((pos = input.find("$", nameStartPos); + if (endPos == input.npos) + { + errorString = "$ expression incomplete"; + } + const std::string targetName = input.substr(nameStartPos, + endPos - nameStartPos); + if(targetName.find("$<", lastPos) != input.npos) + { + errorString = "$ requires its parameter to be a " + "literal."; + } + if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) + { + if(tgt->IsImported()) + { + input.replace(pos, sizeof("$ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input.replace(pos, sizeof("$Namespace + targetName); + pos += sizeof("$HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input.replace(pos, sizeof("$IssueMessage(cmake::FATAL_ERROR, errorString); + } +} + //---------------------------------------------------------------------------- void cmExportFileGenerator @@ -162,7 +357,8 @@ cmExportFileGenerator } // Add the transitive link dependencies for this configuration. - if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config)) + if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config, + target)) { this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", @@ -286,6 +482,37 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os) << "\n"; } +//---------------------------------------------------------------------------- +void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os, + const std::string &expectedTargets) +{ + os << "SET(_targetsDefined)\n" + "SET(_targetsNotDefined)\n" + "SET(_expectedTargets)\n" + "FOREACH(_expectedTarget " << expectedTargets << ")\n" + " LIST(APPEND _expectedTargets ${_expectedTarget})\n" + " IF(NOT TARGET ${_expectedTarget})\n" + " LIST(APPEND _targetsNotDefined ${_expectedTarget})\n" + " ENDIF(NOT TARGET ${_expectedTarget})\n" + " IF(TARGET ${_expectedTarget})\n" + " LIST(APPEND _targetsDefined ${_expectedTarget})\n" + " ENDIF(TARGET ${_expectedTarget})\n" + "ENDFOREACH(_expectedTarget)\n" + "IF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" + " SET(CMAKE_IMPORT_FILE_VERSION)\n" + " CMAKE_POLICY(POP)\n" + " RETURN()\n" + "ENDIF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" + "IF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" + " MESSAGE(FATAL_ERROR \"Some (but not all) targets in this export " + "set were already defined.\\nTargets Defined: ${_targetsDefined}\\n" + "Targets not yet defined: ${_targetsNotDefined}\\n\")\n" + "ENDIF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" + "UNSET(_targetsDefined)\n" + "UNSET(_targetsNotDefined)\n" + "UNSET(_expectedTargets)\n" + "\n\n"; +} //---------------------------------------------------------------------------- void cmExportFileGenerator diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 70bc65de5..7c58ad8b4 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -13,6 +13,7 @@ #define cmExportFileGenerator_h #include "cmCommand.h" +#include "cmGeneratorExpression.h" /** \class cmExportFileGenerator * \brief Generate a file exporting targets from a build or install tree. @@ -63,6 +64,8 @@ protected: void GenerateMissingTargetsCheckCode(std::ostream& os, const std::vector& missingTargets); + void GenerateExpectedTargetsCode(std::ostream& os, + const std::string &expectedTargets); // Collect properties with detailed information about targets beyond // their location on disk. @@ -91,6 +94,17 @@ protected: cmMakefile* mf, cmTarget* depender, cmTarget* dependee) = 0; + void PopulateInterfaceProperty(const char *, + cmTarget *target, + cmGeneratorExpression::PreprocessContext, + ImportPropertyMap &properties, + std::vector &missingTargets); + void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, + const ImportPropertyMap &properties); + + void ResolveTargetsInGeneratorExpressions(std::string &input, + cmTarget* target, + std::vector &missingTargets); // The namespace in which the exports are placed in the generated file. std::string Namespace; @@ -107,6 +121,13 @@ protected: // The set of targets included in the export. std::set ExportedTargets; + +private: + void PopulateInterfaceProperty(const char *, const char *, + cmTarget *target, + cmGeneratorExpression::PreprocessContext, + ImportPropertyMap &properties, + std::vector &missingTargets); }; #endif diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 784173172..bc953c9c1 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -39,15 +39,20 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob() //---------------------------------------------------------------------------- bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) { - // Create all the imported targets. + std::vector allTargets; + { + std::string expectedTargets; + std::string sep; for(std::vector::const_iterator tei = this->IEGen->GetExportSet()->GetTargetExports()->begin(); tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) { + expectedTargets += sep + this->Namespace + (*tei)->Target->GetName(); + sep = " "; cmTargetExport const* te = *tei; if(this->ExportedTargets.insert(te->Target).second) { - this->GenerateImportTargetCode(os, te->Target); + allTargets.push_back(te->Target); } else { @@ -61,6 +66,35 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) } } + this->GenerateExpectedTargetsCode(os, expectedTargets); + } + + std::vector missingTargets; + + // Create all the imported targets. + for(std::vector::const_iterator + tei = allTargets.begin(); + tei != allTargets.end(); ++tei) + { + cmTarget* te = *tei; + this->GenerateImportTargetCode(os, te); + + ImportPropertyMap properties; + + this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", + te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", + te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); + + this->GenerateInterfaceProperties(te, os, properties); + } + + this->GenerateMissingTargetsCheckCode(os, missingTargets); + // Now load per-configuration properties for them. os << "# Load information for each installed configuration.\n" << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n" diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 25b13e52e..0cf9cbbf2 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -811,6 +811,11 @@ std::string cmExtraCodeBlocksGenerator::BuildMakeCommand( command += " VERBOSE=1 "; command += target; } + else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0) + { + command += " -v "; + command += target; + } else { std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index b877f3c3a..0cdbb82d7 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -17,6 +17,8 @@ #include "cmFileTimeComparison.h" #include "cmCryptoHash.h" +#include "cmTimestamp.h" + #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_curl.h" #endif @@ -161,6 +163,10 @@ bool cmFileCommand { return this->HandleCMakePathCommand(args, true); } + else if ( subCommand == "TIMESTAMP" ) + { + return this->HandleTimestampCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -3241,3 +3247,54 @@ cmFileCommand::HandleUploadCommand(std::vector const& args) return false; #endif } + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleTimestampCommand( + std::vector const& args) +{ + if(args.size() < 3) + { + this->SetError("sub-command TIMESTAMP requires at least two arguments."); + return false; + } + else if(args.size() > 5) + { + this->SetError("sub-command TIMESTAMP takes at most four arguments."); + return false; + } + + unsigned int argsIndex = 1; + + const std::string& filename = args[argsIndex++]; + + const std::string& outputVariable = args[argsIndex++]; + + std::string formatString; + if(args.size() > argsIndex && args[argsIndex] != "UTC") + { + formatString = args[argsIndex++]; + } + + bool utcFlag = false; + if(args.size() > argsIndex) + { + if(args[argsIndex] == "UTC") + { + utcFlag = true; + } + else + { + std::string e = " TIMESTAMP sub-command does not recognize option " + + args[argsIndex] + "."; + this->SetError(e.c_str()); + return false; + } + } + + cmTimestamp timestamp; + std::string result = timestamp.FileModificationTime( + filename.c_str(), formatString, utcFlag); + this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str()); + + return true; +} diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index a0862ec9b..5973fa732 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -87,6 +87,7 @@ public: " [TLS_VERIFY on|off] [TLS_CAINFO file])\n" " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n" + " file(TIMESTAMP filename variable [] [UTC])\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exist. (If the file is a build input, use " @@ -200,6 +201,12 @@ public: "If SHOW_PROGRESS is specified, progress information will be printed " "as status messages until the operation is complete." "\n" + "TIMESTAMP will write a string representation of " + "the modification time of filename to variable.\n" + "Should the command be unable to obtain a timestamp " + "variable will be set to the empty string \"\".\n" + "See documentation of the string TIMESTAMP sub-command for more details." + "\n" "The file() command also provides COPY and INSTALL signatures:\n" " file( files... DESTINATION \n" " [FILE_PERMISSIONS permissions...]\n" @@ -260,6 +267,8 @@ protected: bool HandleInstallCommand(std::vector const& args); bool HandleDownloadCommand(std::vector const& args); bool HandleUploadCommand(std::vector const& args); + + bool HandleTimestampCommand(std::vector const& args); }; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 1de3982f4..7ce003216 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -360,13 +360,13 @@ void cmFindBase::AddPrefixPaths(std::vector const& in_paths, { dir += "/"; } - if(subdir == "lib") + if(subdir == "include" || subdir == "lib") { const char* arch = this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); if(arch && *arch) { - this->AddPathInternal(dir+"lib/"+arch, pathType); + this->AddPathInternal(dir+subdir+"/"+arch, pathType); } } std::string add = dir + subdir; diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 952492463..6a432984d 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -45,8 +45,10 @@ void cmFindPathCommand::GenerateDocumentation() "SEARCH_XXX", "file in a directory"); cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "include"); - cmSystemTools::ReplaceString(this->GenericDocumentation, - "XXX_EXTRA_PREFIX_ENTRY", ""); + cmSystemTools::ReplaceString( + this->GenericDocumentation, + "XXX_EXTRA_PREFIX_ENTRY", + " /include/ if CMAKE_LIBRARY_ARCHITECTURE is set, and\n"); cmSystemTools::ReplaceString(this->GenericDocumentation, "CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"); diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 7d8df3733..4063697cd 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -25,55 +25,55 @@ //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( cmListFileBacktrace const& backtrace): - Backtrace(backtrace), CompiledExpression(0) + Backtrace(backtrace) { } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr cmGeneratorExpression::Parse(std::string const& input) { return this->Parse(input.c_str()); } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr cmGeneratorExpression::Parse(const char* input) { - cmGeneratorExpressionLexer l; - std::vector tokens = l.Tokenize(input); - bool needsParsing = l.GetSawGeneratorExpression(); - std::vector evaluators; - - if (needsParsing) - { - cmGeneratorExpressionParser p(tokens); - p.Parse(evaluators); - } - - delete this->CompiledExpression; - this->CompiledExpression = new cmCompiledGeneratorExpression( - this->Backtrace, - evaluators, - input, - needsParsing); - return *this->CompiledExpression; + return cmsys::auto_ptr( + new cmCompiledGeneratorExpression( + this->Backtrace, + input)); } cmGeneratorExpression::~cmGeneratorExpression() { - delete this->CompiledExpression; } //---------------------------------------------------------------------------- const char *cmCompiledGeneratorExpression::Evaluate( cmMakefile* mf, const char* config, bool quiet, - cmGeneratorTarget *target, + cmTarget *headTarget, + cmGeneratorExpressionDAGChecker *dagChecker) const +{ + return this->Evaluate(mf, + config, + quiet, + headTarget, + headTarget, + dagChecker); +} + +//---------------------------------------------------------------------------- +const char *cmCompiledGeneratorExpression::Evaluate( + cmMakefile* mf, const char* config, bool quiet, + cmTarget *headTarget, + cmTarget *currentTarget, cmGeneratorExpressionDAGChecker *dagChecker) const { if (!this->NeedsParsing) { - return this->Input; + return this->Input.c_str(); } this->Output = ""; @@ -88,12 +88,21 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Config = config; context.Quiet = quiet; context.HadError = false; - context.Target = target; + context.HeadTarget = headTarget; + context.CurrentTarget = currentTarget ? currentTarget : headTarget; context.Backtrace = this->Backtrace; for ( ; it != end; ++it) { - this->Output += (*it)->Evaluate(&context, dagChecker); + const std::string result = (*it)->Evaluate(&context, dagChecker); + this->Output += result; + + for(std::set::const_iterator + p = context.SeenTargetProperties.begin(); + p != context.SeenTargetProperties.end(); ++p) + { + this->SeenTargetProperties[*p] += result + ";"; + } if (context.HadError) { this->Output = ""; @@ -108,12 +117,19 @@ const char *cmCompiledGeneratorExpression::Evaluate( cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmListFileBacktrace const& backtrace, - const std::vector &evaluators, - const char *input, bool needsParsing) - : Backtrace(backtrace), Evaluators(evaluators), Input(input), - NeedsParsing(needsParsing) + const char *input) + : Backtrace(backtrace), Input(input ? input : "") { + cmGeneratorExpressionLexer l; + std::vector tokens = + l.Tokenize(this->Input.c_str()); + this->NeedsParsing = l.GetSawGeneratorExpression(); + if (this->NeedsParsing) + { + cmGeneratorExpressionParser p(tokens); + p.Parse(this->Evaluators); + } } @@ -131,15 +147,9 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() } } -std::string cmGeneratorExpression::Preprocess(const std::string &input, - PreprocessContext context) +//---------------------------------------------------------------------------- +static std::string stripAllGeneratorExpressions(const std::string &input) { - if (context != StripAllGeneratorExpressions) - { - assert(!"cmGeneratorExpression::Preprocess called with invalid args"); - return std::string(); - } - std::string result; std::string::size_type pos = 0; std::string::size_type lastPos = pos; @@ -178,3 +188,81 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input, result += input.substr(lastPos); return result; } + +//---------------------------------------------------------------------------- +static std::string stripExportInterface(const std::string &input, + cmGeneratorExpression::PreprocessContext context) +{ + std::string result; + + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + while((pos = input.find("$') + { + --nestingLevel; + if (nestingLevel != 0) + { + continue; + } + if(context == cmGeneratorExpression::BuildInterface + && !gotInstallInterface) + { + result += input.substr(pos, c - cStart); + } + else if(context == cmGeneratorExpression::InstallInterface + && gotInstallInterface) + { + result += input.substr(pos, c - cStart); + } + break; + } + } + const std::string::size_type traversed = (c - cStart) + 1; + if (!*c) + { + result += std::string(gotInstallInterface ? "$ #include +#include class cmTarget; -class cmGeneratorTarget; class cmMakefile; class cmListFileBacktrace; @@ -45,11 +46,14 @@ public: cmGeneratorExpression(cmListFileBacktrace const& backtrace); ~cmGeneratorExpression(); - const cmCompiledGeneratorExpression& Parse(std::string const& input); - const cmCompiledGeneratorExpression& Parse(const char* input); + cmsys::auto_ptr Parse( + std::string const& input); + cmsys::auto_ptr Parse(const char* input); enum PreprocessContext { - StripAllGeneratorExpressions + StripAllGeneratorExpressions, + BuildInterface, + InstallInterface }; static std::string Preprocess(const std::string &input, @@ -60,7 +64,6 @@ private: void operator=(const cmGeneratorExpression &); cmListFileBacktrace const& Backtrace; - cmCompiledGeneratorExpression *CompiledExpression; }; class cmCompiledGeneratorExpression @@ -68,31 +71,49 @@ class cmCompiledGeneratorExpression public: const char* Evaluate(cmMakefile* mf, const char* config, bool quiet = false, - cmGeneratorTarget *target = 0, + cmTarget *headTarget = 0, + cmTarget *currentTarget = 0, cmGeneratorExpressionDAGChecker *dagChecker = 0) const; + const char* Evaluate(cmMakefile* mf, const char* config, + bool quiet, + cmTarget *headTarget, + cmGeneratorExpressionDAGChecker *dagChecker) const; /** Get set of targets found during evaluations. */ std::set const& GetTargets() const { return this->Targets; } + std::map const& GetSeenTargetProperties() const + { return this->SeenTargetProperties; } + ~cmCompiledGeneratorExpression(); + std::string GetInput() const + { + return this->Input; + } + + cmListFileBacktrace GetBacktrace() const + { + return this->Backtrace; + } + private: cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, - const std::vector &evaluators, - const char *input, bool needsParsing); + const char *input); friend class cmGeneratorExpression; cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &); void operator=(const cmCompiledGeneratorExpression &); - cmListFileBacktrace const& Backtrace; - const std::vector Evaluators; - const char* const Input; - const bool NeedsParsing; + cmListFileBacktrace Backtrace; + std::vector Evaluators; + const std::string Input; + bool NeedsParsing; mutable std::set Targets; + mutable std::map SeenTargetProperties; mutable std::string Output; }; diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index bfb0ddf92..2e5b5ae11 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -24,13 +24,14 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( : Parent(parent), Target(target), Property(property), Content(content), Backtrace(backtrace) { - this->IsDAG = this->isDAG(); + this->CheckResult = this->checkGraph(); } //---------------------------------------------------------------------------- -bool cmGeneratorExpressionDAGChecker::check() const +cmGeneratorExpressionDAGChecker::Result +cmGeneratorExpressionDAGChecker::check() const { - return this->IsDAG; + return this->CheckResult; } //---------------------------------------------------------------------------- @@ -38,7 +39,7 @@ void cmGeneratorExpressionDAGChecker::reportError( cmGeneratorExpressionContext *context, const std::string &expr) { - if (this->IsDAG) + if (this->CheckResult == DAG) { return; } @@ -57,7 +58,7 @@ void cmGeneratorExpressionDAGChecker::reportError( e << "Error evaluating generator expression:\n" << " " << expr << "\n" << "Self reference on target \"" - << context->Target->GetName() << "\".\n"; + << context->HeadTarget->GetName() << "\".\n"; context->Makefile->GetCMakeInstance() ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), parent->Backtrace); @@ -91,16 +92,17 @@ void cmGeneratorExpressionDAGChecker::reportError( } //---------------------------------------------------------------------------- -bool cmGeneratorExpressionDAGChecker::isDAG() const +cmGeneratorExpressionDAGChecker::Result +cmGeneratorExpressionDAGChecker::checkGraph() const { const cmGeneratorExpressionDAGChecker *parent = this->Parent; while (parent) { if (this->Target == parent->Target && this->Property == parent->Property) { - return false; + return parent->Parent ? CYCLIC_REFERENCE : SELF_REFERENCE; } parent = parent->Parent; } - return true; + return DAG; } diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index ffc84f8fd..48f26ed38 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -25,12 +25,18 @@ struct cmGeneratorExpressionDAGChecker const GeneratorExpressionContent *content, cmGeneratorExpressionDAGChecker *parent); - bool check() const; + enum Result { + DAG, + SELF_REFERENCE, + CYCLIC_REFERENCE + }; + + Result check() const; void reportError(cmGeneratorExpressionContext *context, const std::string &expr); private: - bool isDAG() const; + Result checkGraph() const; private: const cmGeneratorExpressionDAGChecker * const Parent; @@ -38,7 +44,7 @@ private: const std::string Property; const GeneratorExpressionContent * const Content; const cmListFileBacktrace Backtrace; - bool IsDAG; + Result CheckResult; }; #endif diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 2e123a4d9..f4e413123 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -18,6 +18,8 @@ #include +#include + //---------------------------------------------------------------------------- #if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510 static @@ -47,6 +49,8 @@ struct cmGeneratorExpressionNode virtual bool GeneratesContent() const { return true; } + virtual bool RequiresLiteralInput() const { return false; } + virtual bool AcceptsSingleArbitraryContentParameter() const { return false; } @@ -66,6 +70,8 @@ static const struct ZeroNode : public cmGeneratorExpressionNode virtual bool GeneratesContent() const { return false; } + virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } + std::string Evaluate(const std::vector &, cmGeneratorExpressionContext *, const GeneratorExpressionContent *, @@ -93,6 +99,12 @@ static const struct OneNode : public cmGeneratorExpressionNode } } oneNode; +//---------------------------------------------------------------------------- +static const struct OneNode buildInterfaceNode; + +//---------------------------------------------------------------------------- +static const struct ZeroNode installInterfaceNode; + //---------------------------------------------------------------------------- #define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \ static const struct OP ## Node : public cmGeneratorExpressionNode \ @@ -255,11 +267,34 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode return parameters.front().empty() ? "1" : "0"; } - return cmsysString_strcasecmp(parameters.begin()->c_str(), - context->Config) == 0 ? "1" : "0"; + if (cmsysString_strcasecmp(parameters.begin()->c_str(), + context->Config) == 0) + { + return "1"; + } + + if (context->CurrentTarget + && context->CurrentTarget->IsImported()) + { + const char* loc = 0; + const char* imp = 0; + std::string suffix; + return context->CurrentTarget->GetMappedConfig(context->Config, + &loc, + &imp, + suffix) ? "1" : "0"; + } + return "0"; } } configurationTestNode; + +//---------------------------------------------------------------------------- +static const char* targetPropertyTransitiveWhitelist[] = { + "INTERFACE_INCLUDE_DIRECTORIES" + , "INTERFACE_COMPILE_DEFINITIONS" +}; + //---------------------------------------------------------------------------- static const struct TargetPropertyNode : public cmGeneratorExpressionNode { @@ -287,8 +322,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmsys::RegularExpression propertyNameValidator; propertyNameValidator.compile("^[A-Za-z0-9_]+$"); - cmGeneratorTarget* target = context->Target; + cmTarget* target = context->HeadTarget; std::string propertyName = *parameters.begin(); + + if (!target && parameters.size() == 1) + { + reportError(context, content->GetOriginalExpression(), + "$ may only be used with targets. It may not " + "be used with add_custom_command. Specify the target to read a " + "property from using the $ signature " + "instead."); + return std::string(); + } + if (parameters.size() == 2) { if (parameters.begin()->empty() && parameters[1].empty()) @@ -320,7 +366,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "Target name not supported."); return std::string(); } - target = context->Makefile->FindGeneratorTargetToUse( + target = context->Makefile->FindTargetToUse( targetName.c_str()); if (!target) @@ -334,6 +380,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } } + if (target == context->HeadTarget) + { + // Keep track of the properties seen while processing. + // The evaluation of the LINK_LIBRARIES generator expressions + // will check this to ensure that properties form a DAG. + context->SeenTargetProperties.insert(propertyName); + } + if (propertyName.empty()) { reportError(context, content->GetOriginalExpression(), @@ -349,23 +403,74 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return std::string(); } + assert(target); + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, target->GetName(), propertyName, content, dagCheckerParent); - if (!dagChecker.check()) + switch (dagChecker.check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: dagChecker.reportError(context, content->GetOriginalExpression()); return std::string(); + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return std::string(); + case cmGeneratorExpressionDAGChecker::DAG: + break; } const char *prop = target->GetProperty(propertyName.c_str()); - return prop ? prop : ""; + if (!prop) + { + return std::string(); + } + + for (size_t i = 0; + i < (sizeof(targetPropertyTransitiveWhitelist) / + sizeof(*targetPropertyTransitiveWhitelist)); + ++i) + { + if (targetPropertyTransitiveWhitelist[i] == propertyName) + { + cmGeneratorExpression ge(context->Backtrace); + return ge.Parse(prop)->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + &dagChecker); + } + } + return prop; } } targetPropertyNode; +//---------------------------------------------------------------------------- +static const struct TargetNameNode : public cmGeneratorExpressionNode +{ + TargetNameNode() {} + + virtual bool GeneratesContent() const { return true; } + + virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } + virtual bool RequiresLiteralInput() const { return true; } + + std::string Evaluate(const std::vector ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return parameters.front(); + } + + virtual int NumExpectedParameters() const { return 1; } + +} targetNameNode; + //---------------------------------------------------------------------------- template struct TargetFilesystemArtifactResultCreator @@ -551,13 +656,13 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) { if (identifier == "0") return &zeroNode; - if (identifier == "1") + else if (identifier == "1") return &oneNode; - if (identifier == "AND") + else if (identifier == "AND") return &andNode; - if (identifier == "OR") + else if (identifier == "OR") return &orNode; - if (identifier == "NOT") + else if (identifier == "NOT") return ¬Node; else if (identifier == "CONFIGURATION") return &configurationNode; @@ -591,6 +696,12 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &commaNode; else if (identifier == "TARGET_PROPERTY") return &targetPropertyNode; + else if (identifier == "TARGET_NAME") + return &targetNameNode; + else if (identifier == "BUILD_INTERFACE") + return &buildInterfaceNode; + else if (identifier == "INSTALL_INTERFACE") + return &installInterfaceNode; return 0; } @@ -642,6 +753,20 @@ std::string GeneratorExpressionContent::Evaluate( if (!node->GeneratesContent()) { + if (node->AcceptsSingleArbitraryContentParameter()) + { + if (this->ParamChildren.empty()) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires a parameter."); + } + } + else + { + std::vector parameters; + this->EvaluateParameters(node, identifier, context, dagChecker, + parameters); + } return std::string(); } @@ -666,6 +791,15 @@ std::string GeneratorExpressionContent::Evaluate( = pit->end(); for ( ; it != end; ++it) { + if (node->RequiresLiteralInput()) + { + if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires literal input."); + return std::string(); + } + } result += (*it)->Evaluate(context, dagChecker); if (context->HadError) { @@ -673,10 +807,33 @@ std::string GeneratorExpressionContent::Evaluate( } } } + if (node->RequiresLiteralInput()) + { + std::vector parameters; + parameters.push_back(result); + return node->Evaluate(parameters, context, this, dagChecker); + } return result; } std::vector parameters; + this->EvaluateParameters(node, identifier, context, dagChecker, parameters); + if (context->HadError) + { + return std::string(); + } + + return node->Evaluate(parameters, context, this, dagChecker); +} + +//---------------------------------------------------------------------------- +std::string GeneratorExpressionContent::EvaluateParameters( + const cmGeneratorExpressionNode *node, + const std::string &identifier, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + std::vector ¶meters) const +{ { std::vector >::const_iterator pit = this->ParamChildren.begin(); @@ -732,10 +889,8 @@ std::string GeneratorExpressionContent::Evaluate( { reportError(context, this->GetOriginalExpression(), "$<" + identifier + "> expression requires at least one parameter."); - return std::string(); } - - return node->Evaluate(parameters, context, this, dagChecker); + return std::string(); } //---------------------------------------------------------------------------- diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 04a2acdc6..fb6c7eee5 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -18,21 +18,24 @@ #include "cmListFileCache.h" class cmTarget; -class cmGeneratorTarget; //---------------------------------------------------------------------------- struct cmGeneratorExpressionContext { cmListFileBacktrace Backtrace; std::set Targets; + std::set SeenTargetProperties; cmMakefile *Makefile; const char *Config; - cmGeneratorTarget *Target; + cmTarget *HeadTarget; // The target whose property is being evaluated. + cmTarget *CurrentTarget; // The dependent of HeadTarget which appears + // directly or indirectly in the property. bool Quiet; bool HadError; }; struct cmGeneratorExpressionDAGChecker; +struct cmGeneratorExpressionNode; //---------------------------------------------------------------------------- struct cmGeneratorExpressionEvaluator @@ -117,6 +120,13 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator ~GeneratorExpressionContent(); +private: + std::string EvaluateParameters(const cmGeneratorExpressionNode *node, + const std::string &identifier, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + std::vector ¶meters) const; + private: std::vector IdentifierChildren; std::vector > ParamChildren; diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index 7a8fc510d..a619cecd0 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -88,7 +88,15 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator) { - this->ParseContent(identifier); + if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) + { + extendText(identifier, this->it); + ++this->it; + } + else + { + this->ParseContent(identifier); + } if (this->it == this->Tokens.end()) { break; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 19b55c62c..62ee26a22 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -14,14 +14,11 @@ #include "cmTarget.h" #include "cmMakefile.h" #include "cmLocalGenerator.h" -#include "cmComputeLinkInformation.h" #include "cmGlobalGenerator.h" #include "cmSourceFile.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" -#include - //---------------------------------------------------------------------------- cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) { @@ -32,15 +29,6 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) this->LookupObjectLibraries(); } -cmGeneratorTarget::~cmGeneratorTarget() -{ - for(std::map::iterator i - = LinkInformation.begin(); i != LinkInformation.end(); ++i) - { - delete i->second; - } -} - //---------------------------------------------------------------------------- int cmGeneratorTarget::GetType() const { @@ -220,32 +208,6 @@ void cmGeneratorTarget::UseObjectLibraries(std::vector& objs) } } -//---------------------------------------------------------------------------- -cmComputeLinkInformation* -cmGeneratorTarget::GetLinkInformation(const char* config) -{ - // Lookup any existing information for this configuration. - std::map::iterator - i = this->LinkInformation.find(config?config:""); - if(i == this->LinkInformation.end()) - { - // Compute information for this configuration. - cmComputeLinkInformation* info = - new cmComputeLinkInformation(this->Target, config); - if(!info || !info->Compute()) - { - delete info; - info = 0; - } - - // Store the information for this configuration. - std::map::value_type - entry(config?config:"", info); - i = this->LinkInformation.insert(entry).first; - } - return i->second; -} - //---------------------------------------------------------------------------- void cmGeneratorTarget::GetAppleArchs(const char* config, std::vector& archVec) @@ -290,45 +252,7 @@ const char* cmGeneratorTarget::GetCreateRuleVariable() std::vector cmGeneratorTarget::GetIncludeDirectories( const char *config) { - std::vector includes; - const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES"); - if(!prop) - { - return includes; - } - - cmListFileBacktrace lfbt; - cmGeneratorExpression ge(lfbt); - - cmGeneratorExpressionDAGChecker dagChecker(lfbt, - this->GetName(), - "INCLUDE_DIRECTORIES", 0, 0); - - cmSystemTools::ExpandListArgument(ge.Parse(prop) - .Evaluate(this->Makefile, - config, - false, - this, - &dagChecker), - includes); - - std::set uniqueIncludes; - std::vector orderedAndUniqueIncludes; - for(std::vector::const_iterator - li = includes.begin(); li != includes.end(); ++li) - { - std::string inc = *li; - if (!cmSystemTools::IsOff(inc.c_str())) - { - cmSystemTools::ConvertToUnixSlashes(inc); - } - if(uniqueIncludes.insert(inc).second) - { - orderedAndUniqueIncludes.push_back(inc); - } - } - - return orderedAndUniqueIncludes; + return this->Target->GetIncludeDirectories(config); } //---------------------------------------------------------------------------- @@ -353,9 +277,9 @@ std::string cmGeneratorTarget::GetCompileDefinitions(const char *config) cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), defPropName, 0, 0); - return ge.Parse(prop).Evaluate(this->Makefile, + return ge.Parse(prop)->Evaluate(this->Makefile, config, false, - this, + this->Target, &dagChecker); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a29a9f904..6f5ecb7e9 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -14,7 +14,6 @@ #include "cmStandardIncludes.h" -class cmComputeLinkInformation; class cmCustomCommand; class cmGlobalGenerator; class cmLocalGenerator; @@ -26,7 +25,6 @@ class cmGeneratorTarget { public: cmGeneratorTarget(cmTarget*); - ~cmGeneratorTarget(); int GetType() const; const char *GetName() const; @@ -60,10 +58,6 @@ public: void UseObjectLibraries(std::vector& objs); - std::map LinkInformation; - - cmComputeLinkInformation* GetLinkInformation(const char* config); - void GetAppleArchs(const char* config, std::vector& archVec); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 154e6298f..d030aa7ba 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -938,6 +938,23 @@ void cmGlobalGenerator::Generate() (*targets)[tit->first] = tit->second; (*targets)[tit->first].SetMakefile(mf); } + + for ( tit = targets->begin(); tit != targets->end(); ++ tit ) + { + if (mf->IsOn("CMAKE_BUILD_INTERFACE_INCLUDES")) + { + const char *binDir = mf->GetStartOutputDirectory(); + const char *srcDir = mf->GetStartDirectory(); + const std::string dirs = std::string(binDir ? binDir : "") + + std::string(binDir ? ";" : "") + + std::string(srcDir ? srcDir : ""); + if (!dirs.empty()) + { + tit->second.AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", + ("$").c_str()); + } + } + } } // Add generator specific helper commands @@ -2047,7 +2064,7 @@ bool cmGlobalGenerator::UseFolderProperty() } // By default, this feature is OFF, since it is not supported in the - // Visual Studio Express editions: + // Visual Studio Express editions until VS11: // return false; } diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index c218c97ec..d9920366b 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -144,8 +144,7 @@ void cmGlobalVisualStudio10Generator ::EnableLanguage(std::vectorconst & lang, cmMakefile *mf, bool optional) { - if(!strcmp(this->ArchitectureId, "Itanium") || - !strcmp(this->ArchitectureId, "x64")) + if(this->ArchitectureId == "Itanium" || this->ArchitectureId == "x64") { if(this->IsExpressEdition() && !this->Find64BitTools(mf)) { diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index ba30e18cb..b6d7d0452 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -93,3 +93,12 @@ cmLocalGenerator *cmGlobalVisualStudio11Generator::CreateLocalGenerator() lg->SetGlobalGenerator(this); return lg; } + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio11Generator::UseFolderProperty() +{ + // Intentionally skip over the parent class implementation and call the + // grand-parent class's implementation. Folders are not supported by the + // Express editions in VS10 and earlier, but they are in VS11 Express. + return cmGlobalVisualStudio8Generator::UseFolderProperty(); +} diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index 8898c5d24..174f1ccb0 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -33,6 +33,7 @@ public: virtual std::string GetUserMacrosDirectory() { return ""; } protected: virtual const char* GetIDEVersion() { return "11.0"; } + bool UseFolderProperty(); private: class Factory; }; diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index db584b804..2494f559c 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -277,7 +277,7 @@ void cmGlobalVisualStudio71Generator // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator ::WriteProjectConfigurations( - std::ostream& fout, const char* name, + std::ostream& fout, const char* name, cmTarget::TargetType, const std::set& configsPartOfDefaultBuild, const char* platformMapping) { diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index e9cab0683..6d91f97fc 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -63,7 +63,7 @@ protected: virtual void WriteProjectDepends(std::ostream& fout, const char* name, const char* path, cmTarget &t); virtual void WriteProjectConfigurations( - std::ostream& fout, const char* name, + std::ostream& fout, const char* name, cmTarget::TargetType type, const std::set& configsPartOfDefaultBuild, const char* platformMapping = NULL); virtual void WriteExternalProject(std::ostream& fout, diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index b82a4f46f..71d79a170 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -247,7 +247,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( std::set allConfigurations(this->Configurations.begin(), this->Configurations.end()); this->WriteProjectConfigurations( - fout, target->GetName(), + fout, target->GetName(), target->GetType(), allConfigurations, target->GetProperty("VS_PLATFORM_MAPPING")); } else @@ -259,7 +259,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) { - this->WriteProjectConfigurations(fout, vcprojName, + this->WriteProjectConfigurations(fout, vcprojName, target->GetType(), configsPartOfDefaultBuild); } } @@ -587,7 +587,7 @@ cmGlobalVisualStudio7Generator // executables to the libraries it uses are also done here void cmGlobalVisualStudio7Generator ::WriteProjectConfigurations( - std::ostream& fout, const char* name, + std::ostream& fout, const char* name, cmTarget::TargetType, const std::set& configsPartOfDefaultBuild, const char* platformMapping) { diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 9eb9687d7..6e786201b 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -108,7 +108,7 @@ protected: virtual void WriteProjectDepends(std::ostream& fout, const char* name, const char* path, cmTarget &t); virtual void WriteProjectConfigurations( - std::ostream& fout, const char* name, + std::ostream& fout, const char* name, cmTarget::TargetType type, const std::set& configsPartOfDefaultBuild, const char* platformMapping = NULL); virtual void WriteSLNGlobalSections(std::ostream& fout, diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 855727b7b..864e8db02 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -13,32 +13,58 @@ #include "cmGlobalVisualStudio8Generator.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmVisualStudioWCEPlatformParser.h" #include "cmake.h" #include "cmGeneratedFileStream.h" -static const char vs8Win32generatorName[] = "Visual Studio 8 2005"; -static const char vs8Win64generatorName[] = "Visual Studio 8 2005 Win64"; +static const char vs8generatorName[] = "Visual Studio 8 2005"; class cmGlobalVisualStudio8Generator::Factory : public cmGlobalGeneratorFactory { public: virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const { - if(!strcmp(name, vs8Win32generatorName)) + if(strstr(name, vs8generatorName) != name) + { + return 0; + } + + const char* p = name + sizeof(vs8generatorName) - 1; + if(p[0] == '\0') { return new cmGlobalVisualStudio8Generator( - vs8Win32generatorName, NULL, NULL); + name, NULL, NULL); } - if(!strcmp(name, vs8Win64generatorName)) + + if(p[0] != ' ') + { + return 0; + } + + ++p; + + if(!strcmp(p, "Win64")) { return new cmGlobalVisualStudio8Generator( - vs8Win64generatorName, "x64", "CMAKE_FORCE_WIN64"); + name, "x64", "CMAKE_FORCE_WIN64"); } - return 0; + + cmVisualStudioWCEPlatformParser parser(p); + parser.ParseVersion("8.0"); + if (!parser.Found()) + { + return 0; + } + + cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator( + name, parser.GetArchitectureFamily(), NULL); + ret->PlatformName = p; + ret->WindowsCEVersion = parser.GetOSVersion(); + return ret; } virtual void GetDocumentation(cmDocumentationEntry& entry) const { - entry.Name = "Visual Studio 8 2005"; + entry.Name = vs8generatorName; entry.Brief = "Generates Visual Studio 8 2005 project files."; entry.Full = "It is possible to append a space followed by the platform name " @@ -48,8 +74,18 @@ public: } virtual void GetGenerators(std::vector& names) const { - names.push_back(vs8Win32generatorName); - names.push_back(vs8Win64generatorName); } + names.push_back(vs8generatorName); + names.push_back(vs8generatorName + std::string(" Win64")); + cmVisualStudioWCEPlatformParser parser; + parser.ParseVersion("8.0"); + const std::vector& availablePlatforms = + parser.GetAvailablePlatforms(); + for(std::vector::const_iterator i = + availablePlatforms.begin(); i != availablePlatforms.end(); ++i) + { + names.push_back("Visual Studio 8 2005 " + *i); + } + } }; //---------------------------------------------------------------------------- @@ -79,11 +115,15 @@ cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator( //---------------------------------------------------------------------------- const char* cmGlobalVisualStudio8Generator::GetPlatformName() const { - if (!strcmp(this->ArchitectureId, "X86")) + if (!this->PlatformName.empty()) + { + return this->PlatformName.c_str(); + } + if (this->ArchitectureId == "X86") { return "Win32"; } - return this->ArchitectureId; + return this->ArchitectureId.c_str(); } //---------------------------------------------------------------------------- @@ -98,6 +138,19 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator() return lg; } +//---------------------------------------------------------------------------- +void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) +{ + cmGlobalVisualStudio71Generator::AddPlatformDefinitions(mf); + mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName()); + + if(this->TargetsWindowsCE()) + { + mf->AddDefinition("CMAKE_VS_WINCE_VERSION", + this->WindowsCEVersion.c_str()); + } +} + //---------------------------------------------------------------------------- // ouput standard header for dsw file void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout) @@ -321,7 +374,7 @@ cmGlobalVisualStudio8Generator void cmGlobalVisualStudio8Generator ::WriteProjectConfigurations( - std::ostream& fout, const char* name, + std::ostream& fout, const char* name, cmTarget::TargetType type, const std::set& configsPartOfDefaultBuild, const char* platformMapping) { @@ -342,6 +395,15 @@ cmGlobalVisualStudio8Generator << (platformMapping ? platformMapping : this->GetPlatformName()) << "\n"; } + bool needsDeploy = (type == cmTarget::EXECUTABLE || + type == cmTarget::SHARED_LIBRARY); + if(this->TargetsWindowsCE() && needsDeploy) + { + fout << "\t\t{" << guid << "}." << *i + << "|" << this->GetPlatformName() << ".Deploy.0 = " << *i << "|" + << (platformMapping ? platformMapping : this->GetPlatformName()) + << "\n"; + } } } diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index f68bb9ee1..bcbd7a0bd 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -28,7 +28,7 @@ public: static cmGlobalGeneratorFactory* NewFactory(); ///! Get the name for the generator. - virtual const char* GetName() const {return this->Name;} + virtual const char* GetName() const {return this->Name.c_str();} const char* GetPlatformName() const; @@ -38,6 +38,8 @@ public: ///! Create a local generator appropriate to this Global Generator virtual cmLocalGenerator *CreateLocalGenerator(); + virtual void AddPlatformDefinitions(cmMakefile* mf); + /** * Override Configure and Generate to add the build-system check * target. @@ -62,6 +64,10 @@ public: LinkLibraryDependencies and link to .sln dependencies. */ virtual bool NeedLinkLibraryDependencies(cmTarget& target); + /** Return true if building for Windows CE */ + virtual bool TargetsWindowsCE() const { + return !this->WindowsCEVersion.empty(); } + protected: virtual const char* GetIDEVersion() { return "8.0"; } @@ -73,16 +79,19 @@ protected: virtual void WriteSLNHeader(std::ostream& fout); virtual void WriteSolutionConfigurations(std::ostream& fout); virtual void WriteProjectConfigurations( - std::ostream& fout, const char* name, + std::ostream& fout, const char* name, cmTarget::TargetType type, const std::set& configsPartOfDefaultBuild, const char* platformMapping = NULL); virtual bool ComputeTargetDepends(); virtual void WriteProjectDepends(std::ostream& fout, const char* name, const char* path, cmTarget &t); - const char* Name; + std::string Name; + std::string PlatformName; + std::string WindowsCEVersion; private: class Factory; + friend class Factory; }; #endif diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 87599efd3..2082384e6 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -13,37 +13,63 @@ #include "cmGlobalVisualStudio9Generator.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmVisualStudioWCEPlatformParser.h" #include "cmake.h" -static const char vs9Win32generatorName[] = "Visual Studio 9 2008"; -static const char vs9Win64generatorName[] = "Visual Studio 8 2005 Win64"; -static const char vs9IA64generatorName[] = "Visual Studio 9 2008 IA64"; +static const char vs9generatorName[] = "Visual Studio 9 2008"; class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory { public: virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const { - if(!strcmp(name, vs9Win32generatorName)) + if(strstr(name, vs9generatorName) != name) + { + return 0; + } + + const char* p = name + sizeof(vs9generatorName) - 1; + if(p[0] == '\0') { return new cmGlobalVisualStudio9Generator( - vs9Win32generatorName, NULL, NULL); + name, NULL, NULL); } - if(!strcmp(name, vs9Win64generatorName)) + + if(p[0] != ' ') + { + return 0; + } + + ++p; + + if(!strcmp(p, "IA64")) { return new cmGlobalVisualStudio9Generator( - vs9Win64generatorName, "x64", "CMAKE_FORCE_WIN64"); + name, "Itanium", "CMAKE_FORCE_IA64"); } - if(!strcmp(name, vs9IA64generatorName)) + + if(!strcmp(p, "Win64")) { return new cmGlobalVisualStudio9Generator( - vs9IA64generatorName, "Itanium", "CMAKE_FORCE_IA64"); + name, "x64", "CMAKE_FORCE_WIN64"); } - return 0; + + cmVisualStudioWCEPlatformParser parser(p); + parser.ParseVersion("9.0"); + if (!parser.Found()) + { + return 0; + } + + cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator( + name, parser.GetArchitectureFamily(), NULL); + ret->PlatformName = p; + ret->WindowsCEVersion = parser.GetOSVersion(); + return ret; } virtual void GetDocumentation(cmDocumentationEntry& entry) const { - entry.Name = "Visual Studio 9 2008"; + entry.Name = vs9generatorName; entry.Brief = "Generates Visual Studio 9 2008 project files."; entry.Full = "It is possible to append a space followed by the platform name " @@ -53,9 +79,19 @@ public: } virtual void GetGenerators(std::vector& names) const { - names.push_back(vs9Win32generatorName); - names.push_back(vs9Win64generatorName); - names.push_back(vs9IA64generatorName); } + names.push_back(vs9generatorName); + names.push_back(vs9generatorName + std::string(" Win64")); + names.push_back(vs9generatorName + std::string(" IA64")); + cmVisualStudioWCEPlatformParser parser; + parser.ParseVersion("9.0"); + const std::vector& availablePlatforms = + parser.GetAvailablePlatforms(); + for(std::vector::const_iterator i = + availablePlatforms.begin(); i != availablePlatforms.end(); ++i) + { + names.push_back("Visual Studio 9 2008 " + *i); + } + } }; //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index f05d3773d..1310a93ac 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -55,5 +55,6 @@ protected: virtual const char* GetIDEVersion() { return "9.0"; } private: class Factory; + friend class Factory; }; #endif diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index a51735154..808664d44 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -32,10 +32,17 @@ cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator() //---------------------------------------------------------------------------- std::string cmGlobalVisualStudioGenerator::GetRegistryBase() +{ + return cmGlobalVisualStudioGenerator::GetRegistryBase( + this->GetIDEVersion()); +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudioGenerator::GetRegistryBase( + const char* version) { std::string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\"; - key += this->GetIDEVersion(); - return key; + return key + version; } //---------------------------------------------------------------------------- @@ -492,8 +499,8 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) //---------------------------------------------------------------------------- void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf) { - mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", this->ArchitectureId); - mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", this->ArchitectureId); + mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", this->ArchitectureId.c_str()); + mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", this->ArchitectureId.c_str()); if(this->AdditionalPlatformDefinition) { diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 7258e313e..9d811706b 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -65,10 +65,16 @@ public: /** Get the top-level registry key for this VS version. */ std::string GetRegistryBase(); + /** Get the top-level registry key for the given VS version. */ + static std::string GetRegistryBase(const char* version); + /** Return true if the generated build tree may contain multiple builds. i.e. "Can I build Debug and Release in the same tree?" */ virtual bool IsMultiConfig() { return true; } + /** Return true if building for Windows CE */ + virtual bool TargetsWindowsCE() const { return false; } + class TargetSet: public std::set {}; struct TargetCompare { @@ -98,7 +104,7 @@ protected: std::string GetUtilityDepend(cmTarget* target); typedef std::map UtilityDependsMap; UtilityDependsMap UtilityDepends; - const char* ArchitectureId; + std::string ArchitectureId; const char* AdditionalPlatformDefinition; private: diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 4ef2f5736..2cfe4daba 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1206,7 +1206,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget) // If the language is compiled as a source trust Xcode to link with it. cmTarget::LinkImplementation const* impl = - cmtarget.GetLinkImplementation("NOCONFIG"); + cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget); for(std::vector::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { @@ -1639,14 +1639,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, if(strcmp(lang, "CXX") == 0) { this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName); - this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, "C"); + this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, + "C", configName); } // Add language-specific flags. this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName); // Add shared-library flags if needed. - this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang); + this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, + lang, configName); } else if(binary) { @@ -1997,15 +1999,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, dirs.Add(incpath.c_str()); } } - std::vector& frameworks = target.GetFrameworks(); - if(frameworks.size()) + if(target.GetType() != cmTarget::OBJECT_LIBRARY && + target.GetType() != cmTarget::STATIC_LIBRARY) { - for(std::vector::iterator fmIt = frameworks.begin(); - fmIt != frameworks.end(); ++fmIt) + // Add framework search paths needed for linking. + if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName)) { - if(emitted.insert(*fmIt).second) + std::vector const& fwDirs = cli->GetFrameworkPaths(); + for(std::vector::const_iterator fdi = fwDirs.begin(); + fdi != fwDirs.end(); ++fdi) { - fdirs.Add(this->XCodeEscapePath(fmIt->c_str()).c_str()); + if(emitted.insert(*fdi).second) + { + fdirs.Add(this->XCodeEscapePath(fdi->c_str()).c_str()); + } } } } @@ -2649,8 +2656,7 @@ void cmGlobalXCodeGenerator } // Compute the link library and directory information. - cmGeneratorTarget* gtgt = this->GetGeneratorTarget(cmtarget); - cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName); + cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName); if(!pcli) { continue; @@ -2692,25 +2698,6 @@ void cmGlobalXCodeGenerator linkDirs.c_str(), configName); } - // add the framework search paths - { - const char* sep = ""; - std::string fdirs; - std::vector const& fwDirs = cli.GetFrameworkPaths(); - for(std::vector::const_iterator fdi = fwDirs.begin(); - fdi != fwDirs.end(); ++fdi) - { - fdirs += sep; - sep = " "; - fdirs += this->XCodeEscapePath(fdi->c_str()); - } - if(!fdirs.empty()) - { - this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS", - fdirs.c_str(), configName); - } - } - // now add the link libraries { std::string linkLibs; diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 15bad5265..4816da9ea 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -15,8 +15,6 @@ #include "cmGlobalGenerator.h" #include "cmGeneratedFileStream.h" -#include - static const char* getShapeForTarget(const cmTarget* target) @@ -67,7 +65,7 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, cmake cm; cmGlobalGenerator ggi; ggi.SetCMakeInstance(&cm); - std::auto_ptr lg(ggi.CreateLocalGenerator()); + cmsys::auto_ptr lg(ggi.CreateLocalGenerator()); cmMakefile *mf = lg->GetMakefile(); const char* inFileName = settingsFileName; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 347ad3ec5..5f9b6585e 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -16,7 +16,6 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmake.h" -#include "cmGeneratorTarget.h" #include @@ -27,8 +26,7 @@ cmInstallTargetGenerator std::vector const& configurations, const char* component, bool optional): cmInstallGenerator(dest, configurations, component), Target(&t), - ImportLibrary(implib), FilePermissions(file_permissions), - Optional(optional), GeneratorTarget(0) + ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional) { this->ActionsPerConfig = true; this->NamelinkMode = NamelinkModeNone; @@ -486,17 +484,6 @@ void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os, this->AddStripRule(os, indent, file); } -void cmInstallTargetGenerator::CreateGeneratorTarget() -{ - if (!this->GeneratorTarget) - { - this->GeneratorTarget = this->Target->GetMakefile() - ->GetLocalGenerator() - ->GetGlobalGenerator() - ->GetGeneratorTarget(this->Target); - } -} - //---------------------------------------------------------------------------- void cmInstallTargetGenerator @@ -520,13 +507,10 @@ cmInstallTargetGenerator return; } - this->CreateGeneratorTarget(); - // Build a map of build-tree install_name to install-tree install_name for // shared libraries linked to this target. std::map install_name_remap; - if(cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(config)) + if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config)) { std::set const& sharedLibs = cli->GetSharedLibrariesLinked(); for(std::set::const_iterator j = sharedLibs.begin(); @@ -624,12 +608,9 @@ cmInstallTargetGenerator return; } - this->CreateGeneratorTarget(); - // Get the link information for this target. // It can provide the RPATH. - cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(config); + cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); if(!cli) { return; @@ -658,12 +639,9 @@ cmInstallTargetGenerator return; } - this->CreateGeneratorTarget(); - // Get the link information for this target. // It can provide the RPATH. - cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(config); + cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); if(!cli) { return; diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index cab3e9065..8cf72f975 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -14,8 +14,7 @@ #include "cmInstallGenerator.h" #include "cmTarget.h" - -class cmGeneratorTarget; +#include "cmGeneratorTarget.h" /** \class cmInstallTargetGenerator * \brief Generate target installation rules. @@ -94,8 +93,6 @@ protected: void AddRanlibRule(std::ostream& os, Indent const& indent, const std::string& toDestDirPath); - void CreateGeneratorTarget(); - cmTarget* Target; bool ImportLibrary; std::string FilePermissions; diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 181b922b1..b2acf06ad 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -224,10 +224,6 @@ cmLoadedCommand::~cmLoadedCommand() bool cmLoadCommandCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) { - this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, - "The \"load_command\" command will be removed in CMake 3.0. " - "See command documentation for details."); if(args.size() < 1 ) { return true; diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h index bcd1831e4..f0b34ee59 100644 --- a/Source/cmLoadCommandCommand.h +++ b/Source/cmLoadCommandCommand.h @@ -47,7 +47,7 @@ public: */ virtual const char* GetTerseDocumentation() const { - return "Deprecated. Use macro() or function() instead."; + return "Load a command into a running CMake."; } /** @@ -56,13 +56,6 @@ public: virtual const char* GetFullDocumentation() const { return - "This command will be removed in CMake 3.0. " - "It works only when the target architecture matches the " - "running CMake binary. " - "Use macro() or function() to add commands. " - "Use execute_process() to run advanced computations " - "in external processes." - "\n" " load_command(COMMAND_NAME [loc2 ...])\n" "The given locations are searched for a library whose name is " "cmCOMMAND_NAME. If found, it is loaded as a module and the command " @@ -74,12 +67,6 @@ public: "Otherwise the variable will not be set."; } - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmLoadCommandCommand, cmCommand); }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4952a8ce9..ecf6b413a 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1329,7 +1329,9 @@ std::string cmLocalGenerator::GetIncludeFlags( void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, cmGeneratorTarget* target, const char* lang, - const char *config) + const char *config, + bool stripImplicitInclDirs + ) { // Need to decide whether to automatically include the source and // binary directories at the beginning of the include path. @@ -1404,18 +1406,21 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, return; } - // Load implicit include directories for this language. - std::string impDirVar = "CMAKE_"; - impDirVar += lang; - impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES"; - if(const char* value = this->Makefile->GetDefinition(impDirVar.c_str())) + if (stripImplicitInclDirs) { - std::vector impDirVec; - cmSystemTools::ExpandListArgument(value, impDirVec); - for(std::vector::const_iterator i = impDirVec.begin(); - i != impDirVec.end(); ++i) + // Load implicit include directories for this language. + std::string impDirVar = "CMAKE_"; + impDirVar += lang; + impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES"; + if(const char* value = this->Makefile->GetDefinition(impDirVar.c_str())) { - emitted.insert(*i); + std::vector impDirVec; + cmSystemTools::ExpandListArgument(value, impDirVec); + for(std::vector::const_iterator i = impDirVec.begin(); + i != impDirVec.end(); ++i) + { + emitted.insert(*i); + } } } @@ -1671,7 +1676,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, { cmOStringStream fout; const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); - cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config); + cmComputeLinkInformation* pcli = tgt.Target->GetLinkInformation(config); if(!pcli) { return; @@ -1703,7 +1708,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, for(std::vector::const_iterator fdi = fwDirs.begin(); fdi != fwDirs.end(); ++fdi) { - frameworkPath = " -F"; + frameworkPath += "-F"; frameworkPath += this->Convert(fdi->c_str(), NONE, SHELL, false); frameworkPath += " "; } @@ -1875,6 +1880,14 @@ bool cmLocalGenerator::GetRealDependency(const char* inName, // modify the name so stripping down to just the file name should // produce the target name in this case. std::string name = cmSystemTools::GetFilenameName(inName); + + // If the input name is the empty string, there is no real + // dependency. Short-circuit the other checks: + if(name == "") + { + return false; + } + if(cmSystemTools::GetFilenameLastExtension(name) == ".exe") { name = cmSystemTools::GetFilenameWithoutLastExtension(name); @@ -1971,7 +1984,8 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, //---------------------------------------------------------------------------- void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, - std::string const& lang) + std::string const& lang, + const char *config) { int targetType = target->GetType(); @@ -1984,8 +1998,18 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, } else { - // Add position independendent flags, if needed. - if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) + if (target->GetType() == cmTarget::OBJECT_LIBRARY) + { + if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) + { + this->AddPositionIndependentFlags(flags, lang, targetType); + } + return; + } + + if (target->GetLinkInterfaceDependentBoolProperty( + "POSITION_INDEPENDENT_CODE", + config)) { this->AddPositionIndependentFlags(flags, lang, targetType); } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index bd582181c..b2ff0c48f 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -142,7 +142,7 @@ public: void AddLanguageFlags(std::string& flags, const char* lang, const char* config); void AddCMP0018Flags(std::string &flags, cmTarget* target, - std::string const& lang); + std::string const& lang, const char *config); void AddConfigVariableFlags(std::string& flags, const char* var, const char* config); ///! Append flags to a string. @@ -212,7 +212,8 @@ public: /** Get the include flags for the current makefile and language. */ void GetIncludeDirectories(std::vector& dirs, cmGeneratorTarget* target, - const char* lang = "C", const char *config = 0); + const char* lang = "C", const char *config = 0, + bool stripImplicitInclDirs = true); /** Compute the language used to compile the given source file. */ const char* GetSourceFileLanguage(const cmSourceFile& source); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 820d25a9d..d629e7135 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -32,7 +32,6 @@ #include -#include // auto_ptr #include //---------------------------------------------------------------------------- diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 9497e3146..6c78ac47e 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -1785,10 +1785,8 @@ void cmLocalVisualStudio6Generator const std::string extraOptions, std::string& options) { - cmGeneratorTarget* gt = - this->GlobalGenerator->GetGeneratorTarget(&target); // Compute the link information for this configuration. - cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); + cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); if(!pcli) { return; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index d954a5290..918b21e4d 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -229,6 +229,9 @@ void cmLocalVisualStudio7Generator this->FortranProject = static_cast(this->GlobalGenerator) ->TargetIsFortranOnly(target); + this->WindowsCEProject = + static_cast(this->GlobalGenerator) + ->TargetsWindowsCE(); // Intel Fortran for VS10 uses VS9 format ".vfproj" files. VSVersion realVersion = this->Version; @@ -1076,9 +1079,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmGeneratorTarget* gt = - this->GlobalGenerator->GetGeneratorTarget(&target); - cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); + cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); if(!pcli) { return; @@ -1163,9 +1164,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmGeneratorTarget* gt = - this->GlobalGenerator->GetGeneratorTarget(&target); - cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); + cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); if(!pcli) { return; @@ -1173,6 +1172,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, cmComputeLinkInformation& cli = *pcli; const char* linkLanguage = cli.GetLinkLanguage(); + bool isWin32Executable = target.GetPropertyAsBool("WIN32_EXECUTABLE"); + // Compute the variable name to lookup standard libraries for this // language. std::string standardLibsVar = "CMAKE_"; @@ -1220,15 +1221,24 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, { fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n"; } - if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") ) + if ( this->WindowsCEProject ) + { + fout << "\t\t\t\tSubSystem=\"9\"\n" + << "\t\t\t\tEntryPointSymbol=\"" + << (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup") + << "\"\n"; + } + else if ( this->FortranProject ) { fout << "\t\t\t\tSubSystem=\"" - << (this->FortranProject? "subSystemWindows" : "2") << "\"\n"; + << (isWin32Executable ? "subSystemWindows" : "subSystemConsole") + << "\"\n"; } else { fout << "\t\t\t\tSubSystem=\"" - << (this->FortranProject? "subSystemConsole" : "1") << "\"\n"; + << (isWin32Executable ? "2" : "1") + << "\"\n"; } std::string stackVar = "CMAKE_"; stackVar += linkLanguage; diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 95db2cc8c..5a1d208ef 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -122,6 +122,7 @@ private: cmVS7FlagTable const* ExtraFlagTable; std::string ModuleDefinitionFile; bool FortranProject; + bool WindowsCEProject; std::string PlatformName; // Win32 or x64 cmLocalVisualStudio7GeneratorInternals* Internal; }; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 8498d72fd..b432986a8 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -814,7 +814,7 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major, void cmMakefile::FinalPass() { // do all the variable expansions here - this->ExpandVariables(); + this->ExpandVariablesCMP0019(); // give all the commands a chance to do something // after the file has been parsed before generation @@ -1485,9 +1485,12 @@ void cmMakefile::InitializeFromParent() // Initialize definitions with the closure of the parent scope. this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure(); - // copy include paths - this->SetProperty("INCLUDE_DIRECTORIES", - parent->GetProperty("INCLUDE_DIRECTORIES")); + const std::vector parentIncludes = + parent->GetIncludeDirectoriesEntries(); + this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(), + parentIncludes.begin(), + parentIncludes.end()); + this->SystemIncludeDirectories = parent->SystemIncludeDirectories; // define flags @@ -1612,41 +1615,6 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath, } } -//---------------------------------------------------------------------------- -void AddStringToProperty(cmProperty *prop, const char* name, const char* s, - bool before) -{ - if (!prop) - { - return; - } - - // Don't worry about duplicates at this point. We eliminate them when - // we convert the property to a vector in GetIncludeDirectories. - - if (before) - { - const char *val = prop->GetValue(); - cmOStringStream oss; - - if(val && *val) - { - oss << s << ";" << val; - } - else - { - oss << s; - } - - std::string newVal = oss.str(); - prop->Set(name, newVal.c_str()); - } - else - { - prop->Append(name, s); - } -} - //---------------------------------------------------------------------------- void cmMakefile::AddIncludeDirectory(const char* inc, bool before) { @@ -1655,18 +1623,21 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before) return; } - // Directory property: - cmProperty *prop = - this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES"); - AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before); + std::vector::iterator position = + before ? this->IncludeDirectoriesEntries.begin() + : this->IncludeDirectoriesEntries.end(); + + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + IncludeDirectoriesEntry entry(inc, lfbt); + this->IncludeDirectoriesEntries.insert(position, entry); // Property on each target: for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end(); ++l) { cmTarget &t = l->second; - prop = t.GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES"); - AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before); + t.InsertInclude(entry, before); } } @@ -2122,21 +2093,33 @@ void cmMakefile::AddExtraDirectory(const char* dir) this->AuxSourceDirectories.push_back(dir); } - -// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the -// include and library directories. - -void cmMakefile::ExpandVariables() +static bool mightExpandVariablesCMP0019(const char* s) { - // Now expand variables in the include and link strings + return s && *s && strstr(s,"${") && strchr(s,'}'); +} + +void cmMakefile::ExpandVariablesCMP0019() +{ + // Drop this ancient compatibility behavior with a policy. + cmPolicies::PolicyStatus pol = this->GetPolicyStatus(cmPolicies::CMP0019); + if(pol != cmPolicies::OLD && pol != cmPolicies::WARN) + { + return; + } + cmOStringStream w; - // May not be necessary anymore... But may need a policy for strict - // backwards compatibility const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES"); - if (includeDirs) + if(mightExpandVariablesCMP0019(includeDirs)) { std::string dirs = includeDirs; this->ExpandVariablesInString(dirs, true, true); + if(pol == cmPolicies::WARN && dirs != includeDirs) + { + w << "Evaluated directory INCLUDE_DIRECTORIES\n" + << " " << includeDirs << "\n" + << "as\n" + << " " << dirs << "\n"; + } this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); } @@ -2146,10 +2129,17 @@ void cmMakefile::ExpandVariables() { cmTarget &t = l->second; includeDirs = t.GetProperty("INCLUDE_DIRECTORIES"); - if (includeDirs) + if(mightExpandVariablesCMP0019(includeDirs)) { std::string dirs = includeDirs; this->ExpandVariablesInString(dirs, true, true); + if(pol == cmPolicies::WARN && dirs != includeDirs) + { + w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n" + << " " << includeDirs << "\n" + << "as\n" + << " " << dirs << "\n"; + } t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); } } @@ -2157,13 +2147,45 @@ void cmMakefile::ExpandVariables() for(std::vector::iterator d = this->LinkDirectories.begin(); d != this->LinkDirectories.end(); ++d) { - this->ExpandVariablesInString(*d, true, true); + if(mightExpandVariablesCMP0019(d->c_str())) + { + std::string orig = *d; + this->ExpandVariablesInString(*d, true, true); + if(pol == cmPolicies::WARN && *d != orig) + { + w << "Evaluated link directory\n" + << " " << orig << "\n" + << "as\n" + << " " << *d << "\n"; + } + } } for(cmTarget::LinkLibraryVectorType::iterator l = this->LinkLibraries.begin(); l != this->LinkLibraries.end(); ++l) { - this->ExpandVariablesInString(l->first, true, true); + if(mightExpandVariablesCMP0019(l->first.c_str())) + { + std::string orig = l->first; + this->ExpandVariablesInString(l->first, true, true); + if(pol == cmPolicies::WARN && l->first != orig) + { + w << "Evaluated link library\n" + << " " << orig << "\n" + << "as\n" + << " " << l->first << "\n"; + } + } + } + + if(!w.str().empty()) + { + cmOStringStream m; + m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019) + << "\n" + << "The following variable evaluations were encountered:\n" + << w.str(); + this->IssueMessage(cmake::AUTHOR_WARNING, m.str()); } } @@ -3400,6 +3422,15 @@ void cmMakefile::SetProperty(const char* prop, const char* value) this->SetLinkDirectories(varArgsExpanded); return; } + if (propname == "INCLUDE_DIRECTORIES") + { + this->IncludeDirectoriesEntries.clear(); + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->IncludeDirectoriesEntries.push_back( + IncludeDirectoriesEntry(value, lfbt)); + return; + } if ( propname == "INCLUDE_REGULAR_EXPRESSION" ) { @@ -3431,6 +3462,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value, // handle special props std::string propname = prop; + if (propname == "INCLUDE_DIRECTORIES") + { + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->IncludeDirectoriesEntries.push_back( + IncludeDirectoriesEntry(value, lfbt)); + return; + } if ( propname == "LINK_DIRECTORIES" ) { std::vector varArgsExpanded; @@ -3542,6 +3581,20 @@ const char *cmMakefile::GetProperty(const char* prop, output = str.str(); return output.c_str(); } + else if (!strcmp("INCLUDE_DIRECTORIES",prop)) + { + std::string sep; + for (std::vector::const_iterator + it = this->IncludeDirectoriesEntries.begin(), + end = this->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + output += sep; + output += it->Value; + sep = ";"; + } + return output.c_str(); + } bool chain = false; const char *retVal = diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 70cfe5421..a85015fe6 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -22,6 +22,7 @@ #include "cmNewLineStyle.h" #include "cmGeneratorTarget.h" #include "cmake.h" +#include "cmMakefileIncludeDirectoriesEntry.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmSourceGroup.h" @@ -693,7 +694,7 @@ public: /** * Expand variables in the makefiles ivars such as link directories etc */ - void ExpandVariables(); + void ExpandVariablesCMP0019(); /** * Replace variables and #cmakedefine lines in the given string. @@ -861,6 +862,13 @@ public: /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } + typedef cmMakefileIncludeDirectoriesEntry IncludeDirectoriesEntry; + + std::vector GetIncludeDirectoriesEntries() const + { + return this->IncludeDirectoriesEntries; + } + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -909,6 +917,8 @@ protected: std::vector HeaderFileExtensions; std::string DefineFlags; + std::vector IncludeDirectoriesEntries; + // Track the value of the computed DEFINITIONS property. void AddDefineFlag(const char*, std::string&); void RemoveDefineFlag(const char*, std::string::size_type, std::string&); diff --git a/Source/cmMakefileIncludeDirectoriesEntry.h b/Source/cmMakefileIncludeDirectoriesEntry.h new file mode 100644 index 000000000..f35642dfb --- /dev/null +++ b/Source/cmMakefileIncludeDirectoriesEntry.h @@ -0,0 +1,28 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 Stephen Kelly + + 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 cmMakefileIncludeDirectoriesEntry_h +#define cmMakefileIncludeDirectoriesEntry_h + +#include +#include "cmListFileCache.h" + +struct cmMakefileIncludeDirectoriesEntry { + cmMakefileIncludeDirectoriesEntry(const std::string &value, + const cmListFileBacktrace &bt) + : Value(value), Backtrace(bt) + {} + std::string Value; + cmListFileBacktrace Backtrace; +}; + +#endif diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index e7004d668..5b4e4d774 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -19,8 +19,6 @@ #include "cmTarget.h" #include "cmake.h" -#include // auto_ptr - //---------------------------------------------------------------------------- cmMakefileLibraryTargetGenerator ::cmMakefileLibraryTargetGenerator(cmTarget* target): diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 3d02d6a04..64fcfcefa 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -268,7 +268,8 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) this->AddFortranFlags(flags); } - this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang); + this->LocalGenerator->AddCMP0018Flags(flags, this->Target, + lang, this->ConfigName); // Add include directory flags. this->AddIncludeFlags(flags, lang); @@ -1017,8 +1018,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n"; std::set emitted; const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); - if(cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(cfg)) + if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) { cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); for(cmComputeLinkInformation::ItemVector::const_iterator @@ -1551,10 +1551,10 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags() this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, "C", config); - std::vector::iterator i; // check all include directories for frameworks as this // will already have added a -F for the framework - for(i = includes.begin(); i != includes.end(); ++i) + for(std::vector::iterator i = includes.begin(); + i != includes.end(); ++i) { if(this->Target->NameResolvesToFramework(i->c_str())) { @@ -1566,17 +1566,21 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags() } std::string flags; - std::vector& frameworks = this->Target->GetFrameworks(); - for(i = frameworks.begin(); - i != frameworks.end(); ++i) + const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); + if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) { - if(emitted.insert(*i).second) + std::vector const& frameworks = cli->GetFrameworkPaths(); + for(std::vector::const_iterator i = frameworks.begin(); + i != frameworks.end(); ++i) { - flags += "-F"; - flags += this->Convert(i->c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL, true); - flags += " "; + if(emitted.insert(*i).second) + { + flags += "-F"; + flags += this->Convert(i->c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL, true); + flags += " "; + } } } return flags; @@ -1594,8 +1598,7 @@ void cmMakefileTargetGenerator // Loop over all library dependencies. const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); - if(cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(cfg)) + if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) { std::vector const& libDeps = cli->GetDepends(); for(std::vector::const_iterator j = libDeps.begin(); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 853bc1220..65967a517 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -439,6 +439,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() this->GetGeneratorTarget()); this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]); + vars["LINK_FLAGS"] = cmGlobalNinjaGenerator + ::EncodeLiteral(vars["LINK_FLAGS"]); + vars["LINK_PATH"] = frameworkPath + linkPath; // Compute architecture specific link flags. Yes, these go into a different diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 0f1015208..0f484da4c 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -147,7 +147,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, // Add shared-library flags if needed. this->LocalGenerator->AddCMP0018Flags(flags, this->Target, - language.c_str()); + language.c_str(), + this->GetConfigName()); // Add include directory flags. { @@ -257,7 +258,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const return cmNinjaDeps(); cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); + this->Target->GetLinkInformation(this->GetConfigName()); if(!cli) return cmNinjaDeps(); @@ -423,17 +424,19 @@ cmNinjaTargetGenerator std::vector compileCmds; cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + if(useClDeps) + { + std::string cmdPrefix = clDepsBinary + lang + " $in \"$DEP_FILE\" $out " + + clShowPrefix + clBinary; + compileCmds.front().insert(0, cmdPrefix); + } + for (std::vector::iterator i = compileCmds.begin(); i != compileCmds.end(); ++i) this->GetLocalGenerator()->ExpandRuleVariables(*i, vars); - std::string cmdLine; - if(useClDeps) - { - cmdLine = clDepsBinary + lang + " $in \"$DEP_FILE\" $out " + - clShowPrefix + clBinary; - } - cmdLine += this->GetLocalGenerator()->BuildCommandLine(compileCmds); + std::string cmdLine = + this->GetLocalGenerator()->BuildCommandLine(compileCmds); // Write the rule for compiling file of the given language. diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 6aef50243..eb7d6668e 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -491,6 +491,23 @@ cmPolicies::cmPolicies() "CMAKE_SHARED_LIBRARY__FLAGS whether it is modified or not and " "honor the POSITION_INDEPENDENT_CODE target property.", 2,8,9,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0019, "CMP0019", + "Do not re-expand variables in include and link information.", + "CMake 2.8.10 and lower re-evaluated values given to the " + "include_directories, link_directories, and link_libraries " + "commands to expand any leftover variable references at the " + "end of the configuration step. " + "This was for strict compatibility with VERY early CMake versions " + "because all variable references are now normally evaluated during " + "CMake language processing. " + "CMake 2.8.11 and higher prefer to skip the extra evaluation." + "\n" + "The OLD behavior for this policy is to re-evaluate the values " + "for strict compatibility. " + "The NEW behavior for this policy is to leave the values untouched.", + 2,8,11,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 6932565ab..d7d945c42 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -68,6 +68,7 @@ public: CMP0018, ///< Ignore language flags for shared libs, and adhere to /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C} /// instead. + CMP0019, ///< No variable re-expansion in include and link info /** \brief Always the last entry. * diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index 83688dd75..bf034cf44 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -212,36 +212,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) } - const char* qtIncDir = 0; - const char* qtCoreIncDir = 0; - - // check whether ${QT_INCLUDE_DIR} is part of the implicit include dirs, - // see http://public.kitware.com/Bug/view.php?id=13667 - bool qtIncludeDirMayHaveBeenRemoved = false; - if (makefile->IsSet("QT_INCLUDE_DIR")) - { - qtIncDir = makefile->GetDefinition("QT_INCLUDE_DIR"); - std::string s = - makefile->GetSafeDefinition("CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES"); - std::vector implIncDirs; - cmSystemTools::ExpandListArgument(s, implIncDirs); - if (std::find(implIncDirs.begin(), implIncDirs.end(),std::string(qtIncDir)) - != implIncDirs.end()) - { - qtIncludeDirMayHaveBeenRemoved = true; - if (makefile->IsSet("QT_QTCORE_INCLUDE_DIR")) - { - qtCoreIncDir = makefile->GetDefinition("QT_QTCORE_INCLUDE_DIR"); - } - } - } - - bool haveQtCoreIncDir = false; - bool haveQtIncDir = false; - std::vector includeDirs; cmGeneratorTarget gtgt(target); - localGen->GetIncludeDirectories(includeDirs, >gt, "CXX"); + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 + localGen->GetIncludeDirectories(includeDirs, >gt, "CXX", 0, false); std::string _moc_incs = ""; const char* sep = ""; for(std::vector::const_iterator incDirIt = includeDirs.begin(); @@ -251,37 +226,6 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) _moc_incs += sep; sep = ";"; _moc_incs += *incDirIt; - - if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir) // #13667 - { - if (*incDirIt == qtIncDir) - { - haveQtIncDir = true; - qtIncludeDirMayHaveBeenRemoved = false; // it's here, i.e. not removed - } - if (*incDirIt == qtCoreIncDir) - { - haveQtCoreIncDir = true; - } - } - } - - // Some projects (kdelibs, phonon) query the compiler for its default - // include search dirs, and add those to - // CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES. - // These may include e.g./usr/lib/qt/include . This is typically also part - // of ${QT_INCLUDES}. If this directory is then contained in the implicit - // include dirs, it is removed from the include dirs returned from the - // target above. So we add ${QT_INCLUDE_DIR} manually for moc if we detected - // that ${QT_QTCORE_INCLUDE_DIR} is among the include dirs (there shouldn't - // be a way to use Qt4 without using ${QT_QTCORE_INCLUDE_DIR} I think. - // See #13646 and #13667. - if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir - && (haveQtCoreIncDir == true) && (haveQtIncDir == false)) - { - _moc_incs += sep; - sep = ";"; - _moc_incs += qtIncDir; } const char* tmp = target->GetProperty("COMPILE_DEFINITIONS"); diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index 4fd98518b..f09976f44 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -182,10 +182,6 @@ cmSourceGroup *cmSourceGroup::MatchChildrenRegex(const char *name) std::vector::iterator end = this->Internal->GroupChildren.end(); - if(this->MatchesRegex(name)) - { - return this; - } for(;iter!=end; ++iter) { cmSourceGroup *result = iter->MatchChildrenRegex(name); @@ -194,6 +190,11 @@ cmSourceGroup *cmSourceGroup::MatchChildrenRegex(const char *name) return result; } } + if(this->MatchesRegex(name)) + { + return this; + } + return 0; } diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 0193dc9e7..e49edd878 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -19,6 +19,8 @@ #include #include +#include + //---------------------------------------------------------------------------- bool cmStringCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) @@ -87,6 +89,10 @@ bool cmStringCommand { return this->HandleFindCommand(args); } + else if(subCommand == "TIMESTAMP") + { + return this->HandleTimestampCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -879,3 +885,51 @@ bool cmStringCommand this->Makefile->AddDefinition(variableName.c_str(), &*result.begin()); return true; } + +//---------------------------------------------------------------------------- +bool cmStringCommand +::HandleTimestampCommand(std::vector const& args) +{ + if(args.size() < 2) + { + this->SetError("sub-command TIMESTAMP requires at least one argument."); + return false; + } + else if(args.size() > 4) + { + this->SetError("sub-command TIMESTAMP takes at most three arguments."); + return false; + } + + unsigned int argsIndex = 1; + + const std::string &outputVariable = args[argsIndex++]; + + std::string formatString; + if(args.size() > argsIndex && args[argsIndex] != "UTC") + { + formatString = args[argsIndex++]; + } + + bool utcFlag = false; + if(args.size() > argsIndex) + { + if(args[argsIndex] == "UTC") + { + utcFlag = true; + } + else + { + std::string e = " TIMESTAMP sub-command does not recognize option " + + args[argsIndex] + "."; + this->SetError(e.c_str()); + return false; + } + } + + cmTimestamp timestamp; + std::string result = timestamp.CurrentTime(formatString, utcFlag); + this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str()); + + return true; +} diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 728b1bc5f..4423a90e9 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -93,6 +93,7 @@ public: " string(RANDOM [LENGTH ] [ALPHABET ]\n" " [RANDOM_SEED ] )\n" " string(FIND [REVERSE])\n" + " string(TIMESTAMP [] [UTC])\n" "REGEX MATCH will match the regular expression once and store the " "match in the output variable.\n" "REGEX MATCHALL will match the regular expression as many times as " @@ -142,7 +143,33 @@ public: " () Saves a matched subexpression, which can be referenced \n" " in the REGEX REPLACE operation. Additionally it is saved\n" " by all regular expression-related commands, including \n" - " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9)."; + " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).\n" + "TIMESTAMP will write a string representation of " + "the current date and/or time to the output variable.\n" + "Should the command be unable to obtain a timestamp " + "the output variable will be set to the empty string \"\".\n" + "The optional UTC flag requests the current date/time " + "representation to be in Coordinated Universal Time (UTC) " + "rather than local time.\n" + "The optional may contain the following " + "format specifiers: \n" + " %d The day of the current month (01-31).\n" + " %H The hour on a 24-hour clock (00-23).\n" + " %I The hour on a 12-hour clock (01-12).\n" + " %j The day of the current year (001-366).\n" + " %m The month of the current year (01-12).\n" + " %M The minute of the current hour (00-59).\n" + " %S The second of the current minute.\n" + " 60 represents a leap second. (00-60)\n" + " %U The week number of the current year (00-53).\n" + " %w The day of the current week. 0 is Sunday. (0-6)\n" + " %y The last two digits of the current year (00-99)\n" + " %Y The current year. \n" + "Unknown format specifiers will be ignored " + "and copied to the output as-is.\n" + "If no explicit is given it will default to:\n" + " %Y-%m-%dT%H:%M:%S for local time.\n" + " %Y-%m-%dT%H:%M:%SZ for UTC."; } cmTypeMacro(cmStringCommand, cmCommand); @@ -165,6 +192,7 @@ protected: bool HandleStripCommand(std::vector const& args); bool HandleRandomCommand(std::vector const& args); bool HandleFindCommand(std::vector const& args); + bool HandleTimestampCommand(std::vector const& args); class RegexReplacement { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 89f03f62c..c2521d99f 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -52,7 +52,6 @@ #endif #if defined(CMAKE_BUILD_WITH_CMAKE) -# include // auto_ptr # include # include "cmCryptoHash.h" #endif @@ -1932,6 +1931,7 @@ bool extract_tar(const char* outFileName, bool verbose, { cmSystemTools::Error("Problem with archive_read_next_header(): ", archive_error_string(a)); + break; } if (verbose && extract) { @@ -1954,6 +1954,7 @@ bool extract_tar(const char* outFileName, bool verbose, cmSystemTools::Error( "Problem with archive_write_disk_set_options(): ", archive_error_string(ext)); + break; } r = archive_write_header(ext, entry); @@ -1963,6 +1964,7 @@ bool extract_tar(const char* outFileName, bool verbose, archive_error_string(ext)); cmSystemTools::Error("Current file:", archive_entry_pathname(entry)); + break; } else { @@ -1972,6 +1974,7 @@ bool extract_tar(const char* outFileName, bool verbose, { cmSystemTools::Error("Problem with archive_write_finish_entry(): ", archive_error_string(ext)); + break; } } } @@ -1982,8 +1985,7 @@ bool extract_tar(const char* outFileName, bool verbose, } archive_read_close(a); archive_read_finish(a); - return true; - + return r == ARCHIVE_EOF || r == ARCHIVE_OK; } } #endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 7c62ea8f1..2cfb1bfd5 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -15,11 +15,13 @@ #include "cmSourceFile.h" #include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" +#include "cmComputeLinkInformation.h" #include "cmDocumentCompileDefinitions.h" #include "cmDocumentGeneratorExpressions.h" #include "cmDocumentLocationUndefined.h" #include "cmListFileCache.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionDAGChecker.h" #include #include #include @@ -70,6 +72,11 @@ struct cmTarget::ImportInfo cmTarget::LinkInterface LinkInterface; }; +struct TargetConfigPair : public std::pair { + TargetConfigPair(cmTarget* tgt, const std::string &config) + : std::pair(tgt, config) {} +}; + //---------------------------------------------------------------------------- class cmTargetInternals { @@ -98,25 +105,37 @@ public: OptionalLinkInterface(): Exists(false) {} bool Exists; }; - typedef std::map LinkInterfaceMapType; + typedef std::map + LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; typedef std::map OutputInfoMapType; OutputInfoMapType OutputInfoMap; - typedef std::map ImportInfoMapType; + typedef std::map + ImportInfoMapType; ImportInfoMapType ImportInfoMap; // Cache link implementation computation from each configuration. - typedef std::map LinkImplMapType; + typedef std::map LinkImplMapType; LinkImplMapType LinkImplMap; - typedef std::map LinkClosureMapType; + typedef std::map + LinkClosureMapType; LinkClosureMapType LinkClosureMap; struct SourceEntry { std::vector Depends; }; typedef std::map SourceEntriesType; SourceEntriesType SourceEntries; + + struct IncludeDirectoriesEntry { + IncludeDirectoriesEntry(cmsys::auto_ptr cge) + : ge(cge) + {} + const cmsys::auto_ptr ge; + }; + std::vector IncludeDirectoriesEntries; }; //---------------------------------------------------------------------------- @@ -500,6 +519,22 @@ void cmTarget::DefineProperties(cmake *cm) "Installing a target with EXCLUDE_FROM_ALL set to true has " "undefined behavior."); + cm->DefineProperty + ("LINK_LIBRARIES", cmProperty::TARGET, + "List of direct link dependencies.", + "This property specifies the list of libraries or targets which will be " + "used for linking. " + "In addition to accepting values from the target_link_libraries " + "command, values may be set directly on any target using the " + "set_property command. " + "\n" + "The target property values are used by the generators to set " + "the link libraries for the compiler. " + "See also the target_link_libraries command.\n" + "Contents of LINK_LIBRARIES may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + cm->DefineProperty ("INCLUDE_DIRECTORIES", cmProperty::TARGET, "List of preprocessor include file search directories.", @@ -709,6 +744,28 @@ void cmTarget::DefineProperties(cmake *cm) "If set, this property completely overrides the generic property " "for the named configuration."); + cm->DefineProperty + ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET, + "List of public include directories for a library.", + "Targets may populate this property to publish the include directories " + "required to compile against the headers for the target. Consuming " + "targets can add entries to their own INCLUDE_DIRECTORIES property such " + "as $ to use the " + "include directories specified in the interface of 'foo'." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + + cm->DefineProperty + ("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET, + "List of public compile definitions for a library.", + "Targets may populate this property to publish the compile definitions " + "required to compile against the headers for the target. Consuming " + "targets can add entries to their own COMPILE_DEFINITIONS property such " + "as $ to use the " + "compile definitions specified in the interface of 'foo'." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + cm->DefineProperty ("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET, "Repetition count for STATIC libraries with cyclic dependencies.", @@ -820,6 +877,20 @@ void cmTarget::DefineProperties(cmake *cm) "CMAKE_POSITION_INDEPENDENT_CODE if it is set when a target is " "created."); + cm->DefineProperty + ("INTERFACE_POSITION_INDEPENDENT_CODE", cmProperty::TARGET, + "Whether consumers need to create a position-independent target", + "The INTERFACE_POSITION_INDEPENDENT_CODE property informs consumers of " + "this target whether they must set their POSITION_INDEPENDENT_CODE " + "property to ON. If this property is set to ON, then the " + "POSITION_INDEPENDENT_CODE property on all consumers will be set to " + "ON. Similarly, if this property is set to OFF, then the " + "POSITION_INDEPENDENT_CODE property on all consumers will be set to " + "OFF. If this property is undefined, then consumers will determine " + "their POSITION_INDEPENDENT_CODE property by other means. Consumers " + "must ensure that the targets that they link to have a consistent " + "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property."); + cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, "Deprecated install support.", @@ -1391,8 +1462,14 @@ void cmTarget::SetMakefile(cmMakefile* mf) // Initialize the INCLUDE_DIRECTORIES property based on the current value // of the same directory property: - this->SetProperty("INCLUDE_DIRECTORIES", - this->Makefile->GetProperty("INCLUDE_DIRECTORIES")); + const std::vector parentIncludes = + this->Makefile->GetIncludeDirectoriesEntries(); + + for (std::vector::const_iterator it + = parentIncludes.begin(); it != parentIncludes.end(); ++it) + { + this->InsertInclude(*it); + } if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) @@ -1727,9 +1804,10 @@ cmTargetTraceDependencies for(cmCustomCommandLine::const_iterator cli = cit->begin(); cli != cit->end(); ++cli) { - const cmCompiledGeneratorExpression &cge = ge.Parse(*cli); - cge.Evaluate(this->Makefile, 0, true); - std::set geTargets = cge.GetTargets(); + const cmsys::auto_ptr cge + = ge.Parse(*cli); + cge->Evaluate(this->Makefile, 0, true); + std::set geTargets = cge->GetTargets(); for(std::set::const_iterator it = geTargets.begin(); it != geTargets.end(); ++it) { @@ -2092,23 +2170,66 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname) } //---------------------------------------------------------------------------- -bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType) +void cmTarget::GetDirectLinkLibraries(const char *config, + std::vector &libs, cmTarget *head) { - if(this->NameResolvesToFramework(libname.c_str())) + const char *prop = this->GetProperty("LINK_LIBRARIES"); + if (prop) { - std::string frameworkDir = libname; - frameworkDir += "/../"; - frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str()); - std::vector::iterator i = - std::find(this->Frameworks.begin(), - this->Frameworks.end(), frameworkDir); - if(i == this->Frameworks.end()) - { - this->Frameworks.push_back(frameworkDir); - } - return true; + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + const cmsys::auto_ptr cge = ge.Parse(prop); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "LINK_LIBRARIES", 0, 0); + cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile, + config, + false, + head, + &dagChecker), + libs); + + this->AddLinkDependentTargetsForProperties(cge->GetSeenTargetProperties()); } - return false; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt) +{ + if (llt == GENERAL) + { + return value; + } + + // Get the list of configurations considered to be DEBUG. + std::vector const& debugConfigs = + this->Makefile->GetCMakeInstance()->GetDebugConfigs(); + + std::string configString = "$"; + + if (debugConfigs.size() > 1) + { + for(std::vector::const_iterator + li = debugConfigs.begin() + 1; li != debugConfigs.end(); ++li) + { + configString += ",$"; + } + configString = "$"; + } + + if (llt == OPTIMIZED) + { + configString = "$"; + } + return "$<" + configString + ":" + value + ">"; +} + +//---------------------------------------------------------------------------- +static std::string targetNameGenex(const char *lib) +{ + return std::string("$"; } //---------------------------------------------------------------------------- @@ -2121,7 +2242,18 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, { return; } - this->AddFramework(lib, llt); + + { + cmTarget *tgt = this->Makefile->FindTargetToUse(lib); + const bool isNonImportedTarget = tgt && !tgt->IsImported(); + + std::string libName = isNonImportedTarget ? targetNameGenex(lib) + : std::string(lib); + this->AppendProperty("LINK_LIBRARIES", + this->GetDebugGeneratorExpressions(libName, + llt).c_str()); + } + cmTarget::LibraryID tmp; tmp.first = lib; tmp.second = llt; @@ -2464,6 +2596,20 @@ void cmTarget::GatherDependencies( const cmMakefile& mf, } } +//---------------------------------------------------------------------------- +void deleteAndClear( + std::vector &entries) +{ + for (std::vector::const_iterator + it = entries.begin(), + end = entries.end(); + it != end; ++it) + { + delete *it; + } + entries.clear(); +} + //---------------------------------------------------------------------------- void cmTarget::SetProperty(const char* prop, const char* value) { @@ -2472,6 +2618,17 @@ void cmTarget::SetProperty(const char* prop, const char* value) return; } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->IncludeDirectoriesEntries); + cmsys::auto_ptr cge = ge.Parse(value); + this->Internal->IncludeDirectoriesEntries.push_back( + new cmTargetInternals::IncludeDirectoriesEntry(cge)); + return; + } this->Properties.SetProperty(prop, value, cmProperty::TARGET); this->MaybeInvalidatePropertyCache(prop); } @@ -2484,10 +2641,99 @@ void cmTarget::AppendProperty(const char* prop, const char* value, { return; } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->IncludeDirectoriesEntries.push_back( + new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value))); + return; + } this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); this->MaybeInvalidatePropertyCache(prop); } +//---------------------------------------------------------------------------- +void cmTarget::InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, + bool before) +{ + cmGeneratorExpression ge(entry.Backtrace); + + std::vector::iterator position + = before ? this->Internal->IncludeDirectoriesEntries.begin() + : this->Internal->IncludeDirectoriesEntries.end(); + + this->Internal->IncludeDirectoriesEntries.insert(position, + new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value))); +} + +//---------------------------------------------------------------------------- +std::vector cmTarget::GetIncludeDirectories(const char *config) +{ + std::vector includes; + std::set uniqueIncludes; + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "INCLUDE_DIRECTORIES", 0, 0); + + + std::vector debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugIncludes = std::find(debugProperties.begin(), + debugProperties.end(), + "INCLUDE_DIRECTORIES") + != debugProperties.end(); + + for (std::vector::const_iterator + it = this->Internal->IncludeDirectoriesEntries.begin(), + end = this->Internal->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + std::vector entryIncludes; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile, + config, + false, + this, + &dagChecker), + entryIncludes); + std::string usedIncludes; + for(std::vector::const_iterator + li = entryIncludes.begin(); li != entryIncludes.end(); ++li) + { + std::string inc = *li; + if (!cmSystemTools::IsOff(inc.c_str())) + { + cmSystemTools::ConvertToUnixSlashes(inc); + } + + if(uniqueIncludes.insert(inc).second) + { + includes.push_back(*li); + if (debugIncludes) + { + usedIncludes += " * " + *li + "\n"; + } + } + } + if (!usedIncludes.empty()) + { + this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, + "Used includes:\n" + usedIncludes, + (*it)->ge->GetBacktrace()); + } + } + return includes; +} + //---------------------------------------------------------------------------- void cmTarget::MaybeInvalidatePropertyCache(const char* prop) { @@ -2815,6 +3061,24 @@ const char *cmTarget::GetProperty(const char* prop, } } } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::IncludeDirectoriesEntry + IncludeDirectoriesEntry; + for (std::vector::const_iterator + it = this->Internal->IncludeDirectoriesEntries.begin(), + end = this->Internal->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } if (strcmp(prop,"IMPORTED") == 0) { @@ -2874,8 +3138,11 @@ class cmTargetCollectLinkLanguages { public: cmTargetCollectLinkLanguages(cmTarget* target, const char* config, - std::set& languages): - Config(config), Languages(languages) { this->Visited.insert(target); } + std::set& languages, + cmTarget* head): + Config(config), Languages(languages), HeadTarget(head) + { this->Visited.insert(target); } + void Visit(cmTarget* target) { if(!target || !this->Visited.insert(target).second) @@ -2884,7 +3151,7 @@ public: } cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config); + target->GetLinkInterface(this->Config, this->HeadTarget); if(!iface) { return; } for(std::vector::const_iterator @@ -2903,26 +3170,30 @@ public: private: const char* Config; std::set& Languages; + cmTarget* HeadTarget; std::set Visited; }; //---------------------------------------------------------------------------- -const char* cmTarget::GetLinkerLanguage(const char* config) +const char* cmTarget::GetLinkerLanguage(const char* config, cmTarget *head) { - const char* lang = this->GetLinkClosure(config)->LinkerLanguage.c_str(); + cmTarget *headTarget = head ? head : this; + const char* lang = this->GetLinkClosure(config, headTarget) + ->LinkerLanguage.c_str(); return *lang? lang : 0; } //---------------------------------------------------------------------------- -cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config) +cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config, + cmTarget *head) { - std::string key = cmSystemTools::UpperCase(config? config : ""); + TargetConfigPair key(head, cmSystemTools::UpperCase(config ? config : "")); cmTargetInternals::LinkClosureMapType::iterator i = this->Internal->LinkClosureMap.find(key); if(i == this->Internal->LinkClosureMap.end()) { LinkClosure lc; - this->ComputeLinkClosure(config, lc); + this->ComputeLinkClosure(config, lc, head); cmTargetInternals::LinkClosureMapType::value_type entry(key, lc); i = this->Internal->LinkClosureMap.insert(entry).first; } @@ -2983,11 +3254,12 @@ public: }; //---------------------------------------------------------------------------- -void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc) +void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc, + cmTarget *head) { // Get languages built in this target. std::set languages; - LinkImplementation const* impl = this->GetLinkImplementation(config); + LinkImplementation const* impl = this->GetLinkImplementation(config, head); for(std::vector::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { @@ -2995,7 +3267,7 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc) } // Add interface languages from linked targets. - cmTargetCollectLinkLanguages cll(this, config, languages); + cmTargetCollectLinkLanguages cll(this, config, languages, head); for(std::vector::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { @@ -3134,7 +3406,8 @@ bool cmTarget::HasSOName(const char* config) return ((this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::MODULE_LIBRARY) && !this->GetPropertyAsBool("NO_SONAME") && - this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config))); + this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config, + this))); } //---------------------------------------------------------------------------- @@ -3143,7 +3416,7 @@ std::string cmTarget::GetSOName(const char* config) if(this->IsImported()) { // Lookup the imported soname. - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) { if(info->NoSOName) { @@ -3180,7 +3453,7 @@ bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) { if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY) { - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) { return info->NoSOName; } @@ -3294,7 +3567,7 @@ std::string cmTarget::NormalGetFullPath(const char* config, bool implib, std::string cmTarget::ImportedGetFullPath(const char* config, bool implib) { std::string result; - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) { result = implib? info->ImportLibrary : info->Location; } @@ -3379,7 +3652,7 @@ void cmTarget::GetFullNameInternal(const char* config, const char* suffixVar = this->GetSuffixVariableInternal(implib); // Check for language-specific default prefix and suffix. - if(const char* ll = this->GetLinkerLanguage(config)) + if(const char* ll = this->GetLinkerLanguage(config, this)) { if(!targetSuffix && suffixVar && *suffixVar) { @@ -3750,7 +4023,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config) } // Check for rpath support on this platform. - if(const char* ll = this->GetLinkerLanguage(config)) + if(const char* ll = this->GetLinkerLanguage(config, this)) { std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; flagVar += ll; @@ -4120,6 +4393,171 @@ const char* cmTarget::GetExportMacro() } } +//---------------------------------------------------------------------------- +void cmTarget::GetLinkDependentTargetsForProperty(const std::string &p, + std::set &targets) +{ + const std::map >::const_iterator findIt + = this->LinkDependentProperties.find(p); + if (findIt != this->LinkDependentProperties.end()) + { + targets = findIt->second; + } +} + +//---------------------------------------------------------------------------- +bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) +{ + return this->LinkImplicitNullProperties.find(p) + != this->LinkImplicitNullProperties.end(); +} + +//---------------------------------------------------------------------------- +void cmTarget::AddLinkDependentTargetsForProperties( + const std::map &map) +{ + for (std::map::const_iterator it = map.begin(); + it != map.end(); ++it) + { + std::vector targets; + cmSystemTools::ExpandListArgument(it->second.c_str(), targets); + this->LinkDependentProperties[it->first].insert(targets.begin(), + targets.end()); + if (!this->GetProperty(it->first.c_str())) + { + this->LinkImplicitNullProperties.insert(it->first); + } + } +} + +//---------------------------------------------------------------------------- +bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config) +{ + bool propContent = this->GetPropertyAsBool(p.c_str()); + const bool explicitlySet = this->GetProperties() + .find(p.c_str()) + != this->GetProperties().end(); + std::set dependentTargets; + this->GetLinkDependentTargetsForProperty(p, + dependentTargets); + const bool impliedByUse = + this->IsNullImpliedByLinkLibraries(p); + assert((impliedByUse ^ explicitlySet) + || (!impliedByUse && !explicitlySet)); + + cmComputeLinkInformation *info = this->GetLinkInformation(config); + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + bool propInitialized = explicitlySet; + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + // An error should be reported if one dependency + // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other + // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the + // target itself has a POSITION_INDEPENDENT_CODE which disagrees + // with a dependency. + + if (!li->Target) + { + continue; + } + + const bool ifaceIsSet = li->Target->GetProperties() + .find("INTERFACE_" + p) + != li->Target->GetProperties().end(); + const bool ifacePropContent = li->Target->GetPropertyAsBool( + ("INTERFACE_" + p).c_str()); + if (explicitlySet) + { + if (ifaceIsSet) + { + if (propContent != ifacePropContent) + { + cmOStringStream e; + e << "Property " << p << " on target \"" + << this->GetName() << "\" does\nnot match the " + "INTERFACE_" << p << " property requirement\nof " + "dependency \"" << li->Target->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + } + else + { + // Agree + continue; + } + } + else + { + // Explicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else if (impliedByUse) + { + if (ifaceIsSet) + { + if (propContent != ifacePropContent) + { + cmOStringStream e; + e << "Property " << p << " on target \"" + << this->GetName() << "\" is\nimplied to be FALSE because it " + "was used to determine the link libraries\nalready. The " + "INTERFACE_" << p << " property on\ndependency \"" + << li->Target->GetName() << "\" is in conflict.\n"; + cmSystemTools::Error(e.str().c_str()); + } + else + { + // Agree + continue; + } + } + else + { + // Implicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else + { + if (ifaceIsSet) + { + if (propInitialized) + { + if (propContent != ifacePropContent) + { + cmOStringStream e; + e << "The INTERFACE_" << p << " property of \"" + << li->Target->GetName() << "\" does\nnot agree with the value " + "of " << p << " already determined\nfor \"" + << this->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + } + else + { + // Agree. + continue; + } + } + else + { + propContent = ifacePropContent; + propInitialized = true; + } + } + else + { + // Not set. Nothing to agree on. + continue; + } + } + } + return propContent; +} + //---------------------------------------------------------------------------- void cmTarget::GetLanguages(std::set& languages) const { @@ -4172,7 +4610,7 @@ bool cmTarget::IsChrpathUsed(const char* config) // Enable if the rpath flag uses a separator and the target uses ELF // binaries. - if(const char* ll = this->GetLinkerLanguage(config)) + if(const char* ll = this->GetLinkerLanguage(config, this)) { std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; sepVar += ll; @@ -4196,7 +4634,7 @@ bool cmTarget::IsChrpathUsed(const char* config) //---------------------------------------------------------------------------- cmTarget::ImportInfo const* -cmTarget::GetImportInfo(const char* config) +cmTarget::GetImportInfo(const char* config, cmTarget *headTarget) { // There is no imported information for non-imported targets. if(!this->IsImported()) @@ -4215,14 +4653,16 @@ cmTarget::GetImportInfo(const char* config) { config_upper = "NOCONFIG"; } + TargetConfigPair key(headTarget, config_upper); typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType; + ImportInfoMapType::const_iterator i = - this->Internal->ImportInfoMap.find(config_upper); + this->Internal->ImportInfoMap.find(key); if(i == this->Internal->ImportInfoMap.end()) { ImportInfo info; - this->ComputeImportInfo(config_upper, info); - ImportInfoMapType::value_type entry(config_upper, info); + this->ComputeImportInfo(config_upper, info, headTarget); + ImportInfoMapType::value_type entry(key, info); i = this->Internal->ImportInfoMap.insert(entry).first; } @@ -4237,27 +4677,15 @@ cmTarget::GetImportInfo(const char* config) return &i->second; } -//---------------------------------------------------------------------------- -void cmTarget::ComputeImportInfo(std::string const& desired_config, - ImportInfo& info) +bool cmTarget::GetMappedConfig(std::string const& desired_config, + const char** loc, + const char** imp, + std::string& suffix) { - // This method finds information about an imported target from its - // properties. The "IMPORTED_" namespace is reserved for properties - // defined by the project exporting the target. - - // Initialize members. - info.NoSOName = false; - // Track the configuration-specific property suffix. - std::string suffix = "_"; + suffix = "_"; suffix += desired_config; - // On a DLL platform there may be only IMPORTED_IMPLIB for a shared - // library or an executable with exports. - bool allowImp = this->HasImportLibrary(); - - // Look for a mapping from the current project's configuration to - // the imported project's configuration. std::vector mappedConfigs; { std::string mapProp = "MAP_IMPORTED_CONFIG_"; @@ -4268,26 +4696,29 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } } + // If we needed to find one of the mapped configurations but did not + // On a DLL platform there may be only IMPORTED_IMPLIB for a shared + // library or an executable with exports. + bool allowImp = this->HasImportLibrary(); + // If a mapping was found, check its configurations. - const char* loc = 0; - const char* imp = 0; for(std::vector::const_iterator mci = mappedConfigs.begin(); - !loc && !imp && mci != mappedConfigs.end(); ++mci) + !*loc && !*imp && mci != mappedConfigs.end(); ++mci) { // Look for this configuration. std::string mcUpper = cmSystemTools::UpperCase(mci->c_str()); std::string locProp = "IMPORTED_LOCATION_"; locProp += mcUpper; - loc = this->GetProperty(locProp.c_str()); + *loc = this->GetProperty(locProp.c_str()); if(allowImp) { std::string impProp = "IMPORTED_IMPLIB_"; impProp += mcUpper; - imp = this->GetProperty(impProp.c_str()); + *imp = this->GetProperty(impProp.c_str()); } // If it was found, use it for all properties below. - if(loc || imp) + if(*loc || *imp) { suffix = "_"; suffix += mcUpper; @@ -4297,45 +4728,45 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, // If we needed to find one of the mapped configurations but did not // then the target is not found. The project does not want any // other configuration. - if(!mappedConfigs.empty() && !loc && !imp) + if(!mappedConfigs.empty() && !*loc && !*imp) { - return; + return false; } // If we have not yet found it then there are no mapped // configurations. Look for an exact-match. - if(!loc && !imp) + if(!*loc && !*imp) { std::string locProp = "IMPORTED_LOCATION"; locProp += suffix; - loc = this->GetProperty(locProp.c_str()); + *loc = this->GetProperty(locProp.c_str()); if(allowImp) { std::string impProp = "IMPORTED_IMPLIB"; impProp += suffix; - imp = this->GetProperty(impProp.c_str()); + *imp = this->GetProperty(impProp.c_str()); } } // If we have not yet found it then there are no mapped // configurations and no exact match. - if(!loc && !imp) + if(!*loc && !*imp) { // The suffix computed above is not useful. suffix = ""; // Look for a configuration-less location. This may be set by // manually-written code. - loc = this->GetProperty("IMPORTED_LOCATION"); + *loc = this->GetProperty("IMPORTED_LOCATION"); if(allowImp) { - imp = this->GetProperty("IMPORTED_IMPLIB"); + *imp = this->GetProperty("IMPORTED_IMPLIB"); } } // If we have not yet found it then the project is willing to try // any available configuration. - if(!loc && !imp) + if(!*loc && !*imp) { std::vector availableConfigs; if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) @@ -4344,24 +4775,47 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } for(std::vector::const_iterator aci = availableConfigs.begin(); - !loc && !imp && aci != availableConfigs.end(); ++aci) + !*loc && !*imp && aci != availableConfigs.end(); ++aci) { suffix = "_"; suffix += cmSystemTools::UpperCase(*aci); std::string locProp = "IMPORTED_LOCATION"; locProp += suffix; - loc = this->GetProperty(locProp.c_str()); + *loc = this->GetProperty(locProp.c_str()); if(allowImp) { std::string impProp = "IMPORTED_IMPLIB"; impProp += suffix; - imp = this->GetProperty(impProp.c_str()); + *imp = this->GetProperty(impProp.c_str()); } } } - // If we have not yet found it then the target is not available. - if(!loc && !imp) + if(!*loc && !*imp) + { + return false; + } + + return true; +} + +//---------------------------------------------------------------------------- +void cmTarget::ComputeImportInfo(std::string const& desired_config, + ImportInfo& info, + cmTarget *headTarget) +{ + (void)headTarget; + // This method finds information about an imported target from its + // properties. The "IMPORTED_" namespace is reserved for properties + // defined by the project exporting the target. + + // Initialize members. + info.NoSOName = false; + + const char* loc = 0; + const char* imp = 0; + std::string suffix; + if (!this->GetMappedConfig(desired_config, &loc, &imp, suffix)) { return; } @@ -4507,12 +4961,13 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } //---------------------------------------------------------------------------- -cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config) +cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, + cmTarget *head) { // Imported targets have their own link interface. if(this->IsImported()) { - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) { return &info->LinkInterface; } @@ -4528,14 +4983,15 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config) } // Lookup any existing link interface for this configuration. - std::string key = cmSystemTools::UpperCase(config? config : ""); + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + cmTargetInternals::LinkInterfaceMapType::iterator i = this->Internal->LinkInterfaceMap.find(key); if(i == this->Internal->LinkInterfaceMap.end()) { // Compute the link interface for this configuration. cmTargetInternals::OptionalLinkInterface iface; - iface.Exists = this->ComputeLinkInterface(config, iface); + iface.Exists = this->ComputeLinkInterface(config, iface, head); // Store the information for this configuration. cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); @@ -4546,7 +5002,8 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config) } //---------------------------------------------------------------------------- -bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) +bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, + cmTarget *headTarget) { // Construct the property name suffix for this configuration. std::string suffix = "_"; @@ -4603,7 +5060,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) { emitted.insert(*li); } - LinkImplementation const* impl = this->GetLinkImplementation(config); + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); for(std::vector::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { @@ -4631,7 +5089,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) else { // The link implementation is the default link interface. - LinkImplementation const* impl = this->GetLinkImplementation(config); + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); iface.Libraries = impl->Libraries; iface.WrongConfigLibraries = impl->WrongConfigLibraries; if(this->GetType() == cmTarget::STATIC_LIBRARY) @@ -4663,7 +5122,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) //---------------------------------------------------------------------------- cmTarget::LinkImplementation const* -cmTarget::GetLinkImplementation(const char* config) +cmTarget::GetLinkImplementation(const char* config, cmTarget *head) { // There is no link implementation for imported targets. if(this->IsImported()) @@ -4672,14 +5131,15 @@ cmTarget::GetLinkImplementation(const char* config) } // Lookup any existing link implementation for this configuration. - std::string key = cmSystemTools::UpperCase(config? config : ""); + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + cmTargetInternals::LinkImplMapType::iterator i = this->Internal->LinkImplMap.find(key); if(i == this->Internal->LinkImplMap.end()) { // Compute the link implementation for this configuration. LinkImplementation impl; - this->ComputeLinkImplementation(config, impl); + this->ComputeLinkImplementation(config, impl, head); // Store the information for this configuration. cmTargetInternals::LinkImplMapType::value_type entry(key, impl); @@ -4691,30 +5151,39 @@ cmTarget::GetLinkImplementation(const char* config) //---------------------------------------------------------------------------- void cmTarget::ComputeLinkImplementation(const char* config, - LinkImplementation& impl) + LinkImplementation& impl, + cmTarget *head) { // Compute which library configuration to link. cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); // Collect libraries directly linked in this configuration. - LinkLibraryVectorType const& llibs = this->GetOriginalLinkLibraries(); - for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin(); + std::vector llibs; + this->GetDirectLinkLibraries(config, llibs, head); + for(std::vector::const_iterator li = llibs.begin(); li != llibs.end(); ++li) { // Skip entries that resolve to the target itself or are empty. - std::string item = this->CheckCMP0004(li->first); + std::string item = this->CheckCMP0004(*li); if(item == this->GetName() || item.empty()) { continue; } + // The entry is meant for this configuration. + impl.Libraries.push_back(item); + } - if(li->second == cmTarget::GENERAL || li->second == linkType) - { - // The entry is meant for this configuration. - impl.Libraries.push_back(item); - } - else + LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries(); + for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin(); + li != oldllibs.end(); ++li) + { + if(li->second != cmTarget::GENERAL && li->second != linkType) { + std::string item = this->CheckCMP0004(li->first); + if(item == this->GetName() || item.empty()) + { + continue; + } // Support OLD behavior for CMP0003. impl.WrongConfigLibraries.push_back(item); } @@ -4803,6 +5272,34 @@ std::string cmTarget::CheckCMP0004(std::string const& item) return lib; } +//---------------------------------------------------------------------------- +cmComputeLinkInformation* +cmTarget::GetLinkInformation(const char* config, cmTarget *head) +{ + cmTarget *headTarget = head ? head : this; + // Lookup any existing information for this configuration. + TargetConfigPair key(headTarget, + cmSystemTools::UpperCase(config?config:"")); + cmTargetLinkInformationMap::iterator + i = this->LinkInformation.find(key); + if(i == this->LinkInformation.end()) + { + // Compute information for this configuration. + cmComputeLinkInformation* info = + new cmComputeLinkInformation(this, config, headTarget); + if(!info || !info->Compute()) + { + delete info; + info = 0; + } + + // Store the information for this configuration. + cmTargetLinkInformationMap::value_type entry(key, info); + i = this->LinkInformation.insert(entry).first; + } + return i->second; +} + //---------------------------------------------------------------------------- std::string cmTarget::GetFrameworkDirectory(const char* config) { @@ -4860,6 +5357,29 @@ std::string cmTarget::GetMacContentDirectory(const char* config, return fpath; } +//---------------------------------------------------------------------------- +cmTargetLinkInformationMap +::cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r): derived() +{ + // Ideally cmTarget instances should never be copied. However until + // we can make a sweep to remove that, this copy constructor avoids + // allowing the resources (LinkInformation) from getting copied. In + // the worst case this will lead to extra cmComputeLinkInformation + // instances. We also enforce in debug mode that the map be emptied + // when copied. + static_cast(r); + assert(r.empty()); +} + +//---------------------------------------------------------------------------- +cmTargetLinkInformationMap::~cmTargetLinkInformationMap() +{ + for(derived::iterator i = this->begin(); i != this->end(); ++i) + { + delete i->second; + } +} + //---------------------------------------------------------------------------- cmTargetInternalPointer::cmTargetInternalPointer() { @@ -4879,6 +5399,7 @@ cmTargetInternalPointer //---------------------------------------------------------------------------- cmTargetInternalPointer::~cmTargetInternalPointer() { + deleteAndClear(this->Pointer->IncludeDirectoriesEntries); delete this->Pointer; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index e442d259a..1188a6a6a 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -15,6 +15,7 @@ #include "cmCustomCommand.h" #include "cmPropertyMap.h" #include "cmPolicies.h" +#include "cmMakefileIncludeDirectoriesEntry.h" #include @@ -22,7 +23,19 @@ class cmake; class cmMakefile; class cmSourceFile; class cmGlobalGenerator; +class cmComputeLinkInformation; class cmListFileBacktrace; +class cmTarget; + +struct cmTargetLinkInformationMap: + public std::map, cmComputeLinkInformation*> +{ + typedef std::map, + cmComputeLinkInformation*> derived; + cmTargetLinkInformationMap() {} + cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r); + ~cmTargetLinkInformationMap(); +}; class cmTargetInternals; class cmTargetInternalPointer @@ -99,9 +112,6 @@ public: std::vector &GetPostBuildCommands() {return this->PostBuildCommands;} - ///! Return the list of frameworks being linked to this target - std::vector &GetFrameworks() {return this->Frameworks;} - /** * Get the list of the source files used by this target */ @@ -158,6 +168,9 @@ public: return this->LinkLibraries;} const LinkLibraryVectorType &GetOriginalLinkLibraries() const {return this->OriginalLinkLibraries;} + void GetDirectLinkLibraries(const char *config, + std::vector &, + cmTarget *head); /** Compute the link type to use for the given configuration. */ LinkLibraryType ComputeLinkType(const char* config); @@ -169,7 +182,6 @@ public: // Check to see if a library is a framework and treat it different on Mac bool NameResolvesToFramework(const std::string& libname); - bool AddFramework(const std::string& lib, LinkLibraryType llt); void AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, LinkLibraryType llt); @@ -251,7 +263,8 @@ public: /** Get the link interface for the given configuration. Returns 0 if the target cannot be linked. */ - LinkInterface const* GetLinkInterface(const char* config); + LinkInterface const* GetLinkInterface(const char* config, + cmTarget *headTarget); /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ @@ -267,7 +280,8 @@ public: // Needed only for OLD behavior of CMP0003. std::vector WrongConfigLibraries; }; - LinkImplementation const* GetLinkImplementation(const char* config); + LinkImplementation const* GetLinkImplementation(const char* config, + cmTarget *head); /** Link information from the transitive closure of the link implementation and the interfaces of its dependencies. */ @@ -279,7 +293,7 @@ public: // Languages whose runtime libraries must be linked. std::vector Languages; }; - LinkClosure const* GetLinkClosure(const char* config); + LinkClosure const* GetLinkClosure(const char* config, cmTarget *head); /** Strip off leading and trailing whitespace from an item named in the link dependencies of this target. */ @@ -324,7 +338,7 @@ public: bool FindSourceFiles(); ///! Return the preferred linker language for this target - const char* GetLinkerLanguage(const char* config = 0); + const char* GetLinkerLanguage(const char* config = 0, cmTarget *head = 0); /** Get the full name of the target according to the settings in its makefile. */ @@ -392,9 +406,17 @@ public: std::string GetInstallNameDirForInstallTree(const char* config, bool for_xcode = false); + cmComputeLinkInformation* GetLinkInformation(const char* config, + cmTarget *head = 0); + // Get the properties cmPropertyMap &GetProperties() { return this->Properties; }; + bool GetMappedConfig(std::string const& desired_config, + const char** loc, + const char** imp, + std::string& suffix); + // Define the properties static void DefineProperties(cmake *cm); @@ -462,6 +484,19 @@ public: /** @return the Mac framework directory without the base. */ std::string GetFrameworkDirectory(const char* config = 0); + std::vector GetIncludeDirectories(const char *config); + void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, + bool before = false); + + void GetLinkDependentTargetsForProperty(const std::string &p, + std::set &targets); + bool IsNullImpliedByLinkLibraries(const std::string &p); + + void AddLinkDependentTargetsForProperties( + const std::map &map); + + bool GetLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. @@ -557,7 +592,6 @@ private: LinkLibraryVectorType LinkLibraries; LinkLibraryVectorType PrevLinkedLibraries; bool LinkLibrariesAnalyzed; - std::vector Frameworks; std::vector LinkDirectories; std::set LinkDirectoriesEmmitted; bool HaveInstallRule; @@ -572,6 +606,9 @@ private: bool DLLPlatform; bool IsApple; bool IsImportedTarget; + mutable std::map > + LinkDependentProperties; + mutable std::set LinkImplicitNullProperties; // Cache target output paths for each configuration. struct OutputInfo; @@ -581,14 +618,19 @@ private: // Cache import information from properties for each configuration. struct ImportInfo; - ImportInfo const* GetImportInfo(const char* config); - void ComputeImportInfo(std::string const& desired_config, ImportInfo& info); + ImportInfo const* GetImportInfo(const char* config, + cmTarget *workingTarget); + void ComputeImportInfo(std::string const& desired_config, ImportInfo& info, + cmTarget *head); - bool ComputeLinkInterface(const char* config, LinkInterface& iface); + cmTargetLinkInformationMap LinkInformation; + + bool ComputeLinkInterface(const char* config, LinkInterface& iface, + cmTarget *head); void ComputeLinkImplementation(const char* config, - LinkImplementation& impl); - void ComputeLinkClosure(const char* config, LinkClosure& lc); + LinkImplementation& impl, cmTarget *head); + void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget *head); void ClearLinkMaps(); @@ -596,6 +638,9 @@ private: void ProcessSourceExpression(std::string const& expr); + std::string GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt); + // The cmMakefile instance that owns this target. This should // always be set. cmMakefile* Makefile; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx new file mode 100644 index 000000000..492a1b7d0 --- /dev/null +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -0,0 +1,57 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 "cmTargetCompileDefinitionsCommand.h" + +#include "cmMakefileIncludeDirectoriesEntry.h" + +bool cmTargetCompileDefinitionsCommand +::InitialPass(std::vector const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "COMPILE_DEFINITIONS"); +} + +void cmTargetCompileDefinitionsCommand +::HandleImportedTargetInvalidScope(const std::string &scope, + const std::string &tgt) +{ + cmOStringStream e; + e << "Cannot specify " << scope << " compile definitions for imported " + "target \"" << tgt << "\". Compile definitions can only be " + "specified for an imported target in the INTERFACE mode."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +void cmTargetCompileDefinitionsCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify compile definitions for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +bool cmTargetCompileDefinitionsCommand +::HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &) +{ + content += sep + entry; + return true; +} + +void cmTargetCompileDefinitionsCommand +::HandleDirectContent(cmTarget *tgt, const std::string &content, + bool) +{ + tgt->AppendProperty("COMPILE_DEFINITIONS", content.c_str()); +} diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h new file mode 100644 index 000000000..707610e3e --- /dev/null +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -0,0 +1,91 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 cmTargetCompileDefinitionsCommand_h +#define cmTargetCompileDefinitionsCommand_h + +#include "cmTargetPropCommandBase.h" + +class cmTargetCompileDefinitionsCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetCompileDefinitionsCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const { return "target_compile_definitions";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return + "Add compile definitions to a target."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " target_compile_definitions( " + " [items1...]\n" + " [ [items2...] ...])\n" + "Specify compile definitions or targets to use when compiling a given " + "target. " + "The named must have been created by a command such as " + "add_executable or add_library. " + "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " + "the scope of the following arguments. PRIVATE and PUBLIC items will " + "populate the COMPILE_DEFINITIONS property of . PUBLIC and " + "INTERFACE items will populate the INTERFACE_COMPILE_DEFINITIONS " + "property of . " + "The non-scope arguments specify compile definitions or targets to use " + "INTERFACE_COMPILE_DEFINITIONS from. " + "Repeated calls for the same append items in the order called." + "\n" + ; + } + + cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand); + +private: + virtual void HandleImportedTargetInvalidScope(const std::string &scope, + const std::string &tgt); + virtual void HandleMissingTarget(const std::string &name); + + virtual bool HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt); + + virtual void HandleDirectContent(cmTarget *tgt, const std::string &content, + bool prepend); +}; + +#endif diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx new file mode 100644 index 000000000..18e2cba4e --- /dev/null +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -0,0 +1,74 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 "cmTargetIncludeDirectoriesCommand.h" + +#include "cmMakefileIncludeDirectoriesEntry.h" + +//---------------------------------------------------------------------------- +bool cmTargetIncludeDirectoriesCommand +::InitialPass(std::vector const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE); +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleImportedTargetInvalidScope(const std::string &tgt, + const std::string &scope) +{ + cmOStringStream e; + e << "Cannot specify " << scope << " include directories for imported " + "target \"" << tgt << "\". Include directories can only be " + "specified for an imported target in the INTERFACE mode."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify include directories for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +bool cmTargetIncludeDirectoriesCommand +::HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt) +{ + if (!cmSystemTools::FileIsFullPath(entry.c_str())) + { + cmOStringStream e; + e << "Cannot specify relative include directory \"" << entry << "\" for " + "target \"" << tgt << "\". Only absolute paths are permitted"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + + content += sep + entry; + return true; +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleDirectContent(cmTarget *tgt, const std::string &content, + bool prepend) +{ + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmMakefileIncludeDirectoriesEntry entry(content, lfbt); + tgt->InsertInclude(entry, prepend); +} diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h new file mode 100644 index 000000000..c1957d6d9 --- /dev/null +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -0,0 +1,95 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 cmTargetIncludeDirectoriesCommand_h +#define cmTargetIncludeDirectoriesCommand_h + +#include "cmTargetPropCommandBase.h" + +//---------------------------------------------------------------------------- +class cmTargetIncludeDirectoriesCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetIncludeDirectoriesCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const { return "target_include_directories";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return + "Add include directories to a target."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " target_include_directories( [BEFORE] " + " [items1...]\n" + " [ [items2...] ...])\n" + "Specify include directories or targets to use when compiling a given " + "target. " + "The named must have been created by a command such as " + "add_executable or add_library.\n" + "If BEFORE is specified, the content will be prepended to the property " + "instead of being appended.\n" + "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " + "the scope of the following arguments. PRIVATE and PUBLIC items will " + "populate the INCLUDE_DIRECTORIES property of . PUBLIC and " + "INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES " + "property of . " + "The non-scope arguments specify either include directories or targets " + "to use INTERFACE_INCLUDE_DIRECTORIES from. Any specified include " + "directories must be absolute paths, not relative paths. " + "Repeated calls for the same append items in the order called." + "\n" + ; + } + + cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand); + +private: + virtual void HandleImportedTargetInvalidScope(const std::string &tgt, + const std::string &scope); + virtual void HandleMissingTarget(const std::string &name); + + virtual bool HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt); + + virtual void HandleDirectContent(cmTarget *tgt, const std::string &content, + bool prepend); +}; + +#endif diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index f42b0f687..0705fb4d6 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -33,6 +33,10 @@ bool cmTargetLinkLibrariesCommand this->Target = this->Makefile->GetCMakeInstance() ->GetGlobalGenerator()->FindTarget(0, args[0].c_str()); + if(!this->Target) + { + this->Target = this->Makefile->FindTargetToUse(args[0].c_str()); + } if(!this->Target) { cmake::MessageType t = cmake::FATAL_ERROR; // fail by default @@ -257,6 +261,16 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, // Handle normal case first. if(this->CurrentProcessingState != ProcessingLinkInterface) { + if (this->Target->IsImported()) + { + cmOStringStream e; + e << "Imported targets may only be used with the " + "LINK_INTERFACE_LIBRARIES specifier to target_link_libraries."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + + this->Makefile ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt); if (this->CurrentProcessingState != ProcessingPublicInterface) diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx new file mode 100644 index 000000000..69aaf1777 --- /dev/null +++ b/Source/cmTargetPropCommandBase.cxx @@ -0,0 +1,144 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 "cmTargetPropCommandBase.h" + +#include "cmGlobalGenerator.h" + +//---------------------------------------------------------------------------- +bool cmTargetPropCommandBase +::HandleArguments(std::vector const& args, const char *prop, + ArgumentFlags flags) +{ + if(args.size() < 3) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + // Lookup the target for which libraries are specified. + this->Target = + this->Makefile->GetCMakeInstance() + ->GetGlobalGenerator()->FindTarget(0, args[0].c_str()); + if(!this->Target) + { + this->Target = this->Makefile->FindTargetToUse(args[0].c_str()); + } + if(!this->Target) + { + this->HandleMissingTarget(args[0]); + return false; + } + + unsigned int argIndex = 1; + + bool prepend = false; + if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") + { + if (args.size() < 4) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + prepend = true; + ++argIndex; + } + + this->Property = prop; + + while (argIndex < args.size()) + { + if (!this->ProcessContentArgs(args, argIndex, prepend)) + { + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmTargetPropCommandBase +::ProcessContentArgs(std::vector const& args, + unsigned int &argIndex, bool prepend) +{ + const std::string scope = args[argIndex]; + + if(scope != "PUBLIC" + && scope != "PRIVATE" + && scope != "INTERFACE" ) + { + this->SetError("called with invalid arguments"); + return false; + } + + if(this->Target->IsImported() && scope != "INTERFACE") + { + this->HandleImportedTargetInvalidScope(args[0], scope); + return false; + } + + ++argIndex; + + std::string content; + + std::string sep; + for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex) + { + if(args[i] == "PUBLIC" + || args[i] == "PRIVATE" + || args[i] == "INTERFACE" ) + { + this->PopulateTargetProperies(scope, content, prepend); + return true; + } + if (this->Makefile->FindTargetToUse(args[i].c_str())) + { + content += sep + "$Property + ">"; + } + else if (!this->HandleNonTargetArg(content, sep, args[i], args[0])) + { + return false; + } + sep = ";"; + } + this->PopulateTargetProperies(scope, content, prepend); + return true; +} + +//---------------------------------------------------------------------------- +void cmTargetPropCommandBase +::PopulateTargetProperies(const std::string &scope, + const std::string &content, bool prepend) +{ + if (scope == "PRIVATE" || scope == "PUBLIC") + { + this->HandleDirectContent(this->Target, content, prepend); + } + if (scope == "INTERFACE" || scope == "PUBLIC") + { + if (prepend) + { + const std::string propName = std::string("INTERFACE_") + this->Property; + const char *propValue = this->Target->GetProperty(propName.c_str()); + const std::string totalContent = content + (propValue + ? std::string(";") + propValue + : std::string()); + this->Target->SetProperty(propName.c_str(), totalContent.c_str()); + } + else + { + this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(), + content.c_str()); + } + } +} diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h new file mode 100644 index 000000000..90e3bbb7f --- /dev/null +++ b/Source/cmTargetPropCommandBase.h @@ -0,0 +1,57 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 cmTargetPropCommandBase_h +#define cmTargetPropCommandBase_h + +#include "cmCommand.h" + +class cmTarget; + +//---------------------------------------------------------------------------- +class cmTargetPropCommandBase : public cmCommand +{ +public: + + enum ArgumentFlags { + NO_FLAGS = 0, + PROCESS_BEFORE = 1 + }; + + bool HandleArguments(std::vector const& args, + const char *prop, ArgumentFlags flags = NO_FLAGS); + +private: + virtual void HandleImportedTargetInvalidScope(const std::string &tgt, + const std::string &scope) = 0; + virtual void HandleMissingTarget(const std::string &name) = 0; + + virtual bool HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt) = 0; + + virtual void HandleDirectContent(cmTarget *tgt, + const std::string &content, + bool prepend) = 0; + + bool ProcessContentArgs(std::vector const& args, + unsigned int &argIndex, bool prepend); + void PopulateTargetProperies(const std::string &scope, + const std::string &content, bool prepend); + +private: + cmTarget *Target; + std::string Property; +}; + +#endif diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 2f650e72e..42f511ea3 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -112,7 +112,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, else { // Use the command name given. - exe = ge.Parse(exe.c_str()).Evaluate(mf, config); + exe = ge.Parse(exe.c_str())->Evaluate(mf, config); cmSystemTools::ConvertToUnixSlashes(exe); } @@ -122,7 +122,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, for(std::vector::const_iterator ci = command.begin()+1; ci != command.end(); ++ci) { - os << " " << lg->EscapeForCMake(ge.Parse(*ci).Evaluate(mf, config)); + os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config)); } // Finish the test command. diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx new file mode 100644 index 000000000..ac26503c6 --- /dev/null +++ b/Source/cmTimestamp.cxx @@ -0,0 +1,134 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 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 "cmTimestamp.h" + +#include + +#include +#include + +//---------------------------------------------------------------------------- +std::string cmTimestamp::CurrentTime( + const std::string& formatString, bool utcFlag) +{ + time_t currentTimeT = time(0); + if(currentTimeT == time_t(-1)) + { + return std::string(); + } + + return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag); +} + +//---------------------------------------------------------------------------- +std::string cmTimestamp::FileModificationTime(const char* path, + const std::string& formatString, bool utcFlag) +{ + struct stat info; + memset(&info, 0, sizeof(info)); + + if(stat(path, &info) != 0) + { + return std::string(); + } + + return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag); +} + +//---------------------------------------------------------------------------- +std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, + std::string formatString, bool utcFlag) +{ + if(formatString.empty()) + { + formatString = "%Y-%m-%dT%H:%M:%S"; + if(utcFlag) + { + formatString += "Z"; + } + } + + struct tm timeStruct; + memset(&timeStruct, 0, sizeof(timeStruct)); + + struct tm* ptr = (struct tm*) 0; + if(utcFlag) + { + ptr = gmtime(&timeT); + } + else + { + ptr = localtime(&timeT); + } + + if(ptr == 0) + { + return std::string(); + } + + timeStruct = *ptr; + + std::string result; + for(std::string::size_type i = 0; i < formatString.size(); ++i) + { + char c1 = formatString[i]; + char c2 = (i+1 < formatString.size()) ? + formatString[i+1] : static_cast(0); + + if(c1 == '%' && c2 != 0) + { + result += AddTimestampComponent(c2, timeStruct); + ++i; + } + else + { + result += c1; + } + } + + return result; +} + +//---------------------------------------------------------------------------- +std::string cmTimestamp::AddTimestampComponent( + char flag, struct tm& timeStruct) +{ + std::string formatString = "%"; + formatString += flag; + + switch(flag) + { + case 'd': + case 'H': + case 'I': + case 'j': + case 'm': + case 'M': + case 'S': + case 'U': + case 'w': + case 'y': + case 'Y': + break; + default: + { + return formatString; + } + } + + char buffer[16]; + + size_t size = strftime(buffer, sizeof(buffer), + formatString.c_str(), &timeStruct); + + return std::string(buffer, size); +} diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h new file mode 100644 index 000000000..24c186983 --- /dev/null +++ b/Source/cmTimestamp.h @@ -0,0 +1,40 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 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. +============================================================================*/ +#ifndef cmTimestamp_h +#define cmTimestamp_h + +#include +#include + +/** \class cmTimestamp + * \brief Utility class to generate sting representation of a timestamp + * + */ +class cmTimestamp +{ +public: + cmTimestamp() {} + + std::string CurrentTime(const std::string& formatString, bool utcFlag); + + std::string FileModificationTime(const char* path, + const std::string& formatString, bool utcFlag); + +private: + std::string CreateTimestampFromTimeT(time_t timeT, + std::string formatString, bool utcFlag); + + std::string AddTimestampComponent(char flag, struct tm& timeStruct); +}; + + +#endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index d3b395098..2596d7340 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -572,6 +572,12 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, sep = ";"; } (*this->BuildFileStream ) << "\n"; + if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10) + { + // VS >= 11 let us turn off linking of custom command outputs. + this->WritePlatformConfigTag("LinkObjects", i->c_str(), 3); + (*this->BuildFileStream ) << "false\n"; + } } this->WriteString("\n", 2); } @@ -879,14 +885,23 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } } - for(std::vector::const_iterator - si = this->GeneratorTarget->ExternalObjects.begin(); - si != this->GeneratorTarget->ExternalObjects.end(); ++si) + if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10) + { + // For VS >= 11 we use LinkObjects to avoid linking custom command + // outputs. Use Object for all external objects, generated or not. + this->WriteSources("Object", this->GeneratorTarget->ExternalObjects); + } + else { // If an object file is generated in this target, then vs10 will use // it in the build, and we have to list it as None instead of Object. - std::vector const* d = this->Target->GetSourceDepends(*si); - this->WriteSource((d && !d->empty())? "None":"Object", *si); + for(std::vector::const_iterator + si = this->GeneratorTarget->ExternalObjects.begin(); + si != this->GeneratorTarget->ExternalObjects.end(); ++si) + { + std::vector const* d=this->Target->GetSourceDepends(*si); + this->WriteSource((d && !d->empty())? "None":"Object", *si); + } } this->WriteSources("None", this->GeneratorTarget->ExtraSources); @@ -1430,7 +1445,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) // Replace spaces in libs with ; cmSystemTools::ReplaceString(libs, " ", ";"); cmComputeLinkInformation* pcli = - this->GeneratorTarget->GetLinkInformation(config.c_str()); + this->Target->GetLinkInformation(config.c_str()); if(!pcli) { cmSystemTools::Error diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx new file mode 100644 index 000000000..b302246ea --- /dev/null +++ b/Source/cmVisualStudioWCEPlatformParser.cxx @@ -0,0 +1,175 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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 "cmVisualStudioWCEPlatformParser.h" +#include "cmGlobalVisualStudioGenerator.h" +#include "cmXMLParser.h" + +int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version) +{ + const std::string registryBase = + cmGlobalVisualStudioGenerator::GetRegistryBase(version); + const std::string vckey = registryBase + "\\Setup\\VC;ProductDir"; + const std::string vskey = registryBase + "\\Setup\\VS;ProductDir"; + + if(!cmSystemTools::ReadRegistryValue(vckey.c_str(), this->VcInstallDir) || + !cmSystemTools::ReadRegistryValue(vskey.c_str(), this->VsInstallDir)) + { + return 0; + } + cmSystemTools::ConvertToUnixSlashes(this->VcInstallDir); + cmSystemTools::ConvertToUnixSlashes(this->VsInstallDir); + this->VcInstallDir.append("/"); + this->VsInstallDir.append("/"); + + const std::string configFilename = + this->VcInstallDir + "vcpackages/WCE.VCPlatform.config"; + + return this->ParseFile(configFilename.c_str()); +} + +std::string cmVisualStudioWCEPlatformParser::GetOSVersion() const +{ + if (this->OSMinorVersion.empty()) + { + return OSMajorVersion; + } + + return OSMajorVersion + "." + OSMinorVersion; +} + +const char* cmVisualStudioWCEPlatformParser::GetArchitectureFamily() const +{ + std::map::const_iterator it = + this->Macros.find("ARCHFAM"); + if (it != this->Macros.end()) + { + return it->second.c_str(); + } + + return 0; +} + +void cmVisualStudioWCEPlatformParser::StartElement(const char* name, + const char** attributes) +{ + if(this->FoundRequiredName) + { + return; + } + + this->CharacterData = ""; + + if(strcmp(name, "PlatformData") == 0) + { + this->PlatformName = ""; + this->OSMajorVersion = ""; + this->OSMinorVersion = ""; + this->Macros.clear(); + } + + if(strcmp(name, "Macro") == 0) + { + std::string macroName; + std::string macroValue; + + for(const char** attr = attributes; *attr; attr += 2) + { + if(strcmp(attr[0], "Name") == 0) + { + macroName = attr[1]; + } + else if(strcmp(attr[0], "Value") == 0) + { + macroValue = attr[1]; + } + } + + if(!macroName.empty()) + { + this->Macros[macroName] = macroValue; + } + } + else if(strcmp(name, "Directories") == 0) + { + for(const char** attr = attributes; *attr; attr += 2) + { + if(strcmp(attr[0], "Include") == 0) + { + this->Include = attr[1]; + } + else if(strcmp(attr[0], "Library") == 0) + { + this->Library = attr[1]; + } + else if(strcmp(attr[0], "Path") == 0) + { + this->Path = attr[1]; + } + } + } +} + +void cmVisualStudioWCEPlatformParser::EndElement(const char* name) +{ + if(!this->RequiredName) + { + if(strcmp(name, "PlatformName") == 0) + { + this->AvailablePlatforms.push_back(this->CharacterData); + } + return; + } + + if(this->FoundRequiredName) + { + return; + } + + if(strcmp(name, "PlatformName") == 0) + { + this->PlatformName = this->CharacterData; + } + else if(strcmp(name, "OSMajorVersion") == 0) + { + this->OSMajorVersion = this->CharacterData; + } + else if(strcmp(name, "OSMinorVersion") == 0) + { + this->OSMinorVersion = this->CharacterData; + } + else if(strcmp(name, "Platform") == 0) + { + if(this->PlatformName == this->RequiredName) + { + this->FoundRequiredName = true; + } + } +} + +void cmVisualStudioWCEPlatformParser::CharacterDataHandler(const char* data, + int length) +{ + this->CharacterData.append(data, length); +} + +std::string cmVisualStudioWCEPlatformParser::FixPaths( + const std::string& paths) const +{ + std::string ret = paths; + cmSystemTools::ReplaceString(ret, "$(PATH)", "%PATH%"); + cmSystemTools::ReplaceString(ret, "$(VCInstallDir)", VcInstallDir.c_str()); + cmSystemTools::ReplaceString(ret, "$(VSInstallDir)", VsInstallDir.c_str()); + cmSystemTools::ReplaceString(ret, "\\", "/"); + cmSystemTools::ReplaceString(ret, "//", "/"); + cmSystemTools::ReplaceString(ret, "/", "\\"); + return ret; +} diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h new file mode 100644 index 000000000..466e1dd43 --- /dev/null +++ b/Source/cmVisualStudioWCEPlatformParser.h @@ -0,0 +1,68 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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. +============================================================================*/ +#ifndef cmVisualStudioWCEPlatformParser_h +#define cmVisualStudioWCEPlatformParser_h +#include "cmStandardIncludes.h" + +#include "cmXMLParser.h" + +// This class is used to parse XML with configuration +// of installed SDKs in system +class cmVisualStudioWCEPlatformParser : public cmXMLParser +{ +public: + cmVisualStudioWCEPlatformParser(const char* name = NULL) + : RequiredName(name) + , FoundRequiredName(false) + { + } + + int ParseVersion(const char* version); + + bool Found() const {return this->FoundRequiredName;} + const char* GetArchitectureFamily() const; + std::string GetOSVersion() const; + std::string GetIncludeDirectories() const { + return this->FixPaths(this->Include); } + std::string GetLibraryDirectories() const { + return this->FixPaths(this->Library); } + std::string GetPathDirectories() const { + return this->FixPaths(this->Path); } + const std::vector& GetAvailablePlatforms() const { + return this->AvailablePlatforms; } + +protected: + virtual void StartElement(const char* name, const char** attributes); + void EndElement(const char* name); + void CharacterDataHandler(const char* data, int length); + +private: + std::string FixPaths(const std::string& paths) const; + + std::string CharacterData; + + std::string Include; + std::string Library; + std::string Path; + std::string PlatformName; + std::string OSMajorVersion; + std::string OSMinorVersion; + std::map Macros; + std::vector AvailablePlatforms; + + const char* RequiredName; + bool FoundRequiredName; + std::string VcInstallDir; + std::string VsInstallDir; +}; + +#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 7bc141122..42b7f7992 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -82,6 +82,7 @@ #if defined(CMAKE_HAVE_VS_GENERATORS) #include "cmCallVisualStudioMacro.h" +#include "cmVisualStudioWCEPlatformParser.h" #endif #if !defined(CMAKE_BOOT_MINGW) @@ -111,8 +112,6 @@ #include // struct stat -#include // auto_ptr - static bool cmakeCheckStampFile(const char* stampName); static bool cmakeCheckStampList(const char* stampName); @@ -520,7 +519,7 @@ void cmake::ReadListFile(const std::vector& args, // read in the list file to fill the cache if(path) { - std::auto_ptr lg(gg->CreateLocalGenerator()); + cmsys::auto_ptr lg(gg->CreateLocalGenerator()); lg->GetMakefile()->SetHomeOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); lg->GetMakefile()->SetStartOutputDirectory @@ -559,7 +558,7 @@ bool cmake::FindPackage(const std::vector& args) this->SetGlobalGenerator(gg); // read in the list file to fill the cache - std::auto_ptr lg(gg->CreateLocalGenerator()); + cmsys::auto_ptr lg(gg->CreateLocalGenerator()); cmMakefile* mf = lg->GetMakefile(); mf->SetHomeOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); @@ -955,7 +954,7 @@ int cmake::AddCMakePaths() cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str()); cMakeSelf += "/cmake"; cMakeSelf += cmSystemTools::GetExecutableExtension(); -#if __APPLE__ +#ifdef __APPLE__ // on the apple this might be the gui bundle if(!cmSystemTools::FileExists(cMakeSelf.c_str())) { @@ -1146,6 +1145,10 @@ void CMakeCommandUsage(const char* program) << "Available on Windows only:\n" << " comspec - on windows 9x use this for RunCommand\n" << " delete_regv key - delete registry value\n" + << " env_vs8_wince sdkname - displays a batch file which sets the " + "environment for the provided Windows CE SDK installed in VS2005\n" + << " env_vs9_wince sdkname - displays a batch file which sets the " + "environment for the provided Windows CE SDK installed in VS2008\n" << " write_regv key value - write registry value\n" #else << "Available on UNIX only:\n" @@ -1655,7 +1658,7 @@ int cmake::ExecuteCMakeCommand(std::vector& args) if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str())) { cm.SetGlobalGenerator(ggd); - std::auto_ptr lgd(ggd->CreateLocalGenerator()); + cmsys::auto_ptr lgd(ggd->CreateLocalGenerator()); lgd->GetMakefile()->SetStartDirectory(startDir.c_str()); lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str()); lgd->GetMakefile()->MakeStartDirectoriesCurrent(); @@ -1811,6 +1814,14 @@ int cmake::ExecuteCMakeCommand(std::vector& args) } return cmWin32ProcessExecution::Windows9xHack(command.c_str()); } + else if (args[1] == "env_vs8_wince" && args.size() == 3) + { + return cmake::WindowsCEEnvironment("8.0", args[2]); + } + else if (args[1] == "env_vs9_wince" && args.size() == 3) + { + return cmake::WindowsCEEnvironment("9.0", args[2]); + } #endif } @@ -2797,7 +2808,7 @@ int cmake::CheckBuildSystem() cmake cm; cmGlobalGenerator gg; gg.SetCMakeInstance(&cm); - std::auto_ptr lg(gg.CreateLocalGenerator()); + cmsys::auto_ptr lg(gg.CreateLocalGenerator()); cmMakefile* mf = lg->GetMakefile(); if(!mf->ReadListFile(0, this->CheckBuildSystemArgument.c_str()) || cmSystemTools::GetErrorOccuredFlag()) @@ -2823,11 +2834,11 @@ int cmake::CheckBuildSystem() } // Create the generator and use it to clear the dependencies. - std::auto_ptr + cmsys::auto_ptr ggd(this->CreateGlobalGenerator(genName)); if(ggd.get()) { - std::auto_ptr lgd(ggd->CreateLocalGenerator()); + cmsys::auto_ptr lgd(ggd->CreateLocalGenerator()); lgd->ClearDependencies(mf, verbose); } } @@ -3070,7 +3081,7 @@ void cmake::MarkCliAsUsed(const std::string& variable) void cmake::GenerateGraphViz(const char* fileName) const { #ifdef CMAKE_BUILD_WITH_CMAKE - std::auto_ptr gvWriter( + cmsys::auto_ptr gvWriter( new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators())); std::string settingsFile = this->GetHomeOutputDirectory(); @@ -4006,6 +4017,29 @@ static bool cmakeCheckStampList(const char* stampList) return true; } +//---------------------------------------------------------------------------- +int cmake::WindowsCEEnvironment(const char* version, const std::string& name) +{ +#if defined(CMAKE_HAVE_VS_GENERATORS) + cmVisualStudioWCEPlatformParser parser(name.c_str()); + parser.ParseVersion(version); + if (parser.Found()) + { + std::cout << "@echo off" << std::endl; + std::cout << "echo Environment Selection: " << name << std::endl; + std::cout << "set PATH=" << parser.GetPathDirectories() << std::endl; + std::cout << "set INCLUDE=" << parser.GetIncludeDirectories() < gen( + cmsys::auto_ptr gen( this->CreateGlobalGenerator(it.GetValue())); std::string output; std::string projName; diff --git a/Source/cmake.h b/Source/cmake.h index 79e05ca0c..e5aa07656 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -445,6 +445,8 @@ protected: std::string const& link); static int ExecuteEchoColor(std::vector& args); static int ExecuteLinkScript(std::vector& args); + static int WindowsCEEnvironment(const char* version, + const std::string& name); static int VisualStudioLink(std::vector& args, int type); static int VisualStudioLinkIncremental(std::vector& args, int type, diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 777d76f4b..6bfcab040 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -116,7 +116,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(KWSYS_USE_MD5 1) SET(KWSYS_USE_Process 1) SET(KWSYS_USE_RegularExpression 1) - SET(KWSYS_USE_Registry 1) SET(KWSYS_USE_System 1) SET(KWSYS_USE_SystemTools 1) SET(KWSYS_USE_CommandLineArguments 1) @@ -597,6 +596,13 @@ IF(KWSYS_USE_SystemInformation) ENDIF() ENDIF() ENDIF() + IF(CMAKE_SYSTEM MATCHES "HP-UX") + CHECK_INCLUDE_FILES("sys/mpctl.h" KWSYS_SYS_HAS_MPCTL_H) + IF(KWSYS_SYS_HAS_MPCTL_H) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1) + ENDIF() + ENDIF() IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE) SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1) ENDIF() @@ -762,7 +768,7 @@ SET(KWSYS_HXX_FILES Configure String # Add selected C++ classes. SET(cppclasses Directory DynamicLoader Glob RegularExpression SystemTools - CommandLineArguments Registry IOStream SystemInformation + CommandLineArguments IOStream SystemInformation ) FOREACH(cpp ${cppclasses}) IF(KWSYS_USE_${cpp}) @@ -800,12 +806,8 @@ SET(KWSYS_CXX_SRCS) # Add the proper sources for this platform's Process implementation. IF(KWSYS_USE_Process) IF(NOT UNIX) - # Use the Windows implementation. We need the encoded forwarding executable. - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c - ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c) - SET_SOURCE_FILES_PROPERTIES( - ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c - PROPERTIES GENERATED 1) + # Use the Windows implementation. + SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c) ELSE(NOT UNIX) # Use the UNIX implementation. SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c) @@ -937,43 +939,6 @@ IF(KWSYS_USE_String) COMPILE_FLAGS "-DKWSYS_STRING_C") ENDIF(KWSYS_USE_String) -#----------------------------------------------------------------------------- -# Process execution on windows needs to build a forwarding executable -# that works around a Win9x bug. We encode the executable into a C -# file and build it into the library. Win9x platforms reproduce the -# executable into a temporary directory when it is needed. -IF(KWSYS_USE_Process) - IF(NOT UNIX) - # Build the forwarding executable itself and a program that will - # encode it into a C file. - ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY LABELS ${KWSYS_LABELS_EXE}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY LABELS ${KWSYS_LABELS_EXE}) - - SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}") - IF(CMAKE_BUILD_TOOL MATCHES "make") - SET(CFG_INTDIR "") - ENDIF(CMAKE_BUILD_TOOL MATCHES "make") - - # Take advantage of a better custom command syntax if possible. - SET(CMD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe) - SET(FWD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe) - ADD_CUSTOM_COMMAND( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c - COMMAND ${CMD} - ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c - ${KWSYS_NAMESPACE} ProcessFwd9x - DEPENDS ${CMD} ${FWD}) - - # Make sure build occurs in proper order. - ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x - ${KWSYS_NAMESPACE}EncodeExecutable) - ENDIF(NOT UNIX) -ENDIF(KWSYS_USE_Process) - #----------------------------------------------------------------------------- # Setup testing if not being built as part of another project. IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) @@ -1012,7 +977,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) ) ENDIF(NOT WATCOM) SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} - testRegistry testIOS testSystemTools testCommandLineArguments @@ -1116,8 +1080,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) # We expect test to fail SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON) GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv) - SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR_NOT_VALGRIND;FAIL;Test failed") - SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES PASS_REGULAR_EXPRESSION "Test passed") SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value") MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}") ENDIF() diff --git a/Source/kwsys/CPU.h.in b/Source/kwsys/CPU.h.in index ecd29d133..2e1a584b1 100644 --- a/Source/kwsys/CPU.h.in +++ b/Source/kwsys/CPU.h.in @@ -98,6 +98,14 @@ #elif defined(__SYSC_ZARCH__) # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG +/* Aarch64 */ +#elif defined(__aarch64__) +# if !defined(__AARCH64EB__) +# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE +# else +# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG +# endif + /* Unknown CPU */ #else # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID 0 diff --git a/Source/kwsys/EncodeExecutable.c b/Source/kwsys/EncodeExecutable.c deleted file mode 100644 index bc30568ff..000000000 --- a/Source/kwsys/EncodeExecutable.c +++ /dev/null @@ -1,114 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - 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 -#ifdef __WATCOMC__ -#define _unlink unlink -#endif -int main(int argc, char* argv[]) -{ - FILE* ifp; - FILE* ofp; - int i; - int n; - int count = 0; - unsigned char buffer[1024]; - - /* Check arguments. */ - if(argc != 5) - { - fprintf(stderr, "Usage: %s \n", - argv[0]); - return 1; - } - - /* Open the input file. */ - ifp = fopen(argv[1], "rb"); - if(!ifp) - { - fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]); - return 2; - } - ofp = fopen(argv[2], "w"); - if(!ofp) - { - fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]); - fclose(ifp); - return 2; - } - - /* Prepend header comment. */ - fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n"); - fprintf(ofp, " * %s\n */\n\n", argv[0]); - fprintf(ofp, "#include \"kwsysPrivate.h\"\n"); - fprintf(ofp, "#include KWSYS_HEADER(Configure.h)\n\n"); - fprintf(ofp, "#include \n\n"); - fprintf(ofp, "#if defined(_WIN32)\n"); - fprintf(ofp, "# include \n"); - fprintf(ofp, "#else\n"); - fprintf(ofp, "# include \n"); - fprintf(ofp, "#endif\n"); - fprintf(ofp, "\n"); - fprintf(ofp, "static void kwsys_unlink(const char* fname)\n"); - fprintf(ofp, "{\n"); - fprintf(ofp, "#if defined(__WATCOMC__)\n"); - fprintf(ofp, " unlink(fname);\n"); - fprintf(ofp, "#else\n"); - fprintf(ofp, " _unlink(fname);\n"); - fprintf(ofp, "#endif\n"); - fprintf(ofp, "}\n"); - fprintf(ofp, "\n"); - - /* Split file up in 1024-byte chunks. */ - while((n = (int)fread(buffer, 1, 1024, ifp)) > 0) - { - fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n", - argv[4], count++, n); - for(i=0; i < n-1; ++i) - { - fprintf(ofp, "0x%02X", buffer[i]); - if(i%10 == 9) - { - fprintf(ofp, ",\n"); - } - else - { - fprintf(ofp, ", "); - } - } - fprintf(ofp, "0x%02X};\n\n", buffer[n-1]); - } - fclose(ifp); - - /* Provide a function to write the data to a file. */ - fprintf(ofp, "extern %s_EXPORT int %sEncodedWriteArray%s(const char* fname)\n", - argv[3], argv[3], argv[4]); - fprintf(ofp, "{\n"); - fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n"); - fprintf(ofp, " if(!ofp) { return 0; }\n"); - for(i=0; i < count; ++i) - { - fprintf(ofp, " if(fwrite(kwsysEncodedArray%s_%d, 1,\n" - " sizeof(kwsysEncodedArray%s_%d), ofp) !=\n" - " sizeof(kwsysEncodedArray%s_%d))\n", - argv[4], i, argv[4], i, argv[4], i); - fprintf(ofp, " {\n"); - fprintf(ofp, " fclose(ofp);\n"); - fprintf(ofp, " kwsys_unlink(fname);\n"); - fprintf(ofp, " return 0;\n"); - fprintf(ofp, " }\n"); - } - fprintf(ofp, " fclose(ofp);\n"); - fprintf(ofp, " return 1;\n"); - fprintf(ofp, "}\n"); - fclose(ofp); - return 0; -} diff --git a/Source/kwsys/IOStream.hxx.in b/Source/kwsys/IOStream.hxx.in index 9eb99e058..2eeedf2ff 100644 --- a/Source/kwsys/IOStream.hxx.in +++ b/Source/kwsys/IOStream.hxx.in @@ -26,12 +26,9 @@ /* Whether ostream supports long long. */ #define @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_IOS_HAS_OSTREAM_LONG_LONG@ -/* Size of type long long and 0 if not available. */ -#define @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG @KWSYS_SIZEOF_LONG_LONG@ - /* Determine whether we need to define the streaming operators for long long or __int64. */ -#if @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG +#if @KWSYS_USE_LONG_LONG@ # if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \ !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG # define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1 @@ -136,7 +133,6 @@ operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamULL value) /* If building a C++ file in kwsys itself, give the source file access to the macros without a configured namespace. */ #if defined(KWSYS_NAMESPACE) -# define KWSYS_IOS_SIZEOF_LONG_LONG @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG # define KWSYS_IOS_HAS_ISTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG # define KWSYS_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG # define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL diff --git a/Source/kwsys/ProcessFwd9x.c b/Source/kwsys/ProcessFwd9x.c deleted file mode 100644 index 536c54b67..000000000 --- a/Source/kwsys/ProcessFwd9x.c +++ /dev/null @@ -1,211 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - 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. -============================================================================*/ - -/* - On Windows9x platforms, this executable is spawned between a parent - process and the child it is invoking to work around a bug. See the - Win32 implementation file for details. - - Future Work: This executable must be linked statically against the C - runtime library before being encoded into the library. Building it - in this way may be hard because CMake has limited abilities to build - different targets with different configurations in the same - directory. We may just have to create and encode the executable - once instead of generating it during the build. This would be an - acceptable solution because the forwarding executable should not - change very often and is pretty simple. -*/ - -#ifdef _MSC_VER -#pragma warning (push, 1) -#endif -#include -#include - -void ReportLastError(HANDLE errorPipe); - -int main() -{ - /* Process startup information for the real child. */ - STARTUPINFO si; - PROCESS_INFORMATION pi; - - /* The result of waiting for the child to exit. */ - DWORD waitResult; - - /* The child's process return code. */ - DWORD retVal; - - /* The command line used to invoke this process. */ - LPSTR commandLine = GetCommandLine(); - - /* Pointer that will be advanced to the beginning of the command - line of the real child process. */ - LPSTR cmdLine = commandLine; - - /* Handle to the error reporting pipe provided by the parent. This - is parsed off the command line. */ - HANDLE errorPipe = 0; - HANDLE errorPipeOrig = 0; - - /* Handle to the event the parent uses to tell us to resume the child. - This is parsed off the command line. */ - HANDLE resumeEvent = 0; - - /* Handle to the event the parent uses to tell us to kill the child. - This is parsed off the command line. */ - HANDLE killEvent = 0; - - /* Flag for whether to hide window of child process. */ - int hideWindow = 0; - - /* An array of the handles on which we wait when the child is - running. */ - HANDLE waitHandles[2] = {0, 0}; - - /* Move the pointer past the name of this executable. */ - if(*cmdLine == '"') - { - ++cmdLine; - while(*cmdLine && *cmdLine != '"') { ++cmdLine; } - if(*cmdLine) { ++cmdLine; } - } - else - { - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - } - - /* Parse the error pipe handle. */ - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%p", &errorPipeOrig); - - /* Parse the resume event handle. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%p", &resumeEvent); - - /* Parse the kill event handle. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%p", &killEvent); - - /* Parse the hide window flag. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%d", &hideWindow); - - /* Skip to the beginning of the command line of the real child. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - - /* Create a non-inherited copy of the error pipe. We do not want - the child to get it. */ - if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig, - GetCurrentProcess(), &errorPipe, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - /* Have a non-inherited duplicate. Close the inherited one. */ - CloseHandle(errorPipeOrig); - } - else - { - /* Could not duplicate handle. Report the error. */ - ReportLastError(errorPipeOrig); - return 1; - } - - /* Create the subprocess. */ - ZeroMemory(&si, sizeof(si)); - ZeroMemory(&pi, sizeof(pi)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; - si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT; - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi)) - { - /* Process created successfully. Close the error reporting pipe - to notify the parent of success. */ - CloseHandle(errorPipe); - } - else - { - /* Error creating the process. Report the error to the parent - process through the special error reporting pipe. */ - ReportLastError(errorPipe); - return 1; - } - - /* Wait for resume or kill event from parent. */ - waitHandles[0] = killEvent; - waitHandles[1] = resumeEvent; - waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE); - - /* Check what happened. */ - if(waitResult == WAIT_OBJECT_0) - { - /* We were asked to kill the child. */ - TerminateProcess(pi.hProcess, 255); - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return 1; - } - else - { - /* We were asked to resume the child. */ - ResumeThread(pi.hThread); - CloseHandle(pi.hThread); - } - - /* Wait for subprocess to exit or for kill event from parent. */ - waitHandles[0] = killEvent; - waitHandles[1] = pi.hProcess; - waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE); - - /* Check what happened. */ - if(waitResult == WAIT_OBJECT_0) - { - /* We were asked to kill the child. */ - TerminateProcess(pi.hProcess, 255); - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - return 1; - } - else - { - /* The child exited. Get the return code. */ - GetExitCodeProcess(pi.hProcess, &retVal); - CloseHandle(pi.hProcess); - return retVal; - } -} - -void ReportLastError(HANDLE errorPipe) -{ - LPVOID lpMsgBuf; - DWORD n; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0); - LocalFree( lpMsgBuf ); -} diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 19922111a..83838affc 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -63,10 +63,6 @@ do. #include /* DIR, dirent */ #include /* isspace */ -#ifdef __HAIKU__ -#undef __BEOS__ -#endif - #if defined(__VMS) # define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK #else diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 5aa4d8bf6..c836f9b08 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -28,14 +28,6 @@ On windows, a thread is created to wait for data on each pipe. The threads are synchronized with the main thread to simulate the use of a UNIX-style select system call. -On Windows9x platforms, a small WIN32 console application is spawned -in-between the calling process and the actual child to be executed. -This is to work-around a problem with connecting pipes from WIN16 -console applications to WIN32 applications. - -For more information, please check Microsoft Knowledge Base Articles -Q190351 and Q150956. - */ #ifdef _MSC_VER @@ -91,18 +83,12 @@ Q190351 and Q150956. # define KWSYSPE_DEBUG(x) (void)1 #endif -#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x) - typedef LARGE_INTEGER kwsysProcessTime; typedef struct kwsysProcessCreateInformation_s { /* Windows child startup control data. */ STARTUPINFO StartupInfo; - - /* Special error reporting pipe for Win9x forwarding executable. */ - HANDLE ErrorPipeRead; - HANDLE ErrorPipeWrite; } kwsysProcessCreateInformation; /*--------------------------------------------------------------------------*/ @@ -146,7 +132,6 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc static void kwsysProcessSetExitException(kwsysProcess* cp, int code); static void kwsysProcessKillTree(int pid); static void kwsysProcessDisablePipeThreads(kwsysProcess* cp); -extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname); /*--------------------------------------------------------------------------*/ /* A structure containing synchronization data for each thread. */ @@ -233,15 +218,6 @@ struct kwsysProcess_s /* Whether to treat command lines as verbatim. */ int Verbatim; - /* On Win9x platforms, the path to the forwarding executable. */ - char* Win9x; - - /* On Win9x platforms, the resume event for the forwarding executable. */ - HANDLE Win9xResumeEvent; - - /* On Win9x platforms, the kill event for the forwarding executable. */ - HANDLE Win9xKillEvent; - /* Mutex to protect the shared index used by threads to report data. */ HANDLE SharedIndexMutex; @@ -269,9 +245,6 @@ struct kwsysProcess_s HANDLE PipeNativeSTDOUT[2]; HANDLE PipeNativeSTDERR[2]; - /* Handle to automatically delete the Win9x forwarding executable. */ - HANDLE Win9xHandle; - /* ------------- Data managed per call to Execute ------------- */ /* The exceptional behavior that terminated the process, if any. */ @@ -311,7 +284,7 @@ struct kwsysProcess_s for pipes to close after process termination. */ int PipesLeft; - /* Buffer for error messages (possibly from Win9x child). */ + /* Buffer for error messages. */ char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; /* Description for the ExitException. */ @@ -337,9 +310,6 @@ kwsysProcess* kwsysProcess_New(void) /* Process control structure. */ kwsysProcess* cp; - /* Path to Win9x forwarding executable. */ - char* win9x = 0; - /* Windows version number data. */ OSVERSIONINFO osv; @@ -365,73 +335,11 @@ kwsysProcess* kwsysProcess_New(void) GetVersionEx(&osv); if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { - /* This is Win9x. We need the console forwarding executable to - work-around a Windows 9x bug. */ - char fwdName[_MAX_FNAME+1] = ""; - char tempDir[_MAX_PATH+1] = ""; - - /* We will try putting the executable in the system temp - directory. Note that the returned path already has a trailing - slash. */ - DWORD length = GetTempPath(_MAX_PATH+1, tempDir); - - /* Construct the executable name from the process id and kwsysProcess - instance. This should be unique. */ - sprintf(fwdName, KWSYS_NAMESPACE_STRING "pew9xfwd_%ld_%p.exe", - GetCurrentProcessId(), cp); - - /* If we have a temp directory, use it. */ - if(length > 0 && length <= _MAX_PATH) - { - /* Allocate a buffer to hold the forwarding executable path. */ - size_t tdlen = strlen(tempDir); - win9x = (char*)malloc(tdlen + strlen(fwdName) + 2); - if(!win9x) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Construct the full path to the forwarding executable. */ - sprintf(win9x, "%s%s", tempDir, fwdName); - } - - /* If we found a place to put the forwarding executable, try to - write it. */ - if(win9x) - { - if(!kwsysEncodedWriteArrayProcessFwd9x(win9x)) - { - /* Failed to create forwarding executable. Give up. */ - free(win9x); - kwsysProcess_Delete(cp); - return 0; - } - - /* Get a handle to the file that will delete it when closed. */ - cp->Win9xHandle = CreateFile(win9x, GENERIC_READ, FILE_SHARE_READ, 0, - OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); - if(cp->Win9xHandle == INVALID_HANDLE_VALUE) - { - /* We were not able to get a read handle for the forwarding - executable. It will not be deleted properly. Give up. */ - _unlink(win9x); - free(win9x); - kwsysProcess_Delete(cp); - return 0; - } - } - else - { - /* Failed to find a place to put forwarding executable. */ - kwsysProcess_Delete(cp); - return 0; - } + /* Win9x no longer supported. */ + kwsysProcess_Delete(cp); + return 0; } - /* Save the path to the forwarding executable. */ - cp->Win9x = win9x; - /* Initially no thread owns the mutex. Initialize semaphore to 1. */ if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0))) { @@ -446,30 +354,6 @@ kwsysProcess* kwsysProcess_New(void) return 0; } - if(cp->Win9x) - { - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - - /* Create an event to tell the forwarding executable to resume the - child. */ - if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Create an event to tell the forwarding executable to kill the - child. */ - if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - } - /* Create the thread to read each pipe. */ for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) { @@ -620,13 +504,6 @@ void kwsysProcess_Delete(kwsysProcess* cp) kwsysProcessCleanupHandle(&cp->SharedIndexMutex); kwsysProcessCleanupHandle(&cp->Full); - /* Close the Win9x resume and kill event handles. */ - if(cp->Win9x) - { - kwsysProcessCleanupHandle(&cp->Win9xResumeEvent); - kwsysProcessCleanupHandle(&cp->Win9xKillEvent); - } - /* Free memory. */ kwsysProcess_SetCommand(cp, 0); kwsysProcess_SetWorkingDirectory(cp, 0); @@ -637,12 +514,6 @@ void kwsysProcess_Delete(kwsysProcess* cp) { free(cp->CommandExitCodes); } - if(cp->Win9x) - { - /* Close our handle to the forwarding executable file. This will - cause it to be deleted. */ - kwsysProcessCleanupHandle(&cp->Win9xHandle); - } free(cp); } @@ -1017,21 +888,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) SetCurrentDirectory(cp->WorkingDirectory); } - /* Reset the Win9x resume and kill events. */ - if(cp->Win9x) - { - if(!ResetEvent(cp->Win9xResumeEvent)) - { - kwsysProcessCleanup(cp, 1); - return; - } - if(!ResetEvent(cp->Win9xKillEvent)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - /* Initialize startup info data. */ ZeroMemory(&si, sizeof(si)); si.StartupInfo.cb = sizeof(si.StartupInfo); @@ -1130,8 +986,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) STD_OUTPUT_HANDLE); kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, STD_ERROR_HANDLE); - kwsysProcessCleanupHandle(&si.ErrorPipeRead); - kwsysProcessCleanupHandle(&si.ErrorPipeWrite); return; } } @@ -1160,16 +1014,9 @@ void kwsysProcess_Execute(kwsysProcess* cp) /* All processes in the pipeline have been started in suspended mode. Resume them all now. */ - if(cp->Win9x) + for(i=0; i < cp->NumberOfCommands; ++i) { - SetEvent(cp->Win9xResumeEvent); - } - else - { - for(i=0; i < cp->NumberOfCommands; ++i) - { - ResumeThread(cp->ProcessInformation[i].hThread); - } + ResumeThread(cp->ProcessInformation[i].hThread); } /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */ @@ -1480,21 +1327,12 @@ void kwsysProcess_Kill(kwsysProcess* cp) /* Kill the children. */ cp->Killed = 1; - if(cp->Win9x) + for(i=0; i < cp->NumberOfCommands; ++i) { - /* Windows 9x. Tell the forwarding executable to kill the child. */ - SetEvent(cp->Win9xKillEvent); - } - else - { - /* Not Windows 9x. Just terminate the children. */ - for(i=0; i < cp->NumberOfCommands; ++i) - { - kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); - // close the handle if we kill it - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); - } + kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); + // close the handle if we kill it + kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); + kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); } /* We are killing the children and ignoring all data. Do not wait @@ -1815,97 +1653,13 @@ int kwsysProcessCreate(kwsysProcess* cp, int index, } } - /* Create the child process. */ - { - BOOL r; - char* realCommand; - if(cp->Win9x) - { - /* Create an error reporting pipe for the forwarding executable. - Neither end is directly inherited. */ - if(!CreatePipe(&si->ErrorPipeRead, &si->ErrorPipeWrite, 0, 0)) - { - return 0; - } - - /* Create an inherited duplicate of the write end. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), si->ErrorPipeWrite, - GetCurrentProcess(), &si->ErrorPipeWrite, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - - /* The forwarding executable is given a handle to the error pipe - and resume and kill events. */ - realCommand = (char*)malloc(strlen(cp->Win9x)+strlen(cp->Commands[index])+100); - if(!realCommand) - { - return 0; - } - sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x, - si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent, - cp->HideWindow, cp->Commands[index]); - } - else - { - realCommand = cp->Commands[index]; - } - /* Create the child in a suspended state so we can wait until all children have been created before running any one. */ - r = CreateProcess(0, realCommand, 0, 0, TRUE, - cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0, - &si->StartupInfo, &cp->ProcessInformation[index]); - if(cp->Win9x) - { - /* Free memory. */ - free(realCommand); - - /* Close the error pipe write end so we can detect when the - forwarding executable closes it. */ - kwsysProcessCleanupHandle(&si->ErrorPipeWrite); - if(r) - { - /* Wait for the forwarding executable to report an error or - close the error pipe to report success. */ - DWORD total = 0; - DWORD n = 1; - while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0) - { - if(ReadFile(si->ErrorPipeRead, cp->ErrorMessage+total, - KWSYSPE_PIPE_BUFFER_SIZE-total, &n, 0)) - { - total += n; - } - else - { - n = 0; - } - } - if(total > 0 || GetLastError() != ERROR_BROKEN_PIPE) - { - /* The forwarding executable could not run the process, or - there was an error reading from its error pipe. Preserve - the last error while cleaning up the forwarding executable - so the cleanup our caller does reports the proper error. */ - DWORD error = GetLastError(); - kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread); - kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); - SetLastError(error); - return 0; - } - } - kwsysProcessCleanupHandle(&si->ErrorPipeRead); - } - - if(!r) + if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, + 0, &si->StartupInfo, &cp->ProcessInformation[index])) { return 0; } - } /* Successfully created this child process. Close the current process's copies of the inherited stdout and stdin handles. The @@ -2152,19 +1906,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) /* Cleanup any processes already started in a suspended state. */ if(cp->ProcessInformation) { - if(cp->Win9x) + for(i=0; i < cp->NumberOfCommands; ++i) { - SetEvent(cp->Win9xKillEvent); - } - else - { - for(i=0; i < cp->NumberOfCommands; ++i) + if(cp->ProcessInformation[i].hProcess) { - if(cp->ProcessInformation[i].hProcess) - { - TerminateProcess(cp->ProcessInformation[i].hProcess, 255); - WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE); - } + TerminateProcess(cp->ProcessInformation[i].hProcess, 255); + WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE); } } for(i=0; i < cp->NumberOfCommands; ++i) diff --git a/Source/kwsys/Registry.cxx b/Source/kwsys/Registry.cxx deleted file mode 100644 index cd521c966..000000000 --- a/Source/kwsys/Registry.cxx +++ /dev/null @@ -1,818 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - 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 "kwsysPrivate.h" -#include KWSYS_HEADER(Registry.hxx) - -#include KWSYS_HEADER(Configure.hxx) -#include KWSYS_HEADER(ios/iostream) -#include KWSYS_HEADER(stl/string) -#include KWSYS_HEADER(stl/map) -#include KWSYS_HEADER(ios/iostream) -#include KWSYS_HEADER(ios/fstream) -#include KWSYS_HEADER(ios/sstream) -// Work-around CMake dependency scanning limitation. This must -// duplicate the above list of headers. -#if 0 -# include "Registry.hxx.in" -# include "Configure.hxx.in" -# include "kwsys_stl.hxx.in" -# include "kwsys_stl_string.hxx.in" -# include "kwsys_stl_map.hxx.in" -# include "kwsys_ios_iostream.h.in" -# include "kwsys_ios_fstream.h.in" -# include "kwsys_ios_sstream.h.in" -#endif - -#include // for isspace -#include -#include /* strlen, strncpy */ -#include /* getenv */ - -#ifdef _WIN32 -# include -#endif - - -namespace KWSYS_NAMESPACE -{ -class RegistryHelper { -public: - RegistryHelper(Registry::RegistryType registryType); - virtual ~RegistryHelper(); - - // Read a value from the registry. - virtual bool ReadValue(const char *key, const char **value); - - // Delete a key from the registry. - virtual bool DeleteKey(const char *key); - - // Delete a value from a given key. - virtual bool DeleteValue(const char *key); - - // Set value in a given key. - virtual bool SetValue(const char *key, const char *value); - - // Open the registry at toplevel/subkey. - virtual bool Open(const char *toplevel, const char *subkey, - int readonly); - - // Close the registry. - virtual bool Close(); - - // Set the value of changed - void SetChanged(bool b) { m_Changed = b; } - void SetTopLevel(const char* tl); - const char* GetTopLevel() { return m_TopLevel.c_str(); } - - //! Read from local or global scope. On Windows this mean from local machine - // or local user. On unix this will read from $HOME/.Projectrc or - // /etc/Project - void SetGlobalScope(bool b); - bool GetGlobalScope(); - - kwsys_stl::string EncodeKey(const char* str); - kwsys_stl::string EncodeValue(const char* str); - kwsys_stl::string DecodeValue(const char* str); - -protected: - bool m_Changed; - kwsys_stl::string m_TopLevel; - bool m_GlobalScope; - -#ifdef _WIN32 - HKEY HKey; -#endif - // Strip trailing and ending spaces. - char *Strip(char *str); - void SetSubKey(const char* sk); - kwsys_stl::string CreateKey(const char *key); - - typedef kwsys_stl::map StringToStringMap; - StringToStringMap EntriesMap; - kwsys_stl::string m_SubKey; - bool m_Empty; - bool m_SubKeySpecified; - kwsys_stl::string m_HomeDirectory; - - Registry::RegistryType m_RegistryType; -}; - -//---------------------------------------------------------------------------- -#define Registry_BUFFER_SIZE 8192 - -//---------------------------------------------------------------------------- -Registry::Registry(Registry::RegistryType registryType) -{ - m_Opened = false; - m_Locked = false; - this->Helper = 0; - this->Helper = new RegistryHelper(registryType); -} - -//---------------------------------------------------------------------------- -Registry::~Registry() -{ - if ( m_Opened ) - { - kwsys_ios::cerr << "Registry::Close should be " - "called here. The registry is not closed." - << kwsys_ios::endl; - } - delete this->Helper; -} - -//---------------------------------------------------------------------------- -void Registry::SetGlobalScope(bool b) -{ - this->Helper->SetGlobalScope(b); -} - -//---------------------------------------------------------------------------- -bool Registry::GetGlobalScope() -{ - return this->Helper->GetGlobalScope(); -} - -//---------------------------------------------------------------------------- -bool Registry::Open(const char *toplevel, - const char *subkey, int readonly) -{ - bool res = false; - if ( m_Locked ) - { - return res; - } - if ( m_Opened ) - { - if ( !this->Close() ) - { - return res; - } - } - if ( !toplevel || !*toplevel ) - { - kwsys_ios::cerr << "Registry::Opened() Toplevel not defined" - << kwsys_ios::endl; - return res; - } - - if ( isspace(toplevel[0]) || - isspace(toplevel[strlen(toplevel)-1]) ) - { - kwsys_ios::cerr << "Toplevel has to start with letter or number and end" - " with one" << kwsys_ios::endl; - return res; - } - - res = this->Helper->Open(toplevel, subkey, readonly); - if ( readonly != Registry::READONLY ) - { - m_Locked = true; - } - - if ( res ) - { - m_Opened = true; - this->Helper->SetTopLevel(toplevel); - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::Close() -{ - bool res = false; - if ( m_Opened ) - { - res = this->Helper->Close(); - } - - if ( res ) - { - m_Opened = false; - m_Locked = false; - this->Helper->SetChanged(false); - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::ReadValue(const char *subkey, - const char *key, - const char **value) -{ - bool res = false; - bool open = false; - if ( ! value ) - { - return res; - } - *value = 0; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READONLY) ) - { - return res; - } - open = true; - } - res = this->Helper->ReadValue(key, value); - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::DeleteKey(const char *subkey, const char *key) -{ - bool res = false; - bool open = false; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READWRITE) ) - { - return res; - } - open = true; - } - - res = this->Helper->DeleteKey(key); - if ( res ) - { - this->Helper->SetChanged(true); - } - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::DeleteValue(const char *subkey, const char *key) -{ - bool res = false; - bool open = false; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READWRITE) ) - { - return res; - } - open = true; - } - - res = this->Helper->DeleteValue(key); - if ( res ) - { - this->Helper->SetChanged(true); - } - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::SetValue(const char *subkey, const char *key, - const char *value) -{ - bool res = false; - bool open = false; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READWRITE) ) - { - return res; - } - open = true; - } - - res = this->Helper->SetValue( key, value ); - if ( res ) - { - this->Helper->SetChanged(true); - } - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -const char* Registry::GetTopLevel() -{ - return this->Helper->GetTopLevel(); -} - -//---------------------------------------------------------------------------- -void Registry::SetTopLevel(const char* tl) -{ - this->Helper->SetTopLevel(tl); -} - -//---------------------------------------------------------------------------- -void RegistryHelper::SetTopLevel(const char* tl) -{ - if ( tl ) - { - m_TopLevel = tl; - } - else - { - m_TopLevel = ""; - } -} - -//---------------------------------------------------------------------------- -RegistryHelper::RegistryHelper(Registry::RegistryType registryType) -{ - m_Changed = false; - m_TopLevel = ""; - m_SubKey = ""; - m_SubKeySpecified = false; - m_Empty = true; - m_GlobalScope = false; - m_RegistryType = registryType; -} - -//---------------------------------------------------------------------------- -RegistryHelper::~RegistryHelper() -{ -} - - -//---------------------------------------------------------------------------- -bool RegistryHelper::Open(const char *toplevel, const char *subkey, - int readonly) -{ - this->EntriesMap.clear(); - m_Empty = 1; - -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - HKEY scope = HKEY_CURRENT_USER; - if ( this->GetGlobalScope() ) - { - scope = HKEY_LOCAL_MACHINE; - } - int res = 0; - kwsys_ios::ostringstream str; - DWORD dwDummy; - str << "Software\\Kitware\\" << toplevel << "\\" << subkey; - if ( readonly == Registry::READONLY ) - { - res = ( RegOpenKeyEx(scope, str.str().c_str(), - 0, KEY_READ, &this->HKey) == ERROR_SUCCESS ); - } - else - { - char lpClass[] = ""; - res = ( RegCreateKeyEx(scope, str.str().c_str(), - 0, lpClass, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, - NULL, &this->HKey, &dwDummy) == ERROR_SUCCESS ); - } - if ( res != 0 ) - { - this->SetSubKey( subkey ); - } - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - bool res = false; - int cc; - kwsys_ios::ostringstream str; - const char* homeDirectory; - if ( (homeDirectory = getenv("HOME")) == 0 ) - { - if ( (homeDirectory = getenv("USERPROFILE")) == 0 ) - { - return false; - } - } - m_HomeDirectory = homeDirectory; - str << m_HomeDirectory.c_str() << "/." << toplevel << "rc"; - if ( readonly == Registry::READWRITE ) - { - kwsys_ios::ofstream ofs( str.str().c_str(), kwsys_ios::ios::out|kwsys_ios::ios::app ); - if ( ofs.fail() ) - { - return false; - } - ofs.close(); - } - - kwsys_ios::ifstream *ifs = new kwsys_ios::ifstream(str.str().c_str(), kwsys_ios::ios::in -#ifndef KWSYS_IOS_USE_ANSI - | kwsys_ios::ios::nocreate -#endif - ); - if ( !ifs ) - { - return false; - } - if ( ifs->fail()) - { - delete ifs; - return false; - } - - res = true; - char buffer[Registry_BUFFER_SIZE]; - while( !ifs->fail() ) - { - ifs->getline(buffer, Registry_BUFFER_SIZE); - if ( ifs->fail() || ifs->eof() ) - { - break; - } - char *line = this->Strip(buffer); - if ( *line == '#' || *line == 0 ) - { - // Comment - continue; - } - int linelen = static_cast(strlen(line)); - for ( cc = 0; cc < linelen; cc++ ) - { - if ( line[cc] == '=' ) - { - char *key = new char[ cc+1 ]; - strncpy( key, line, cc ); - key[cc] = 0; - char *value = line + cc + 1; - char *nkey = this->Strip(key); - char *nvalue = this->Strip(value); - this->EntriesMap[nkey] = this->DecodeValue(nvalue); - m_Empty = 0; - delete [] key; - break; - } - } - } - ifs->close(); - this->SetSubKey( subkey ); - delete ifs; - return res; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::Close() -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - int res; - res = ( RegCloseKey(this->HKey) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - if ( !m_Changed ) - { - this->SetSubKey(0); - return true; - } - - kwsys_ios::ostringstream str; - str << m_HomeDirectory.c_str() << "/." << this->GetTopLevel() << "rc"; - kwsys_ios::ofstream *ofs = new kwsys_ios::ofstream(str.str().c_str(), kwsys_ios::ios::out); - if ( !ofs ) - { - return false; - } - if ( ofs->fail()) - { - delete ofs; - return false; - } - *ofs << "# This file is automatically generated by the application" << kwsys_ios::endl - << "# If you change any lines or add new lines, note that all" << kwsys_ios::endl - << "# comments and empty lines will be deleted. Every line has" << kwsys_ios::endl - << "# to be in format: " << kwsys_ios::endl - << "# key = value" << kwsys_ios::endl - << "#" << kwsys_ios::endl; - - if ( !this->EntriesMap.empty() ) - { - RegistryHelper::StringToStringMap::iterator it; - for ( it = this->EntriesMap.begin(); - it != this->EntriesMap.end(); - ++ it ) - { - *ofs << it->first.c_str() << " = " << this->EncodeValue(it->second.c_str()).c_str() << kwsys_ios::endl; - } - } - this->EntriesMap.clear(); - ofs->close(); - delete ofs; - this->SetSubKey(0); - m_Empty = 1; - return true; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::ReadValue(const char *skey, const char **value) - -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - DWORD dwType, dwSize; - dwType = REG_SZ; - char buffer[1024]; // Replace with RegQueryInfoKey - dwSize = sizeof(buffer); - int res = ( RegQueryValueEx(this->HKey, skey, NULL, &dwType, - (BYTE *)buffer, &dwSize) == ERROR_SUCCESS ); - if ( !res ) - { - return false; - } - this->EntriesMap[key] = buffer; - RegistryHelper::StringToStringMap::iterator it - = this->EntriesMap.find(key); - *value = it->second.c_str(); - return true; - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - bool res = false; - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - - RegistryHelper::StringToStringMap::iterator it - = this->EntriesMap.find(key); - if ( it != this->EntriesMap.end() ) - { - *value = it->second.c_str(); - res = true; - } - return res; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::DeleteKey(const char* skey) -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - int res = ( RegDeleteKey( this->HKey, skey ) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - this->EntriesMap.erase(key); - return true; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::DeleteValue(const char *skey) -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - int res = ( RegDeleteValue( this->HKey, skey ) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - this->EntriesMap.erase(key); - return true; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::SetValue(const char *skey, const char *value) -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - DWORD len = (DWORD)(value ? strlen(value) : 0); - int res = ( RegSetValueEx(this->HKey, skey, 0, REG_SZ, - (CONST BYTE *)(const char *)value, - len+1) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return 0; - } - this->EntriesMap[key] = value; - return 1; - } - return false; -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::CreateKey( const char *key ) -{ - if ( !m_SubKeySpecified || m_SubKey.empty() || !key ) - { - return ""; - } - kwsys_ios::ostringstream ostr; - ostr << this->EncodeKey(this->m_SubKey.c_str()).c_str() - << "\\" << this->EncodeKey(key).c_str(); - return ostr.str(); -} - -//---------------------------------------------------------------------------- -void RegistryHelper::SetSubKey(const char* sk) -{ - if ( !sk ) - { - m_SubKey = ""; - m_SubKeySpecified = false; - } - else - { - m_SubKey = sk; - m_SubKeySpecified = true; - } -} - -//---------------------------------------------------------------------------- -char *RegistryHelper::Strip(char *str) -{ - int cc; - size_t len; - char *nstr; - if ( !str ) - { - return NULL; - } - len = strlen(str); - nstr = str; - for( cc=0; cc < static_cast(len); cc++ ) - { - if ( !isspace( *nstr ) ) - { - break; - } - nstr ++; - } - for( cc= static_cast(strlen(nstr))-1; cc>=0; cc-- ) - { - if ( !isspace( nstr[cc] ) ) - { - nstr[cc+1] = 0; - break; - } - } - return nstr; -} - -//---------------------------------------------------------------------------- -void RegistryHelper::SetGlobalScope(bool b) -{ - m_GlobalScope = b; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::GetGlobalScope() -{ - return m_GlobalScope; -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::EncodeKey(const char* str) -{ - kwsys_ios::ostringstream ostr; - while ( *str ) - { - switch ( *str ) - { - case '%': case '=': case '\n': case '\r': case '\t': - char buffer[4]; - sprintf(buffer, "%%%02X", *str); - ostr << buffer; - break; - default: - ostr << *str; - } - str ++; - } - return ostr.str(); -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::EncodeValue(const char* str) -{ - kwsys_ios::ostringstream ostr; - while ( *str ) - { - switch ( *str ) - { - case '%': case '=': case '\n': case '\r': case '\t': - char buffer[4]; - sprintf(buffer, "%%%02X", *str); - ostr << buffer; - break; - default: - ostr << *str; - } - str ++; - } - return ostr.str(); -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::DecodeValue(const char* str) -{ - kwsys_ios::ostringstream ostr; - while ( *str ) - { - unsigned int val; - switch ( *str ) - { - case '%': - if ( *(str+1) && *(str+2) && sscanf(str+1, "%x", &val) == 1 ) - { - ostr << static_cast(val); - str += 2; - } - else - { - ostr << *str; - } - break; - default: - ostr << *str; - } - str ++; - } - return ostr.str(); -} - -} // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/Registry.hxx.in b/Source/kwsys/Registry.hxx.in deleted file mode 100644 index ed9b01072..000000000 --- a/Source/kwsys/Registry.hxx.in +++ /dev/null @@ -1,107 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - 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. -============================================================================*/ -#ifndef @KWSYS_NAMESPACE@_Registry_hxx -#define @KWSYS_NAMESPACE@_Registry_hxx - -#include <@KWSYS_NAMESPACE@/Configure.h> - -#include <@KWSYS_NAMESPACE@/stl/string> - -namespace @KWSYS_NAMESPACE@ -{ - -class RegistryHelper; - -/** \class Registry - * \brief Portable registry class - * - * This class abstracts the storing of data that can be restored - * when the program executes again. On Win32 platform it is - * implemented using the registry and on unix as a file in - * the user's home directory. - */ -class @KWSYS_NAMESPACE@_EXPORT Registry -{ -public: - enum RegistryType - { -#ifdef _WIN32 - WIN32_REGISTRY, -#endif - FILE_REGISTRY - }; - -#ifdef _WIN32 - Registry(RegistryType registryType = WIN32_REGISTRY); -#else - Registry(RegistryType registryType = FILE_REGISTRY); -#endif - - virtual ~Registry(); - - //! Read a value from the registry. - bool ReadValue(const char *subkey, const char *key, const char **value); - - //! Delete a key from the registry. - bool DeleteKey(const char *subkey, const char *key); - - //! Delete a value from a given key. - bool DeleteValue(const char *subkey, const char *key); - - //! Set value in a given key. - bool SetValue(const char *subkey, const char *key, - const char *value); - - //! Open the registry at toplevel/subkey. - bool Open(const char *toplevel, const char *subkey, - int readonly); - - //! Close the registry. - bool Close(); - - //! Read from local or global scope. On Windows this mean from local machine - // or local user. On unix this will read from $HOME/.Projectrc or - // /etc/Project - void GlobalScopeOn() { this->SetGlobalScope(1); } - void GlobalScopeOff() { this->SetGlobalScope(0); } - void SetGlobalScope(bool b); - bool GetGlobalScope(); - - // Set or get the toplevel registry key. - void SetTopLevel(const char* tl); - const char* GetTopLevel(); - - // Return true if registry opened - bool GetOpened() { return m_Opened; } - - // Should the registry be locked? - bool GetLocked() { return m_Locked; } - - enum { - READONLY, - READWRITE - }; - - // Return true if the character is space. - int IsSpace(char c); - -private: - RegistryHelper* Helper; - - bool m_Opened; - - bool m_Locked; -}; // End Class: Registry - -} // namespace @KWSYS_NAMESPACE@ - -#endif diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 6d990a99d..0460b2906 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -86,6 +86,15 @@ typedef int siginfo_t; # endif #endif +#if defined(__OpenBSD__) || defined(__NetBSD__) +# include +# include +#endif + +#if defined(__DragonFly__) +# include +#endif + #ifdef __APPLE__ # include # include @@ -133,6 +142,9 @@ typedef struct rlimit ResourceLimitType; #elif defined( __hpux ) # include # include +# if defined(KWSYS_SYS_HAS_MPCTL_H) +# include +# endif #endif #ifdef __HAIKU__ @@ -173,6 +185,87 @@ typedef struct rlimit ResourceLimitType; # endif #endif +#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) +#define USE_ASM_INSTRUCTIONS 1 +#else +#define USE_ASM_INSTRUCTIONS 0 +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#include +#define USE_CPUID_INTRINSICS 1 +#else +#define USE_CPUID_INTRINSICS 0 +#endif + +#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS +# define USE_CPUID 1 +#else +# define USE_CPUID 0 +#endif + +#if USE_CPUID + +#define CPUID_AWARE_COMPILER + +/** + * call CPUID instruction + * + * Will return false if the instruction failed. + */ +static bool call_cpuid(int select, int result[4]) +{ +#if USE_CPUID_INTRINSICS + __cpuid(result, select); + return true; +#else + int tmp[4]; + // Use SEH to determine CPUID presence + __try { + _asm { +#ifdef CPUID_AWARE_COMPILER + ; we must push/pop the registers <> writes to, as the + ; optimiser doesn't know about <>, and so doesn't expect + ; these registers to change. + push eax + push ebx + push ecx + push edx +#endif + ; <> + mov eax, select +#ifdef CPUID_AWARE_COMPILER + cpuid +#else + _asm _emit 0x0f + _asm _emit 0xa2 +#endif + mov tmp[0 * TYPE int], eax + mov tmp[1 * TYPE int], ebx + mov tmp[2 * TYPE int], ecx + mov tmp[3 * TYPE int], edx + +#ifdef CPUID_AWARE_COMPILER + pop edx + pop ecx + pop ebx + pop eax +#endif + } + } + __except(1) + { + return false; + } + + memcpy(result, tmp, sizeof(tmp)); + // The cpuid instruction succeeded. + return true; +#endif +} +#endif + + namespace KWSYS_NAMESPACE { template @@ -307,7 +400,7 @@ public: enum Manufacturer { AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM, - Motorola, UnknownManufacturer + Motorola, HP, UnknownManufacturer }; protected: @@ -336,17 +429,20 @@ protected: unsigned char LogicalCPUPerPhysicalCPU(); unsigned char GetAPICId(); unsigned int IsHyperThreadingSupported(); - LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); + static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For Linux and Cygwin, /proc/cpuinfo formats are slightly different - int RetreiveInformationFromCpuInfoFile(); + bool RetreiveInformationFromCpuInfoFile(); kwsys_stl::string ExtractValueFromCpuInfoFile(kwsys_stl::string buffer, const char* word, size_t init=0); + bool QueryLinuxMemory(); + bool QueryCygwinMemory(); + static void Delay (unsigned int); static void DelayOverhead (unsigned int); - void FindManufacturer(); + void FindManufacturer(const kwsys_stl::string &family = ""); // For Mac bool ParseSysCtl(); @@ -367,8 +463,24 @@ protected: bool QueryQNXMemory(); bool QueryQNXProcessor(); + //For OpenBSD, FreeBSD, NetBSD, DragonFly + bool QueryBSDMemory(); + bool QueryBSDProcessor(); + + //For HP-UX + bool QueryHPUXMemory(); + bool QueryHPUXProcessor(); + + //For Microsoft Windows + bool QueryWindowsMemory(); + + //For AIX + bool QueryAIXMemory(); + + bool QueryProcessor(); + // Evaluate the memory information. - int QueryMemory(); + bool QueryMemory(); size_t TotalVirtualMemory; size_t AvailableVirtualMemory; size_t TotalPhysicalMemory; @@ -695,24 +807,11 @@ void SystemInformation::RunMemoryCheck() // -------------------------------------------------------------- // SystemInformationImplementation starts here -#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) -#define USE_ASM_INSTRUCTIONS 1 -#else -#define USE_ASM_INSTRUCTIONS 0 -#endif - #define STORE_TLBCACHE_INFO(x,y) x = (x < y) ? y : x #define TLBCACHE_INFO_UNITS (15) #define CLASSICAL_CPU_FREQ_LOOP 10000000 #define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31 -#define CPUID_AWARE_COMPILER -#ifdef CPUID_AWARE_COMPILER - #define CPUID_INSTRUCTION cpuid -#else - #define CPUID_INSTRUCTION _asm _emit 0x0f _asm _emit 0xa2 -#endif - #define MMX_FEATURE 0x00000001 #define MMX_PLUS_FEATURE 0x00000002 #define SSE_FEATURE 0x00000004 @@ -1144,6 +1243,7 @@ void SystemInformationImplementation::RunCPUCheck() { // Retrieve the CPU details. RetrieveCPUIdentity(); + this->FindManufacturer(); RetrieveCPUFeatures(); } @@ -1188,8 +1288,14 @@ void SystemInformationImplementation::RunCPUCheck() this->QueryHaikuInfo(); #elif defined(__QNX__) this->QueryQNXProcessor(); -#else +#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + this->QueryBSDProcessor(); +#elif defined(__hpux) + this->QueryHPUXProcessor(); +#elif defined(__linux) || defined(__CYGWIN__) this->RetreiveInformationFromCpuInfoFile(); +#else + this->QueryProcessor(); #endif } @@ -1208,6 +1314,18 @@ void SystemInformationImplementation::RunMemoryCheck() this->QueryHaikuInfo(); #elif defined(__QNX__) this->QueryQNXMemory(); +#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + this->QueryBSDMemory(); +#elif defined(__CYGWIN__) + this->QueryCygwinMemory(); +#elif defined(_WIN32) + this->QueryWindowsMemory(); +#elif defined(__hpux) + this->QueryHPUXMemory(); +#elif defined(__linux) + this->QueryLinuxMemory(); +#elif defined(_AIX) + this->QueryAIXMemory(); #else this->QueryMemory(); #endif @@ -1415,6 +1533,8 @@ const char * SystemInformationImplementation::GetVendorID() return "IBM"; case Motorola: return "Motorola"; + case HP: + return "Hewlett-Packard"; default: return "Unknown Manufacturer"; } @@ -1609,40 +1729,15 @@ void SystemInformationImplementation::Delay(unsigned int uiMS) bool SystemInformationImplementation::DoesCPUSupportCPUID() { +#if USE_CPUID + int dummy[4] = { 0, 0, 0, 0 }; + #if USE_ASM_INSTRUCTIONS - // Use SEH to determine CPUID presence - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx + return call_cpuid(0, dummy); +#else + call_cpuid(0, dummy); + return dummy[0] || dummy[1] || dummy[2] || dummy[3]; #endif - ; <> - mov eax, 0 - CPUID_INSTRUCTION - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) - { - // Stop the class from trying to use CPUID again! - return false; - } - - // The cpuid instruction succeeded. - return true; - #else // Assume no cpuid instruction. return false; @@ -1652,58 +1747,29 @@ bool SystemInformationImplementation::DoesCPUSupportCPUID() bool SystemInformationImplementation::RetrieveCPUFeatures() { -#if USE_ASM_INSTRUCTIONS - int localCPUFeatures = 0; - int localCPUAdvanced = 0; +#if USE_CPUID + int cpuinfo[4] = { 0, 0, 0, 0 }; - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID - ; edx: CPU feature flags - mov eax,1 - CPUID_INSTRUCTION - mov localCPUFeatures, edx - mov localCPUAdvanced, ebx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(1, cpuinfo)) { return false; } // Retrieve the features of CPU present. - this->Features.HasFPU = ((localCPUFeatures & 0x00000001) != 0); // FPU Present --> Bit 0 - this->Features.HasTSC = ((localCPUFeatures & 0x00000010) != 0); // TSC Present --> Bit 4 - this->Features.HasAPIC = ((localCPUFeatures & 0x00000200) != 0); // APIC Present --> Bit 9 - this->Features.HasMTRR = ((localCPUFeatures & 0x00001000) != 0); // MTRR Present --> Bit 12 - this->Features.HasCMOV = ((localCPUFeatures & 0x00008000) != 0); // CMOV Present --> Bit 15 - this->Features.HasSerial = ((localCPUFeatures & 0x00040000) != 0); // Serial Present --> Bit 18 - this->Features.HasACPI = ((localCPUFeatures & 0x00400000) != 0); // ACPI Capable --> Bit 22 - this->Features.HasMMX = ((localCPUFeatures & 0x00800000) != 0); // MMX Present --> Bit 23 - this->Features.HasSSE = ((localCPUFeatures & 0x02000000) != 0); // SSE Present --> Bit 25 - this->Features.HasSSE2 = ((localCPUFeatures & 0x04000000) != 0); // SSE2 Present --> Bit 26 - this->Features.HasThermal = ((localCPUFeatures & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29 - this->Features.HasIA64 = ((localCPUFeatures & 0x40000000) != 0); // IA64 Present --> Bit 30 + this->Features.HasFPU = ((cpuinfo[3] & 0x00000001) != 0); // FPU Present --> Bit 0 + this->Features.HasTSC = ((cpuinfo[3] & 0x00000010) != 0); // TSC Present --> Bit 4 + this->Features.HasAPIC = ((cpuinfo[3] & 0x00000200) != 0); // APIC Present --> Bit 9 + this->Features.HasMTRR = ((cpuinfo[3] & 0x00001000) != 0); // MTRR Present --> Bit 12 + this->Features.HasCMOV = ((cpuinfo[3] & 0x00008000) != 0); // CMOV Present --> Bit 15 + this->Features.HasSerial = ((cpuinfo[3] & 0x00040000) != 0); // Serial Present --> Bit 18 + this->Features.HasACPI = ((cpuinfo[3] & 0x00400000) != 0); // ACPI Capable --> Bit 22 + this->Features.HasMMX = ((cpuinfo[3] & 0x00800000) != 0); // MMX Present --> Bit 23 + this->Features.HasSSE = ((cpuinfo[3] & 0x02000000) != 0); // SSE Present --> Bit 25 + this->Features.HasSSE2 = ((cpuinfo[3] & 0x04000000) != 0); // SSE2 Present --> Bit 26 + this->Features.HasThermal = ((cpuinfo[3] & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29 + this->Features.HasIA64 = ((cpuinfo[3] & 0x40000000) != 0); // IA64 Present --> Bit 30 +#if USE_ASM_INSTRUCTIONS // Retrieve extended SSE capabilities if SSE is available. if (this->Features.HasSSE) { @@ -1732,17 +1798,20 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() // Set the advanced SSE capabilities to not available. this->Features.HasSSEFP = false; } +#else + this->Features.HasSSEFP = false; +#endif // Retrieve Intel specific extended features. if (this->ChipManufacturer == Intel) { - this->Features.ExtendedFeatures.SupportsHyperthreading = ((localCPUFeatures & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28 - this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (this->Features.ExtendedFeatures.SupportsHyperthreading) ? ((localCPUAdvanced & 0x00FF0000) >> 16) : 1; + this->Features.ExtendedFeatures.SupportsHyperthreading = ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28 + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (this->Features.ExtendedFeatures.SupportsHyperthreading) ? ((cpuinfo[1] & 0x00FF0000) >> 16) : 1; if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && (this->Features.HasAPIC)) { // Retrieve APIC information if there is one present. - this->Features.ExtendedFeatures.APIC_ID = ((localCPUAdvanced & 0xFF000000) >> 24); + this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24); } } @@ -1755,7 +1824,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() /** Find the manufacturer given the vendor id */ -void SystemInformationImplementation::FindManufacturer() +void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& family) { if (this->ChipID.Vendor == "GenuineIntel") this->ChipManufacturer = Intel; // Intel Corp. else if (this->ChipID.Vendor == "UMC UMC UMC ") this->ChipManufacturer = UMC; // United Microelectronics Corp. @@ -1770,7 +1839,9 @@ void SystemInformationImplementation::FindManufacturer() else if (this->ChipID.Vendor == "Geode By NSC") this->ChipManufacturer = NSC; // National Semiconductor else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics + else if (this->ChipID.Vendor == "Hewlett-Packard") this->ChipManufacturer = HP; // Hewlett-Packard else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics + else if (family.substr(0, 7) == "PA-RISC") this->ChipManufacturer = HP; // Hewlett-Packard else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer } @@ -1778,73 +1849,41 @@ void SystemInformationImplementation::FindManufacturer() /** */ bool SystemInformationImplementation::RetrieveCPUIdentity() { -#if USE_ASM_INSTRUCTIONS - int localCPUVendor[3]; - int localCPUSignature; +#if USE_CPUID + int localCPUVendor[4]; + int localCPUSignature[4]; - // Use assembly to detect CPUID information... - __try + if (!call_cpuid(0, localCPUVendor)) { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0 --> eax: maximum value of CPUID instruction. - ; ebx: part 1 of 3; CPU signature. - ; edx: part 2 of 3; CPU signature. - ; ecx: part 3 of 3; CPU signature. - mov eax, 0 - CPUID_INSTRUCTION - mov localCPUVendor[0 * TYPE int], ebx - mov localCPUVendor[1 * TYPE int], edx - mov localCPUVendor[2 * TYPE int], ecx - - ; <> - ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID - ; edx: CPU feature flags - mov eax,1 - CPUID_INSTRUCTION - mov localCPUSignature, eax - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif + return false; } - } - __except(1) + if (!call_cpuid(1, localCPUSignature)) { return false; } // Process the returned information. + // ; eax = 0 --> eax: maximum value of CPUID instruction. + // ; ebx: part 1 of 3; CPU signature. + // ; edx: part 2 of 3; CPU signature. + // ; ecx: part 3 of 3; CPU signature. char vbuf[13]; - memcpy (&(vbuf[0]), &(localCPUVendor[0]), sizeof (int)); - memcpy (&(vbuf[4]), &(localCPUVendor[1]), sizeof (int)); + memcpy (&(vbuf[0]), &(localCPUVendor[1]), sizeof (int)); + memcpy (&(vbuf[4]), &(localCPUVendor[3]), sizeof (int)); memcpy (&(vbuf[8]), &(localCPUVendor[2]), sizeof (int)); vbuf[12] = '\0'; this->ChipID.Vendor = vbuf; - this->FindManufacturer(); - // Retrieve the family of CPU present. - this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used - this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used - this->ChipID.Type = ((localCPUSignature & 0x0000F000) >> 12); // Bits 15..12 Used - this->ChipID.Family = ((localCPUSignature & 0x00000F00) >> 8); // Bits 11..8 Used - this->ChipID.Model = ((localCPUSignature & 0x000000F0) >> 4); // Bits 7..4 Used - this->ChipID.Revision = ((localCPUSignature & 0x0000000F) >> 0); // Bits 3..0 Used + // ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision + // ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID + // ; edx: CPU feature flags + this->ChipID.ExtendedFamily = ((localCPUSignature[0] & 0x0FF00000) >> 20); // Bits 27..20 Used + this->ChipID.ExtendedModel = ((localCPUSignature[0] & 0x000F0000) >> 16); // Bits 19..16 Used + this->ChipID.Type = ((localCPUSignature[0] & 0x0000F000) >> 12); // Bits 15..12 Used + this->ChipID.Family = ((localCPUSignature[0] & 0x00000F00) >> 8); // Bits 11..8 Used + this->ChipID.Model = ((localCPUSignature[0] & 0x000000F0) >> 4); // Bits 7..4 Used + this->ChipID.Revision = ((localCPUSignature[0] & 0x0000000F) >> 0); // Bits 3..0 Used return true; @@ -1857,48 +1896,14 @@ bool SystemInformationImplementation::RetrieveCPUIdentity() /** */ bool SystemInformationImplementation::RetrieveCPUCacheDetails() { -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID int L1Cache[4] = { 0, 0, 0, 0 }; int L2Cache[4] = { 0, 0, 0, 0 }; // Check to see if what we are about to do is supported... if (RetrieveCPUExtendedLevelSupport (0x80000005)) { - // Use assembly to retrieve the L1 cache information ... - __try - { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000005 --> eax: L1 cache information - Part 1 of 4. - ; ebx: L1 cache information - Part 2 of 4. - ; edx: L1 cache information - Part 3 of 4. - ; ecx: L1 cache information - Part 4 of 4. - mov eax, 0x80000005 - CPUID_INSTRUCTION - mov L1Cache[0 * TYPE int], eax - mov L1Cache[1 * TYPE int], ebx - mov L1Cache[2 * TYPE int], ecx - mov L1Cache[3 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000005, L1Cache)) { return false; } @@ -1915,41 +1920,7 @@ bool SystemInformationImplementation::RetrieveCPUCacheDetails() // Check to see if what we are about to do is supported... if (RetrieveCPUExtendedLevelSupport (0x80000006)) { - // Use assembly to retrieve the L2 cache information ... - __try - { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000006 --> eax: L2 cache information - Part 1 of 4. - ; ebx: L2 cache information - Part 2 of 4. - ; edx: L2 cache information - Part 3 of 4. - ; ecx: L2 cache information - Part 4 of 4. - mov eax, 0x80000006 - CPUID_INSTRUCTION - mov L2Cache[0 * TYPE int], eax - mov L2Cache[1 * TYPE int], ebx - mov L2Cache[2 * TYPE int], ecx - mov L2Cache[3 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000006, L2Cache)) { return false; } @@ -1975,7 +1946,7 @@ bool SystemInformationImplementation::RetrieveCPUCacheDetails() /** */ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails() { -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1, L2Unified = -1, L3Unified = -1; int TLBCacheData[4] = { 0, 0, 0, 0 }; int TLBPassCounter = 0; @@ -1983,39 +1954,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails() do { - // Use assembly to retrieve the L2 cache information ... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 2 --> eax: TLB and cache information - Part 1 of 4. - ; ebx: TLB and cache information - Part 2 of 4. - ; ecx: TLB and cache information - Part 3 of 4. - ; edx: TLB and cache information - Part 4 of 4. - mov eax, 2 - CPUID_INSTRUCTION - mov TLBCacheData[0 * TYPE int], eax - mov TLBCacheData[1 * TYPE int], ebx - mov TLBCacheData[2 * TYPE int], ecx - mov TLBCacheData[3 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(2, TLBCacheData)) { return false; } @@ -2182,11 +2121,40 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() bool retrieved = false; #if defined(_WIN32) - // First of all we check to see if the RDTSC (0x0F, 0x31) instruction is - // supported. If not, we fallback to trying to read this value from the - // registry: - // - if (!this->Features.HasTSC) + unsigned int uiRepetitions = 1; + unsigned int uiMSecPerRepetition = 50; + __int64 i64Total = 0; + __int64 i64Overhead = 0; + + // Check if the TSC implementation works at all + if (this->Features.HasTSC && + GetCyclesDifference(SystemInformationImplementation::Delay, + uiMSecPerRepetition) > 0) + { + for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) + { + i64Total += GetCyclesDifference (SystemInformationImplementation::Delay, + uiMSecPerRepetition); + i64Overhead += + GetCyclesDifference (SystemInformationImplementation::DelayOverhead, + uiMSecPerRepetition); + } + + // Calculate the MHz speed. + i64Total -= i64Overhead; + i64Total /= uiRepetitions; + i64Total /= uiMSecPerRepetition; + i64Total /= 1000; + + // Save the CPU speed. + this->CPUSpeedInMHz = (float) i64Total; + + retrieved = true; + } + + // If RDTSC is not supported, we fallback to trying to read this value + // from the registry: + if (!retrieved) { HKEY hKey = NULL; LONG err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, @@ -2211,34 +2179,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() RegCloseKey(hKey); hKey = NULL; } - - return retrieved; } - - unsigned int uiRepetitions = 1; - unsigned int uiMSecPerRepetition = 50; - __int64 i64Total = 0; - __int64 i64Overhead = 0; - - for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) - { - i64Total += GetCyclesDifference (SystemInformationImplementation::Delay, - uiMSecPerRepetition); - i64Overhead += - GetCyclesDifference (SystemInformationImplementation::DelayOverhead, - uiMSecPerRepetition); - } - - // Calculate the MHz speed. - i64Total -= i64Overhead; - i64Total /= uiRepetitions; - i64Total /= uiMSecPerRepetition; - i64Total /= 1000; - - // Save the CPU speed. - this->CPUSpeedInMHz = (float) i64Total; - - retrieved = true; #endif return retrieved; @@ -2310,7 +2251,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed() /** */ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULevelToCheck) { - int MaxCPUExtendedLevel = 0; + int cpuinfo[4] = { 0, 0, 0, 0 }; // The extended CPUID is supported by various vendors starting with the following CPU models: // @@ -2353,35 +2294,8 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev } } -#if USE_ASM_INSTRUCTIONS - - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000000 --> eax: maximum supported extended level - mov eax,0x80000000 - CPUID_INSTRUCTION - mov MaxCPUExtendedLevel, eax - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) +#if USE_CPUID + if (!call_cpuid(0x80000000, cpuinfo)) { return false; } @@ -2389,7 +2303,7 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev // Now we have to check the level wanted vs level returned... int nLevelWanted = (CPULevelToCheck & 0x7FFFFFFF); - int nLevelReturn = (MaxCPUExtendedLevel & 0x7FFFFFFF); + int nLevelReturn = (cpuinfo[0] & 0x7FFFFFFF); // Check to see if the level provided is supported... if (nLevelWanted > nLevelReturn) @@ -2417,60 +2331,30 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures() return false; } -#if USE_ASM_INSTRUCTIONS - int localCPUExtendedFeatures = 0; +#if USE_CPUID + int localCPUExtendedFeatures[4] = { 0, 0, 0, 0 }; - // Use assembly to detect CPUID information... - __try - { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID - ; edx: CPU feature flags - mov eax,0x80000001 - CPUID_INSTRUCTION - mov localCPUExtendedFeatures, edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000001, localCPUExtendedFeatures)) { return false; } // Retrieve the extended features of CPU present. - this->Features.ExtendedFeatures.Has3DNow = ((localCPUExtendedFeatures & 0x80000000) != 0); // 3DNow Present --> Bit 31. - this->Features.ExtendedFeatures.Has3DNowPlus = ((localCPUExtendedFeatures & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30. - this->Features.ExtendedFeatures.HasSSEMMX = ((localCPUExtendedFeatures & 0x00400000) != 0); // SSE MMX Present --> Bit 22. - this->Features.ExtendedFeatures.SupportsMP = ((localCPUExtendedFeatures & 0x00080000) != 0); // MP Capable -- > Bit 19. + this->Features.ExtendedFeatures.Has3DNow = ((localCPUExtendedFeatures[3] & 0x80000000) != 0); // 3DNow Present --> Bit 31. + this->Features.ExtendedFeatures.Has3DNowPlus = ((localCPUExtendedFeatures[3] & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30. + this->Features.ExtendedFeatures.HasSSEMMX = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // SSE MMX Present --> Bit 22. + this->Features.ExtendedFeatures.SupportsMP = ((localCPUExtendedFeatures[3] & 0x00080000) != 0); // MP Capable -- > Bit 19. // Retrieve AMD specific extended features. if (this->ChipManufacturer == AMD) { - this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22 + this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22 } // Retrieve Cyrix specific extended features. if (this->ChipManufacturer == Cyrix) { - this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24 + this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24 } return true; @@ -2490,51 +2374,20 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber() return false; } -#if USE_ASM_INSTRUCTIONS - int SerialNumber[3]; +#if USE_CPUID + int SerialNumber[4]; - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!? - ; ecx: middle 32 bits are the processor signature bits - ; edx: bottom 32 bits are the processor signature bits - mov eax, 3 - CPUID_INSTRUCTION - mov SerialNumber[0 * TYPE int], ebx - mov SerialNumber[1 * TYPE int], ecx - mov SerialNumber[2 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(3, SerialNumber)) { return false; } // Process the returned information. + // ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!? + // ; ecx: middle 32 bits are the processor signature bits + // ; edx: bottom 32 bits are the processor signature bits char sn[128]; sprintf (sn, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x", - ((SerialNumber[0] & 0xff000000) >> 24), - ((SerialNumber[0] & 0x00ff0000) >> 16), - ((SerialNumber[0] & 0x0000ff00) >> 8), - ((SerialNumber[0] & 0x000000ff) >> 0), ((SerialNumber[1] & 0xff000000) >> 24), ((SerialNumber[1] & 0x00ff0000) >> 16), ((SerialNumber[1] & 0x0000ff00) >> 8), @@ -2542,7 +2395,11 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber() ((SerialNumber[2] & 0xff000000) >> 24), ((SerialNumber[2] & 0x00ff0000) >> 16), ((SerialNumber[2] & 0x0000ff00) >> 8), - ((SerialNumber[2] & 0x000000ff) >> 0)); + ((SerialNumber[2] & 0x000000ff) >> 0), + ((SerialNumber[3] & 0xff000000) >> 24), + ((SerialNumber[3] & 0x00ff0000) >> 16), + ((SerialNumber[3] & 0x0000ff00) >> 8), + ((SerialNumber[3] & 0x000000ff) >> 0)); this->ChipID.SerialNumber = sn; return true; @@ -2564,45 +2421,18 @@ bool SystemInformationImplementation::RetrieveCPUPowerManagement() return false; } -#if USE_ASM_INSTRUCTIONS - int localCPUPowerManagement = 0; +#if USE_CPUID + int localCPUPowerManagement[4] = { 0, 0, 0, 0 }; - - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000007 --> edx: get processor power management - mov eax,0x80000007 - CPUID_INSTRUCTION - mov localCPUPowerManagement, edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000007, localCPUPowerManagement)) { return false; } // Check for the power management capabilities of the CPU. - this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((localCPUPowerManagement & 0x00000001) != 0); - this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((localCPUPowerManagement & 0x00000002) != 0); - this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((localCPUPowerManagement & 0x00000004) != 0); + this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((localCPUPowerManagement[3] & 0x00000001) != 0); + this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((localCPUPowerManagement[3] & 0x00000002) != 0); + this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((localCPUPowerManagement[3] & 0x00000004) != 0); return true; @@ -2632,57 +2462,18 @@ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity() if (!RetrieveCPUExtendedLevelSupport(static_cast(0x80000004))) return false; -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID int CPUExtendedIdentity[12]; - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000002 --> eax, ebx, ecx, edx: get processor name string (part 1) - mov eax,0x80000002 - CPUID_INSTRUCTION - mov CPUExtendedIdentity[0 * TYPE int], eax - mov CPUExtendedIdentity[1 * TYPE int], ebx - mov CPUExtendedIdentity[2 * TYPE int], ecx - mov CPUExtendedIdentity[3 * TYPE int], edx - - ; <> - ; eax = 0x80000003 --> eax, ebx, ecx, edx: get processor name string (part 2) - mov eax,0x80000003 - CPUID_INSTRUCTION - mov CPUExtendedIdentity[4 * TYPE int], eax - mov CPUExtendedIdentity[5 * TYPE int], ebx - mov CPUExtendedIdentity[6 * TYPE int], ecx - mov CPUExtendedIdentity[7 * TYPE int], edx - - ; <> - ; eax = 0x80000004 --> eax, ebx, ecx, edx: get processor name string (part 3) - mov eax,0x80000004 - CPUID_INSTRUCTION - mov CPUExtendedIdentity[8 * TYPE int], eax - mov CPUExtendedIdentity[9 * TYPE int], ebx - mov CPUExtendedIdentity[10 * TYPE int], ecx - mov CPUExtendedIdentity[11 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif + if (!call_cpuid(0x80000002, CPUExtendedIdentity)) + { + return false; } - } - __except(1) + if (!call_cpuid(0x80000003, CPUExtendedIdentity + 4)) + { + return false; + } + if (!call_cpuid(0x80000004, CPUExtendedIdentity + 8)) { return false; } @@ -3002,6 +2793,16 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k size_t pos2 = buffer.find("\n",pos); if(pos!=buffer.npos && pos2!=buffer.npos) { + // It may happen that the beginning matches, but this is still not the requested key. + // An example is looking for "cpu" when "cpu family" comes first. So we check that + // we have only spaces from here to pos, otherwise we search again. + for(size_t i=this->CurrentPositionInFile+strlen(word); i < pos; ++i) + { + if(buffer[i] != ' ' && buffer[i] != '\t') + { + return this->ExtractValueFromCpuInfoFile(buffer, word, pos2); + } + } return buffer.substr(pos+2,pos2-pos-2); } } @@ -3010,7 +2811,7 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k } /** Query for the cpu status */ -int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() +bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() { this->NumberOfLogicalCPU = 0; this->NumberOfPhysicalCPU = 0; @@ -3020,7 +2821,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if ( !fd ) { kwsys_ios::cout << "Problem opening /proc/cpuinfo" << kwsys_ios::endl; - return 0; + return false; } size_t fileSize = 0; @@ -3073,7 +2874,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() this->NumberOfLogicalCPU = atoi(cpucount.c_str()); #endif // gotta have one, and if this is 0 then we get a / by 0n - // beter to have a bad answer than a crash + // better to have a bad answer than a crash if(this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; @@ -3082,33 +2883,156 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical= this->NumberOfLogicalCPU/this->NumberOfPhysicalCPU; - // CPU speed (checking only the first proc + // CPU speed (checking only the first processor) kwsys_stl::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer,"cpu MHz"); this->CPUSpeedInMHz = static_cast(atof(CPUSpeed.c_str())); // Chip family - this->ChipID.Family = atoi(this->ExtractValueFromCpuInfoFile(buffer,"cpu family").c_str()); + kwsys_stl::string familyStr = + this->ExtractValueFromCpuInfoFile(buffer,"cpu family"); + if(familyStr.empty()) + { + familyStr = this->ExtractValueFromCpuInfoFile(buffer,"CPU architecture"); + } + this->ChipID.Family = atoi(familyStr.c_str()); // Chip Vendor this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer,"vendor_id"); - this->FindManufacturer(); + this->FindManufacturer(familyStr); + + // second try for setting family + if (this->ChipID.Family == 0 && this->ChipManufacturer == HP) + { + if (familyStr == "PA-RISC 1.1a") + this->ChipID.Family = 0x11a; + else if (familyStr == "PA-RISC 2.0") + this->ChipID.Family = 0x200; + // If you really get CMake to work on a machine not belonging to + // any of those families I owe you a dinner if you get it to + // contribute nightly builds regularly. + } // Chip Model this->ChipID.Model = atoi(this->ExtractValueFromCpuInfoFile(buffer,"model").c_str()); - this->RetrieveClassicalCPUIdentity(); + if(!this->RetrieveClassicalCPUIdentity()) + { + // Some platforms (e.g. PA-RISC) tell us their CPU name here. + // Note: x86 does not. + kwsys_stl::string cpuname = this->ExtractValueFromCpuInfoFile(buffer,"cpu"); + if(!cpuname.empty()) + { + this->ChipID.ProcessorName = cpuname; + } + } + + // Chip revision + kwsys_stl::string cpurev = this->ExtractValueFromCpuInfoFile(buffer,"stepping"); + if(cpurev.empty()) + { + cpurev = this->ExtractValueFromCpuInfoFile(buffer,"CPU revision"); + } + this->ChipID.Revision = atoi(cpurev.c_str()); // Chip Model Name this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str(); // L1 Cache size - kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,"cache size"); - pos = cacheSize.find(" KB"); - if(pos!=cacheSize.npos) + // Different architectures may show different names for the caches. + // Sum up everything we find. + kwsys_stl::vector cachename; + cachename.clear(); + + cachename.push_back("cache size"); // e.g. x86 + cachename.push_back("I-cache"); // e.g. PA-RISC + cachename.push_back("D-cache"); // e.g. PA-RISC + + this->Features.L1CacheSize = 0; + for (size_t index = 0; index < cachename.size(); index ++) { - cacheSize = cacheSize.substr(0,pos); + kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,cachename[index]); + if (!cacheSize.empty()) + { + pos = cacheSize.find(" KB"); + if(pos!=cacheSize.npos) + { + cacheSize = cacheSize.substr(0,pos); + } + this->Features.L1CacheSize += atoi(cacheSize.c_str()); + } } - this->Features.L1CacheSize = atoi(cacheSize.c_str()); - return 1; + + // processor feature flags (probably x86 specific) + kwsys_stl::string cpuflags = this->ExtractValueFromCpuInfoFile(buffer,"flags"); + if(!cpurev.empty()) + { + // now we can match every flags as space + flag + space + cpuflags = " " + cpuflags + " "; + if ((cpuflags.find(" fpu ")!=kwsys_stl::string::npos)) + { + this->Features.HasFPU = true; + } + if ((cpuflags.find(" tsc ")!=kwsys_stl::string::npos)) + { + this->Features.HasTSC = true; + } + if ((cpuflags.find(" mmx ")!=kwsys_stl::string::npos)) + { + this->Features.HasMMX = true; + } + if ((cpuflags.find(" sse ")!=kwsys_stl::string::npos)) + { + this->Features.HasSSE = true; + } + if ((cpuflags.find(" sse2 ")!=kwsys_stl::string::npos)) + { + this->Features.HasSSE2 = true; + } + if ((cpuflags.find(" apic ")!=kwsys_stl::string::npos)) + { + this->Features.HasAPIC = true; + } + if ((cpuflags.find(" cmov ")!=kwsys_stl::string::npos)) + { + this->Features.HasCMOV = true; + } + if ((cpuflags.find(" mtrr ")!=kwsys_stl::string::npos)) + { + this->Features.HasMTRR = true; + } + if ((cpuflags.find(" acpi ")!=kwsys_stl::string::npos)) + { + this->Features.HasACPI = true; + } + if ((cpuflags.find(" 3dnow ")!=kwsys_stl::string::npos)) + { + this->Features.ExtendedFeatures.Has3DNow = true; + } + } + + return true; +} + +bool SystemInformationImplementation::QueryProcessor() +{ +#if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) +// IRIX names this slightly different +# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN +#endif + +#ifdef _SC_NPROCESSORS_ONLN + long c = sysconf(_SC_NPROCESSORS_ONLN); + if (c <= 0) + { + return false; + } + + this->NumberOfPhysicalCPU = c; + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + + return true; +#else + return false; +#endif } /** @@ -3438,16 +3362,9 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) #endif } -/** Query for the memory status */ -int SystemInformationImplementation::QueryMemory() +bool SystemInformationImplementation::QueryWindowsMemory() { - this->TotalVirtualMemory = 0; - this->TotalPhysicalMemory = 0; - this->AvailableVirtualMemory = 0; - this->AvailablePhysicalMemory = 0; -#ifdef __CYGWIN__ - return 0; -#elif defined(_WIN32) +#if defined(_WIN32) # if defined(_MSC_VER) && _MSC_VER < 1300 MEMORYSTATUS ms; unsigned long tv, tp, av, ap; @@ -3472,8 +3389,15 @@ int SystemInformationImplementation::QueryMemory() this->TotalPhysicalMemory = tp>>10>>10; this->AvailableVirtualMemory = av>>10>>10; this->AvailablePhysicalMemory = ap>>10>>10; - return 1; -#elif defined(__linux) + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryLinuxMemory() +{ +#if defined(__linux) unsigned long tv=0; unsigned long tp=0; unsigned long av=0; @@ -3490,7 +3414,7 @@ int SystemInformationImplementation::QueryMemory() if( errorFlag!=0 ) { kwsys_ios::cout << "Problem calling uname(): " << strerror(errno) << kwsys_ios::endl; - return 0; + return false; } if( unameInfo.release!=0 && strlen(unameInfo.release)>=3 ) @@ -3514,7 +3438,7 @@ int SystemInformationImplementation::QueryMemory() if ( !fd ) { kwsys_ios::cout << "Problem opening /proc/meminfo" << kwsys_ios::endl; - return 0; + return false; } if( linuxMajor>=3 || ( (linuxMajor>=2) && (linuxMinor>=6) ) ) @@ -3553,7 +3477,7 @@ int SystemInformationImplementation::QueryMemory() { kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl; fclose(fd); - return 0; + return false; } } else @@ -3585,39 +3509,87 @@ int SystemInformationImplementation::QueryMemory() { kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl; fclose(fd); - return 0; + return false; } } fclose( fd ); - return 1; -#elif defined(__hpux) - unsigned long tv=0; - unsigned long tp=0; - unsigned long av=0; - unsigned long ap=0; - struct pst_static pst; - struct pst_dynamic pdy; - unsigned long ps = 0; - if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) != -1) - { - ps = pst.page_size; - tp = pst.physical_memory *ps; - tv = (pst.physical_memory + pst.pst_maxmem) * ps; - if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t) 1, 0) != -1) - { - ap = tp - pdy.psd_rm * ps; - av = tv - pdy.psd_vm; - this->TotalVirtualMemory = tv>>10>>10; - this->TotalPhysicalMemory = tp>>10>>10; - this->AvailableVirtualMemory = av>>10>>10; - this->AvailablePhysicalMemory = ap>>10>>10; - return 1; - } - } - return 0; + return true; #else - return 0; + return false; +#endif +} + +bool SystemInformationImplementation::QueryCygwinMemory() +{ +#ifdef __CYGWIN__ + // _SC_PAGE_SIZE does return the mmap() granularity on Cygwin, + // see http://cygwin.com/ml/cygwin/2006-06/msg00350.html + // Therefore just use 4096 as the page size of Windows. + long m = sysconf(_SC_PHYS_PAGES); + if (m < 0) + { + return false; + } + this->TotalPhysicalMemory = m >> 8; + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryAIXMemory() +{ +#if defined(_AIX) + long c = sysconf(_SC_AIX_REALMEM); + if (c <= 0) + { + return false; + } + + this->TotalPhysicalMemory = c / 1024; + + return true; +#else + return false; +#endif +} + +/** Query for the memory status */ +bool SystemInformationImplementation::QueryMemory() +{ +#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) + // Assume the mmap() granularity as returned by _SC_PAGESIZE is also + // the system page size. The only known system where this isn't true + // is Cygwin. + long p = sysconf(_SC_PHYS_PAGES); + long m = sysconf(_SC_PAGESIZE); + + if (p < 0 || m < 0) + { + return false; + } + + // assume pagesize is a power of 2 and smaller 1 MiB + size_t pagediv = (1024 * 1024 / m); + + this->TotalPhysicalMemory = p; + this->TotalPhysicalMemory /= pagediv; + +#if defined(_SC_AVPHYS_PAGES) + p = sysconf(_SC_AVPHYS_PAGES); + if (p < 0) + { + return false; + } + + this->AvailablePhysicalMemory = p; + this->AvailablePhysicalMemory /= pagediv; +#endif + + return true; +#else + return false; #endif } @@ -3649,7 +3621,15 @@ SystemInformation::LongLong SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayFunction, unsigned int uiParameter) { -#if USE_ASM_INSTRUCTIONS +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + unsigned __int64 stamp1, stamp2; + + stamp1 = __rdtsc(); + DelayFunction(uiParameter); + stamp2 = __rdtsc(); + + return stamp2 - stamp1; +#elif USE_ASM_INSTRUCTIONS unsigned int edx1, eax1; unsigned int edx2, eax2; @@ -3731,20 +3711,15 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) } return static_cast(cores_per_package); #else - unsigned int Regebx = 0; -#if USE_ASM_INSTRUCTIONS + int Regs[4] = { 0, 0, 0, 0 }; +#if USE_CPUID if (!this->IsHyperThreadingSupported()) { return static_cast(1); // HT not supported } - __asm - { - mov eax, 1 - cpuid - mov Regebx, ebx - } + call_cpuid(1, Regs); #endif - return static_cast ((Regebx & NUM_LOGICAL_BITS) >> 16); + return static_cast ((Regs[1] & NUM_LOGICAL_BITS) >> 16); #endif } @@ -3752,40 +3727,30 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) /** Works only for windows */ unsigned int SystemInformationImplementation::IsHyperThreadingSupported() { -#if USE_ASM_INSTRUCTIONS - unsigned int Regedx = 0, - Regeax = 0, - VendorId[3] = {0, 0, 0}; - __try // Verify cpuid instruction is supported +#if USE_CPUID + int Regs[4] = { 0, 0, 0, 0 }, + VendorId[4] = { 0, 0, 0, 0 }; + // Get vendor id string + if (!call_cpuid(0, VendorId)) { - __asm - { - xor eax, eax // call cpuid with eax = 0 - cpuid // Get vendor id string - mov VendorId, ebx - mov VendorId + 4, edx - mov VendorId + 8, ecx - - mov eax, 1 // call cpuid with eax = 1 - cpuid - mov Regeax, eax // eax contains family processor type - mov Regedx, edx // edx has info about the availability of hyper-Threading - } + return false; } - __except (EXCEPTION_EXECUTE_HANDLER) + // eax contains family processor type + // edx has info about the availability of hyper-Threading + if (!call_cpuid(1, Regs)) { - return(0); // cpuid is unavailable + return false; } - if (((Regeax & FAMILY_ID) == PENTIUM4_ID) || (Regeax & EXT_FAMILY_ID)) + if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) { - if (VendorId[0] == 'uneG') + if (VendorId[1] == 'uneG') { - if (VendorId[1] == 'Ieni') + if (VendorId[3] == 'Ieni') { if (VendorId[2] == 'letn') { - return(Regedx & HT_BIT); // Genuine Intel with hyper-Threading technology + return(Regs[3] & HT_BIT); // Genuine Intel with hyper-Threading technology } } } @@ -3799,22 +3764,17 @@ unsigned int SystemInformationImplementation::IsHyperThreadingSupported() /** Return the APIC Id. Works only for windows. */ unsigned char SystemInformationImplementation::GetAPICId() { - unsigned int Regebx = 0; + int Regs[4] = { 0, 0, 0, 0 }; -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID if (!this->IsHyperThreadingSupported()) { return static_cast(-1); // HT not supported } // Logical processor = 1 - __asm - { - mov eax, 1 - cpuid - mov Regebx, ebx - } + call_cpuid(1, Regs); #endif - return static_cast((Regebx & INITIAL_APIC_ID_BITS) >> 24); + return static_cast((Regs[1] & INITIAL_APIC_ID_BITS) >> 24); } @@ -4221,25 +4181,24 @@ bool SystemInformationImplementation::QuerySolarisInfo() this->NumberOfPhysicalCPU = static_cast( atoi(this->ParseValueFromKStat("-n syste_misc -s ncpus").c_str())); this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; - - if(this->NumberOfPhysicalCPU!=0) - { - this->NumberOfLogicalCPU /= this->NumberOfPhysicalCPU; - } + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = 1; this->CPUSpeedInMHz = static_cast(atoi(this->ParseValueFromKStat("-s clock_MHz").c_str())); // Chip family this->ChipID.Family = 0; - // Chip Vendor - this->ChipID.Vendor = "Sun"; - this->FindManufacturer(); - // Chip Model this->ChipID.ProcessorName = this->ParseValueFromKStat("-s cpu_type"); this->ChipID.Model = 0; + // Chip Vendor + if (this->ChipID.ProcessorName != "i386") + { + this->ChipID.Vendor = "Sun"; + this->FindManufacturer(); + } + // Cache size this->Features.L1CacheSize = 0; this->Features.L2CacheSize = 0; @@ -4247,9 +4206,7 @@ bool SystemInformationImplementation::QuerySolarisInfo() char* tail; unsigned long totalMemory = strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0); - this->TotalPhysicalMemory = totalMemory/1024; - this->TotalPhysicalMemory *= 8192; - this->TotalPhysicalMemory /= 1024; + this->TotalPhysicalMemory = totalMemory/128; // Undefined values (for now at least) this->TotalVirtualMemory = 0; @@ -4363,6 +4320,31 @@ bool SystemInformationImplementation::QueryQNXMemory() return false; } +bool SystemInformationImplementation::QueryBSDMemory() +{ +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + int ctrl[2] = { CTL_HW, HW_PHYSMEM }; +#if defined(HW_PHYSMEM64) + int64_t k; + ctrl[1] = HW_PHYSMEM64; +#else + int k; +#endif + size_t sz = sizeof(k); + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->TotalPhysicalMemory = k>>10>>10; + + return true; +#else + return false; +#endif +} + bool SystemInformationImplementation::QueryQNXProcessor() { #if defined(__QNX__) @@ -4416,6 +4398,124 @@ bool SystemInformationImplementation::QueryQNXProcessor() #endif } +bool SystemInformationImplementation::QueryBSDProcessor() +{ +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + int k; + size_t sz = sizeof(k); + int ctrl[2] = { CTL_HW, HW_NCPU }; + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->NumberOfPhysicalCPU = k; + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + +#if defined(HW_CPUSPEED) + ctrl[1] = HW_CPUSPEED; + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->CPUSpeedInMHz = (float) k; +#endif + + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryHPUXMemory() +{ +#if defined(__hpux) + unsigned long tv=0; + unsigned long tp=0; + unsigned long av=0; + unsigned long ap=0; + struct pst_static pst; + struct pst_dynamic pdy; + + unsigned long ps = 0; + if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) == -1) + { + return false; + } + + ps = pst.page_size; + tp = pst.physical_memory *ps; + tv = (pst.physical_memory + pst.pst_maxmem) * ps; + if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t) 1, 0) == -1) + { + return false; + } + + ap = tp - pdy.psd_rm * ps; + av = tv - pdy.psd_vm; + this->TotalVirtualMemory = tv>>10>>10; + this->TotalPhysicalMemory = tp>>10>>10; + this->AvailableVirtualMemory = av>>10>>10; + this->AvailablePhysicalMemory = ap>>10>>10; + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryHPUXProcessor() +{ +#if defined(__hpux) +# if defined(KWSYS_SYS_HAS_MPCTL_H) + int c = mpctl(MPC_GETNUMSPUS_SYS, 0, 0); + if (c <= 0) + { + return false; + } + + this->NumberOfPhysicalCPU = c; + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + + long t = sysconf(_SC_CPU_VERSION); + + if (t == -1) + { + return false; + } + + switch (t) + { + case CPU_PA_RISC1_0: + this->ChipID.Vendor = "Hewlett-Packard"; + this->ChipID.Family = 0x100; + case CPU_PA_RISC1_1: + this->ChipID.Vendor = "Hewlett-Packard"; + this->ChipID.Family = 0x110; + case CPU_PA_RISC2_0: + this->ChipID.Vendor = "Hewlett-Packard"; + this->ChipID.Family = 0x200; + case CPU_IA64_ARCHREV_0: + this->ChipID.Vendor = "GenuineIntel"; + this->Features.HasIA64 = true; + break; + default: + return false; + } + + this->FindManufacturer(); + + return true; +# else + return false; +# endif +#else + return false; +#endif +} + /** Query the operating system information */ bool SystemInformationImplementation::QueryOSInformation() { diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 085d98836..b75993ea6 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -157,7 +157,7 @@ public: #include #endif -#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__) +#if defined(__BEOS__) && !defined(__ZETA__) #include #include @@ -622,11 +622,7 @@ bool SystemTools::MakeDirectory(const char* path) } SystemTools::ConvertToUnixSlashes(dir); - kwsys_stl::string::size_type pos = dir.find(':'); - if(pos == kwsys_stl::string::npos) - { - pos = 0; - } + kwsys_stl::string::size_type pos = 0; kwsys_stl::string topdir; while((pos = dir.find('/', pos)) != kwsys_stl::string::npos) { @@ -634,14 +630,7 @@ bool SystemTools::MakeDirectory(const char* path) Mkdir(topdir.c_str()); pos++; } - if(dir[dir.size()-1] == '/') - { - topdir = dir.substr(0, dir.size()); - } - else - { - topdir = dir; - } + topdir = dir; if(Mkdir(topdir.c_str()) != 0) { // There is a bug in the Borland Run time library which makes MKDIR @@ -2754,9 +2743,15 @@ kwsys_stl::string SystemTools::GetRealPath(const char* path) bool SystemTools::FileIsDirectory(const char* name) { + size_t length = strlen(name); + if (length == 0) + { + return false; + } + // Remove any trailing slash from the name. char buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; - size_t last = strlen(name)-1; + size_t last = length-1; if(last > 0 && (name[last] == '/' || name[last] == '\\') && strcmp(name, "/") !=0) { @@ -4048,7 +4043,7 @@ kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format) return kwsys_stl::string(buf); } -kwsys_stl::string SystemTools::MakeCindentifier(const char* s) +kwsys_stl::string SystemTools::MakeCidentifier(const char* s) { kwsys_stl::string str(s); if (str.find_first_of("0123456789") == 0) diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 5171125ce..9c56e96b0 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -91,8 +91,13 @@ public: * then an underscore is prepended. Note that this can produce * identifiers that the standard reserves (_[A-Z].* and __.*). */ - static kwsys_stl::string MakeCindentifier(const char* s); - + static kwsys_stl::string MakeCidentifier(const char* s); + + static kwsys_stl::string MakeCindentifier(const char* s) + { + return MakeCidentifier(s); + } + /** * Replace replace all occurences of the string in the source string. */ diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx index a7adbcad9..cbfb65b1c 100644 --- a/Source/kwsys/testDynamicLoader.cxx +++ b/Source/kwsys/testDynamicLoader.cxx @@ -15,7 +15,7 @@ #include KWSYS_HEADER(ios/iostream) #include KWSYS_HEADER(stl/string) -#if defined(__BEOS__) && !defined(__HAIKU__) +#if defined(__BEOS__) #include /* disable_debugger() API. */ #endif diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c index 877002a14..269b84ba8 100644 --- a/Source/kwsys/testProcess.c +++ b/Source/kwsys/testProcess.c @@ -32,7 +32,7 @@ # pragma warn -8060 /* possibly incorrect assignment */ #endif -#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__) +#if defined(__BEOS__) && !defined(__ZETA__) /* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */ # include static inline void testProcess_usleep(unsigned int msec) @@ -82,6 +82,14 @@ int test3(int argc, const char* argv[]) int test4(int argc, const char* argv[]) { + /* Prepare a pointer to an invalid address. Don't use null, because + dereferencing null is undefined behaviour and compilers are free to + do whatever they want. ex: Clang will warn at compile time, or even + optimize away the write. We hope to 'outsmart' them by using + 'volatile' and a slightly larger address, based on a runtime value. */ + volatile int* invalidAddress = 0; + invalidAddress += argc?1:2; + #if defined(_WIN32) /* Avoid error diagnostic popups since we are crashing on purpose. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); @@ -94,11 +102,8 @@ int test4(int argc, const char* argv[]) fprintf(stderr, "Output before crash on stderr from crash test.\n"); fflush(stdout); fflush(stderr); -#if defined(__clang__) - *(int*)1 = 0; /* Clang warns about 0-ptr; undefined behavior. */ -#else - *(int*)0 = 0; -#endif + /* Provoke deliberate crash by writing to the invalid address. */ + *invalidAddress = 0; fprintf(stdout, "Output after crash on stdout from crash test.\n"); fprintf(stderr, "Output after crash on stderr from crash test.\n"); return 0; diff --git a/Source/kwsys/testRegistry.cxx b/Source/kwsys/testRegistry.cxx deleted file mode 100644 index 7e9b0d49b..000000000 --- a/Source/kwsys/testRegistry.cxx +++ /dev/null @@ -1,109 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - 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 "kwsysPrivate.h" - -#include KWSYS_HEADER(Registry.hxx) -#include KWSYS_HEADER(ios/iostream) -#include - -// Work-around CMake dependency scanning limitation. This must -// duplicate the above list of headers. -#if 0 -# include "Registry.hxx.in" -# include "kwsys_ios_iostream.h.in" -#endif - -#define IFT(x,res) if ( !x ) \ - { \ - res = 1; \ - kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \ - } -#define IFNT(x,res) if ( x ) \ - { \ - res = 1; \ - kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \ - } - -#define CHE(x,y,res) if ( x && strcmp(x,y) ) \ - { \ - res = 1; \ - kwsys_ios::cout << "Error, " << x << " != " << y << kwsys_ios::endl; \ - } - -int testRegistry(int, char*[]) -{ - int res = 0; - - kwsys::Registry reg; - reg.SetTopLevel("TestRegistry"); - - IFT(reg.SetValue("TestSubkey", "TestKey1", "Test Value 1"), res); - IFT(reg.SetValue("TestSubkey1", "TestKey2", "Test Value 2"), res); - IFT(reg.SetValue("TestSubkey", "TestKey3", "Test Value 3"), res); - IFT(reg.SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res); - - const char *buffer; - IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res); - CHE(buffer, "Test Value 1", res); - IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res); - CHE(buffer, "Test Value 2", res); - IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res); - CHE(buffer, "Test Value 3", res); - IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res); - CHE(buffer, "Test Value 4", res); - - IFT(reg.SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res); - IFT(reg.SetValue("TestSubkey1", "TestKey2", "New Test Value 2"), res); - IFT(reg.SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res); - IFT(reg.SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res); - - IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res); - CHE(buffer, "New Test Value 1", res); - IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res); - CHE(buffer, "New Test Value 2", res); - IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res); - CHE(buffer, "New Test Value 3", res); - IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res); - CHE(buffer, "New Test Value 4", res); - - IFT( reg.DeleteValue("TestSubkey", "TestKey1"), res); - IFNT(reg.ReadValue( "TestSubkey", "TestKey1", &buffer), res); - IFT( reg.DeleteValue("TestSubkey1", "TestKey2"), res); - IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", &buffer), res); - IFT( reg.DeleteValue("TestSubkey", "TestKey3"), res); - IFNT(reg.ReadValue( "TestSubkey", "TestKey3", &buffer), res); - IFT( reg.DeleteValue("TestSubkey2", "TestKey4"), res); - IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", &buffer), res); - - const char* longStringWithNewLines = "Value with embedded CR and LF characters CR='\015' LF='\012' CRLF='\015\012'"; - IFT(reg.SetValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", longStringWithNewLines), res); - IFT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res); - CHE(buffer, longStringWithNewLines, res); - IFT(reg.DeleteValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1"), res); - IFNT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res); - - IFT(reg.SetValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", "Some value"), res); - IFT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res); - CHE(buffer, "Some value", res); - IFT(reg.DeleteValue("TestSubkeyWith = EqualSignChar", "TestKey = 1"), res); - IFNT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res); - - if ( res ) - { - kwsys_ios::cout << "Test failed" << kwsys_ios::endl; - } - else - { - kwsys_ios::cout << "Test passed" << kwsys_ios::endl; - } - return res; -} diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 41fcf384b..49a686c17 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -47,6 +47,8 @@ int testSystemInformation(int, char*[]) { + kwsys_ios::cout << "CTEST_FULL_OUTPUT\n"; // avoid truncation + kwsys::SystemInformation info; info.RunCPUCheck(); info.RunOSCheck(); @@ -66,6 +68,7 @@ int testSystemInformation(int, char*[]) printMethod(info, GetFamilyID); printMethod(info, GetModelID); printMethod(info, GetExtendedProcessorName); + printMethod(info, GetSteppingCode); printMethod(info, GetProcessorSerialNumber); printMethod2(info, GetProcessorCacheSize, "KB"); printMethod(info, GetLogicalProcessorsPerPhysical); @@ -85,6 +88,13 @@ int testSystemInformation(int, char*[]) printMethod3(info, GetHostMemoryUsed(), "KiB"); printMethod3(info, GetProcMemoryUsed(), "KiB"); + for (int i = 0; i <= 31; i++) + { + if (info.DoesCPUSupportFeature(1 << i)) + { + kwsys_ios::cout << "CPU feature " << i << "\n"; + } + } //int GetProcessorCacheXSize(long int); // bool DoesCPUSupportFeature(long int); return 0; diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt new file mode 100644 index 000000000..84a23efc3 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt @@ -0,0 +1,26 @@ + +cmake_minimum_required(VERSION 2.8) + +project(target_compile_definitions) + +add_executable(target_compile_definitions + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +target_compile_definitions(target_compile_definitions + PRIVATE MY_PRIVATE_DEFINE + PUBLIC MY_PUBLIC_DEFINE + INTERFACE MY_INTERFACE_DEFINE +) + +add_library(importedlib UNKNOWN IMPORTED) +target_compile_definitions(importedlib + INTERFACE MY_IMPORTEDINTERFACE_DEFINE +) + +add_executable(consumer + "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" +) + +target_compile_definitions(consumer + PRIVATE target_compile_definitions importedlib +) diff --git a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp new file mode 100644 index 000000000..e3788ddb2 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp @@ -0,0 +1,18 @@ + +#ifdef MY_PRIVATE_DEFINE +#error Unexpected MY_PRIVATE_DEFINE +#endif + +#ifndef MY_PUBLIC_DEFINE +#error Expected MY_PUBLIC_DEFINE +#endif + +#ifndef MY_INTERFACE_DEFINE +#error Expected MY_INTERFACE_DEFINE +#endif + +#ifndef MY_IMPORTEDINTERFACE_DEFINE +#error Expected MY_IMPORTEDINTERFACE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_compile_definitions/main.cpp b/Tests/CMakeCommands/target_compile_definitions/main.cpp new file mode 100644 index 000000000..addb33cf9 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_definitions/main.cpp @@ -0,0 +1,14 @@ + +#ifndef MY_PRIVATE_DEFINE +#error Expected MY_PRIVATE_DEFINE +#endif + +#ifndef MY_PUBLIC_DEFINE +#error Expected MY_PUBLIC_DEFINE +#endif + +#ifdef MY_INTERFACE_DEFINE +#error Unexpected MY_INTERFACE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt new file mode 100644 index 000000000..a0f2ee08c --- /dev/null +++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 2.8) + +project(target_include_directories) + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/privateinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/privateinclude/privateinclude.h" "#define PRIVATEINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/publicinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/publicinclude/publicinclude.h" "#define PUBLICINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude/interfaceinclude.h" "#define INTERFACEINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude/importedinterfaceinclude.h" "#define IMPORTEDINTERFACEINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/poison") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/poison/common.h" "#error Should not be included\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cure") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cure/common.h" "#define CURE_DEFINE\n") + +add_executable(target_include_directories + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +target_include_directories(target_include_directories + PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/privateinclude" + PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/publicinclude" + INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude" +) + +target_include_directories(target_include_directories + PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/poison" +) +target_include_directories(target_include_directories + BEFORE PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/cure" +) + +add_library(importedlib UNKNOWN IMPORTED) +target_include_directories(importedlib + INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude" +) + +add_executable(consumer + "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" +) + +target_include_directories(consumer + PRIVATE target_include_directories importedlib +) diff --git a/Tests/CMakeCommands/target_include_directories/consumer.cpp b/Tests/CMakeCommands/target_include_directories/consumer.cpp new file mode 100644 index 000000000..6fd61d5b7 --- /dev/null +++ b/Tests/CMakeCommands/target_include_directories/consumer.cpp @@ -0,0 +1,27 @@ + +#include "common.h" +#include "publicinclude.h" +#include "interfaceinclude.h" +#include "importedinterfaceinclude.h" + +#ifdef PRIVATEINCLUDE_DEFINE +#error Unexpected PRIVATEINCLUDE_DEFINE +#endif + +#ifndef PUBLICINCLUDE_DEFINE +#error Expected PUBLICINCLUDE_DEFINE +#endif + +#ifndef INTERFACEINCLUDE_DEFINE +#error Expected INTERFACEINCLUDE_DEFINE +#endif + +#ifndef IMPORTEDINTERFACEINCLUDE_DEFINE +#error Expected IMPORTEDINTERFACEINCLUDE_DEFINE +#endif + +#ifndef CURE_DEFINE +#error Expected CURE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_include_directories/main.cpp b/Tests/CMakeCommands/target_include_directories/main.cpp new file mode 100644 index 000000000..8434b97d8 --- /dev/null +++ b/Tests/CMakeCommands/target_include_directories/main.cpp @@ -0,0 +1,22 @@ + +#include "common.h" +#include "privateinclude.h" +#include "publicinclude.h" + +#ifndef PRIVATEINCLUDE_DEFINE +#error Expected PRIVATEINCLUDE_DEFINE +#endif + +#ifndef PUBLICINCLUDE_DEFINE +#error Expected PUBLICINCLUDE_DEFINE +#endif + +#ifdef INTERFACEINCLUDE_DEFINE +#error Unexpected INTERFACEINCLUDE_DEFINE +#endif + +#ifndef CURE_DEFINE +#error Expected CURE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 1faa88848..746d30c27 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -29,11 +29,21 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) add_library(depA SHARED depA.cpp) generate_export_header(depA) +add_library(importedlib UNKNOWN IMPORTED) +target_link_libraries(importedlib LINK_INTERFACE_LIBRARIES depA) + add_library(depB SHARED depB.cpp) generate_export_header(depB) target_link_libraries(depB LINK_PRIVATE depA) +add_library(libgenex SHARED libgenex.cpp) +generate_export_header(libgenex) + +set_property(TARGET depB APPEND PROPERTY + LINK_LIBRARIES $<1:libgenex> +) + add_library(depC SHARED depC.cpp) generate_export_header(depC) @@ -53,6 +63,20 @@ set_target_properties(targetA PROPERTIES LINK_INTERFACE_LIBRARIES "") assert_property(targetA LINK_INTERFACE_LIBRARIES "") +add_subdirectory(subdir) +target_link_libraries(targetA subdirlib) +set_property(TARGET targetA APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) + target_link_libraries(targetA depB depC) assert_property(targetA LINK_INTERFACE_LIBRARIES "") + +# Exclude depIfaceOnly from ALL so that it will only be built if something +# depends on it. As it is in the link interface of depB, targetA +# will depend on it. That dependency is what is being tested here. +add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp) +generate_export_header(depIfaceOnly) +set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly) diff --git a/Tests/CMakeCommands/target_link_libraries/depB.cpp b/Tests/CMakeCommands/target_link_libraries/depB.cpp index 97e5be274..4f46552d7 100644 --- a/Tests/CMakeCommands/target_link_libraries/depB.cpp +++ b/Tests/CMakeCommands/target_link_libraries/depB.cpp @@ -3,9 +3,13 @@ #include "depA.h" +#include "libgenex.h" + int DepB::foo() { DepA a; - return 0; + LibGenex lg; + + return a.foo() + lg.foo(); } diff --git a/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.cpp b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.cpp new file mode 100644 index 000000000..3b90af008 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.cpp @@ -0,0 +1,7 @@ + +#include "depIfaceOnly.h" + +int DepIfaceOnly::foo() +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.h b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.h new file mode 100644 index 000000000..dddf6a5e4 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.h @@ -0,0 +1,7 @@ + +#include "depifaceonly_export.h" + +struct DEPIFACEONLY_EXPORT DepIfaceOnly +{ + int foo(); +}; diff --git a/Tests/CMakeCommands/target_link_libraries/libgenex.cpp b/Tests/CMakeCommands/target_link_libraries/libgenex.cpp new file mode 100644 index 000000000..c925c0821 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/libgenex.cpp @@ -0,0 +1,7 @@ + +#include "libgenex.h" + +int LibGenex::foo() +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/libgenex.h b/Tests/CMakeCommands/target_link_libraries/libgenex.h new file mode 100644 index 000000000..733f9b6df --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/libgenex.h @@ -0,0 +1,12 @@ + +#include "libgenex_export.h" + +#ifndef LIBGENEX_H +#define LIBGENEX_H + +struct LIBGENEX_EXPORT LibGenex +{ + int foo(); +}; + +#endif diff --git a/Tests/CMakeCommands/target_link_libraries/subdir/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/subdir/CMakeLists.txt new file mode 100644 index 000000000..61a1a5988 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/subdir/CMakeLists.txt @@ -0,0 +1,5 @@ + +set(CMAKE_BUILD_INTERFACE_INCLUDES ON) + +add_library(subdirlib SHARED subdirlib.cpp) +generate_export_header(subdirlib) diff --git a/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.cpp b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.cpp new file mode 100644 index 000000000..cd2f1a23a --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.cpp @@ -0,0 +1,7 @@ + +#include "subdirlib.h" + +int SubDirLibObject::foo() const +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.h b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.h new file mode 100644 index 000000000..e386f87b2 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.h @@ -0,0 +1,12 @@ + +#ifndef SUBDIRLIB_H +#define SUBDIRLIB_H + +#include "subdirlib_export.h" + +struct SUBDIRLIB_EXPORT SubDirLibObject +{ + int foo() const; +}; + +#endif diff --git a/Tests/CMakeCommands/target_link_libraries/targetA.cpp b/Tests/CMakeCommands/target_link_libraries/targetA.cpp index 3c6472e9a..559aef7f0 100644 --- a/Tests/CMakeCommands/target_link_libraries/targetA.cpp +++ b/Tests/CMakeCommands/target_link_libraries/targetA.cpp @@ -1,6 +1,9 @@ #include "depB.h" #include "depC.h" +#include "depIfaceOnly.h" + +#include "subdirlib.h" int main(int argc, char **argv) { @@ -8,5 +11,9 @@ int main(int argc, char **argv) DepB b; DepC c; - return a.foo() + b.foo() + c.foo(); + DepIfaceOnly iface_only; + + SubDirLibObject sd; + + return a.foo() + b.foo() + c.foo() + iface_only.foo() + sd.foo(); } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index f2a198cff..2f7df01cf 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -573,6 +573,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustomCommand") + ADD_TEST_MACRO(EmptyDepends ${CMAKE_CTEST_COMMAND}) + add_test(CustomCommandWorkingDirectory ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/CustomCommandWorkingDirectory" @@ -695,6 +697,29 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ endif() endif() + # On Windows run the CPackWiXGenerator test + # if the WiX Toolset seems to be available + if(WIN32) + file(TO_CMAKE_PATH "$ENV{WIX}" WIX_ROOT) + + find_program(WIX_LIGHT_EXECUTABLE light + PATHS "${WIX_ROOT}/bin" + DOC "WiX Toolset light.exe location") + + if(WIX_LIGHT_EXECUTABLE) + add_test(CPackWiXGenerator ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/CPackWiXGenerator" + "${CMake_BINARY_DIR}/Tests/CPackWiXGenerator" + --build-generator ${CMAKE_TEST_GENERATOR} + --build-project CPackWiXGenerator + --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM} + --test-command ${CMAKE_CMAKE_COMMAND} + "-DCPackWiXGenerator_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/CPackWiXGenerator" + -P "${CMake_SOURCE_DIR}/Tests/CPackWiXGenerator/RunCPackVerifyResult.cmake") + endif() + endif() + if(CTEST_RUN_CPackComponents) set(CPackComponents_EXTRA_OPTIONS) if(APPLE) @@ -742,7 +767,6 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ # ACTIVE_CPACK_GENERATORS variable # now contains the list of 'active generators' set(CPackComponentsForAll_EXTRA_OPTIONS) - set(CPackRun_CPackCommand "-DCPackCommand=${CMAKE_CPACK_COMMAND}") # set up list of CPack generators list(APPEND GENLST "ZIP") if(APPLE) @@ -782,7 +806,6 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --graphviz=CPackComponentsForAll.dot --test-command ${CMAKE_CMAKE_COMMAND} "-DCPackComponentsForAll_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/CPackComponentsForAll/build${CPackGen}-${CPackComponentWay}" - "${CPackRun_CPackCommand}" "${CPackRun_CPackGen}" "${CPackRun_CPackComponentWay}" -P "${CMake_SOURCE_DIR}/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake") @@ -817,7 +840,6 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --test-command ${CMAKE_CMAKE_COMMAND} -D dir=${CMake_BINARY_DIR}/Tests/CPackTestAllGenerators - -D cpack=${CMAKE_CPACK_COMMAND} -P ${CMake_SOURCE_DIR}/Tests/CPackTestAllGenerators/RunCPack.cmake ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackTestAllGenerators") @@ -967,6 +989,21 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomoc") endif() + if(QT4_WORKS AND QT_QTGUI_FOUND) + add_test(Qt4Targets ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Qt4Targets" + "${CMake_BINARY_DIR}/Tests/Qt4Targets" + --build-generator ${CMAKE_TEST_GENERATOR} + --build-project Qt4Targets + --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM} + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4Targets" + --force-new-ctest-process + --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + --test-command ${CMAKE_CTEST_COMMAND} -V + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Targets") + endif() add_test(ExternalProject ${CMAKE_CTEST_COMMAND} --build-and-test @@ -1893,6 +1930,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ) ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries) + ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories) + ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions) configure_file( "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in" @@ -1937,6 +1976,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --output-log "${CMake_BINARY_DIR}/Tests/CTestTestParallel/testOutput.log" ) + add_test_macro(CTestLimitDashJ ${CMAKE_CTEST_COMMAND} -j 4 + --output-on-failure -C "\${CTestTest_CONFIG}") + add_test(CTestTestPrintLabels ${CMAKE_CTEST_COMMAND} --print-labels) set_tests_properties(CTestTestPrintLabels PROPERTIES LABELS "Label1;Label2") set_tests_properties(CTestTestPrintLabels PROPERTIES PASS_REGULAR_EXPRESSION diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index 1b4ebc425..be7ddbc21 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -32,6 +32,7 @@ add_CMakeOnly_test(SelectLibraryConfigurations) add_CMakeOnly_test(TargetScope) add_CMakeOnly_test(find_library) +add_CMakeOnly_test(find_path) add_test(CMakeOnly.ProjectInclude ${CMAKE_CMAKE_COMMAND} -DTEST=ProjectInclude diff --git a/Tests/CMakeOnly/find_path/CMakeLists.txt b/Tests/CMakeOnly/find_path/CMakeLists.txt new file mode 100644 index 000000000..0e64ed467 --- /dev/null +++ b/Tests/CMakeOnly/find_path/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.8) +project(FindPathTest NONE) + +set(CMAKE_FIND_DEBUG_MODE 1) + +macro(test_find_path expected) + unset(HDR CACHE) + find_path(HDR ${ARGN} + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + ) + if(HDR) + # Convert to relative path for comparison to expected location. + file(RELATIVE_PATH REL_HDR "${CMAKE_CURRENT_SOURCE_DIR}" "${HDR}") + + # Check and report failure. + if(NOT "${REL_HDR}" STREQUAL "${expected}") + message(SEND_ERROR "Header ${expected} found as [${REL_HDR}]") + elseif(CMAKE_FIND_DEBUG_MODE) + message(STATUS "Header ${expected} found as [${REL_HDR}]") + endif() + else() + message(SEND_ERROR "Header ${expected} NOT FOUND") + endif() +endmacro() + +set(CMAKE_SYSTEM_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +set(CMAKE_LIBRARY_ARCHITECTURE arch) + +test_find_path(include NAMES test1.h) +test_find_path(include/arch NAMES test1arch.h) diff --git a/Tests/CMakeOnly/find_path/include/arch/test1arch.h b/Tests/CMakeOnly/find_path/include/arch/test1arch.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_path/include/test1.h b/Tests/CMakeOnly/find_path/include/test1.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake b/Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake new file mode 100644 index 000000000..cc15c77a8 --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake @@ -0,0 +1 @@ +file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") diff --git a/Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake b/Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake new file mode 100644 index 000000000..62390e792 --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake @@ -0,0 +1,2 @@ +file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/DoesNotExist.cmake" output) +message("~${output}~") diff --git a/Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake b/Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake new file mode 100644 index 000000000..d0e5fe35f --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake @@ -0,0 +1,24 @@ +set(STAMP_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/FileTimestamp-Stamp") +set(STAMP_FORMAT "%Y-%m-%d") + +string(TIMESTAMP timestamp1 "${STAMP_FORMAT}") + +file(WRITE "${STAMP_FILENAME}" "foo") +file(TIMESTAMP "${STAMP_FILENAME}" timestamp2 "${STAMP_FORMAT}") + +string(TIMESTAMP timestamp3 "${STAMP_FORMAT}") + +message(STATUS "timestamp1 [${timestamp1}]") +message(STATUS "timestamp2 [${timestamp2}]") +message(STATUS "timestamp3 [${timestamp3}]") + +if(timestamp1 STREQUAL timestamp3) + if(NOT timestamp1 STREQUAL timestamp2) + message(FATAL_ERROR + "timestamp mismatch [${timestamp1}] != [${timestamp2}]") + else() + message("all timestamps match") + endif() +else() + message(WARNING "this test may race when run at midnight") +endif() diff --git a/Tests/CMakeTests/File-TIMESTAMP-Works.cmake b/Tests/CMakeTests/File-TIMESTAMP-Works.cmake new file mode 100644 index 000000000..4351b19dd --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-Works.cmake @@ -0,0 +1,2 @@ +file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt" output UTC) +message("~${output}~") diff --git a/Tests/CMakeTests/FileTest.cmake.in b/Tests/CMakeTests/FileTest.cmake.in index 960d3c172..61523e6f6 100644 --- a/Tests/CMakeTests/FileTest.cmake.in +++ b/Tests/CMakeTests/FileTest.cmake.in @@ -36,6 +36,14 @@ set(SHA384-Works-RESULT 0) set(SHA384-Works-STDERR "1de9560b4e030e02051ea408200ffc55d70c97ac64ebf822461a5c786f495c36df43259b14483bc8d364f0106f4971ee") set(SHA512-Works-RESULT 0) set(SHA512-Works-STDERR "3982a1b4e651768bec70ab1fb97045cb7a659f4ba7203d501c52ab2e803071f9d5fd272022df15f27727fc67f8cd022e710e29010b2a9c0b467c111e2f6abf51") +set(TIMESTAMP-NoFile-RESULT 0) +set(TIMESTAMP-NoFile-STDERR "~~") +set(TIMESTAMP-BadArg1-RESULT 1) +set(TIMESTAMP-BadArg1-STDERR "file sub-command TIMESTAMP requires at least two arguments") +set(TIMESTAMP-NotBogus-RESULT 0) +set(TIMESTAMP-NotBogus-STDERR "all timestamps match") +set(TIMESTAMP-Works-RESULT 0) +set(TIMESTAMP-Works-STDERR "~[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z~") include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") check_cmake_test(File @@ -58,6 +66,10 @@ check_cmake_test(File SHA256-Works SHA384-Works SHA512-Works + TIMESTAMP-NoFile + TIMESTAMP-BadArg1 + TIMESTAMP-NotBogus + TIMESTAMP-Works ) file(GLOB hum) diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index dbe95005e..31488c0ff 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -102,30 +102,132 @@ list(APPEND platforms linux64_test1) #----------------------------------------------------------------------------- # Mac +# gcc -arch i686 dummy.c -v -Wl,-v +set(mac_i686_gcc_Wlv_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (i686 Darwin) +/usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccSiuUhD.o -v -lSystem -lgcc -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_i686_gcc_Wlv_libs "") +set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_i686_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") +list(APPEND platforms mac_i686_gcc_Wlv) + # gcc -arch i686 dummy.c -v set(mac_i686_gcc_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem") set(mac_i686_gcc_libs "") set(mac_i686_gcc_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_gcc) +# g++ -arch i686 dummy.cxx -v -Wl,-v +set(mac_i686_g++_Wlv_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (i686 Darwin) +/usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccWrBoVl.o -v -lstdc++ -lSystem -lgcc -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_i686_g++_Wlv_libs "stdc++") +set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_i686_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") +list(APPEND platforms mac_i686_g++_Wlv) + # g++ -arch i686 dummy.cxx -v set(mac_i686_g++_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem") set(mac_i686_g++_libs "stdc++") set(mac_i686_g++_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_g++) +# gfortran dummy.f -v -Wl,-v +set(mac_i686_gfortran_Wlv_text " /usr/local/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//cc9zXNax.o -v -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem +collect2 version 4.4.1 20090623 (prerelease) (i686 Darwin) +/usr/bin/ld -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//cc9zXNax.o -v -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 + /usr/local/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran") +set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib") +set(mac_i686_gfortran_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") +list(APPEND platforms mac_i686_gfortran_Wlv) + # gfortran dummy.f -v set(mac_i686_gfortran_text " /usr/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/lib/gcc -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//ccgqbX5P.o -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem") set(mac_i686_gfortran_libs "gfortranbegin;gfortran") set(mac_i686_gfortran_dirs "/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/lib/gcc;/usr/lib") list(APPEND platforms mac_i686_gfortran) +# gcc -arch ppc dummy.c -v -Wl,-v +set(mac_ppc_gcc_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//cclziQY4.o -v -lgcc -lSystemStubs -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (Darwin/PowerPC) +/usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/ld -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//cclziQY4.o -v -lgcc -lSystemStubs -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_ppc_gcc_Wlv_libs "") +set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_ppc_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") +list(APPEND platforms mac_ppc_gcc_Wlv) + # gcc -arch ppc dummy.c -v set(mac_ppc_gcc_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccdcolsP.o -lgcc -lSystemStubs -lSystem") set(mac_ppc_gcc_libs "") set(mac_ppc_gcc_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_ppc_gcc) +# g++ -arch ppc dummy.cxx -v -Wl,-v +set(mac_ppc_g++_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccaFTkwq.o -v -lstdc++ -lgcc -lSystemStubs -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (Darwin/PowerPC) +/usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/ld -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccaFTkwq.o -v -lstdc++ -lgcc -lSystemStubs -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_ppc_g++_Wlv_libs "stdc++") +set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_ppc_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") +list(APPEND platforms mac_ppc_g++_Wlv) + # g++ -arch ppc dummy.cxx -v set(mac_ppc_g++_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccbjB6Lj.o -lstdc++ -lgcc -lSystemStubs -lSystem") set(mac_ppc_g++_libs "stdc++") @@ -402,10 +504,10 @@ list(APPEND platforms msys_g77) # Test parsing for all above examples. foreach(p IN LISTS platforms) - cmake_parse_implicit_link_info("${${p}_text}" libs dirs log "${${p}_obj_regex}") + cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}") - foreach(v libs dirs) - if(NOT "${${v}}" STREQUAL "${${p}_${v}}") + foreach(v libs dirs fwks) + if(DEFINED "${p}_${v}" AND NOT "${${v}}" STREQUAL "${${p}_${v}}") message(FATAL_ERROR "cmake_parse_implicit_link_info failed\n" "Expected '${p}' implicit ${v}\n" diff --git a/Tests/CMakeTests/String-TIMESTAMP-AllSpecifiers.cmake b/Tests/CMakeTests/String-TIMESTAMP-AllSpecifiers.cmake new file mode 100644 index 000000000..2d0fcc89c --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-AllSpecifiers.cmake @@ -0,0 +1,11 @@ +string(TIMESTAMP output "%d;%H;%I;%j;%m;%M;%S;%U;%w;%y;%Y") +message("~${output}~") + +list(LENGTH output output_length) + +set(expected_output_length 11) + +if(NOT output_length EQUAL ${expected_output_length}) + message(FATAL_ERROR "expected ${expected_output_length} entries in output " + "with all specifiers; found ${output_length}") +endif() diff --git a/Tests/CMakeTests/String-TIMESTAMP-BadArg1.cmake b/Tests/CMakeTests/String-TIMESTAMP-BadArg1.cmake new file mode 100644 index 000000000..8f2d9f8b4 --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-BadArg1.cmake @@ -0,0 +1 @@ +string(TIMESTAMP) diff --git a/Tests/CMakeTests/String-TIMESTAMP-BadArg2.cmake b/Tests/CMakeTests/String-TIMESTAMP-BadArg2.cmake new file mode 100644 index 000000000..c1e512684 --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-BadArg2.cmake @@ -0,0 +1 @@ +string(TIMESTAMP output_variable "%Y" UTF) diff --git a/Tests/CMakeTests/String-TIMESTAMP-BadArg3.cmake b/Tests/CMakeTests/String-TIMESTAMP-BadArg3.cmake new file mode 100644 index 000000000..3d577df3f --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-BadArg3.cmake @@ -0,0 +1 @@ +string(TIMESTAMP output_variable "%Y" UTC UTC) diff --git a/Tests/CMakeTests/String-TIMESTAMP-CustomFormatLocal.cmake b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatLocal.cmake new file mode 100644 index 000000000..eab2a45de --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatLocal.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "%S") +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-CustomFormatUTC.cmake b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatUTC.cmake new file mode 100644 index 000000000..eab2a45de --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatUTC.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "%S") +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatLocal.cmake b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatLocal.cmake new file mode 100644 index 000000000..d7c7dde1c --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatLocal.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output) +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatUTC.cmake b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatUTC.cmake new file mode 100644 index 000000000..dad6a8d97 --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatUTC.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output UTC) +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-IncompleteSpecifier.cmake b/Tests/CMakeTests/String-TIMESTAMP-IncompleteSpecifier.cmake new file mode 100644 index 000000000..ffc5656fa --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-IncompleteSpecifier.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "foobar%") +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-UnknownSpecifier.cmake b/Tests/CMakeTests/String-TIMESTAMP-UnknownSpecifier.cmake new file mode 100644 index 000000000..0e145e5ec --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-UnknownSpecifier.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "%g") +message("~${output}~") diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in index 49e7dc90c..a9fe428e3 100644 --- a/Tests/CMakeTests/StringTest.cmake.in +++ b/Tests/CMakeTests/StringTest.cmake.in @@ -16,6 +16,26 @@ set(SHA384-Works-RESULT 0) set(SHA384-Works-STDERR "1de9560b4e030e02051ea408200ffc55d70c97ac64ebf822461a5c786f495c36df43259b14483bc8d364f0106f4971ee") set(SHA512-Works-RESULT 0) set(SHA512-Works-STDERR "3982a1b4e651768bec70ab1fb97045cb7a659f4ba7203d501c52ab2e803071f9d5fd272022df15f27727fc67f8cd022e710e29010b2a9c0b467c111e2f6abf51") +set(TIMESTAMP-BadArg1-RESULT 1) +set(TIMESTAMP-BadArg1-STDERR "string sub-command TIMESTAMP requires at least one argument") +set(TIMESTAMP-BadArg2-RESULT 1) +set(TIMESTAMP-BadArg2-STDERR "string TIMESTAMP sub-command does not recognize option UTF") +set(TIMESTAMP-BadArg3-RESULT 1) +set(TIMESTAMP-BadArg3-STDERR "string sub-command TIMESTAMP takes at most three arguments") +set(TIMESTAMP-DefaultFormatLocal-RESULT 0) +set(TIMESTAMP-DefaultFormatLocal-STDERR "~[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]~") +set(TIMESTAMP-DefaultFormatUTC-RESULT 0) +set(TIMESTAMP-DefaultFormatUTC-STDERR "~[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z~") +set(TIMESTAMP-CustomFormatLocal-RESULT 0) +set(TIMESTAMP-CustomFormatLocal-STDERR "~([0-5][0-9])|60~") +set(TIMESTAMP-CustomFormatUTC-RESULT 0) +set(TIMESTAMP-CustomFormatUTC-STDERR "~([0-5][0-9])|60~") +set(TIMESTAMP-UnknownSpecifier-RESULT 0) +set(TIMESTAMP-UnknownSpecifier-STDERR "~%g~") +set(TIMESTAMP-IncompleteSpecifier-RESULT 0) +set(TIMESTAMP-IncompleteSpecifier-STDERR "~foobar%~") +set(TIMESTAMP-AllSpecifiers-RESULT 0) +set(TIMESTAMP-AllSpecifiers-STDERR "~[0-9]+(;[0-9]+)*~") include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") check_cmake_test(String @@ -28,6 +48,16 @@ check_cmake_test(String SHA256-Works SHA384-Works SHA512-Works + TIMESTAMP-BadArg1 + TIMESTAMP-BadArg2 + TIMESTAMP-BadArg3 + TIMESTAMP-DefaultFormatLocal + TIMESTAMP-DefaultFormatUTC + TIMESTAMP-CustomFormatLocal + TIMESTAMP-CustomFormatUTC + TIMESTAMP-UnknownSpecifier + TIMESTAMP-IncompleteSpecifier + TIMESTAMP-AllSpecifiers ) # Execute each test listed in StringTestScript.cmake: diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake index 9a022c580..0b6d07d97 100644 --- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake @@ -9,11 +9,10 @@ endif() if(NOT CPackGen) message(FATAL_ERROR "CPackGen not set") endif() -get_filename_component(CPACK_LOCATION ${CMAKE_COMMAND} PATH) -set(CPackCommand "${CPACK_LOCATION}/cpack") -message("cpack = ${CPackCommand}") -if(NOT CPackCommand) - message(FATAL_ERROR "CPackCommand not set") + +message("CMAKE_CPACK_COMMAND = ${CMAKE_CPACK_COMMAND}") +if(NOT CMAKE_CPACK_COMMAND) + message(FATAL_ERROR "CMAKE_CPACK_COMMAND not set") endif() if(NOT CPackComponentWay) @@ -92,7 +91,7 @@ endif() message("config_args = ${config_args}") message("config_verbose = ${config_verbose}") -execute_process(COMMAND ${CPackCommand} ${config_verbose} -G ${CPackGen} ${config_args} +execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${config_verbose} -G ${CPackGen} ${config_args} RESULT_VARIABLE CPack_result OUTPUT_VARIABLE CPack_output ERROR_VARIABLE CPack_error diff --git a/Tests/CPackTestAllGenerators/RunCPack.cmake b/Tests/CPackTestAllGenerators/RunCPack.cmake index e0c241ec4..952d5f4ae 100644 --- a/Tests/CPackTestAllGenerators/RunCPack.cmake +++ b/Tests/CPackTestAllGenerators/RunCPack.cmake @@ -1,14 +1,10 @@ -if(NOT DEFINED cpack) - message(FATAL_ERROR "cpack not defined") -endif() - if(NOT DEFINED dir) message(FATAL_ERROR "dir not defined") endif() # Analyze 'cpack --help' output for list of available generators: # -execute_process(COMMAND ${cpack} --help +execute_process(COMMAND ${CMAKE_CPACK_COMMAND} --help RESULT_VARIABLE result OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr @@ -43,7 +39,7 @@ message(STATUS "CPack generators='${generators}'") foreach(g ${generators}) message(STATUS "Calling cpack -G ${g}...") - execute_process(COMMAND ${cpack} -G ${g} + execute_process(COMMAND ${CMAKE_CPACK_COMMAND} -G ${g} RESULT_VARIABLE result OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr diff --git a/Tests/CPackWiXGenerator/CMakeLists.txt b/Tests/CPackWiXGenerator/CMakeLists.txt new file mode 100644 index 000000000..ce02f110d --- /dev/null +++ b/Tests/CPackWiXGenerator/CMakeLists.txt @@ -0,0 +1,73 @@ +cmake_minimum_required(VERSION 2.8) + +project(CPackWiXGenerator) + +add_library(mylib mylib.cpp) + +add_executable(mylibapp mylibapp.cpp) +target_link_libraries(mylibapp mylib) + +install(TARGETS mylib + ARCHIVE + DESTINATION lib + COMPONENT libraries) + +install(TARGETS mylibapp + RUNTIME + DESTINATION bin + COMPONENT applications) + +install(FILES mylib.h "file with spaces.h" + DESTINATION include + COMPONENT headers) + +set(CPACK_GENERATOR "WIX") + +set(CPACK_PACKAGE_NAME "MyLib") +set(CPACK_PACKAGE_VENDOR "CMake.org") +set(CPACK_PACKAGE_CONTACT "somebody@cmake.org") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY + "MyLib - CPack Component Installation Example") + +set(CPACK_PACKAGE_VERSION_MAJOR "1") +set(CPACK_PACKAGE_VERSION_MINOR "0") +set(CPACK_PACKAGE_VERSION_PATCH "0") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example") + +set(CPACK_WIX_UPGRADE_GUID "BF20CE5E-7F7C-401D-8F7C-AB45E8D170E6") + +include(CPack) + +cpack_add_install_type(Full DISPLAY_NAME "Everything") +cpack_add_install_type(Developer) + +cpack_add_component_group(Runtime) + +cpack_add_component_group(Development + EXPANDED + DESCRIPTION "All of the tools you'll ever need to develop software") + +cpack_add_component(applications + DISPLAY_NAME "MyLib Application" + DESCRIPTION "An extremely useful application that makes use of MyLib" + GROUP Runtime + INSTALL_TYPES Full) + +cpack_add_component(documentation + DISPLAY_NAME "MyLib Documentation" + DESCRIPTION "The extensive suite of MyLib Application documentation files" + GROUP Runtime + INSTALL_TYPES Full) + +cpack_add_component(libraries + DISPLAY_NAME "Libraries" + DESCRIPTION "Static libraries used to build programs with MyLib" + GROUP Development + INSTALL_TYPES Developer Full) + +cpack_add_component(headers + DISPLAY_NAME "C++ Headers" + DESCRIPTION "C/C++ header files for use with MyLib" + GROUP Development + DEPENDS libraries + INSTALL_TYPES Developer Full) diff --git a/Tests/CPackWiXGenerator/RunCPackVerifyResult.cmake b/Tests/CPackWiXGenerator/RunCPackVerifyResult.cmake new file mode 100644 index 000000000..30e33cf22 --- /dev/null +++ b/Tests/CPackWiXGenerator/RunCPackVerifyResult.cmake @@ -0,0 +1,72 @@ +message(STATUS "=============================================================") +message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") +message(STATUS "") + +if(NOT CPackWiXGenerator_BINARY_DIR) + message(FATAL_ERROR "CPackWiXGenerator_BINARY_DIR not set") +endif() + +message(STATUS "CMAKE_COMMAND: ${CMAKE_COMMAND}") +message(STATUS "CMAKE_CPACK_COMMAND: ${CMAKE_CPACK_COMMAND}") +message(STATUS "CPackWiXGenerator_BINARY_DIR: ${CPackWiXGenerator_BINARY_DIR}") + +execute_process(COMMAND "${CMAKE_CPACK_COMMAND}" + RESULT_VARIABLE CPack_result + OUTPUT_VARIABLE CPack_output + ERROR_VARIABLE CPack_error + WORKING_DIRECTORY "${CPackWiXGenerator_BINARY_DIR}") + +if(CPack_result) + message(FATAL_ERROR "CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}") +else () + message(STATUS "CPack_output=${CPack_output}") +endif() + +set(expected_file_mask "*.msi") +file(GLOB installer_file "${expected_file_mask}") + +message(STATUS "installer_file='${installer_file}'") +message(STATUS "expected_file_mask='${expected_file_mask}'") + +if(NOT installer_file) + message(FATAL_ERROR "installer_file does not exist.") +endif() + +function(run_wix_command command) + file(TO_CMAKE_PATH "$ENV{WIX}" WIX_ROOT) + set(WIX_PROGRAM "${WIX_ROOT}/bin/${command}.exe") + + if(NOT EXISTS "${WIX_PROGRAM}") + message(FATAL_ERROR "Failed to find WiX Tool: ${WIX_PROGRAM}") + endif() + + message(STATUS "Running WiX Tool: ${command} ${ARGN}") + + execute_process(COMMAND "${WIX_PROGRAM}" ${ARGN} + RESULT_VARIABLE WIX_result + OUTPUT_VARIABLE WIX_output + ERROR_VARIABLE WIX_output + WORKING_DIRECTORY "${CPackWiXGenerator_BINARY_DIR}") + + message(STATUS "${command} Output: \n${WIX_output}") + + if(WIX_result) + message(FATAL_ERROR "WiX ${command} failed: ${WIX_result}") + endif() +endfunction() + +file(GLOB WXS_SOURCE_FILES + "${CPackWiXGenerator_BINARY_DIR}/_CPack_Packages/*/WIX/*.wxs") + +if(NOT WXS_SOURCE_FILES) + message(FATAL_ERROR "Failed finding WiX source files to validate.") +endif() + +foreach(WXS_SOURCE_FILE IN LISTS WXS_SOURCE_FILES) + run_wix_command(wixcop "${WXS_SOURCE_FILE}") +endforeach() + +# error SMOK1076 : ICE61: This product should remove only older +# versions of itself. The Maximum version is not less +# than the current product. (1.0.0 1.0.0) +run_wix_command(smoke -nologo -wx -sw1076 "${installer_file}") diff --git a/Tests/CPackWiXGenerator/file with spaces.h b/Tests/CPackWiXGenerator/file with spaces.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CPackWiXGenerator/mylib.cpp b/Tests/CPackWiXGenerator/mylib.cpp new file mode 100644 index 000000000..8ddac198c --- /dev/null +++ b/Tests/CPackWiXGenerator/mylib.cpp @@ -0,0 +1,7 @@ +#include "mylib.h" +#include "stdio.h" + +void mylib_function() +{ + printf("This is mylib"); +} diff --git a/Tests/CPackWiXGenerator/mylib.h b/Tests/CPackWiXGenerator/mylib.h new file mode 100644 index 000000000..5d0a822db --- /dev/null +++ b/Tests/CPackWiXGenerator/mylib.h @@ -0,0 +1 @@ +void mylib_function(); diff --git a/Tests/CPackWiXGenerator/mylibapp.cpp b/Tests/CPackWiXGenerator/mylibapp.cpp new file mode 100644 index 000000000..a438ac77f --- /dev/null +++ b/Tests/CPackWiXGenerator/mylibapp.cpp @@ -0,0 +1,6 @@ +#include "mylib.h" + +int main() +{ + mylib_function(); +} diff --git a/Tests/CTestLimitDashJ/CMakeLists.txt b/Tests/CTestLimitDashJ/CMakeLists.txt new file mode 100644 index 000000000..0c5950c9d --- /dev/null +++ b/Tests/CTestLimitDashJ/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 2.8) +project(CTestLimitDashJ NONE) + +# This file demonstrates http://public.kitware.com/Bug/view.php?id=12904 +# when configured with CMake 2.8.10.2 and earlier, and when running +# "ctest -j 4" in the resulting build tree. This example is hard-coded +# to assume -j 4 just to reproduce the issue easily. Adjust the +# FAIL_REGULAR_EXPRESSION and PROCESSORS values to reproduce this problem +# with a different ctest -j value... + +if(EXISTS "${CMAKE_BINARY_DIR}/Testing/Temporary/CTestCostData.txt") + message(STATUS "Removing CTestCostData.txt to force ordering by COST PROPERTY value rather than prior run data") + file(REMOVE "${CMAKE_BINARY_DIR}/Testing/Temporary/CTestCostData.txt") +endif() + +include(CTest) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/CreateSleepDelete.cmake + ${CMAKE_CURRENT_BINARY_DIR}/CreateSleepDelete.cmake + @ONLY + ) + +foreach(n RANGE 1 100) + add_test(NAME t${n} + COMMAND ${CMAKE_CTEST_COMMAND} + -D basefilename=f${n} + -S ${CMAKE_CURRENT_BINARY_DIR}/CreateSleepDelete.cmake + ) + set_property(TEST t${n} PROPERTY FAIL_REGULAR_EXPRESSION "(c='[5-9]'|c='[1-9][0-9]+')") +endforeach() + +set_property(TEST t1 PROPERTY RUN_SERIAL 1) +set_property(TEST t1 PROPERTY PROCESSORS 4) + +set_property(TEST t51 PROPERTY RUN_SERIAL 1) +set_property(TEST t51 PROPERTY PROCESSORS 4) + +foreach(n RANGE 2 50) + set_property(TEST t${n} PROPERTY DEPENDS t1) +endforeach() +set_property(TEST t1 PROPERTY DEPENDS t51) +set_property(TEST t51 PROPERTY DEPENDS t100) + +foreach(n 50) + set_property(TEST t${n} PROPERTY COST 6) +endforeach() +foreach(n RANGE 52 99) + set_property(TEST t${n} PROPERTY COST 3) +endforeach() diff --git a/Tests/CTestLimitDashJ/CreateSleepDelete.cmake b/Tests/CTestLimitDashJ/CreateSleepDelete.cmake new file mode 100644 index 000000000..b09307feb --- /dev/null +++ b/Tests/CTestLimitDashJ/CreateSleepDelete.cmake @@ -0,0 +1,48 @@ +set(CTEST_RUN_CURRENT_SCRIPT 0) + +if(NOT DEFINED basefilename) + message(FATAL_ERROR "pass -Dbasefilename=f1") +endif() + +if(NOT DEFINED ext) + set(ext "jkqvxz") +endif() + +if(NOT DEFINED sleep_interval) + set(sleep_interval 1) +endif() + +get_filename_component(self_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) +set(filename "${self_dir}/${basefilename}.${ext}") + +# count files +file(GLOB f1 *.${ext}) +list(LENGTH f1 c1) +message("c='${c1}'") + +# write a new file +message("Writing file: filename='${filename}'") +file(WRITE "${filename}" "${filename}") + +# count files again +file(GLOB f2 *.${ext}) +list(LENGTH f2 c2) +message("c='${c2}'") + +# snooze +message("Sleeping: sleep_interval='${sleep_interval}'") +ctest_sleep(${sleep_interval}) + +# count files again +file(GLOB f3 *.${ext}) +list(LENGTH f3 c3) +message("c='${c3}'") + +# delete the file we wrote earlier +message("Removing file: filename='${filename}'") +file(REMOVE "${filename}") + +# count files again +file(GLOB f4 *.${ext}) +list(LENGTH f4 c4) +message("c='${c4}'") diff --git a/Tests/EmptyDepends/CMakeLists.txt b/Tests/EmptyDepends/CMakeLists.txt new file mode 100644 index 000000000..832d9dce6 --- /dev/null +++ b/Tests/EmptyDepends/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) +project(EmptyDepends) + +include(CTest) + +set(extra_dep) + +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/qrc_my.cxx + COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/qrc_my.cxx" + DEPENDS "${extra_dep}" "${CMAKE_BINARY_DIR}/my.qrc") + +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/my.qrc + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/my.qrc) + +add_library(qrc STATIC ${CMAKE_BINARY_DIR}/qrc_my.cxx) diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index e19ab88de..569845a71 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -90,9 +90,82 @@ set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3) # Test exporting dependent libraries into different exports add_library(testLibRequired testLibRequired.c) add_library(testLibDepends testLibDepends.c) +set_property(TARGET testLibDepends APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) +set_property(TARGET testLibDepends APPEND PROPERTY + COMPILE_DEFINITIONS + $ +) +set_property(TARGET testLibDepends APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + $ +) +set_property(TARGET testLibDepends APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS + $ +) target_link_libraries(testLibDepends testLibRequired) -install(TARGETS testLibRequired EXPORT RequiredExp DESTINATION lib ) +macro(add_include_lib _libName) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "// no content\n") + add_library(${_libName} "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c") + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_libName}") + set_property(TARGET ${_libName} APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/${_libName}") + if (NOT "${ARGV1}" STREQUAL "NO_HEADER") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}/${_libName}.h" "// no content\n") + endif() +endmacro() + +add_include_lib(testLibIncludeRequired1) +add_include_lib(testLibIncludeRequired2) +add_include_lib(testLibIncludeRequired3 NO_HEADER) +# Generate testLibIncludeRequired4 in the testLibIncludeRequired3 directory +# with an error. If the includes from testLibIncludeRequired3 appear first, +# the error will be hit. +# Below, the '3' library appears before the '4' library +# but we are testing that the INSTALL_INTERFACE causes it not to be used +# at build time. +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired3/testLibIncludeRequired4.h" "#error Should not be included\n") +add_include_lib(testLibIncludeRequired4) +add_include_lib(testLibIncludeRequired5 NO_HEADER) +# Generate testLibIncludeRequired6 in the testLibIncludeRequired5 directory +# with an error. If the includes from testLibIncludeRequired5 appear first, +# the error will be hit. +# Below, the '5' library appears before the '6' library +# but we are testing that when the installed IMPORTED target is used, from +# the Import side of this unit test, the '6' include from the '5' directory +# will not be used because it is in the BUILD_INTERFACE only. +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired5/testLibIncludeRequired6.h" "#error Should not be included\n") +add_include_lib(testLibIncludeRequired6) + +set_property(TARGET testLibRequired APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + $ + $>,INTERFACE_INCLUDE_DIRECTORIES> + $> + $> + $> + $> +) + +set_property(TARGET testLibRequired APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS + testLibRequired_IFACE_DEFINE + $ + $ +) + +install(TARGETS testLibRequired + testLibIncludeRequired1 + testLibIncludeRequired2 + testLibIncludeRequired3 + testLibIncludeRequired4 + testLibIncludeRequired5 + testLibIncludeRequired6 + EXPORT RequiredExp DESTINATION lib ) install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired) install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib ) diff --git a/Tests/ExportImport/Export/testLibDepends.c b/Tests/ExportImport/Export/testLibDepends.c index 2849b336d..fb5a002e0 100644 --- a/Tests/ExportImport/Export/testLibDepends.c +++ b/Tests/ExportImport/Export/testLibDepends.c @@ -1,4 +1,20 @@ +#include "testLibIncludeRequired1.h" +#include "testLibIncludeRequired2.h" +#include "testLibIncludeRequired4.h" + +#ifndef testLibRequired_IFACE_DEFINE +#error Expected testLibRequired_IFACE_DEFINE +#endif + +#ifndef BuildOnly_DEFINE +#error Expected BuildOnly_DEFINE +#endif + +#ifdef InstallOnly_DEFINE +#error Unexpected InstallOnly_DEFINE +#endif + extern int testLibRequired(void); int testLibDepends(void) { return testLibRequired(); } diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 884179225..b77562ee6 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -152,3 +152,18 @@ check_function_exists(testLib1 HAVE_TESTLIB1_FUNCTION) if (NOT HAVE_TESTLIB1_FUNCTION) message(SEND_ERROR "Using imported target testLib2 in check_function_exists() failed !") endif() + +#----------------------------------------------------------------------------- +# Test that dependent imported targets have usable +# INTERFACE_COMPILE_DEFINITIONS and INTERFACE_INCLUDE_DIRECTORIES + +add_library(deps_iface deps_iface.cpp) +target_link_libraries(deps_iface testLibsDepends) +set_property(TARGET deps_iface APPEND PROPERTY + COMPILE_DEFINITIONS + $ +) +set_property(TARGET deps_iface APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) diff --git a/Tests/ExportImport/Import/A/deps_iface.cpp b/Tests/ExportImport/Import/A/deps_iface.cpp new file mode 100644 index 000000000..7190b9242 --- /dev/null +++ b/Tests/ExportImport/Import/A/deps_iface.cpp @@ -0,0 +1,24 @@ + +#include "testLibIncludeRequired1.h" +#include "testLibIncludeRequired2.h" +#include "testLibIncludeRequired6.h" + +#ifndef testLibRequired_IFACE_DEFINE +#error Expected testLibRequired_IFACE_DEFINE +#endif + +#ifdef BuildOnly_DEFINE +#error Unexpected BuildOnly_DEFINE +#endif + +#ifndef InstallOnly_DEFINE +#error Expected InstallOnly_DEFINE +#endif + +extern int testLibDepends(void); + + +int main(int,char **) +{ + return testLibDepends(); +} diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index 3a92d81b1..ecbbedf44 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.8.8) project(GeneratorExpression NONE) -add_custom_target(check ALL +add_custom_target(check-part1 ALL COMMAND ${CMAKE_COMMAND} -Dtest_0=$<0:nothing> -Dtest_0_with_comma=$<0:-Wl,--no-undefined> @@ -57,6 +57,13 @@ add_custom_target(check ALL -Dtest_colons_3=$<1:Qt5::Core> -Dtest_colons_4=$<1:C:\\CMake> -Dtest_colons_5=$<1:C:/CMake> + -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part1.cmake + COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 2)" + VERBATIM + ) + +add_custom_target(check-part2 ALL + COMMAND ${CMAKE_COMMAND} -Dtest_incomplete_1=$< -Dtest_incomplete_2=$ -Dtest_incomplete_20=$ -Dtest_incomplete_21=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake - COMMAND ${CMAKE_COMMAND} -E echo "check done" + -Dtest_build_interface=$ + -Dtest_install_interface=$ + -Dtest_target_name_1=$ + -Dtest_target_name_2=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake + COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)" VERBATIM ) diff --git a/Tests/GeneratorExpression/check-common.cmake b/Tests/GeneratorExpression/check-common.cmake new file mode 100644 index 000000000..8ffebd740 --- /dev/null +++ b/Tests/GeneratorExpression/check-common.cmake @@ -0,0 +1,5 @@ +macro(check var val) + if(NOT "${${var}}" STREQUAL "${val}") + message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"") + endif() +endmacro() diff --git a/Tests/GeneratorExpression/check.cmake b/Tests/GeneratorExpression/check-part1.cmake similarity index 60% rename from Tests/GeneratorExpression/check.cmake rename to Tests/GeneratorExpression/check-part1.cmake index af436de9e..7abfa823f 100644 --- a/Tests/GeneratorExpression/check.cmake +++ b/Tests/GeneratorExpression/check-part1.cmake @@ -1,8 +1,5 @@ -macro(check var val) - if(NOT "${${var}}" STREQUAL "${val}") - message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"") - endif() -endmacro() + +include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake) message(STATUS "config=[${config}]") check(test_0 "") @@ -57,24 +54,3 @@ check(test_colons_2 "::") check(test_colons_3 "Qt5::Core") check(test_colons_4 "C:\\\\CMake") check(test_colons_5 "C:/CMake") -check(test_incomplete_1 "$<") -check(test_incomplete_2 "$") -check(test_incomplete_6 "") -check(test_incomplete_7 "$") -check(test_incomplete_15 "$") -check(test_incomplete_20 "$") -check(test_incomplete_21 "$") diff --git a/Tests/GeneratorExpression/check-part2.cmake b/Tests/GeneratorExpression/check-part2.cmake new file mode 100644 index 000000000..8855a977c --- /dev/null +++ b/Tests/GeneratorExpression/check-part2.cmake @@ -0,0 +1,28 @@ + +include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake) + +check(test_incomplete_1 "$<") +check(test_incomplete_2 "$") +check(test_incomplete_6 "") +check(test_incomplete_7 "$") +check(test_incomplete_15 "$") +check(test_incomplete_20 "$") +check(test_incomplete_21 "$") +check(test_build_interface "build") +check(test_install_interface "") +check(test_target_name_1 "tgt,ok") +check(test_target_name_2 "tgt:ok") diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt index 7cb1b42e0..21159e044 100644 --- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt @@ -37,6 +37,37 @@ include_directories("sing$<1:/ting>") include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/arguments;${CMAKE_CURRENT_BINARY_DIR}/list>") +create_header(fee) +create_header(fiy) +create_header(foh) +create_header(fum) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp" "#include \"fee.h\"\n") +add_library(lib1 "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp") +set_property(TARGET lib1 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fee") +set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy") +set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<$,EXECUTABLE>:${CMAKE_CURRENT_BINARY_DIR}/foh>") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp" "#include \"fiy.h\"\n") +add_library(lib2 "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp") +set_property(TARGET lib2 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fum;$") +set_property(TARGET lib2 APPEND PROPERTY INCLUDE_DIRECTORIES "$") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n#include \"fum.h\"\nint main(int,char**) { return 0; }\n") +add_executable(exe3 "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp") +set_property(TARGET exe3 APPEND PROPERTY INCLUDE_DIRECTORIES "$") + +# Test cycles +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n") +add_library(lib3 "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp") +set_property(TARGET lib3 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy;$") +set_property(TARGET lib3 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy;$") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n") +add_library(lib4 "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp") +set_property(TARGET lib4 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foh;$") +set_property(TARGET lib4 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foh;$") + add_library(somelib::withcolons UNKNOWN IMPORTED) set_property(TARGET somelib::withcolons PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/target") set_property(TARGET somelib::withcolons PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/target") @@ -45,3 +76,9 @@ set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "$" ) + +add_custom_target(test_custom_target + "some_bogus_custom_tool" + $ + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/Tests/Qt4Targets/CMakeLists.txt b/Tests/Qt4Targets/CMakeLists.txt new file mode 100644 index 000000000..9bd7a6478 --- /dev/null +++ b/Tests/Qt4Targets/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8) + +project(Qt4Targets) + +find_package(Qt4 REQUIRED) + +add_executable(Qt4Targets WIN32 main.cpp) +target_link_libraries(Qt4Targets Qt4::QtGui) + +if (WIN32) + target_link_libraries(Qt4Targets Qt4::qtmain) +endif() + +set_property(TARGET Qt4Targets APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) +set_property(TARGET Qt4Targets APPEND PROPERTY + COMPILE_DEFINITIONS + $ +) diff --git a/Tests/Qt4Targets/main.cpp b/Tests/Qt4Targets/main.cpp new file mode 100644 index 000000000..3c98c99f6 --- /dev/null +++ b/Tests/Qt4Targets/main.cpp @@ -0,0 +1,24 @@ + +#include +#include + +#include + +#ifndef QT_CORE_LIB +#error Expected QT_CORE_LIB +#endif + +#ifndef QT_GUI_LIB +#error Expected QT_GUI_LIB +#endif + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QWidget w; + w.setWindowTitle(QString::fromLatin1("SomeTitle")); + w.show(); + + return 0; +} diff --git a/Tests/RunCMake/CMP0019/CMP0019-NEW.cmake b/Tests/RunCMake/CMP0019/CMP0019-NEW.cmake new file mode 100644 index 000000000..3091e66ac --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0019 NEW) +include(CMP0019-code.cmake) diff --git a/Tests/RunCMake/CMP0019/CMP0019-OLD.cmake b/Tests/RunCMake/CMP0019/CMP0019-OLD.cmake new file mode 100644 index 000000000..0f02f9ce5 --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0019 OLD) +include(CMP0019-code.cmake) diff --git a/Tests/RunCMake/CMP0019/CMP0019-WARN-stderr.txt b/Tests/RunCMake/CMP0019/CMP0019-WARN-stderr.txt new file mode 100644 index 000000000..03faef90e --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-WARN-stderr.txt @@ -0,0 +1,40 @@ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0019 is not set: Do not re-expand variables in include and link + information. Run "cmake --help-policy CMP0019" for policy details. Use + the cmake_policy command to set the policy and suppress this warning. + + The following variable evaluations were encountered: + + Evaluated directory INCLUDE_DIRECTORIES + + /usr/include/\${VAR_INCLUDE};/usr/include/normal + + as + + /usr/include/VAL_INCLUDE;/usr/include/normal + + Evaluated target some_target INCLUDE_DIRECTORIES + + /usr/include/\${VAR_INCLUDE};/usr/include/normal + + as + + /usr/include/VAL_INCLUDE;/usr/include/normal + + Evaluated link directory + + /usr/lib/\${VAR_LINK_DIRS} + + as + + /usr/lib/VAL_LINK_DIRS + + Evaluated link library + + \${VAR_LINK_LIBS} + + as + + VAL_LINK_LIBS + +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/CMP0019/CMP0019-WARN.cmake b/Tests/RunCMake/CMP0019/CMP0019-WARN.cmake new file mode 100644 index 000000000..a419f309e --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-WARN.cmake @@ -0,0 +1 @@ +include(CMP0019-code.cmake) diff --git a/Tests/RunCMake/CMP0019/CMP0019-code.cmake b/Tests/RunCMake/CMP0019/CMP0019-code.cmake new file mode 100644 index 000000000..26c0e5b27 --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-code.cmake @@ -0,0 +1,9 @@ +set(VAR_INCLUDE "VAL_INCLUDE") +set(VAR_LINK_DIRS "VAL_LINK_DIRS") +set(VAR_LINK_LIBS "VAL_LINK_LIBS") +add_custom_target(some_target) +include_directories("/usr/include/\${VAR_INCLUDE}" /usr/include/normal) +link_directories("/usr/lib/\${VAR_LINK_DIRS}" /usr/lib/normal) +link_libraries("\${VAR_LINK_LIBS}" normal) +add_custom_target(other_target) +set_property(TARGET other_target PROPERTY INCLUDE_DIRECTORIES "") diff --git a/Tests/RunCMake/load_command/CMakeLists.txt b/Tests/RunCMake/CMP0019/CMakeLists.txt similarity index 100% rename from Tests/RunCMake/load_command/CMakeLists.txt rename to Tests/RunCMake/CMP0019/CMakeLists.txt diff --git a/Tests/RunCMake/CMP0019/RunCMakeTest.cmake b/Tests/RunCMake/CMP0019/RunCMakeTest.cmake new file mode 100644 index 000000000..119fc2b30 --- /dev/null +++ b/Tests/RunCMake/CMP0019/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0019-WARN) +run_cmake(CMP0019-OLD) +run_cmake(CMP0019-NEW) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 722d9c388..9b133b299 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -45,17 +45,20 @@ macro(add_RunCMake_test test) ) endmacro() +add_RunCMake_test(CMP0019) add_RunCMake_test(GeneratorExpression) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(ObjectLibrary) +if(NOT WIN32) + add_RunCMake_test(PositionIndependentCode) +endif() add_RunCMake_test(build_command) add_RunCMake_test(find_package) add_RunCMake_test(include) add_RunCMake_test(include_directories) add_RunCMake_test(list) -add_RunCMake_test(load_command) if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]") add_RunCMake_test(include_external_msproject) diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetName-result.txt b/Tests/RunCMake/GeneratorExpression/BadTargetName-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetName-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetName-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadTargetName-stderr.txt new file mode 100644 index 000000000..969393acc --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetName-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at BadTargetName.cmake:1 \(add_custom_target\): + Error evaluating generator expression: + + \$> + + \$ expression requires literal input. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetName.cmake b/Tests/RunCMake/GeneratorExpression/BadTargetName.cmake new file mode 100644 index 000000000..e125cab42 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetName.cmake @@ -0,0 +1,3 @@ +add_custom_target(check ALL COMMAND check + $> + VERBATIM) diff --git a/Tests/RunCMake/GeneratorExpression/BadZero-result.txt b/Tests/RunCMake/GeneratorExpression/BadZero-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadZero-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/BadZero-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadZero-stderr.txt new file mode 100644 index 000000000..40db4ae88 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadZero-stderr.txt @@ -0,0 +1,17 @@ +CMake Error at BadZero.cmake:2 \(add_custom_target\): + Error evaluating generator expression: + + \$<0> + + \$<0> expression requires a parameter. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Error at BadZero.cmake:2 \(add_custom_target\): + Error evaluating generator expression: + + \$<0,> + + Expression did not evaluate to a known generator expression +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/BadZero.cmake b/Tests/RunCMake/GeneratorExpression/BadZero.cmake new file mode 100644 index 000000000..559a9fa3d --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadZero.cmake @@ -0,0 +1,5 @@ + +add_custom_target(check ALL COMMAND check + $<0> + $<0,> + VERBATIM) diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index 18a47ae00..8a6967594 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake @@ -5,3 +5,5 @@ run_cmake(BadOR) run_cmake(BadAND) run_cmake(BadNOT) run_cmake(BadStrEqual) +run_cmake(BadZero) +run_cmake(BadTargetName) diff --git a/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt new file mode 100644 index 000000000..22577da4a --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt @@ -0,0 +1,8 @@ + +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} CXX) + +# MSVC creates extra targets which pollute the stderr unless we set this. +set(CMAKE_SUPPRESS_REGENERATION TRUE) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict1-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict1-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict1-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict1-stderr.txt new file mode 100644 index 000000000..cb0710986 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict1-stderr.txt @@ -0,0 +1,3 @@ +CMake Error: Property POSITION_INDEPENDENT_CODE on target "conflict" does +not match the INTERFACE_POSITION_INDEPENDENT_CODE property requirement +of dependency "piciface". diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict1.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict1.cmake new file mode 100644 index 000000000..242bec37a --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict1.cmake @@ -0,0 +1,7 @@ + +add_library(piciface UNKNOWN IMPORTED) +set_property(TARGET piciface PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON) + +add_executable(conflict "main.cpp") +set_property(TARGET conflict PROPERTY POSITION_INDEPENDENT_CODE OFF) +target_link_libraries(conflict piciface) diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict2-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict2-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict2-stderr.txt new file mode 100644 index 000000000..ecd04928d --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict2-stderr.txt @@ -0,0 +1,3 @@ +CMake Error: The INTERFACE_POSITION_INDEPENDENT_CODE property of "picoff" does +not agree with the value of POSITION_INDEPENDENT_CODE already determined +for "conflict". diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict2.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict2.cmake new file mode 100644 index 000000000..215d08dae --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict2.cmake @@ -0,0 +1,9 @@ + +add_library(picon UNKNOWN IMPORTED) +set_property(TARGET picon PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON) + +add_library(picoff UNKNOWN IMPORTED) +set_property(TARGET picoff PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF) + +add_executable(conflict "main.cpp") +target_link_libraries(conflict picon picoff) diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict3-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict3-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict3-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict3-stderr.txt new file mode 100644 index 000000000..0254e5557 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict3-stderr.txt @@ -0,0 +1,4 @@ +Property POSITION_INDEPENDENT_CODE on target "conflict" is +implied to be FALSE because it was used to determine the link libraries +already. The INTERFACE_POSITION_INDEPENDENT_CODE property on +dependency "picon" is in conflict. diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict3.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict3.cmake new file mode 100644 index 000000000..bf669bf4f --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict3.cmake @@ -0,0 +1,12 @@ + +add_library(picoff UNKNOWN IMPORTED) + +add_library(picon UNKNOWN IMPORTED) +set_property(TARGET picon PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON) + +add_executable(conflict "main.cpp") +target_link_libraries(conflict picon) +set_property(TARGET conflict APPEND PROPERTY + LINK_LIBRARIES + $<$>>:picoff> +) diff --git a/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake new file mode 100644 index 000000000..64a340c9c --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(Conflict1) +run_cmake(Conflict2) +run_cmake(Conflict3) diff --git a/Tests/RunCMake/PositionIndependentCode/main.cpp b/Tests/RunCMake/PositionIndependentCode/main.cpp new file mode 100644 index 000000000..31ba48280 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/main.cpp @@ -0,0 +1,5 @@ + +int main(int,char**) +{ + return 0; +} diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt index 3287d19ac..9c146e057 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName1.cmake:7 \(include_directories\): Error evaluating generator expression: \$ Target name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\) diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt index e527e2275..451888cc6 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName2.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Target name and property name not supported.$ + Target name and property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt index 517debbca..39692c4ef 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName3.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Property name not supported.$ + Property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt index eab6fb690..c3aa1b1a9 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName4.cmake:9 \(include_directories\): Error evaluating generator expression: \$ - Property name not supported.$ + Property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt index e2b4fc6fa..1c6fad4b0 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt @@ -1,7 +1,9 @@ -CMake Error: +CMake Error at BadInvalidName5.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty target name and property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt index e94f52fa2..8b147dca6 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName6.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty target name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt index 2548215f4..dad6bf86a 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName7.cmake:9 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt index 2a98f6f06..4e8c14c99 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName8.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt index d2ac7a963..3b3bab07d 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadNonTarget.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Target "NonExistant" not found.$ + Target "NonExistant" not found. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/include_directories/DebugIncludes-result.txt b/Tests/RunCMake/include_directories/DebugIncludes-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt new file mode 100644 index 000000000..948def117 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt @@ -0,0 +1,42 @@ +CMake Warning at DebugIncludes.cmake:8 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/one + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:8 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/two + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:13 \(set_property\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/three + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:18 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/four + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:25 \(set_property\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/five + \* .*/Tests/RunCMake/include_directories/six + +Call Stack \(most recent call first\): + DebugIncludes.cmake:35 \(some_macro\) + DebugIncludes.cmake:38 \(some_function\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/include_directories/DebugIncludes.cmake b/Tests/RunCMake/include_directories/DebugIncludes.cmake new file mode 100644 index 000000000..51daf7480 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes.cmake @@ -0,0 +1,38 @@ + +project(DebugIncludes) + +set(CMAKE_DEBUG_TARGET_PROPERTIES INCLUDE_DIRECTORIES) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp" "enum { dummy };\n") + +include_directories( + "${CMAKE_CURRENT_SOURCE_DIR}/one" + "${CMAKE_CURRENT_SOURCE_DIR}/two" +) + +set_property(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + "${CMAKE_CURRENT_SOURCE_DIR}/three") + +add_library(lll "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp") + +include_directories( + "${CMAKE_CURRENT_SOURCE_DIR}/two" + "${CMAKE_CURRENT_SOURCE_DIR}/three" + "${CMAKE_CURRENT_SOURCE_DIR}/four" +) + +macro(some_macro) + set_property(TARGET lll APPEND PROPERTY + INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/one" + "${CMAKE_CURRENT_SOURCE_DIR}/three" + "${CMAKE_CURRENT_SOURCE_DIR}/four" + "${CMAKE_CURRENT_SOURCE_DIR}/five" + "${CMAKE_CURRENT_SOURCE_DIR}/six" + ) +endmacro() + +function(some_function) + some_macro() +endfunction() + +some_function() diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake index aee3f799b..de3725226 100644 --- a/Tests/RunCMake/include_directories/RunCMakeTest.cmake +++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake @@ -1,3 +1,4 @@ include(RunCMake) run_cmake(NotFoundContent) +run_cmake(DebugIncludes) diff --git a/Tests/RunCMake/load_command/LoadCommandDeprecated-stderr.txt b/Tests/RunCMake/load_command/LoadCommandDeprecated-stderr.txt deleted file mode 100644 index 7d374b2d5..000000000 --- a/Tests/RunCMake/load_command/LoadCommandDeprecated-stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -CMake Warning \(dev\) at LoadCommandDeprecated.cmake:1 \(load_command\): - The "load_command" command will be removed in CMake 3.0. See command - documentation for details. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) -This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/load_command/LoadCommandDeprecated.cmake b/Tests/RunCMake/load_command/LoadCommandDeprecated.cmake deleted file mode 100644 index 9e9b1f464..000000000 --- a/Tests/RunCMake/load_command/LoadCommandDeprecated.cmake +++ /dev/null @@ -1 +0,0 @@ -load_command() diff --git a/Tests/RunCMake/load_command/RunCMakeTest.cmake b/Tests/RunCMake/load_command/RunCMakeTest.cmake deleted file mode 100644 index 9a0f98d52..000000000 --- a/Tests/RunCMake/load_command/RunCMakeTest.cmake +++ /dev/null @@ -1,3 +0,0 @@ -include(RunCMake) - -run_cmake(LoadCommandDeprecated) diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in index ecbc05408..df3bf49d5 100644 --- a/Tests/SystemInformation/SystemInformation.in +++ b/Tests/SystemInformation/SystemInformation.in @@ -96,7 +96,9 @@ CMAKE_CXX_LINK_EXECUTABLE == "${CMAKE_CXX_LINK_EXECUTABLE}" // implicit link info CMAKE_C_IMPLICIT_LINK_LIBRARIES == "${CMAKE_C_IMPLICIT_LINK_LIBRARIES}" CMAKE_C_IMPLICIT_LINK_DIRECTORIES == "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}" +CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES == "${CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES}" CMAKE_CXX_IMPLICIT_LINK_LIBRARIES == "${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES}" CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES == "${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}" +CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES == "${CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES}" XCODE_VERSION == "${XCODE_VERSION}" diff --git a/Utilities/KWIML/ABI.h.in b/Utilities/KWIML/ABI.h.in index f93ddbaae..b71cdfb9f 100644 --- a/Utilities/KWIML/ABI.h.in +++ b/Utilities/KWIML/ABI.h.in @@ -253,7 +253,9 @@ suppression macro @KWIML@_ABI_NO_VERIFY was defined. # else # define @KWIML@_ABI_SIZEOF_LONG_LONG 0 # endif -# elif defined(__hpux) && !defined(__GNUC__) /* Old HP: no __HP_cc/__HP_aCC above */ +# elif defined(__GNUC__) /* GNU */ +# define @KWIML@_ABI_SIZEOF_LONG_LONG 8 +# elif defined(__hpux) /* Old HP: no __HP_cc/__HP_aCC/__GNUC__ above */ # define @KWIML@_ABI_SIZEOF_LONG_LONG 8 # endif #endif @@ -418,6 +420,14 @@ suppression macro @KWIML@_ABI_NO_VERIFY was defined. #elif defined(__vax__) # define @KWIML@_ABI_ENDIAN_ID @KWIML@_ABI_ENDIAN_ID_BIG +/* Aarch64 */ +#elif defined(__aarch64__) +# if !defined(__AARCH64EB__) +# define @KWIML@_ABI_ENDIAN_ID @KWIML@_ABI_ENDIAN_ID_LITTLE +# else +# define @KWIML@_ABI_ENDIAN_ID @KWIML@_ABI_ENDIAN_ID_BIG +# endif + /* Unknown CPU */ #elif !defined(@KWIML@_ABI_NO_ERROR_ENDIAN) # error "Byte order of target CPU unknown." diff --git a/Utilities/cmlibarchive/libarchive/archive_endian.h b/Utilities/cmlibarchive/libarchive/archive_endian.h index bbf58fd10..3c039f702 100644 --- a/Utilities/cmlibarchive/libarchive/archive_endian.h +++ b/Utilities/cmlibarchive/libarchive/archive_endian.h @@ -64,7 +64,13 @@ archive_be16dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[0] << 8) | p[1]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 8) | p1); } static inline uint32_t @@ -72,7 +78,15 @@ archive_be32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p3 = p[3]; + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3); } static inline uint64_t @@ -88,7 +102,13 @@ archive_le16dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[1] << 8) | p[0]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p1 << 8) | p0); } static inline uint32_t @@ -96,7 +116,15 @@ archive_le32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p3 = p[3]; + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0); } static inline uint64_t diff --git a/bootstrap b/bootstrap index 0e6d16ca9..9a4f796fe 100755 --- a/bootstrap +++ b/bootstrap @@ -159,7 +159,9 @@ if ${cmake_system_mingw}; then cmake_default_prefix="c:/Program Files/CMake" fi elif ${cmake_system_haiku}; then - cmake_default_prefix=`/bin/finddir B_COMMON_DIRECTORY` + cmake_default_prefix=`finddir B_COMMON_DIRECTORY` + cmake_man_dir="/documentation/man" + cmake_doc_dir="/documentation/doc/cmake-${cmake_version}" else cmake_default_prefix="/usr/local" fi @@ -284,18 +286,11 @@ if ${cmake_system_mingw}; then ProcessWin32 \ String \ System" - KWSYS_C_MINGW_SOURCES="\ - ProcessFwd9x \ - EncodeExecutable" - KWSYS_C_GENERATED_SOURCES="\ - cmsysProcessFwd9xEnc" else KWSYS_C_SOURCES="\ ProcessUNIX \ String \ System" - KWSYS_C_MINGW_SOURCES="" - KWSYS_C_GENERATED_SOURCES="" fi KWSYS_CXX_SOURCES="\ @@ -1351,7 +1346,7 @@ cmake_compiler_settings_comment="/* * Sources: * ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} * kwSys Sources: - * ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES} ${KWSYS_C_MINGW_SOURCES} + * ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES} */ " @@ -1447,7 +1442,7 @@ done # Generate Makefile dep="cmConfigure.h cmsys/*.hxx cmsys/*.h `cmake_escape \"${cmake_source_dir}\"`/Source/*.h" objs="" -for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES} ${KWSYS_C_GENERATED_SOURCES}; do +for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES}; do objs="${objs} ${a}.o" done @@ -1488,7 +1483,7 @@ for a in ${CMAKE_C_SOURCES}; do echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_c_compiler} ${cmake_c_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done -for a in ${KWSYS_C_SOURCES} ${KWSYS_C_MINGW_SOURCES}; do +for a in ${KWSYS_C_SOURCES}; do src=`cmake_escape "${cmake_source_dir}/Source/kwsys/${a}.c"` src_flags=`eval echo \\${cmake_c_flags_\${a}}` echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" @@ -1500,20 +1495,6 @@ for a in ${KWSYS_CXX_SOURCES}; do echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} -DKWSYS_NAMESPACE=cmsys ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done -if ${cmake_system_mingw}; then - src=`cmake_escape "${cmake_bootstrap_dir}/cmsysProcessFwd9xEnc.c"` - in=`cmake_escape "${cmake_bootstrap_dir}/cmsysProcessFwd9x.exe"` - cmd=`cmake_escape "${cmake_bootstrap_dir}/cmsysEncodeExecutable.exe"` - a="cmsysProcessFwd9xEnc" - echo "${cmd} : EncodeExecutable.o" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_c_compiler} ${cmake_ld_flags} ${cmake_c_flags} EncodeExecutable.o -o ${cmd}" >> "${cmake_bootstrap_dir}/Makefile" - echo "${in} : ProcessFwd9x.o" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_c_compiler} ${cmake_ld_flags} ${cmake_c_flags} ProcessFwd9x.o -o ${in}" >> "${cmake_bootstrap_dir}/Makefile" - echo "${src} : ${cmd} ${in}" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmd} ${in} ${src} cmsys ProcessFwd9x" >> "${cmake_bootstrap_dir}/Makefile" - echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_c_compiler} ${cmake_c_flags} -I`cmake_escape \"${cmake_source_dir}/Source/kwsys\"` -DKWSYS_NAMESPACE=cmsys -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" -fi echo ' rebuild_cache: cd "${cmake_binary_dir}" && "${cmake_source_dir}/bootstrap"