diff options
Diffstat (limited to 'Modules')
66 files changed, 3820 insertions, 941 deletions
diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index fee0a7c..b7975d3 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -457,7 +457,11 @@ endfunction() function(set_bundle_key_values keys_var context item exepath dirs copyflag) - set(rpaths "${ARGV6}") + if(ARGC GREATER 6) + set(rpaths "${ARGV6}") + else() + set(rpaths "") + endif() get_filename_component(item_name "${item}" NAME) get_item_key("${item}" key) @@ -776,7 +780,12 @@ function(fixup_bundle_item resolved_embedded_item exepath dirs) # to install_name_tool: # if(changes) - execute_process(COMMAND install_name_tool ${changes} "${resolved_embedded_item}") + set(cmd install_name_tool ${changes} "${resolved_embedded_item}") + execute_process(COMMAND ${cmd} RESULT_VARIABLE install_name_tool_result) + if(NOT install_name_tool_result EQUAL 0) + string(REPLACE ";" "' '" msg "'${cmd}'") + message(FATAL_ERROR "Command failed:\n ${msg}") + endif() endif() endfunction() diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake index 19b2bbc..3141d60 100644 --- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake +++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake @@ -21,9 +21,9 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR) set(${_VAR} - FAIL_REGEX "unrecognized .*option" # GNU + FAIL_REGEX "[Uu]nrecogni[sz]ed .*option" # GNU, NAG FAIL_REGEX "unknown .*option" # Clang - FAIL_REGEX "ignoring unknown option" # MSVC + FAIL_REGEX "ignoring unknown option" # MSVC, Intel FAIL_REGEX "warning D9002" # MSVC, any lang FAIL_REGEX "option.*not supported" # Intel FAIL_REGEX "invalid argument .*option" # Intel @@ -35,6 +35,7 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR) FAIL_REGEX "command option .* contains an incorrect subargument" # XL FAIL_REGEX "not supported in this configuration. ignored" # AIX FAIL_REGEX "File with unknown suffix passed to linker" # PGI + FAIL_REGEX "[Uu]nknown switch" # PGI FAIL_REGEX "WARNING: unknown flag:" # Open64 FAIL_REGEX "Incorrect command line option:" # Borland FAIL_REGEX "Warning: illegal option" # SunStudio 12 diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index dfed00e..403ac08 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -409,12 +409,28 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) # Read the compiler identification string from the executable file. set(COMPILER_ID) set(COMPILER_VERSION) + set(COMPILER_VERSION_MAJOR 0) + set(COMPILER_VERSION_MINOR 0) + set(COMPILER_VERSION_PATCH 0) + set(COMPILER_VERSION_TWEAK 0) + set(HAVE_COMPILER_VERSION_MAJOR 0) + set(HAVE_COMPILER_VERSION_MINOR 0) + set(HAVE_COMPILER_VERSION_PATCH 0) + set(HAVE_COMPILER_VERSION_TWEAK 0) + set(DIGIT_VALUE_1 1) + set(DIGIT_VALUE_2 10) + set(DIGIT_VALUE_3 100) + set(DIGIT_VALUE_4 1000) + set(DIGIT_VALUE_5 10000) + set(DIGIT_VALUE_6 100000) + set(DIGIT_VALUE_7 1000000) + set(DIGIT_VALUE_8 10000000) set(PLATFORM_ID) set(ARCHITECTURE_ID) set(SIMULATE_ID) set(SIMULATE_VERSION) file(STRINGS ${file} - CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 6 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]") + CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]") set(COMPILER_ID_TWICE) foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS}) if("${info}" MATCHES "INFO:compiler\\[([^]\"]*)\\]") @@ -433,6 +449,15 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION "${CMAKE_MATCH_1}") string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION "${COMPILER_VERSION}") endif() + foreach(comp MAJOR MINOR PATCH TWEAK) + foreach(digit 1 2 3 4 5 6 7 8 9) + if("${info}" MATCHES "INFO:compiler_version_${comp}_digit_${digit}\\[([0-9])\\]") + set(value ${CMAKE_MATCH_1}) + math(EXPR COMPILER_VERSION_${comp} "${COMPILER_VERSION_${comp}} + ${value} * ${DIGIT_VALUE_${digit}}") + set(HAVE_COMPILER_VERSION_${comp} 1) + endif() + endforeach() + endforeach() if("${info}" MATCHES "INFO:simulate\\[([^]\"]*)\\]") set(SIMULATE_ID "${CMAKE_MATCH_1}") endif() @@ -445,6 +470,20 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) endif() endforeach() + # Construct compiler version from components if needed. + if(NOT DEFINED COMPILER_VERSION AND HAVE_COMPILER_VERSION_MAJOR) + set(COMPILER_VERSION "${COMPILER_VERSION_MAJOR}") + if(HAVE_COMPILER_VERSION_MINOR) + set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_MINOR}") + if(HAVE_COMPILER_VERSION_PATCH) + set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_PATCH}") + if(HAVE_COMPILER_VERSION_TWEAK) + set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_TWEAK}") + endif() + endif() + endif() + endif() + # Detect the exact architecture from the PE header. if(WIN32) # The offset to the PE signature is stored at 0x3c. @@ -469,8 +508,6 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) set(ARCHITECTURE_ID "SH4") elseif(peheader STREQUAL "50450000a801") set(ARCHITECTURE_ID "SH5") - elseif(peheader STREQUAL "50450000c201") - set(ARCHITECTURE_ID "THUMB") endif() endif() diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index a4bb86c..3a27127 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -119,6 +119,47 @@ if(NOT CMAKE_Fortran_COMPILER_ID_RUN) set(CMAKE_Fortran_COMPILER_ID_VENDOR_FLAGS_NAG "-V") set(CMAKE_Fortran_COMPILER_ID_VENDOR_REGEX_NAG "NAG Fortran Compiler") + set(_version_info "") + foreach(m MAJOR MINOR PATCH TWEAK) + set(_COMP "_${m}") + set(_version_info "${_version_info} +#if defined(COMPILER_VERSION${_COMP})") + foreach(d 1 2 3 4 5 6 7 8) + set(_version_info "${_version_info} +# undef DEC +# undef HEX +# define DEC(n) DEC_${d}(n) +# define HEX(n) HEX_${d}(n) +# if COMPILER_VERSION${_COMP} == 0 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[0]' +# elif COMPILER_VERSION${_COMP} == 1 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[1]' +# elif COMPILER_VERSION${_COMP} == 2 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[2]' +# elif COMPILER_VERSION${_COMP} == 3 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[3]' +# elif COMPILER_VERSION${_COMP} == 4 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[4]' +# elif COMPILER_VERSION${_COMP} == 5 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[5]' +# elif COMPILER_VERSION${_COMP} == 6 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[6]' +# elif COMPILER_VERSION${_COMP} == 7 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[7]' +# elif COMPILER_VERSION${_COMP} == 8 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[8]' +# elif COMPILER_VERSION${_COMP} == 9 + PRINT *, 'INFO:compiler_version${_COMP}_digit_${d}[9]' +# endif +") + endforeach() + set(_version_info "${_version_info} +#endif") + endforeach() + set(CMAKE_Fortran_COMPILER_ID_VERSION_INFO "${_version_info}") + unset(_version_info) + unset(_COMP) + # Try to identify the compiler. set(CMAKE_Fortran_COMPILER_ID) include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index 5349505..2533d3f 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -4,6 +4,17 @@ #endif #if defined(__INTEL_COMPILER) || defined(__ICC) PRINT *, 'INFO:compiler[Intel]' +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif + # if defined(_MSC_VER) PRINT *, 'INFO:simulate[MSVC]' # if _MSC_VER >= 1800 @@ -22,28 +33,59 @@ PRINT *, 'INFO:simulate_version[013.00]' # endif # endif -#elif defined(__SUNPRO_F90) || defined(__SUNPRO_F95) +#elif defined(__SUNPRO_F95) + PRINT *, 'INFO:compiler[SunPro]' +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_F95>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_F95>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_F95 & 0xF) +#elif defined(__SUNPRO_F90) PRINT *, 'INFO:compiler[SunPro]' +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_F90>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_F90>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_F90 & 0xF) #elif defined(_CRAYFTN) PRINT *, 'INFO:compiler[Cray]' #elif defined(__G95__) PRINT *, 'INFO:compiler[G95]' +# define COMPILER_VERSION_MAJOR DEC(__G95__) +# define COMPILER_VERSION_MINOR DEC(__G95_MINOR__) #elif defined(__PATHSCALE__) PRINT *, 'INFO:compiler[PathScale]' +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif #elif defined(__ABSOFT__) PRINT *, 'INFO:compiler[Absoft]' #elif defined(__GNUC__) PRINT *, 'INFO:compiler[GNU]' +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif #elif defined(__IBMC__) # if defined(__COMPILER_VER__) PRINT *, 'INFO:compiler[zOS]' # elif __IBMC__ >= 800 PRINT *, 'INFO:compiler[XL]' +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) # else PRINT *, 'INFO:compiler[VisualAge]' +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) # endif #elif defined(__PGI) PRINT *, 'INFO:compiler[PGI]' +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif #elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) PRINT *, 'INFO:compiler[MIPSpro]' # if 0 @@ -134,4 +176,26 @@ PRINT *, 'INFO:arch[X86]' # endif #endif + +#if 0 +! Encode compiler version digits +#endif +#define DEC_8(n) (((n) / 10000000) % 10) +#define DEC_7(n) (((n) / 1000000) % 10) +#define DEC_6(n) (((n) / 100000) % 10) +#define DEC_5(n) (((n) / 10000) % 10) +#define DEC_4(n) (((n) / 1000) % 10) +#define DEC_3(n) (((n) / 100) % 10) +#define DEC_2(n) (((n) / 10) % 10) +#define DEC_1(n) (((n) ) % 10) +#define HEX_8(n) ((n)>>28 & 0xF) +#define HEX_7(n) ((n)>>24 & 0xF) +#define HEX_6(n) ((n)>>20 & 0xF) +#define HEX_5(n) ((n)>>16 & 0xF) +#define HEX_4(n) ((n)>>12 & 0xF) +#define HEX_3(n) ((n)>>8 & 0xF) +#define HEX_2(n) ((n)>>4 & 0xF) +#define HEX_1(n) ((n) & 0xF) +@CMAKE_Fortran_COMPILER_ID_VERSION_INFO@ + END diff --git a/Modules/CMakeGraphVizOptions.cmake b/Modules/CMakeGraphVizOptions.cmake index 64c89b9..ff18267 100644 --- a/Modules/CMakeGraphVizOptions.cmake +++ b/Modules/CMakeGraphVizOptions.cmake @@ -10,7 +10,7 @@ # CMake # can generate graphviz files, showing the dependencies between the # targets in a project and also external libraries which are linked -# against. When CMake is run with the --graphiz=foo option, it will +# against. When CMake is run with the --graphviz=foo option, it will # produce # # * a foo.dot file showing all dependencies in the project diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index fcc13da..8abc465 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -124,7 +124,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj # We remove items that are not language-specific. set(implicit_libs "") foreach(lib IN LISTS implicit_libs_tmp) - if("${lib}" MATCHES "^(crt.*\\.o|gcc.*|System.*)$") + if("x${lib}" MATCHES "^x(crt.*\\.o|gcc.*|System.*)$") set(log "${log} remove lib [${lib}]\n") elseif(IS_ABSOLUTE "${lib}") get_filename_component(abs "${lib}" ABSOLUTE) diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index bc26c07..da99b9e 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -1,3 +1,6 @@ +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + /* Identify known platforms by name. */ #if defined(__linux) || defined(__linux__) || defined(linux) # define PLATFORM_ID "Linux" @@ -112,7 +115,13 @@ # define ARCHITECTURE_ID "X86" # elif defined(_M_ARM) -# define ARCHITECTURE_ID "ARM" +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif # elif defined(_M_MIPS) # define ARCHITECTURE_ID "MIPS" diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index ce1536e..532596d 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -314,7 +314,7 @@ macro(cpack_encode_variables) set(_CPACK_OTHER_VARIABLES_) get_cmake_property(res VARIABLES) foreach(var ${res}) - if("xxx${var}" MATCHES "xxxCPACK") + if(var MATCHES "^CPACK") set(_CPACK_OTHER_VARIABLES_ "${_CPACK_OTHER_VARIABLES_}\nSET(${var} \"${${var}}\")") endif() diff --git a/Modules/CPackBundle.cmake b/Modules/CPackBundle.cmake index d26a0b3..b412216 100644 --- a/Modules/CPackBundle.cmake +++ b/Modules/CPackBundle.cmake @@ -52,6 +52,11 @@ # list the main application folder, or the main executable. You should # list any frameworks and plugins that are included in your app bundle. # +# .. variable:: CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER +# +# Additional parameter that will passed to codesign. +# Default value: "--deep -f" +# # .. variable:: CPACK_COMMAND_CODESIGN # # Path to the codesign(1) command used to sign applications with an diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index e3f74d8..b8d518c 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -51,11 +51,12 @@ # * Default : CPACK_PACKAGE_VERSION # # .. variable:: CPACK_RPM_PACKAGE_ARCHITECTURE +# CPACK_RPM_<component>_PACKAGE_ARCHITECTURE # # The RPM package architecture. # -# * Mandatory : NO -# * Default : - +# * Mandatory : YES +# * Default : Native architecture output by "uname -m" # # This may be set to "noarch" if you know you are building a noarch package. # @@ -407,6 +408,51 @@ # # May be used to set per component CPACK_PACKAGING_INSTALL_PREFIX for # relocatable RPM packages. +# +# .. variable:: CPACK_RPM_NO_INSTALL_PREFIX_RELOCATION +# CPACK_RPM_NO_<COMPONENT>_INSTALL_PREFIX_RELOCATION +# +# * Mandatory : NO +# * Default : CPACK_PACKAGING_INSTALL_PREFIX or CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX +# are treated as one of relocation paths +# +# May be used to remove CPACK_PACKAGING_INSTALL_PREFIX and CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX +# from relocatable RPM prefix paths. +# +# Packaging of Symbolic Links +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# CPackRPM supports packaging of symbolic links:: +# +# execute_process(COMMAND ${CMAKE_COMMAND} +# -E create_symlink <relative_path_location> <symlink_name>) +# install(FILES ${CMAKE_CURRENT_BINARY_DIR}/<symlink_name> +# DESTINATION <symlink_location> COMPONENT libraries) +# +# Symbolic links will be optimized (paths will be shortened if possible) +# before being added to the package or if multiple relocation paths are +# detected, a post install symlink relocation script will be generated. +# +# Symbolic links may point to locations that are not packaged by the same +# package (either a different component or even not packaged at all) but +# those locations will be treated as if they were a part of the package +# while determining if symlink should be either created or present in a +# post install script - depending on relocation paths. +# +# Currenty there are a few limitations though: +# +# * Only symbolic links with relative path can be packaged. +# +# * For component based packaging component interdependency is not checked +# when processing symbolic links. Symbolic links pointing to content of +# a different component are treated the same way as if pointing to location +# that will not be packaged. +# +# * Symbolic links pointing to a location through one or more intermediate +# symbolic links will not be handled differently - if the intermediate +# symbolic link(s) is also on a relocatable path, relocating it during +# package installation may cause initial symbolic link to point to an +# invalid location. #============================================================================= # Copyright 2007-2009 Kitware, Inc. @@ -436,8 +482,15 @@ function(cpack_rpm_prepare_relocation_paths) # set base path prefix if(EXISTS "${WDIR}/${PATH_PREFIX}") - set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}Prefix: ${PATH_PREFIX}\n") - list(APPEND RPM_USED_PACKAGE_PREFIXES "${PATH_PREFIX}") + if(NOT CPACK_RPM_NO_INSTALL_PREFIX_RELOCATION AND + NOT CPACK_RPM_NO_${CPACK_RPM_PACKAGE_COMPONENT}_INSTALL_PREFIX_RELOCATION) + set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}Prefix: ${PATH_PREFIX}\n") + list(APPEND RPM_USED_PACKAGE_PREFIXES "${PATH_PREFIX}") + + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: removing '${PATH_PREFIX}' from relocation paths") + endif() + endif() endif() # set other path prefixes @@ -485,706 +538,979 @@ function(cpack_rpm_prepare_relocation_paths) set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}" PARENT_SCOPE) endfunction() -if(CMAKE_BINARY_DIR) - message(FATAL_ERROR "CPackRPM.cmake may only be used by CPack internally.") -endif() +function(cpack_rpm_symlink_get_relocation_prefixes LOCATION PACKAGE_PREFIXES RETURN_VARIABLE) + foreach(PKG_PREFIX IN LISTS PACKAGE_PREFIXES) + string(REGEX MATCH "^${PKG_PREFIX}/.*" FOUND_ "${LOCATION}") + if(FOUND_) + list(APPEND TMP_PREFIXES "${PKG_PREFIX}") + endif() + endforeach() -if(NOT UNIX) - message(FATAL_ERROR "CPackRPM.cmake may only be used under UNIX.") -endif() + set(${RETURN_VARIABLE} "${TMP_PREFIXES}" PARENT_SCOPE) +endfunction() -# rpmbuild is the basic command for building RPM package -# it may be a simple (symbolic) link to rpm command. -find_program(RPMBUILD_EXECUTABLE rpmbuild) - -# Check version of the rpmbuild tool this would be easier to -# track bugs with users and CPackRPM debug mode. -# We may use RPM version in order to check for available version dependent features -if(RPMBUILD_EXECUTABLE) - execute_process(COMMAND ${RPMBUILD_EXECUTABLE} --version - OUTPUT_VARIABLE _TMP_VERSION - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX REPLACE "^.* " "" - RPMBUILD_EXECUTABLE_VERSION - ${_TMP_VERSION}) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: rpmbuild version is <${RPMBUILD_EXECUTABLE_VERSION}>") - endif() -endif() +function(cpack_rpm_symlink_create_relocation_script PACKAGE_PREFIXES) + list(LENGTH PACKAGE_PREFIXES LAST_INDEX) + set(SORTED_PACKAGE_PREFIXES "${PACKAGE_PREFIXES}") + list(SORT SORTED_PACKAGE_PREFIXES) + list(REVERSE SORTED_PACKAGE_PREFIXES) + math(EXPR LAST_INDEX ${LAST_INDEX}-1) + + foreach(SYMLINK_INDEX RANGE ${LAST_INDEX}) + list(GET SORTED_PACKAGE_PREFIXES ${SYMLINK_INDEX} SRC_PATH) + list(FIND PACKAGE_PREFIXES "${SRC_PATH}" SYMLINK_INDEX) # reverse magic + string(LENGTH "${SRC_PATH}" SRC_PATH_LEN) + + set(PARTS_CNT 0) + set(SCRIPT_PART "if [ \"$RPM_INSTALL_PREFIX${SYMLINK_INDEX}\" != \"${SRC_PATH}\" ]; then\n") + + # both paths relocated + foreach(POINT_INDEX RANGE ${LAST_INDEX}) + list(GET SORTED_PACKAGE_PREFIXES ${POINT_INDEX} POINT_PATH) + list(FIND PACKAGE_PREFIXES "${POINT_PATH}" POINT_INDEX) # reverse magic + string(LENGTH "${POINT_PATH}" POINT_PATH_LEN) + + if(_RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX}) + if("${SYMLINK_INDEX}" EQUAL "${POINT_INDEX}") + set(INDENT "") + else() + set(SCRIPT_PART "${SCRIPT_PART} if [ \"$RPM_INSTALL_PREFIX${POINT_INDEX}\" != \"${POINT_PATH}\" ]; then\n") + set(INDENT " ") + endif() -if(NOT RPMBUILD_EXECUTABLE) - message(FATAL_ERROR "RPM package requires rpmbuild executable") -endif() + foreach(RELOCATION_NO IN LISTS _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX}) + math(EXPR PARTS_CNT ${PARTS_CNT}+1) -# Display lsb_release output if DEBUG mode enable -# This will help to diagnose problem with CPackRPM -# because we will know on which kind of Linux we are -if(CPACK_RPM_PACKAGE_DEBUG) - find_program(LSB_RELEASE_EXECUTABLE lsb_release) - if(LSB_RELEASE_EXECUTABLE) - execute_process(COMMAND ${LSB_RELEASE_EXECUTABLE} -a - OUTPUT_VARIABLE _TMP_LSB_RELEASE_OUTPUT - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX REPLACE "\n" ", " - LSB_RELEASE_OUTPUT - ${_TMP_LSB_RELEASE_OUTPUT}) - else () - set(LSB_RELEASE_OUTPUT "lsb_release not installed/found!") + math(EXPR RELOCATION_INDEX ${RELOCATION_NO}-1) + list(GET _RPM_RELOCATION_SCRIPT_PAIRS ${RELOCATION_INDEX} RELOCATION_SCRIPT_PAIR) + string(FIND "${RELOCATION_SCRIPT_PAIR}" ":" SPLIT_INDEX) + + math(EXPR SRC_PATH_END ${SPLIT_INDEX}-${SRC_PATH_LEN}) + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${SRC_PATH_LEN} ${SRC_PATH_END} SYMLINK_) + + math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1+${POINT_PATH_LEN}) + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_) + + set(SCRIPT_PART "${SCRIPT_PART} ${INDENT}if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n") + set(SCRIPT_PART "${SCRIPT_PART} ${INDENT}ln -s \"$RPM_INSTALL_PREFIX${POINT_INDEX}${POINT_}\" \"$RPM_INSTALL_PREFIX${SYMLINK_INDEX}${SYMLINK_}\"\n") + set(SCRIPT_PART "${SCRIPT_PART} ${INDENT}CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n") + set(SCRIPT_PART "${SCRIPT_PART} ${INDENT}fi\n") + endforeach() + + if(NOT "${SYMLINK_INDEX}" EQUAL "${POINT_INDEX}") + set(SCRIPT_PART "${SCRIPT_PART} fi\n") + endif() + endif() + endforeach() + + # source path relocated + if(_RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_X) + foreach(RELOCATION_NO IN LISTS _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_X) + math(EXPR PARTS_CNT ${PARTS_CNT}+1) + + math(EXPR RELOCATION_INDEX ${RELOCATION_NO}-1) + list(GET _RPM_RELOCATION_SCRIPT_PAIRS ${RELOCATION_INDEX} RELOCATION_SCRIPT_PAIR) + string(FIND "${RELOCATION_SCRIPT_PAIR}" ":" SPLIT_INDEX) + + math(EXPR SRC_PATH_END ${SPLIT_INDEX}-${SRC_PATH_LEN}) + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${SRC_PATH_LEN} ${SRC_PATH_END} SYMLINK_) + + math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1) + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_) + + set(SCRIPT_PART "${SCRIPT_PART} if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n") + set(SCRIPT_PART "${SCRIPT_PART} ln -s \"${POINT_}\" \"$RPM_INSTALL_PREFIX${SYMLINK_INDEX}${SYMLINK_}\"\n") + set(SCRIPT_PART "${SCRIPT_PART} CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n") + set(SCRIPT_PART "${SCRIPT_PART} fi\n") + endforeach() + endif() + + if(PARTS_CNT) + set(SCRIPT "${SCRIPT_PART}") + set(SCRIPT "${SCRIPT}fi\n") + endif() + endforeach() + + # point path relocated + foreach(POINT_INDEX RANGE ${LAST_INDEX}) + list(GET SORTED_PACKAGE_PREFIXES ${POINT_INDEX} POINT_PATH) + list(FIND PACKAGE_PREFIXES "${POINT_PATH}" POINT_INDEX) # reverse magic + string(LENGTH "${POINT_PATH}" POINT_PATH_LEN) + + if(_RPM_RELOCATION_SCRIPT_X_${POINT_INDEX}) + set(SCRIPT "${SCRIPT}if [ \"$RPM_INSTALL_PREFIX${POINT_INDEX}\" != \"${POINT_PATH}\" ]; then\n") + + foreach(RELOCATION_NO IN LISTS _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX}) + math(EXPR RELOCATION_INDEX ${RELOCATION_NO}-1) + list(GET _RPM_RELOCATION_SCRIPT_PAIRS ${RELOCATION_INDEX} RELOCATION_SCRIPT_PAIR) + string(FIND "${RELOCATION_SCRIPT_PAIR}" ":" SPLIT_INDEX) + + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} 0 ${SPLIT_INDEX} SYMLINK_) + + math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1+${POINT_PATH_LEN}) + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_) + + set(SCRIPT "${SCRIPT} if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n") + set(SCRIPT "${SCRIPT} ln -s \"$RPM_INSTALL_PREFIX${POINT_INDEX}${POINT_}\" \"${SYMLINK_}\"\n") + set(SCRIPT "${SCRIPT} CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}=true\n") + set(SCRIPT "${SCRIPT} fi\n") + endforeach() + + set(SCRIPT "${SCRIPT}fi\n") + endif() + endforeach() + + # no path relocated + if(_RPM_RELOCATION_SCRIPT_X_X) + foreach(RELOCATION_NO IN LISTS _RPM_RELOCATION_SCRIPT_X_X) + math(EXPR RELOCATION_INDEX ${RELOCATION_NO}-1) + list(GET _RPM_RELOCATION_SCRIPT_PAIRS ${RELOCATION_INDEX} RELOCATION_SCRIPT_PAIR) + string(FIND "${RELOCATION_SCRIPT_PAIR}" ":" SPLIT_INDEX) + + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} 0 ${SPLIT_INDEX} SYMLINK_) + + math(EXPR POINT_PATH_START ${SPLIT_INDEX}+1) + string(SUBSTRING ${RELOCATION_SCRIPT_PAIR} ${POINT_PATH_START} -1 POINT_) + + set(SCRIPT "${SCRIPT}if [ -z \"$CPACK_RPM_RELOCATED_SYMLINK_${RELOCATION_INDEX}\" ]; then\n") + set(SCRIPT "${SCRIPT} ln -s \"${POINT_}\" \"${SYMLINK_}\"\n") + set(SCRIPT "${SCRIPT}fi\n") + endforeach() endif() - message("CPackRPM:Debug: LSB_RELEASE = ${LSB_RELEASE_OUTPUT}") -endif() -# We may use RPM version in the future in order -# to shut down warning about space in buildtree -# some recent RPM version should support space in different places. -# not checked [yet]. -if(CPACK_TOPLEVEL_DIRECTORY MATCHES ".* .*") - message(FATAL_ERROR "${RPMBUILD_EXECUTABLE} can't handle paths with spaces, use a build directory without spaces for building RPMs.") -endif() + set(RPM_SYMLINK_POSTINSTALL "${SCRIPT}" PARENT_SCOPE) +endfunction() -# If rpmbuild is found -# we try to discover alien since we may be on non RPM distro like Debian. -# In this case we may try to to use more advanced features -# like generating RPM directly from DEB using alien. -# FIXME feature not finished (yet) -find_program(ALIEN_EXECUTABLE alien) -if(ALIEN_EXECUTABLE) - message(STATUS "alien found, we may be on a Debian based distro.") -endif() +function(cpack_rpm_symlink_add_for_relocation_script PACKAGE_PREFIXES SYMLINK SYMLINK_RELOCATION_PATHS POINT POINT_RELOCATION_PATHS) + list(LENGTH SYMLINK_RELOCATION_PATHS SYMLINK_PATHS_COUTN) + list(LENGTH POINT_RELOCATION_PATHS POINT_PATHS_COUNT) -# Are we packaging components ? -if(CPACK_RPM_PACKAGE_COMPONENT) - set(CPACK_RPM_PACKAGE_COMPONENT_PART_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}") - string(TOUPPER ${CPACK_RPM_PACKAGE_COMPONENT} CPACK_RPM_PACKAGE_COMPONENT_UPPER) -else() - set(CPACK_RPM_PACKAGE_COMPONENT_PART_NAME "") -endif() + list(APPEND _RPM_RELOCATION_SCRIPT_PAIRS "${SYMLINK}:${POINT}") + list(LENGTH _RPM_RELOCATION_SCRIPT_PAIRS PAIR_NO) -set(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}") + if(SYMLINK_PATHS_COUTN) + foreach(SYMLINK_RELOC_PATH IN LISTS SYMLINK_RELOCATION_PATHS) + list(FIND PACKAGE_PREFIXES "${SYMLINK_RELOC_PATH}" SYMLINK_INDEX) -# -# Use user-defined RPM specific variables value -# or generate reasonable default value from -# CPACK_xxx generic values. -# The variables comes from the needed (mandatory or not) -# values found in the RPM specification file aka ".spec" file. -# The variables which may/should be defined are: -# + # source path relocated + list(APPEND _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_X "${PAIR_NO}") + list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_X") -# CPACK_RPM_PACKAGE_SUMMARY (mandatory) + foreach(POINT_RELOC_PATH IN LISTS POINT_RELOCATION_PATHS) + list(FIND PACKAGE_PREFIXES "${POINT_RELOC_PATH}" POINT_INDEX) -# CPACK_RPM_PACKAGE_SUMMARY_ is used only locally so that it can be unset each time before use otherwise -# component packaging could leak variable content between components -unset(CPACK_RPM_PACKAGE_SUMMARY_) -if(CPACK_RPM_PACKAGE_SUMMARY) - set(CPACK_RPM_PACKAGE_SUMMARY_ ${CPACK_RPM_PACKAGE_SUMMARY}) - unset(CPACK_RPM_PACKAGE_SUMMARY) -endif() + # both paths relocated + list(APPEND _RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX} "${PAIR_NO}") + list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_${SYMLINK_INDEX}_${POINT_INDEX}") -#Check for component summary first. -#If not set, it will use regular package summary logic. -if(CPACK_RPM_PACKAGE_COMPONENT) - if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_SUMMARY) - set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_SUMMARY}) + # point path relocated + list(APPEND _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX} "${PAIR_NO}") + list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_X_${POINT_INDEX}") + endforeach() + endforeach() + elseif(POINT_PATHS_COUNT) + foreach(POINT_RELOC_PATH IN LISTS POINT_RELOCATION_PATHS) + list(FIND PACKAGE_PREFIXES "${POINT_RELOC_PATH}" POINT_INDEX) + + # point path relocated + list(APPEND _RPM_RELOCATION_SCRIPT_X_${POINT_INDEX} "${PAIR_NO}") + list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_X_${POINT_INDEX}") + endforeach() endif() -endif() -if(NOT CPACK_RPM_PACKAGE_SUMMARY) - if(CPACK_RPM_PACKAGE_SUMMARY_) - set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_RPM_PACKAGE_SUMMARY_}) - elseif(CPACK_PACKAGE_DESCRIPTION_SUMMARY) - set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}) - else() - # if neither var is defined lets use the name as summary - string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_SUMMARY) + # no path relocated + list(APPEND _RPM_RELOCATION_SCRIPT_X_X "${PAIR_NO}") + list(APPEND RELOCATION_VARS "_RPM_RELOCATION_SCRIPT_X_X") + + # place variables into parent scope + foreach(VAR IN LISTS RELOCATION_VARS) + set(${VAR} "${${VAR}}" PARENT_SCOPE) + endforeach() + set(_RPM_RELOCATION_SCRIPT_PAIRS "${_RPM_RELOCATION_SCRIPT_PAIRS}" PARENT_SCOPE) + set(REQUIRES_SYMLINK_RELOCATION_SCRIPT "true" PARENT_SCOPE) + set(DIRECTIVE "%ghost " PARENT_SCOPE) +endfunction() + +function(cpack_rpm_prepare_install_files INSTALL_FILES_LIST WDIR PACKAGE_PREFIXES IS_RELOCATABLE) + # Prepend directories in ${CPACK_RPM_INSTALL_FILES} with %dir + # This is necessary to avoid duplicate files since rpmbuild does + # recursion on its own when encountering a pathname which is a directory + # which is not flagged as %dir + string(STRIP "${INSTALL_FILES_LIST}" INSTALL_FILES_LIST) + string(REPLACE "\n" ";" INSTALL_FILES_LIST + "${INSTALL_FILES_LIST}") + string(REPLACE "\"" "" INSTALL_FILES_LIST + "${INSTALL_FILES_LIST}") + string(LENGTH "${WDIR}" WDR_LEN_) + + list(SORT INSTALL_FILES_LIST) # make file order consistent on all platforms + + foreach(F IN LISTS INSTALL_FILES_LIST) + unset(DIRECTIVE) + + if(IS_SYMLINK "${WDIR}/${F}") + if(IS_RELOCATABLE) + # check that symlink has relocatable format + get_filename_component(SYMLINK_LOCATION_ "${WDIR}/${F}" DIRECTORY) + execute_process(COMMAND ls -la "${WDIR}/${F}" + WORKING_DIRECTORY "${WDIR}" + OUTPUT_VARIABLE SYMLINK_POINT_ + OUTPUT_STRIP_TRAILING_WHITESPACE) + + string(FIND "${SYMLINK_POINT_}" "->" SYMLINK_POINT_INDEX_ REVERSE) + math(EXPR SYMLINK_POINT_INDEX_ ${SYMLINK_POINT_INDEX_}+3) + string(LENGTH "${SYMLINK_POINT_}" SYMLINK_POINT_LENGTH_) + + # get destination path + string(SUBSTRING "${SYMLINK_POINT_}" ${SYMLINK_POINT_INDEX_} ${SYMLINK_POINT_LENGTH_} SYMLINK_POINT_) + + # check if path is relative or absolute + string(SUBSTRING "${SYMLINK_POINT_}" 0 1 SYMLINK_IS_ABSOLUTE_) + + if(${SYMLINK_IS_ABSOLUTE_} STREQUAL "/") + # prevent absolute paths from having /../ or /./ section inside of them + get_filename_component(SYMLINK_POINT_ "${SYMLINK_POINT_}" ABSOLUTE) + else() + # handle relative path + get_filename_component(SYMLINK_POINT_ "${SYMLINK_LOCATION_}/${SYMLINK_POINT_}" ABSOLUTE) + endif() + + string(SUBSTRING "${SYMLINK_POINT_}" ${WDR_LEN_} -1 SYMLINK_POINT_WD_) + + cpack_rpm_symlink_get_relocation_prefixes("${F}" "${PACKAGE_PREFIXES}" "SYMLINK_RELOCATIONS") + cpack_rpm_symlink_get_relocation_prefixes("${SYMLINK_POINT_WD_}" "${PACKAGE_PREFIXES}" "POINT_RELOCATIONS") + + list(LENGTH SYMLINK_RELOCATIONS SYMLINK_RELOCATIONS_COUNT) + list(LENGTH POINT_RELOCATIONS POINT_RELOCATIONS_COUNT) + + if(SYMLINK_RELOCATIONS_COUNT AND POINT_RELOCATIONS_COUNT) + # find matching + foreach(SYMLINK_RELOCATION_PREFIX IN LISTS SYMLINK_RELOCATIONS) + list(FIND POINT_RELOCATIONS "${SYMLINK_RELOCATION_PREFIX}" FOUND_INDEX) + if(NOT ${FOUND_INDEX} EQUAL -1) + break() + endif() + endforeach() + + if(NOT ${FOUND_INDEX} EQUAL -1) + # symlinks have the same subpath + if(${SYMLINK_RELOCATIONS_COUNT} EQUAL 1 AND ${POINT_RELOCATIONS_COUNT} EQUAL 1) + # permanent symlink + get_filename_component(SYMLINK_LOCATION_ "${F}" DIRECTORY) + file(RELATIVE_PATH FINAL_PATH_ ${SYMLINK_LOCATION_} ${SYMLINK_POINT_WD_}) + execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${FINAL_PATH_}" "${WDIR}/${F}") + else() + # relocation subpaths + cpack_rpm_symlink_add_for_relocation_script("${PACKAGE_PREFIXES}" "${F}" "${SYMLINK_RELOCATIONS}" + "${SYMLINK_POINT_WD_}" "${POINT_RELOCATIONS}") + endif() + else() + # not on the same relocation path + cpack_rpm_symlink_add_for_relocation_script("${PACKAGE_PREFIXES}" "${F}" "${SYMLINK_RELOCATIONS}" + "${SYMLINK_POINT_WD_}" "${POINT_RELOCATIONS}") + endif() + elseif(POINT_RELOCATIONS_COUNT) + # point is relocatable + cpack_rpm_symlink_add_for_relocation_script("${PACKAGE_PREFIXES}" "${F}" "${SYMLINK_RELOCATIONS}" + "${SYMLINK_POINT_WD_}" "${POINT_RELOCATIONS}") + else() + # is not relocatable or points to non relocatable path - permanent symlink + execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${SYMLINK_POINT_WD_}" "${WDIR}/${F}") + endif() + endif() + elseif(IS_DIRECTORY "${WDIR}/${F}") + set(DIRECTIVE "%dir ") + endif() + + set(INSTALL_FILES "${INSTALL_FILES}${DIRECTIVE}\"${F}\"\n") + endforeach() + + if(REQUIRES_SYMLINK_RELOCATION_SCRIPT) + cpack_rpm_symlink_create_relocation_script("${PACKAGE_PREFIXES}") endif() + + set(RPM_SYMLINK_POSTINSTALL "${RPM_SYMLINK_POSTINSTALL}" PARENT_SCOPE) + set(CPACK_RPM_INSTALL_FILES "${INSTALL_FILES}" PARENT_SCOPE) +endfunction() + +if(CMAKE_BINARY_DIR) + message(FATAL_ERROR "CPackRPM.cmake may only be used by CPack internally.") endif() -# CPACK_RPM_PACKAGE_NAME (mandatory) -if(NOT CPACK_RPM_PACKAGE_NAME) - string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_NAME) +if(NOT UNIX) + message(FATAL_ERROR "CPackRPM.cmake may only be used under UNIX.") endif() -# CPACK_RPM_PACKAGE_VERSION (mandatory) -if(NOT CPACK_RPM_PACKAGE_VERSION) - if(NOT CPACK_PACKAGE_VERSION) - message(FATAL_ERROR "RPM package requires a package version") +function(cpack_rpm_generate_package) + # rpmbuild is the basic command for building RPM package + # it may be a simple (symbolic) link to rpm command. + find_program(RPMBUILD_EXECUTABLE rpmbuild) + + # Check version of the rpmbuild tool this would be easier to + # track bugs with users and CPackRPM debug mode. + # We may use RPM version in order to check for available version dependent features + if(RPMBUILD_EXECUTABLE) + execute_process(COMMAND ${RPMBUILD_EXECUTABLE} --version + OUTPUT_VARIABLE _TMP_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX REPLACE "^.* " "" + RPMBUILD_EXECUTABLE_VERSION + ${_TMP_VERSION}) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: rpmbuild version is <${RPMBUILD_EXECUTABLE_VERSION}>") + endif() endif() - set(CPACK_RPM_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}) -endif() -# Replace '-' in version with '_' -# '-' character is an Illegal RPM version character -# it is illegal because it is used to separate -# RPM "Version" from RPM "Release" -string(REPLACE "-" "_" CPACK_RPM_PACKAGE_VERSION ${CPACK_RPM_PACKAGE_VERSION}) - -# CPACK_RPM_PACKAGE_ARCHITECTURE (optional) -if(CPACK_RPM_PACKAGE_ARCHITECTURE) - set(TMP_RPM_BUILDARCH "Buildarch: ${CPACK_RPM_PACKAGE_ARCHITECTURE}") - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: using user-specified build arch = ${CPACK_RPM_PACKAGE_ARCHITECTURE}") + + if(NOT RPMBUILD_EXECUTABLE) + message(FATAL_ERROR "RPM package requires rpmbuild executable") endif() -else() - set(TMP_RPM_BUILDARCH "") -endif() -# CPACK_RPM_PACKAGE_RELEASE -# The RPM release is the numbering of the RPM package ITSELF -# this is the version of the PACKAGING and NOT the version -# of the CONTENT of the package. -# You may well need to generate a new RPM package release -# without changing the version of the packaged software. -# This is the case when the packaging is buggy (not) the software :=) -# If not set, 1 is a good candidate -if(NOT CPACK_RPM_PACKAGE_RELEASE) - set(CPACK_RPM_PACKAGE_RELEASE 1) -endif() + # Display lsb_release output if DEBUG mode enable + # This will help to diagnose problem with CPackRPM + # because we will know on which kind of Linux we are + if(CPACK_RPM_PACKAGE_DEBUG) + find_program(LSB_RELEASE_EXECUTABLE lsb_release) + if(LSB_RELEASE_EXECUTABLE) + execute_process(COMMAND ${LSB_RELEASE_EXECUTABLE} -a + OUTPUT_VARIABLE _TMP_LSB_RELEASE_OUTPUT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX REPLACE "\n" ", " + LSB_RELEASE_OUTPUT + ${_TMP_LSB_RELEASE_OUTPUT}) + else () + set(LSB_RELEASE_OUTPUT "lsb_release not installed/found!") + endif() + message("CPackRPM:Debug: LSB_RELEASE = ${LSB_RELEASE_OUTPUT}") + endif() -# CPACK_RPM_PACKAGE_LICENSE -if(NOT CPACK_RPM_PACKAGE_LICENSE) - set(CPACK_RPM_PACKAGE_LICENSE "unknown") -endif() + # We may use RPM version in the future in order + # to shut down warning about space in buildtree + # some recent RPM version should support space in different places. + # not checked [yet]. + if(CPACK_TOPLEVEL_DIRECTORY MATCHES ".* .*") + message(FATAL_ERROR "${RPMBUILD_EXECUTABLE} can't handle paths with spaces, use a build directory without spaces for building RPMs.") + endif() -# CPACK_RPM_PACKAGE_GROUP -if(NOT CPACK_RPM_PACKAGE_GROUP) - set(CPACK_RPM_PACKAGE_GROUP "unknown") -endif() + # If rpmbuild is found + # we try to discover alien since we may be on non RPM distro like Debian. + # In this case we may try to to use more advanced features + # like generating RPM directly from DEB using alien. + # FIXME feature not finished (yet) + find_program(ALIEN_EXECUTABLE alien) + if(ALIEN_EXECUTABLE) + message(STATUS "alien found, we may be on a Debian based distro.") + endif() -# CPACK_RPM_PACKAGE_VENDOR -if(NOT CPACK_RPM_PACKAGE_VENDOR) - if(CPACK_PACKAGE_VENDOR) - set(CPACK_RPM_PACKAGE_VENDOR "${CPACK_PACKAGE_VENDOR}") + # Are we packaging components ? + if(CPACK_RPM_PACKAGE_COMPONENT) + set(CPACK_RPM_PACKAGE_COMPONENT_PART_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}") + string(TOUPPER ${CPACK_RPM_PACKAGE_COMPONENT} CPACK_RPM_PACKAGE_COMPONENT_UPPER) else() - set(CPACK_RPM_PACKAGE_VENDOR "unknown") + set(CPACK_RPM_PACKAGE_COMPONENT_PART_NAME "") endif() -endif() -# CPACK_RPM_PACKAGE_SOURCE -# The name of the source tarball in case we generate a source RPM + set(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}") -# CPACK_RPM_PACKAGE_DESCRIPTION -# The variable content may be either -# - explicitly given by the user or -# - filled with the content of CPACK_PACKAGE_DESCRIPTION_FILE -# if it is defined -# - set to a default value -# + # + # Use user-defined RPM specific variables value + # or generate reasonable default value from + # CPACK_xxx generic values. + # The variables comes from the needed (mandatory or not) + # values found in the RPM specification file aka ".spec" file. + # The variables which may/should be defined are: + # -# CPACK_RPM_PACKAGE_DESCRIPTION_ is used only locally so that it can be unset each time before use otherwise -# component packaging could leak variable content between components -unset(CPACK_RPM_PACKAGE_DESCRIPTION_) -if(CPACK_RPM_PACKAGE_DESCRIPTION) - set(CPACK_RPM_PACKAGE_DESCRIPTION_ ${CPACK_RPM_PACKAGE_DESCRIPTION}) - unset(CPACK_RPM_PACKAGE_DESCRIPTION) -endif() + # CPACK_RPM_PACKAGE_SUMMARY (mandatory) -#Check for a component description first. -#If not set, it will use regular package description logic. -if(CPACK_RPM_PACKAGE_COMPONENT) - if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_DESCRIPTION) - set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_DESCRIPTION}) - elseif(CPACK_COMPONENT_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DESCRIPTION) - set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_COMPONENT_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DESCRIPTION}) + #Check for component summary first. + #If not set, it will use regular package summary logic. + if(CPACK_RPM_PACKAGE_COMPONENT) + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_SUMMARY) + set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_SUMMARY}) + endif() endif() -endif() -if(NOT CPACK_RPM_PACKAGE_DESCRIPTION) - if(CPACK_RPM_PACKAGE_DESCRIPTION_) - set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_RPM_PACKAGE_DESCRIPTION_}) - elseif(CPACK_PACKAGE_DESCRIPTION_FILE) - file(READ ${CPACK_PACKAGE_DESCRIPTION_FILE} CPACK_RPM_PACKAGE_DESCRIPTION) - else () - set(CPACK_RPM_PACKAGE_DESCRIPTION "no package description available") - endif () -endif () + if(NOT CPACK_RPM_PACKAGE_SUMMARY) + if(CPACK_PACKAGE_DESCRIPTION_SUMMARY) + set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}) + else() + # if neither var is defined lets use the name as summary + string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_SUMMARY) + endif() + endif() -# CPACK_RPM_COMPRESSION_TYPE -# -if (CPACK_RPM_COMPRESSION_TYPE) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: User Specified RPM compression type: ${CPACK_RPM_COMPRESSION_TYPE}") - endif() - if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "lzma") - set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w9.lzdio") - endif() - if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "xz") - set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w7.xzdio") - endif() - if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "bzip2") - set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w9.bzdio") - endif() - if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "gzip") - set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w9.gzdio") - endif() -else() - set(CPACK_RPM_COMPRESSION_TYPE_TMP "") -endif() + # CPACK_RPM_PACKAGE_NAME (mandatory) + if(NOT CPACK_RPM_PACKAGE_NAME) + string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_NAME) + endif() -if(CPACK_PACKAGE_RELOCATABLE) - set(CPACK_RPM_PACKAGE_RELOCATABLE TRUE) -endif() -if(CPACK_RPM_PACKAGE_RELOCATABLE) - unset(TMP_RPM_PREFIXES) + # CPACK_RPM_PACKAGE_VERSION (mandatory) + if(NOT CPACK_RPM_PACKAGE_VERSION) + if(NOT CPACK_PACKAGE_VERSION) + message(FATAL_ERROR "RPM package requires a package version") + endif() + set(CPACK_RPM_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}) + endif() + # Replace '-' in version with '_' + # '-' character is an Illegal RPM version character + # it is illegal because it is used to separate + # RPM "Version" from RPM "Release" + string(REPLACE "-" "_" CPACK_RPM_PACKAGE_VERSION ${CPACK_RPM_PACKAGE_VERSION}) + + # CPACK_RPM_PACKAGE_ARCHITECTURE (mandatory) + if(NOT CPACK_RPM_PACKAGE_ARCHITECTURE) + execute_process(COMMAND uname "-m" + OUTPUT_VARIABLE CPACK_RPM_PACKAGE_ARCHITECTURE + OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: using user-specified build arch = ${CPACK_RPM_PACKAGE_ARCHITECTURE}") + endif() + endif() - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: Trying to build a relocatable package") + set(_CPACK_RPM_PACKAGE_ARCHITECTURE ${CPACK_RPM_PACKAGE_ARCHITECTURE}) + + #prefer component architecture + if(CPACK_RPM_PACKAGE_COMPONENT) + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_ARCHITECTURE) + set(_CPACK_RPM_PACKAGE_ARCHITECTURE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_ARCHITECTURE}) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: using component build arch = ${_CPACK_RPM_PACKAGE_ARCHITECTURE}") + endif() + endif() endif() - if(CPACK_SET_DESTDIR AND (NOT CPACK_SET_DESTDIR STREQUAL "I_ON")) - message("CPackRPM:Warning: CPACK_SET_DESTDIR is set (=${CPACK_SET_DESTDIR}) while requesting a relocatable package (CPACK_RPM_PACKAGE_RELOCATABLE is set): this is not supported, the package won't be relocatable.") + if(${_CPACK_RPM_PACKAGE_ARCHITECTURE} STREQUAL "noarch") + set(TMP_RPM_BUILDARCH "Buildarch: ${_CPACK_RPM_PACKAGE_ARCHITECTURE}") else() - set(CPACK_RPM_PACKAGE_PREFIX ${CPACK_PACKAGING_INSTALL_PREFIX}) # kept for back compatibility (provided external RPM spec files) - cpack_rpm_prepare_relocation_paths() + set(TMP_RPM_BUILDARCH "") + endif() + + # CPACK_RPM_PACKAGE_RELEASE + # The RPM release is the numbering of the RPM package ITSELF + # this is the version of the PACKAGING and NOT the version + # of the CONTENT of the package. + # You may well need to generate a new RPM package release + # without changing the version of the packaged software. + # This is the case when the packaging is buggy (not) the software :=) + # If not set, 1 is a good candidate + if(NOT CPACK_RPM_PACKAGE_RELEASE) + set(CPACK_RPM_PACKAGE_RELEASE 1) + endif() + + # CPACK_RPM_PACKAGE_LICENSE + if(NOT CPACK_RPM_PACKAGE_LICENSE) + set(CPACK_RPM_PACKAGE_LICENSE "unknown") + endif() + + # CPACK_RPM_PACKAGE_GROUP + if(NOT CPACK_RPM_PACKAGE_GROUP) + set(CPACK_RPM_PACKAGE_GROUP "unknown") + endif() + + # CPACK_RPM_PACKAGE_VENDOR + if(NOT CPACK_RPM_PACKAGE_VENDOR) + if(CPACK_PACKAGE_VENDOR) + set(CPACK_RPM_PACKAGE_VENDOR "${CPACK_PACKAGE_VENDOR}") + else() + set(CPACK_RPM_PACKAGE_VENDOR "unknown") + endif() endif() -endif() -# Check if additional fields for RPM spec header are given -# There may be some COMPONENT specific variables as well -# If component specific var is not provided we use the global one -# for each component -foreach(_RPM_SPEC_HEADER URL REQUIRES SUGGESTS PROVIDES OBSOLETES PREFIX CONFLICTS AUTOPROV AUTOREQ AUTOREQPROV REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN) + # CPACK_RPM_PACKAGE_SOURCE + # The name of the source tarball in case we generate a source RPM + + # CPACK_RPM_PACKAGE_DESCRIPTION + # The variable content may be either + # - explicitly given by the user or + # - filled with the content of CPACK_PACKAGE_DESCRIPTION_FILE + # if it is defined + # - set to a default value + # + + #Check for a component description first. + #If not set, it will use regular package description logic. + if(CPACK_RPM_PACKAGE_COMPONENT) + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_DESCRIPTION) + set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_DESCRIPTION}) + elseif(CPACK_COMPONENT_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DESCRIPTION) + set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_COMPONENT_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DESCRIPTION}) + endif() + endif() + + if(NOT CPACK_RPM_PACKAGE_DESCRIPTION) + if(CPACK_PACKAGE_DESCRIPTION_FILE) + file(READ ${CPACK_PACKAGE_DESCRIPTION_FILE} CPACK_RPM_PACKAGE_DESCRIPTION) + else () + set(CPACK_RPM_PACKAGE_DESCRIPTION "no package description available") + endif () + endif () + + # CPACK_RPM_COMPRESSION_TYPE + # + if (CPACK_RPM_COMPRESSION_TYPE) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: User Specified RPM compression type: ${CPACK_RPM_COMPRESSION_TYPE}") + endif() + if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "lzma") + set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w9.lzdio") + endif() + if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "xz") + set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w7.xzdio") + endif() + if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "bzip2") + set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w9.bzdio") + endif() + if(CPACK_RPM_COMPRESSION_TYPE STREQUAL "gzip") + set(CPACK_RPM_COMPRESSION_TYPE_TMP "%define _binary_payload w9.gzdio") + endif() + else() + set(CPACK_RPM_COMPRESSION_TYPE_TMP "") + endif() + + if(CPACK_PACKAGE_RELOCATABLE) + set(CPACK_RPM_PACKAGE_RELOCATABLE TRUE) + endif() + if(CPACK_RPM_PACKAGE_RELOCATABLE) if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: processing ${_RPM_SPEC_HEADER}") + message("CPackRPM:Debug: Trying to build a relocatable package") endif() - if(CPACK_RPM_PACKAGE_COMPONENT) - if(DEFINED CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: using CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}") - endif() - set(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}}) - else() - if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}) + if(CPACK_SET_DESTDIR AND (NOT CPACK_SET_DESTDIR STREQUAL "I_ON")) + message("CPackRPM:Warning: CPACK_SET_DESTDIR is set (=${CPACK_SET_DESTDIR}) while requesting a relocatable package (CPACK_RPM_PACKAGE_RELOCATABLE is set): this is not supported, the package won't be relocatable.") + else() + set(CPACK_RPM_PACKAGE_PREFIX ${CPACK_PACKAGING_INSTALL_PREFIX}) # kept for back compatibility (provided external RPM spec files) + cpack_rpm_prepare_relocation_paths() + endif() + endif() + + # Check if additional fields for RPM spec header are given + # There may be some COMPONENT specific variables as well + # If component specific var is not provided we use the global one + # for each component + foreach(_RPM_SPEC_HEADER URL REQUIRES SUGGESTS PROVIDES OBSOLETES PREFIX CONFLICTS AUTOPROV AUTOREQ AUTOREQPROV REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: processing ${_RPM_SPEC_HEADER}") + endif() + if(CPACK_RPM_PACKAGE_COMPONENT) + if(DEFINED CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}) if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER} not defined") - message("CPackRPM:Debug: using CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}") + message("CPackRPM:Debug: using CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}") + endif() + set(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER}}) + else() + if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_${_RPM_SPEC_HEADER} not defined") + message("CPackRPM:Debug: using CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}") + endif() + set(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}}) endif() - set(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}}) + endif() + else() + if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: using CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}") endif() - endif() - else() - if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: using CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}") + set(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}}) endif() - set(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}}) - endif() - endif() + endif() - # Do not forget to unset previously set header (from previous component) - unset(TMP_RPM_${_RPM_SPEC_HEADER}) - # Treat the RPM Spec keyword iff it has been properly defined - if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP) - # Transform NAME --> Name e.g. PROVIDES --> Provides - # The Upper-case first letter and lowercase tail is the - # appropriate value required in the final RPM spec file. - string(SUBSTRING ${_RPM_SPEC_HEADER} 1 -1 _PACKAGE_HEADER_TAIL) - string(TOLOWER "${_PACKAGE_HEADER_TAIL}" _PACKAGE_HEADER_TAIL) - string(SUBSTRING ${_RPM_SPEC_HEADER} 0 1 _PACKAGE_HEADER_NAME) - set(_PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_NAME}${_PACKAGE_HEADER_TAIL}") - # The following keywords require parentheses around the "pre" or "post" suffix in the final RPM spec file. - set(SCRIPTS_REQUIREMENTS_LIST REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN) - list(FIND SCRIPTS_REQUIREMENTS_LIST ${_RPM_SPEC_HEADER} IS_SCRIPTS_REQUIREMENT_FOUND) - if(NOT ${IS_SCRIPTS_REQUIREMENT_FOUND} EQUAL -1) - string(REPLACE "_" "(" _PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_NAME}") - set(_PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_NAME})") + # Treat the RPM Spec keyword iff it has been properly defined + if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP) + # Transform NAME --> Name e.g. PROVIDES --> Provides + # The Upper-case first letter and lowercase tail is the + # appropriate value required in the final RPM spec file. + string(SUBSTRING ${_RPM_SPEC_HEADER} 1 -1 _PACKAGE_HEADER_TAIL) + string(TOLOWER "${_PACKAGE_HEADER_TAIL}" _PACKAGE_HEADER_TAIL) + string(SUBSTRING ${_RPM_SPEC_HEADER} 0 1 _PACKAGE_HEADER_NAME) + set(_PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_NAME}${_PACKAGE_HEADER_TAIL}") + # The following keywords require parentheses around the "pre" or "post" suffix in the final RPM spec file. + set(SCRIPTS_REQUIREMENTS_LIST REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN) + list(FIND SCRIPTS_REQUIREMENTS_LIST ${_RPM_SPEC_HEADER} IS_SCRIPTS_REQUIREMENT_FOUND) + if(NOT ${IS_SCRIPTS_REQUIREMENT_FOUND} EQUAL -1) + string(REPLACE "_" "(" _PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_NAME}") + set(_PACKAGE_HEADER_NAME "${_PACKAGE_HEADER_NAME})") + endif() + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: User defined ${_PACKAGE_HEADER_NAME}:\n ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP}") + endif() + set(TMP_RPM_${_RPM_SPEC_HEADER} "${_PACKAGE_HEADER_NAME}: ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP}") + unset(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP) endif() + endforeach() + + # CPACK_RPM_SPEC_INSTALL_POST + # May be used to define a RPM post intallation script + # for example setting it to "/bin/true" may prevent + # rpmbuild from stripping binaries. + if(CPACK_RPM_SPEC_INSTALL_POST) if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: User defined ${_PACKAGE_HEADER_NAME}:\n ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP}") + message("CPackRPM:Debug: User defined CPACK_RPM_SPEC_INSTALL_POST = ${CPACK_RPM_SPEC_INSTALL_POST}") endif() - set(TMP_RPM_${_RPM_SPEC_HEADER} "${_PACKAGE_HEADER_NAME}: ${CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP}") - unset(CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}_TMP) + set(TMP_RPM_SPEC_INSTALL_POST "%define __spec_install_post ${CPACK_RPM_SPEC_INSTALL_POST}") endif() -endforeach() -# CPACK_RPM_SPEC_INSTALL_POST -# May be used to define a RPM post intallation script -# for example setting it to "/bin/true" may prevent -# rpmbuild from stripping binaries. -if(CPACK_RPM_SPEC_INSTALL_POST) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: User defined CPACK_RPM_SPEC_INSTALL_POST = ${CPACK_RPM_SPEC_INSTALL_POST}") - endif() - set(TMP_RPM_SPEC_INSTALL_POST "%define __spec_install_post ${CPACK_RPM_SPEC_INSTALL_POST}") -endif() - -# CPACK_RPM_POST_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_INSTALL_SCRIPT_FILE) -# CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE) -# May be used to embed a post (un)installation script in the spec file. -# The refered script file(s) will be read and directly -# put after the %post or %postun section -if(CPACK_RPM_PACKAGE_COMPONENT) - if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_INSTALL_SCRIPT_FILE) - set(CPACK_RPM_POST_INSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_INSTALL_SCRIPT_FILE}) + # CPACK_RPM_POST_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_INSTALL_SCRIPT_FILE) + # CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE) + # May be used to embed a post (un)installation script in the spec file. + # The refered script file(s) will be read and directly + # put after the %post or %postun section + if(CPACK_RPM_PACKAGE_COMPONENT) + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_INSTALL_SCRIPT_FILE) + set(CPACK_RPM_POST_INSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_INSTALL_SCRIPT_FILE}) + else() + set(CPACK_RPM_POST_INSTALL_READ_FILE ${CPACK_RPM_POST_INSTALL_SCRIPT_FILE}) + endif() + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_UNINSTALL_SCRIPT_FILE) + set(CPACK_RPM_POST_UNINSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_UNINSTALL_SCRIPT_FILE}) + else() + set(CPACK_RPM_POST_UNINSTALL_READ_FILE ${CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE}) + endif() else() set(CPACK_RPM_POST_INSTALL_READ_FILE ${CPACK_RPM_POST_INSTALL_SCRIPT_FILE}) - endif() - if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_UNINSTALL_SCRIPT_FILE) - set(CPACK_RPM_POST_UNINSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_POST_UNINSTALL_SCRIPT_FILE}) - else() set(CPACK_RPM_POST_UNINSTALL_READ_FILE ${CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE}) endif() -else() - set(CPACK_RPM_POST_INSTALL_READ_FILE ${CPACK_RPM_POST_INSTALL_SCRIPT_FILE}) - set(CPACK_RPM_POST_UNINSTALL_READ_FILE ${CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE}) -endif() -# Handle post-install file if it has been specified -if(CPACK_RPM_POST_INSTALL_READ_FILE) - if(EXISTS ${CPACK_RPM_POST_INSTALL_READ_FILE}) - file(READ ${CPACK_RPM_POST_INSTALL_READ_FILE} CPACK_RPM_SPEC_POSTINSTALL) + # Handle post-install file if it has been specified + if(CPACK_RPM_POST_INSTALL_READ_FILE) + if(EXISTS ${CPACK_RPM_POST_INSTALL_READ_FILE}) + file(READ ${CPACK_RPM_POST_INSTALL_READ_FILE} CPACK_RPM_SPEC_POSTINSTALL) + else() + message("CPackRPM:Warning: CPACK_RPM_POST_INSTALL_SCRIPT_FILE <${CPACK_RPM_POST_INSTALL_READ_FILE}> does not exists - ignoring") + endif() else() - message("CPackRPM:Warning: CPACK_RPM_POST_INSTALL_SCRIPT_FILE <${CPACK_RPM_POST_INSTALL_READ_FILE}> does not exists - ignoring") + # reset SPEC var value if no post install file has been specified + # (either globally or component-wise) + set(CPACK_RPM_SPEC_POSTINSTALL "") endif() -else() - # reset SPEC var value if no post install file has been specified - # (either globally or component-wise) - set(CPACK_RPM_SPEC_POSTINSTALL "") -endif() -# Handle post-uninstall file if it has been specified -if(CPACK_RPM_POST_UNINSTALL_READ_FILE) - if(EXISTS ${CPACK_RPM_POST_UNINSTALL_READ_FILE}) - file(READ ${CPACK_RPM_POST_UNINSTALL_READ_FILE} CPACK_RPM_SPEC_POSTUNINSTALL) + # Handle post-uninstall file if it has been specified + if(CPACK_RPM_POST_UNINSTALL_READ_FILE) + if(EXISTS ${CPACK_RPM_POST_UNINSTALL_READ_FILE}) + file(READ ${CPACK_RPM_POST_UNINSTALL_READ_FILE} CPACK_RPM_SPEC_POSTUNINSTALL) + else() + message("CPackRPM:Warning: CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE <${CPACK_RPM_POST_UNINSTALL_READ_FILE}> does not exists - ignoring") + endif() else() - message("CPackRPM:Warning: CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE <${CPACK_RPM_POST_UNINSTALL_READ_FILE}> does not exists - ignoring") + # reset SPEC var value if no post uninstall file has been specified + # (either globally or component-wise) + set(CPACK_RPM_SPEC_POSTUNINSTALL "") endif() -else() - # reset SPEC var value if no post uninstall file has been specified - # (either globally or component-wise) - set(CPACK_RPM_SPEC_POSTUNINSTALL "") -endif() -# CPACK_RPM_PRE_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_PRE_INSTALL_SCRIPT_FILE) -# CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_PRE_UNINSTALL_SCRIPT_FILE) -# May be used to embed a pre (un)installation script in the spec file. -# The refered script file(s) will be read and directly -# put after the %pre or %preun section -if(CPACK_RPM_PACKAGE_COMPONENT) - if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_INSTALL_SCRIPT_FILE) - set(CPACK_RPM_PRE_INSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_INSTALL_SCRIPT_FILE}) + # CPACK_RPM_PRE_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_PRE_INSTALL_SCRIPT_FILE) + # CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_PRE_UNINSTALL_SCRIPT_FILE) + # May be used to embed a pre (un)installation script in the spec file. + # The refered script file(s) will be read and directly + # put after the %pre or %preun section + if(CPACK_RPM_PACKAGE_COMPONENT) + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_INSTALL_SCRIPT_FILE) + set(CPACK_RPM_PRE_INSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_INSTALL_SCRIPT_FILE}) + else() + set(CPACK_RPM_PRE_INSTALL_READ_FILE ${CPACK_RPM_PRE_INSTALL_SCRIPT_FILE}) + endif() + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_UNINSTALL_SCRIPT_FILE) + set(CPACK_RPM_PRE_UNINSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_UNINSTALL_SCRIPT_FILE}) + else() + set(CPACK_RPM_PRE_UNINSTALL_READ_FILE ${CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE}) + endif() else() set(CPACK_RPM_PRE_INSTALL_READ_FILE ${CPACK_RPM_PRE_INSTALL_SCRIPT_FILE}) - endif() - if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_UNINSTALL_SCRIPT_FILE) - set(CPACK_RPM_PRE_UNINSTALL_READ_FILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PRE_UNINSTALL_SCRIPT_FILE}) - else() set(CPACK_RPM_PRE_UNINSTALL_READ_FILE ${CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE}) endif() -else() - set(CPACK_RPM_PRE_INSTALL_READ_FILE ${CPACK_RPM_PRE_INSTALL_SCRIPT_FILE}) - set(CPACK_RPM_PRE_UNINSTALL_READ_FILE ${CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE}) -endif() -# Handle pre-install file if it has been specified -if(CPACK_RPM_PRE_INSTALL_READ_FILE) - if(EXISTS ${CPACK_RPM_PRE_INSTALL_READ_FILE}) - file(READ ${CPACK_RPM_PRE_INSTALL_READ_FILE} CPACK_RPM_SPEC_PREINSTALL) + # Handle pre-install file if it has been specified + if(CPACK_RPM_PRE_INSTALL_READ_FILE) + if(EXISTS ${CPACK_RPM_PRE_INSTALL_READ_FILE}) + file(READ ${CPACK_RPM_PRE_INSTALL_READ_FILE} CPACK_RPM_SPEC_PREINSTALL) + else() + message("CPackRPM:Warning: CPACK_RPM_PRE_INSTALL_SCRIPT_FILE <${CPACK_RPM_PRE_INSTALL_READ_FILE}> does not exists - ignoring") + endif() else() - message("CPackRPM:Warning: CPACK_RPM_PRE_INSTALL_SCRIPT_FILE <${CPACK_RPM_PRE_INSTALL_READ_FILE}> does not exists - ignoring") + # reset SPEC var value if no pre-install file has been specified + # (either globally or component-wise) + set(CPACK_RPM_SPEC_PREINSTALL "") endif() -else() - # reset SPEC var value if no pre-install file has been specified - # (either globally or component-wise) - set(CPACK_RPM_SPEC_PREINSTALL "") -endif() -# Handle pre-uninstall file if it has been specified -if(CPACK_RPM_PRE_UNINSTALL_READ_FILE) - if(EXISTS ${CPACK_RPM_PRE_UNINSTALL_READ_FILE}) - file(READ ${CPACK_RPM_PRE_UNINSTALL_READ_FILE} CPACK_RPM_SPEC_PREUNINSTALL) + # Handle pre-uninstall file if it has been specified + if(CPACK_RPM_PRE_UNINSTALL_READ_FILE) + if(EXISTS ${CPACK_RPM_PRE_UNINSTALL_READ_FILE}) + file(READ ${CPACK_RPM_PRE_UNINSTALL_READ_FILE} CPACK_RPM_SPEC_PREUNINSTALL) + else() + message("CPackRPM:Warning: CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE <${CPACK_RPM_PRE_UNINSTALL_READ_FILE}> does not exists - ignoring") + endif() else() - message("CPackRPM:Warning: CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE <${CPACK_RPM_PRE_UNINSTALL_READ_FILE}> does not exists - ignoring") + # reset SPEC var value if no pre-uninstall file has been specified + # (either globally or component-wise) + set(CPACK_RPM_SPEC_PREUNINSTALL "") endif() -else() - # reset SPEC var value if no pre-uninstall file has been specified - # (either globally or component-wise) - set(CPACK_RPM_SPEC_PREUNINSTALL "") -endif() -# CPACK_RPM_CHANGELOG_FILE -# May be used to embed a changelog in the spec file. -# The refered file will be read and directly put after the %changelog section -if(CPACK_RPM_CHANGELOG_FILE) - if(EXISTS ${CPACK_RPM_CHANGELOG_FILE}) - file(READ ${CPACK_RPM_CHANGELOG_FILE} CPACK_RPM_SPEC_CHANGELOG) + # CPACK_RPM_CHANGELOG_FILE + # May be used to embed a changelog in the spec file. + # The refered file will be read and directly put after the %changelog section + if(CPACK_RPM_CHANGELOG_FILE) + if(EXISTS ${CPACK_RPM_CHANGELOG_FILE}) + file(READ ${CPACK_RPM_CHANGELOG_FILE} CPACK_RPM_SPEC_CHANGELOG) + else() + message(SEND_ERROR "CPackRPM:Warning: CPACK_RPM_CHANGELOG_FILE <${CPACK_RPM_CHANGELOG_FILE}> does not exists - ignoring") + endif() else() - message(SEND_ERROR "CPackRPM:Warning: CPACK_RPM_CHANGELOG_FILE <${CPACK_RPM_CHANGELOG_FILE}> does not exists - ignoring") - endif() -else() - set(CPACK_RPM_SPEC_CHANGELOG "* Sun Jul 4 2010 Eric Noulard <eric.noulard@gmail.com> - ${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n Generated by CPack RPM (no Changelog file were provided)") -endif() - -# CPACK_RPM_SPEC_MORE_DEFINE -# This is a generated spec rpm file spaceholder -if(CPACK_RPM_SPEC_MORE_DEFINE) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: User defined more define spec line specified:\n ${CPACK_RPM_SPEC_MORE_DEFINE}") + set(CPACK_RPM_SPEC_CHANGELOG "* Sun Jul 4 2010 Eric Noulard <eric.noulard@gmail.com> - ${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n Generated by CPack RPM (no Changelog file were provided)") endif() -endif() -# Now we may create the RPM build tree structure -set(CPACK_RPM_ROOTDIR "${CPACK_TOPLEVEL_DIRECTORY}") -message(STATUS "CPackRPM:Debug: Using CPACK_RPM_ROOTDIR=${CPACK_RPM_ROOTDIR}") -# Prepare RPM build tree -file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}) -file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/tmp) -file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/BUILD) -file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/RPMS) -file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SOURCES) -file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SPECS) -file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SRPMS) - -#set(CPACK_RPM_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}-${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm") -set(CPACK_RPM_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}") -# it seems rpmbuild can't handle spaces in the path -# neither escaping (as below) nor putting quotes around the path seem to help -#string(REGEX REPLACE " " "\\\\ " CPACK_RPM_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}") -set(CPACK_RPM_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}") - -# if we are creating a relocatable package, omit parent directories of -# CPACK_RPM_PACKAGE_PREFIX. This is achieved by building a "filter list" -# which is passed to the find command that generates the content-list -if(CPACK_RPM_PACKAGE_RELOCATABLE) - # get a list of the elements in CPACK_RPM_PACKAGE_PREFIXES that are - # destinct parent paths of other relocation paths and remove the - # final element (so the install-prefix dir itself is not omitted - # from the RPM's content-list) - list(SORT RPM_USED_PACKAGE_PREFIXES) - set(_DISTINCT_PATH "NOT_SET") - foreach(_RPM_RELOCATION_PREFIX ${RPM_USED_PACKAGE_PREFIXES}) - if(NOT "${_RPM_RELOCATION_PREFIX}" MATCHES "${_DISTINCT_PATH}/.*") - set(_DISTINCT_PATH "${_RPM_RELOCATION_PREFIX}") - - string(REPLACE "/" ";" _CPACK_RPM_PACKAGE_PREFIX_ELEMS ".${_RPM_RELOCATION_PREFIX}") - list(REMOVE_AT _CPACK_RPM_PACKAGE_PREFIX_ELEMS -1) - unset(_TMP_LIST) - # Now generate all of the parent dirs of the relocation path - foreach(_PREFIX_PATH_ELEM ${_CPACK_RPM_PACKAGE_PREFIX_ELEMS}) - list(APPEND _TMP_LIST "${_PREFIX_PATH_ELEM}") - string(REPLACE ";" "/" _OMIT_DIR "${_TMP_LIST}") - list(FIND _RPM_DIRS_TO_OMIT "${_OMIT_DIR}" _DUPLICATE_FOUND) - if(_DUPLICATE_FOUND EQUAL -1) - set(_OMIT_DIR "-o -path ${_OMIT_DIR}") - separate_arguments(_OMIT_DIR) - list(APPEND _RPM_DIRS_TO_OMIT ${_OMIT_DIR}) - endif() - endforeach() + # CPACK_RPM_SPEC_MORE_DEFINE + # This is a generated spec rpm file spaceholder + if(CPACK_RPM_SPEC_MORE_DEFINE) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: User defined more define spec line specified:\n ${CPACK_RPM_SPEC_MORE_DEFINE}") endif() - endforeach() -endif() - -if (CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: Initial list of path to OMIT in RPM: ${_RPM_DIRS_TO_OMIT}") -endif() + endif() -if (NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) - set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/include) - if (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION) - message("CPackRPM:Debug: Adding ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION} to builtin omit list.") - list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST "${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION}") + # Now we may create the RPM build tree structure + set(CPACK_RPM_ROOTDIR "${CPACK_TOPLEVEL_DIRECTORY}") + message(STATUS "CPackRPM:Debug: Using CPACK_RPM_ROOTDIR=${CPACK_RPM_ROOTDIR}") + # Prepare RPM build tree + file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}) + file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/tmp) + file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/BUILD) + file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/RPMS) + file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SOURCES) + file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SPECS) + file(MAKE_DIRECTORY ${CPACK_RPM_ROOTDIR}/SRPMS) + + #set(CPACK_RPM_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}-${_CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm") + set(CPACK_RPM_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}") + # it seems rpmbuild can't handle spaces in the path + # neither escaping (as below) nor putting quotes around the path seem to help + #string(REGEX REPLACE " " "\\\\ " CPACK_RPM_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}") + set(CPACK_RPM_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}") + + # if we are creating a relocatable package, omit parent directories of + # CPACK_RPM_PACKAGE_PREFIX. This is achieved by building a "filter list" + # which is passed to the find command that generates the content-list + if(CPACK_RPM_PACKAGE_RELOCATABLE) + # get a list of the elements in CPACK_RPM_PACKAGE_PREFIXES that are + # destinct parent paths of other relocation paths and remove the + # final element (so the install-prefix dir itself is not omitted + # from the RPM's content-list) + set(SORTED_RPM_USED_PACKAGE_PREFIXES "${RPM_USED_PACKAGE_PREFIXES}") + list(SORT SORTED_RPM_USED_PACKAGE_PREFIXES) + set(_DISTINCT_PATH "NOT_SET") + foreach(_RPM_RELOCATION_PREFIX ${SORTED_RPM_USED_PACKAGE_PREFIXES}) + if(NOT "${_RPM_RELOCATION_PREFIX}" MATCHES "${_DISTINCT_PATH}/.*") + set(_DISTINCT_PATH "${_RPM_RELOCATION_PREFIX}") + + string(REPLACE "/" ";" _CPACK_RPM_PACKAGE_PREFIX_ELEMS ".${_RPM_RELOCATION_PREFIX}") + list(REMOVE_AT _CPACK_RPM_PACKAGE_PREFIX_ELEMS -1) + unset(_TMP_LIST) + # Now generate all of the parent dirs of the relocation path + foreach(_PREFIX_PATH_ELEM ${_CPACK_RPM_PACKAGE_PREFIX_ELEMS}) + list(APPEND _TMP_LIST "${_PREFIX_PATH_ELEM}") + string(REPLACE ";" "/" _OMIT_DIR "${_TMP_LIST}") + list(FIND _RPM_DIRS_TO_OMIT "${_OMIT_DIR}" _DUPLICATE_FOUND) + if(_DUPLICATE_FOUND EQUAL -1) + set(_OMIT_DIR "-o -path ${_OMIT_DIR}") + separate_arguments(_OMIT_DIR) + list(APPEND _RPM_DIRS_TO_OMIT ${_OMIT_DIR}) + endif() + endforeach() + endif() + endforeach() endif() -endif() -if(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) if (CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST= ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST}") - endif() - foreach(_DIR ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST}) - list(APPEND _RPM_DIRS_TO_OMIT "-o;-path;.${_DIR}") - endforeach() -endif() -if (CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: Final list of path to OMIT in RPM: ${_RPM_DIRS_TO_OMIT}") -endif() + message("CPackRPM:Debug: Initial list of path to OMIT in RPM: ${_RPM_DIRS_TO_OMIT}") + endif() + + if (NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) + set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/include) + if (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION) + message("CPackRPM:Debug: Adding ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION} to builtin omit list.") + list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST "${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION}") + endif() + endif() -# Use files tree to construct files command (spec file) -# We should not forget to include symlinks (thus -o -type l) -# We should include directory as well (thus -type d) -# but not the main local dir "." (thus -a -not -name ".") -# We must remove the './' due to the local search and escape the -# file name by enclosing it between double quotes (thus the sed) -# Then we must authorize any man pages extension (adding * at the end) -# because rpmbuild may automatically compress those files -execute_process(COMMAND find . -type f -o -type l -o (-type d -a -not ( -name "." ${_RPM_DIRS_TO_OMIT} ) ) - COMMAND sed s:.*/man.*/.*:&*: - COMMAND sed s/\\.\\\(.*\\\)/\"\\1\"/ - WORKING_DIRECTORY "${WDIR}" - OUTPUT_VARIABLE CPACK_RPM_INSTALL_FILES) - -# In component case, put CPACK_ABSOLUTE_DESTINATION_FILES_<COMPONENT> -# into CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL -# otherwise, put CPACK_ABSOLUTE_DESTINATION_FILES -# This must be done BEFORE the CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL handling -if(CPACK_RPM_PACKAGE_COMPONENT) - if(CPACK_ABSOLUTE_DESTINATION_FILES) - set(COMPONENT_FILES_TAG "CPACK_ABSOLUTE_DESTINATION_FILES_${CPACK_RPM_PACKAGE_COMPONENT}") - set(CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL "${${COMPONENT_FILES_TAG}}") - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: Handling Absolute Destination Files: <${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}>") - message("CPackRPM:Debug: in component = ${CPACK_RPM_PACKAGE_COMPONENT}") + if(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) + if (CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST= ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST}") endif() + foreach(_DIR ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST}) + list(APPEND _RPM_DIRS_TO_OMIT "-o;-path;.${_DIR}") + endforeach() endif() -else() - if(CPACK_ABSOLUTE_DESTINATION_FILES) - set(CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL "${CPACK_ABSOLUTE_DESTINATION_FILES}") + if (CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: Final list of path to OMIT in RPM: ${_RPM_DIRS_TO_OMIT}") endif() -endif() -# In component case, set CPACK_RPM_USER_FILELIST_INTERNAL with CPACK_RPM_<COMPONENT>_USER_FILELIST. -if(CPACK_RPM_PACKAGE_COMPONENT) - if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_FILELIST) - set(CPACK_RPM_USER_FILELIST_INTERNAL ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_FILELIST}) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: Handling User Filelist: <${CPACK_RPM_USER_FILELIST_INTERNAL}>") - message("CPackRPM:Debug: in component = ${CPACK_RPM_PACKAGE_COMPONENT}") + # Use files tree to construct files command (spec file) + # We should not forget to include symlinks (thus -o -type l) + # We should include directory as well (thus -type d) + # but not the main local dir "." (thus -a -not -name ".") + # We must remove the './' due to the local search and escape the + # file name by enclosing it between double quotes (thus the sed) + # Then we must authorize any man pages extension (adding * at the end) + # because rpmbuild may automatically compress those files + execute_process(COMMAND find . -type f -o -type l -o (-type d -a -not ( -name "." ${_RPM_DIRS_TO_OMIT} ) ) + COMMAND sed s:.*/man.*/.*:&*: + COMMAND sed s/\\.\\\(.*\\\)/\"\\1\"/ + WORKING_DIRECTORY "${WDIR}" + OUTPUT_VARIABLE CPACK_RPM_INSTALL_FILES) + + # In component case, put CPACK_ABSOLUTE_DESTINATION_FILES_<COMPONENT> + # into CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL + # otherwise, put CPACK_ABSOLUTE_DESTINATION_FILES + # This must be done BEFORE the CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL handling + if(CPACK_RPM_PACKAGE_COMPONENT) + if(CPACK_ABSOLUTE_DESTINATION_FILES) + set(COMPONENT_FILES_TAG "CPACK_ABSOLUTE_DESTINATION_FILES_${CPACK_RPM_PACKAGE_COMPONENT}") + set(CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL "${${COMPONENT_FILES_TAG}}") + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: Handling Absolute Destination Files: <${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}>") + message("CPackRPM:Debug: in component = ${CPACK_RPM_PACKAGE_COMPONENT}") + endif() endif() else() - set(CPACK_RPM_USER_FILELIST_INTERNAL "") + if(CPACK_ABSOLUTE_DESTINATION_FILES) + set(CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL "${CPACK_ABSOLUTE_DESTINATION_FILES}") + endif() endif() -else() - if(CPACK_RPM_USER_FILELIST) - set(CPACK_RPM_USER_FILELIST_INTERNAL "${CPACK_RPM_USER_FILELIST}") + + # In component case, set CPACK_RPM_USER_FILELIST_INTERNAL with CPACK_RPM_<COMPONENT>_USER_FILELIST. + if(CPACK_RPM_PACKAGE_COMPONENT) + if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_FILELIST) + set(CPACK_RPM_USER_FILELIST_INTERNAL ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_FILELIST}) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: Handling User Filelist: <${CPACK_RPM_USER_FILELIST_INTERNAL}>") + message("CPackRPM:Debug: in component = ${CPACK_RPM_PACKAGE_COMPONENT}") + endif() + else() + set(CPACK_RPM_USER_FILELIST_INTERNAL "") + endif() else() - set(CPACK_RPM_USER_FILELIST_INTERNAL "") + if(CPACK_RPM_USER_FILELIST) + set(CPACK_RPM_USER_FILELIST_INTERNAL "${CPACK_RPM_USER_FILELIST}") + else() + set(CPACK_RPM_USER_FILELIST_INTERNAL "") + endif() endif() -endif() -# Handle user specified file line list in CPACK_RPM_USER_FILELIST_INTERNAL -# Remove those files from CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL -# or CPACK_RPM_INSTALL_FILES, -# hence it must be done before these auto-generated lists are processed. -if(CPACK_RPM_USER_FILELIST_INTERNAL) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: Handling User Filelist: <${CPACK_RPM_USER_FILELIST_INTERNAL}>") - endif() + # Handle user specified file line list in CPACK_RPM_USER_FILELIST_INTERNAL + # Remove those files from CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL + # or CPACK_RPM_INSTALL_FILES, + # hence it must be done before these auto-generated lists are processed. + if(CPACK_RPM_USER_FILELIST_INTERNAL) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: Handling User Filelist: <${CPACK_RPM_USER_FILELIST_INTERNAL}>") + endif() + + # Create CMake list from CPACK_RPM_INSTALL_FILES + string(STRIP "${CPACK_RPM_INSTALL_FILES}" CPACK_RPM_INSTALL_FILES_LIST) + string(REPLACE "\n" ";" CPACK_RPM_INSTALL_FILES_LIST + "${CPACK_RPM_INSTALL_FILES_LIST}") + string(REPLACE "\"" "" CPACK_RPM_INSTALL_FILES_LIST + "${CPACK_RPM_INSTALL_FILES_LIST}") + + set(CPACK_RPM_USER_INSTALL_FILES "") + foreach(F IN LISTS CPACK_RPM_USER_FILELIST_INTERNAL) + string(REGEX REPLACE "%[A-Za-z0-9\(\),-]* " "" F_PATH ${F}) + string(REGEX MATCH "%[A-Za-z0-9\(\),-]*" F_PREFIX ${F}) - # Create CMake list from CPACK_RPM_INSTALL_FILES - string(STRIP "${CPACK_RPM_INSTALL_FILES}" CPACK_RPM_INSTALL_FILES_LIST) - string(REPLACE "\n" ";" CPACK_RPM_INSTALL_FILES_LIST - "${CPACK_RPM_INSTALL_FILES_LIST}") - string(REPLACE "\"" "" CPACK_RPM_INSTALL_FILES_LIST - "${CPACK_RPM_INSTALL_FILES_LIST}") + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: F_PREFIX=<${F_PREFIX}>, F_PATH=<${F_PATH}>") + endif() + if(F_PREFIX) + set(F_PREFIX "${F_PREFIX} ") + endif() + # Rebuild the user list file + set(CPACK_RPM_USER_INSTALL_FILES "${CPACK_RPM_USER_INSTALL_FILES}${F_PREFIX}\"${F_PATH}\"\n") + + # Remove from CPACK_RPM_INSTALL_FILES and CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL + list(REMOVE_ITEM CPACK_RPM_INSTALL_FILES_LIST ${F_PATH}) + # ABSOLUTE destination files list may not exists at all + if (CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL) + list(REMOVE_ITEM CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL ${F_PATH}) + endif() + + endforeach() - set(CPACK_RPM_USER_INSTALL_FILES "") - foreach(F IN LISTS CPACK_RPM_USER_FILELIST_INTERNAL) - string(REGEX REPLACE "%[A-Za-z0-9\(\),-]* " "" F_PATH ${F}) - string(REGEX MATCH "%[A-Za-z0-9\(\),-]*" F_PREFIX ${F}) + # Rebuild CPACK_RPM_INSTALL_FILES + set(CPACK_RPM_INSTALL_FILES "") + foreach(F IN LISTS CPACK_RPM_INSTALL_FILES_LIST) + set(CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}\"${F}\"\n") + endforeach() + else() + set(CPACK_RPM_USER_INSTALL_FILES "") + endif() + if (CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL) if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: F_PREFIX=<${F_PREFIX}>, F_PATH=<${F_PATH}>") + message("CPackRPM:Debug: Handling Absolute Destination Files: ${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}") endif() - if(F_PREFIX) - set(F_PREFIX "${F_PREFIX} ") - endif() - # Rebuild the user list file - set(CPACK_RPM_USER_INSTALL_FILES "${CPACK_RPM_USER_INSTALL_FILES}${F_PREFIX}\"${F_PATH}\"\n") - - # Remove from CPACK_RPM_INSTALL_FILES and CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL - list(REMOVE_ITEM CPACK_RPM_INSTALL_FILES_LIST ${F_PATH}) - # ABSOLUTE destination files list may not exists at all - if (CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL) - list(REMOVE_ITEM CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL ${F_PATH}) + # Remove trailing space + string(STRIP "${CPACK_RPM_INSTALL_FILES}" CPACK_RPM_INSTALL_FILES_LIST) + # Transform endline separated - string into CMake List + string(REPLACE "\n" ";" CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES_LIST}") + # Remove unecessary quotes + string(REPLACE "\"" "" CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES_LIST}") + # Remove ABSOLUTE install file from INSTALL FILE LIST + list(REMOVE_ITEM CPACK_RPM_INSTALL_FILES_LIST ${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}) + # Rebuild INSTALL_FILES + set(CPACK_RPM_INSTALL_FILES "") + foreach(F IN LISTS CPACK_RPM_INSTALL_FILES_LIST) + set(CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}\"${F}\"\n") + endforeach() + # Build ABSOLUTE_INSTALL_FILES + set(CPACK_RPM_ABSOLUTE_INSTALL_FILES "") + foreach(F IN LISTS CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL) + set(CPACK_RPM_ABSOLUTE_INSTALL_FILES "${CPACK_RPM_ABSOLUTE_INSTALL_FILES}%config \"${F}\"\n") + endforeach() + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: CPACK_RPM_ABSOLUTE_INSTALL_FILES=${CPACK_RPM_ABSOLUTE_INSTALL_FILES}") + message("CPackRPM:Debug: CPACK_RPM_INSTALL_FILES=${CPACK_RPM_INSTALL_FILES}") endif() + else() + # reset vars in order to avoid leakage of value(s) from one component to another + set(CPACK_RPM_ABSOLUTE_INSTALL_FILES "") + endif() - endforeach() + # Prepare install files + cpack_rpm_prepare_install_files( + "${CPACK_RPM_INSTALL_FILES}" + "${WDIR}" + "${RPM_USED_PACKAGE_PREFIXES}" + "${CPACK_RPM_PACKAGE_RELOCATABLE}" + ) - # Rebuild CPACK_RPM_INSTALL_FILES - set(CPACK_RPM_INSTALL_FILES "") - foreach(F IN LISTS CPACK_RPM_INSTALL_FILES_LIST) - set(CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}\"${F}\"\n") - endforeach() -else() - set(CPACK_RPM_USER_INSTALL_FILES "") -endif() + # The name of the final spec file to be used by rpmbuild + set(CPACK_RPM_BINARY_SPECFILE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.spec") -if (CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL) - if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: Handling Absolute Destination Files: ${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}") - endif() - # Remove trailing space - string(STRIP "${CPACK_RPM_INSTALL_FILES}" CPACK_RPM_INSTALL_FILES_LIST) - # Transform endline separated - string into CMake List - string(REPLACE "\n" ";" CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES_LIST}") - # Remove unecessary quotes - string(REPLACE "\"" "" CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES_LIST}") - # Remove ABSOLUTE install file from INSTALL FILE LIST - list(REMOVE_ITEM CPACK_RPM_INSTALL_FILES_LIST ${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL}) - # Rebuild INSTALL_FILES - set(CPACK_RPM_INSTALL_FILES "") - foreach(F IN LISTS CPACK_RPM_INSTALL_FILES_LIST) - set(CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}\"${F}\"\n") - endforeach() - # Build ABSOLUTE_INSTALL_FILES - set(CPACK_RPM_ABSOLUTE_INSTALL_FILES "") - foreach(F IN LISTS CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL) - set(CPACK_RPM_ABSOLUTE_INSTALL_FILES "${CPACK_RPM_ABSOLUTE_INSTALL_FILES}%config \"${F}\"\n") - endforeach() + # Print out some debug information if we were asked for that if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: CPACK_RPM_ABSOLUTE_INSTALL_FILES=${CPACK_RPM_ABSOLUTE_INSTALL_FILES}") - message("CPackRPM:Debug: CPACK_RPM_INSTALL_FILES=${CPACK_RPM_INSTALL_FILES}") - endif() -else() - # reset vars in order to avoid leakage of value(s) from one component to another - set(CPACK_RPM_ABSOLUTE_INSTALL_FILES "") -endif() - -# Prepend directories in ${CPACK_RPM_INSTALL_FILES} with %dir -# This is necessary to avoid duplicate files since rpmbuild do -# recursion on its own when encountering a pathname which is a directory -# which is not flagged as %dir -string(STRIP "${CPACK_RPM_INSTALL_FILES}" CPACK_RPM_INSTALL_FILES_LIST) -string(REPLACE "\n" ";" CPACK_RPM_INSTALL_FILES_LIST - "${CPACK_RPM_INSTALL_FILES_LIST}") -string(REPLACE "\"" "" CPACK_RPM_INSTALL_FILES_LIST - "${CPACK_RPM_INSTALL_FILES_LIST}") -set(CPACK_RPM_INSTALL_FILES "") -foreach(F IN LISTS CPACK_RPM_INSTALL_FILES_LIST) - if(IS_DIRECTORY "${WDIR}/${F}") - set(CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}%dir \"${F}\"\n") - else() - set(CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES}\"${F}\"\n") + message("CPackRPM:Debug: CPACK_TOPLEVEL_DIRECTORY = ${CPACK_TOPLEVEL_DIRECTORY}") + message("CPackRPM:Debug: CPACK_TOPLEVEL_TAG = ${CPACK_TOPLEVEL_TAG}") + message("CPackRPM:Debug: CPACK_TEMPORARY_DIRECTORY = ${CPACK_TEMPORARY_DIRECTORY}") + message("CPackRPM:Debug: CPACK_OUTPUT_FILE_NAME = ${CPACK_OUTPUT_FILE_NAME}") + message("CPackRPM:Debug: CPACK_OUTPUT_FILE_PATH = ${CPACK_OUTPUT_FILE_PATH}") + message("CPackRPM:Debug: CPACK_PACKAGE_FILE_NAME = ${CPACK_PACKAGE_FILE_NAME}") + message("CPackRPM:Debug: CPACK_RPM_BINARY_SPECFILE = ${CPACK_RPM_BINARY_SPECFILE}") + message("CPackRPM:Debug: CPACK_PACKAGE_INSTALL_DIRECTORY = ${CPACK_PACKAGE_INSTALL_DIRECTORY}") + message("CPackRPM:Debug: CPACK_TEMPORARY_PACKAGE_FILE_NAME = ${CPACK_TEMPORARY_PACKAGE_FILE_NAME}") endif() -endforeach() -set(CPACK_RPM_INSTALL_FILES_LIST "") - -# The name of the final spec file to be used by rpmbuild -set(CPACK_RPM_BINARY_SPECFILE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.spec") - -# Print out some debug information if we were asked for that -if(CPACK_RPM_PACKAGE_DEBUG) - message("CPackRPM:Debug: CPACK_TOPLEVEL_DIRECTORY = ${CPACK_TOPLEVEL_DIRECTORY}") - message("CPackRPM:Debug: CPACK_TOPLEVEL_TAG = ${CPACK_TOPLEVEL_TAG}") - message("CPackRPM:Debug: CPACK_TEMPORARY_DIRECTORY = ${CPACK_TEMPORARY_DIRECTORY}") - message("CPackRPM:Debug: CPACK_OUTPUT_FILE_NAME = ${CPACK_OUTPUT_FILE_NAME}") - message("CPackRPM:Debug: CPACK_OUTPUT_FILE_PATH = ${CPACK_OUTPUT_FILE_PATH}") - message("CPackRPM:Debug: CPACK_PACKAGE_FILE_NAME = ${CPACK_PACKAGE_FILE_NAME}") - message("CPackRPM:Debug: CPACK_RPM_BINARY_SPECFILE = ${CPACK_RPM_BINARY_SPECFILE}") - message("CPackRPM:Debug: CPACK_PACKAGE_INSTALL_DIRECTORY = ${CPACK_PACKAGE_INSTALL_DIRECTORY}") - message("CPackRPM:Debug: CPACK_TEMPORARY_PACKAGE_FILE_NAME = ${CPACK_TEMPORARY_PACKAGE_FILE_NAME}") -endif() -# protect @ in pathname in order to avoid their -# interpretation during the configure_file step -set(CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES}") -set(PROTECTED_AT "@") -string(REPLACE "@" "\@PROTECTED_AT\@" CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES_LIST}") -set(CPACK_RPM_INSTALL_FILES_LIST "") + # + # USER generated/provided spec file handling. + # -# -# USER generated/provided spec file handling. -# - -# We can have a component specific spec file. -if(CPACK_RPM_PACKAGE_COMPONENT AND CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE) - set(CPACK_RPM_USER_BINARY_SPECFILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE}) -endif() + # We can have a component specific spec file. + if(CPACK_RPM_PACKAGE_COMPONENT AND CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE) + set(CPACK_RPM_USER_BINARY_SPECFILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE}) + endif() -# We should generate a USER spec file template: -# - either because the user asked for it : CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE -# - or the user did not provide one : NOT CPACK_RPM_USER_BINARY_SPECFILE -if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE) - file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in + # We should generate a USER spec file template: + # - either because the user asked for it : CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE + # - or the user did not provide one : NOT CPACK_RPM_USER_BINARY_SPECFILE + if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE) + file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in "# -*- rpm-spec -*- BuildRoot: \@CPACK_RPM_DIRECTORY\@/\@CPACK_PACKAGE_FILE_NAME\@\@CPACK_RPM_PACKAGE_COMPONENT_PART_PATH\@ Summary: \@CPACK_RPM_PACKAGE_SUMMARY\@ @@ -1239,6 +1565,7 @@ mv \"\@CPACK_TOPLEVEL_DIRECTORY\@/tmpBBroot\" $RPM_BUILD_ROOT %clean %post +\@RPM_SYMLINK_POSTINSTALL\@ \@CPACK_RPM_SPEC_POSTINSTALL\@ %postun @@ -1259,65 +1586,54 @@ mv \"\@CPACK_TOPLEVEL_DIRECTORY\@/tmpBBroot\" $RPM_BUILD_ROOT %changelog \@CPACK_RPM_SPEC_CHANGELOG\@ ") - # Stop here if we were asked to only generate a template USER spec file - # The generated file may then be used as a template by user who wants - # to customize their own spec file. - if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE) - message(FATAL_ERROR "CPackRPM: STOP here Generated USER binary spec file templare is: ${CPACK_RPM_BINARY_SPECFILE}.in") + # Stop here if we were asked to only generate a template USER spec file + # The generated file may then be used as a template by user who wants + # to customize their own spec file. + if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE) + message(FATAL_ERROR "CPackRPM: STOP here Generated USER binary spec file templare is: ${CPACK_RPM_BINARY_SPECFILE}.in") + endif() endif() -endif() - -# After that we may either use a user provided spec file -# or generate one using appropriate variables value. -if(CPACK_RPM_USER_BINARY_SPECFILE) - # User may have specified SPECFILE just use it - message("CPackRPM: Will use USER specified spec file: ${CPACK_RPM_USER_BINARY_SPECFILE}") - # The user provided file is processed for @var replacement - configure_file(${CPACK_RPM_USER_BINARY_SPECFILE} ${CPACK_RPM_BINARY_SPECFILE} @ONLY) -else() - # No User specified spec file, will use the generated spec file - message("CPackRPM: Will use GENERATED spec file: ${CPACK_RPM_BINARY_SPECFILE}") - # Note the just created file is processed for @var replacement - configure_file(${CPACK_RPM_BINARY_SPECFILE}.in ${CPACK_RPM_BINARY_SPECFILE} @ONLY) -endif() -# remove AT protection -unset(PROTECTED_AT) - -if(RPMBUILD_EXECUTABLE) - # Now call rpmbuild using the SPECFILE - execute_process( - COMMAND "${RPMBUILD_EXECUTABLE}" -bb - --define "_topdir ${CPACK_RPM_DIRECTORY}" - --buildroot "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" - "${CPACK_RPM_BINARY_SPECFILE}" - WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" - RESULT_VARIABLE CPACK_RPMBUILD_EXEC_RESULT - ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err" - OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out") - if(CPACK_RPM_PACKAGE_DEBUG OR CPACK_RPMBUILD_EXEC_RESULT) - file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err RPMBUILDERR) - file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out RPMBUILDOUT) - message("CPackRPM:Debug: You may consult rpmbuild logs in: ") - message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err") - message("CPackRPM:Debug: *** ${RPMBUILDERR} ***") - message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out") - message("CPackRPM:Debug: *** ${RPMBUILDERR} ***") + # After that we may either use a user provided spec file + # or generate one using appropriate variables value. + if(CPACK_RPM_USER_BINARY_SPECFILE) + # User may have specified SPECFILE just use it + message("CPackRPM: Will use USER specified spec file: ${CPACK_RPM_USER_BINARY_SPECFILE}") + # The user provided file is processed for @var replacement + configure_file(${CPACK_RPM_USER_BINARY_SPECFILE} ${CPACK_RPM_BINARY_SPECFILE} @ONLY) + else() + # No User specified spec file, will use the generated spec file + message("CPackRPM: Will use GENERATED spec file: ${CPACK_RPM_BINARY_SPECFILE}") + # Note the just created file is processed for @var replacement + configure_file(${CPACK_RPM_BINARY_SPECFILE}.in ${CPACK_RPM_BINARY_SPECFILE} @ONLY) endif() -else() - if(ALIEN_EXECUTABLE) - message(FATAL_ERROR "RPM packaging through alien not done (yet)") + + if(RPMBUILD_EXECUTABLE) + # Now call rpmbuild using the SPECFILE + execute_process( + COMMAND "${RPMBUILD_EXECUTABLE}" -bb + --define "_topdir ${CPACK_RPM_DIRECTORY}" + --buildroot "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" + --target "${_CPACK_RPM_PACKAGE_ARCHITECTURE}" + "${CPACK_RPM_BINARY_SPECFILE}" + WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" + RESULT_VARIABLE CPACK_RPMBUILD_EXEC_RESULT + ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err" + OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out") + if(CPACK_RPM_PACKAGE_DEBUG OR CPACK_RPMBUILD_EXEC_RESULT) + file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err RPMBUILDERR) + file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out RPMBUILDOUT) + message("CPackRPM:Debug: You may consult rpmbuild logs in: ") + message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.err") + message("CPackRPM:Debug: *** ${RPMBUILDERR} ***") + message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_COMPONENT_PART_NAME}.out") + message("CPackRPM:Debug: *** ${RPMBUILDERR} ***") + endif() + else() + if(ALIEN_EXECUTABLE) + message(FATAL_ERROR "RPM packaging through alien not done (yet)") + endif() endif() -endif() +endfunction() -# reset variables from temporary variables -if(CPACK_RPM_PACKAGE_SUMMARY_) - set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_RPM_PACKAGE_SUMMARY_}) -else() - unset(CPACK_RPM_PACKAGE_SUMMARY) -endif() -if(CPACK_RPM_PACKAGE_DESCRIPTION_) - set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_RPM_PACKAGE_DESCRIPTION_}) -else() - unset(CPACK_RPM_PACKAGE_DESCRIPTION) -endif() +cpack_rpm_generate_package() diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 0a47e19..5fe51a6 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -148,6 +148,11 @@ # Currently fragments can be injected into most # Component, File and Directory elements. # +# The following additional special Ids can be used: +# +# * ``#PRODUCT`` for the ``<Product>`` element. +# * ``#PRODUCTFEATURE`` for the root ``<Feature>`` element. +# # The following example illustrates how this works. # # Given that the WiX generator creates the following XML element: @@ -233,7 +238,7 @@ # * ARPSIZE - Size (in kilobytes) of the application #============================================================================= -# Copyright 2014 Kitware, Inc. +# Copyright 2014-2015 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. diff --git a/Modules/CTestCoverageCollectGCOV.cmake b/Modules/CTestCoverageCollectGCOV.cmake index a607c52..4519627 100644 --- a/Modules/CTestCoverageCollectGCOV.cmake +++ b/Modules/CTestCoverageCollectGCOV.cmake @@ -45,6 +45,10 @@ # Specify options to be passed to gcov. The ``gcov`` command # is run as ``gcov <options>... -o <gcov-dir> <file>.gcda``. # If not specified, the default option is just ``-b``. +# +# ``QUIET`` +# Suppress non-error messages that otherwise would have been +# printed out by this function. #============================================================================= # Copyright 2014-2015 Kitware, Inc. @@ -60,7 +64,7 @@ # License text for the above reference.) include(CMakeParseArguments) function(ctest_coverage_collect_gcov) - set(options "") + set(options QUIET) set(oneValueArgs TARBALL SOURCE BUILD GCOV_COMMAND) set(multiValueArgs GCOV_OPTIONS) cmake_parse_arguments(GCOV "${options}" "${oneValueArgs}" @@ -106,8 +110,10 @@ function(ctest_coverage_collect_gcov) # return early if no coverage files were found list(LENGTH gcda_files len) if(len EQUAL 0) - message("ctest_coverage_collect_gcov: No .gcda files found, " - "ignoring coverage request.") + if (NOT GCOV_QUIET) + message("ctest_coverage_collect_gcov: No .gcda files found, " + "ignoring coverage request.") + endif() return() endif() # setup the dir for the coverage files @@ -130,7 +136,9 @@ function(ctest_coverage_collect_gcov) WORKING_DIRECTORY ${coverage_dir}) endforeach() if(NOT "${res}" EQUAL 0) - message(STATUS "Error running gcov: ${res} ${out}") + if (NOT GCOV_QUIET) + message(STATUS "Error running gcov: ${res} ${out}") + endif() endif() # create json file with project information file(WRITE ${coverage_dir}/data.json @@ -151,8 +159,15 @@ function(ctest_coverage_collect_gcov) ${coverage_dir}/data.json ${label_files} ") + + if (GCOV_QUIET) + set(tar_opts "cfj") + else() + set(tar_opts "cvfj") + endif() + execute_process(COMMAND - ${CMAKE_COMMAND} -E tar cvfj ${GCOV_TARBALL} + ${CMAKE_COMMAND} -E tar ${tar_opts} ${GCOV_TARBALL} "--mtime=1970-01-01 0:0:0 UTC" --files-from=${coverage_dir}/coverage_file_list.txt WORKING_DIRECTORY ${binary_dir}) diff --git a/Modules/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake index 53f3454..750e4fb 100644 --- a/Modules/CheckCCompilerFlag.cmake +++ b/Modules/CheckCCompilerFlag.cmake @@ -13,7 +13,7 @@ # Will be created as an internal cache variable. # # This internally calls the check_c_source_compiles macro and sets -# CMAKE_REQUIRED_DEFINITIONS to <flag>. See help for +# CMAKE_REQUIRED_FLAGS to <flag>. See help for # CheckCSourceCompiles for a listing of variables that can otherwise # modify the build. The result only tells that the compiler does not # give an error message when it encounters the flag. If the flag has @@ -38,8 +38,8 @@ include(CheckCSourceCompiles) include(CMakeCheckCompilerFlagCommonPatterns) macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT) - set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") - set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${_FLAG}") # Normalize locale during test compilation. set(_CheckCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) @@ -60,5 +60,5 @@ macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT) unset(_CheckCCompilerFlag_LOCALE_VARS) unset(_CheckCCompilerFlag_COMMON_PATTERNS) - set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") + set (CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") endmacro () diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake index fab3a05..71b3fd2 100644 --- a/Modules/CheckCXXCompilerFlag.cmake +++ b/Modules/CheckCXXCompilerFlag.cmake @@ -12,7 +12,7 @@ # <var> - variable to store the result # # This internally calls the check_cxx_source_compiles macro and sets -# CMAKE_REQUIRED_DEFINITIONS to <flag>. See help for +# CMAKE_REQUIRED_FLAGS to <flag>. See help for # CheckCXXSourceCompiles for a listing of variables that can otherwise # modify the build. The result only tells that the compiler does not # give an error message when it encounters the flag. If the flag has @@ -37,8 +37,8 @@ include(CheckCXXSourceCompiles) include(CMakeCheckCompilerFlagCommonPatterns) macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT) - set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") - set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${_FLAG}") # Normalize locale during test compilation. set(_CheckCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) @@ -59,6 +59,6 @@ macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT) unset(_CheckCXXCompilerFlag_LOCALE_VARS) unset(_CheckCXXCompilerFlag_COMMON_PATTERNS) - set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") + set (CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") endmacro () diff --git a/Modules/CheckFortranCompilerFlag.cmake b/Modules/CheckFortranCompilerFlag.cmake new file mode 100644 index 0000000..c476661 --- /dev/null +++ b/Modules/CheckFortranCompilerFlag.cmake @@ -0,0 +1,66 @@ +#.rst: +# CheckFortranCompilerFlag +# ------------------------ +# +# Check whether the Fortran compiler supports a given flag. +# +# CHECK_Fortran_COMPILER_FLAG(<flag> <var>) +# +# :: +# +# <flag> - the compiler flag +# <var> - variable to store the result +# Will be created as an internal cache variable. +# +# This internally calls the check_fortran_source_compiles macro and +# sets CMAKE_REQUIRED_FLAGS to <flag>. See help for +# CheckFortranSourceCompiles for a listing of variables that can +# otherwise modify the build. The result only tells that the compiler +# does not give an error message when it encounters the flag. If the +# flag has any effect or even a specific one is beyond the scope of +# this module. + +#============================================================================= +# Copyright 2015 Nicolas Bock <nicolasbock@gmail.com> +# Copyright 2006-2011 Kitware, Inc. +# Copyright 2006 Alexander Neundorf <neundorf@kde.org> +# Copyright 2011 Matthias Kretz <kretz@kde.org> +# +# 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.) + +include(CheckFortranSourceCompiles) +include(CMakeCheckCompilerFlagCommonPatterns) + +macro (CHECK_Fortran_COMPILER_FLAG _FLAG _RESULT) + set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${_FLAG}") + + # Normalize locale during test compilation. + set(_CheckFortranCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) + foreach(v ${_CheckFortranCompilerFlag_LOCALE_VARS}) + set(_CheckFortranCompilerFlag_SAVED_${v} "$ENV{${v}}") + set(ENV{${v}} C) + endforeach() + CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckFortranCompilerFlag_COMMON_PATTERNS) + CHECK_Fortran_SOURCE_COMPILES(" program test\n stop\n end program" ${_RESULT} + # Some compilers do not fail with a bad flag + FAIL_REGEX "command line option .* is valid for .* but not for Fortran" # GNU + ${_CheckFortranCompilerFlag_COMMON_PATTERNS} + ) + foreach(v ${_CheckFortranCompilerFlag_LOCALE_VARS}) + set(ENV{${v}} ${_CheckFortranCompilerFlag_SAVED_${v}}) + unset(_CheckFortranCompilerFlag_SAVED_${v}) + endforeach() + unset(_CheckFortranCompilerFlag_LOCALE_VARS) + unset(_CheckFortranCompilerFlag_COMMON_PATTERNS) + + set (CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") +endmacro () diff --git a/Modules/CheckStructHasMember.cmake b/Modules/CheckStructHasMember.cmake index de31d2c..6c15205 100644 --- a/Modules/CheckStructHasMember.cmake +++ b/Modules/CheckStructHasMember.cmake @@ -69,7 +69,7 @@ macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT) ${_INCLUDE_FILES} int main() { - (void)((${_STRUCT} *)0)->${_MEMBER}; + (void)sizeof(((${_STRUCT} *)0)->${_MEMBER}); return 0; } ") diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index 86a31e4..2dc02f0 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -44,10 +44,10 @@ macro(cmake_record_cxx_compile_features) endmacro() set(_result 0) - if (UNIX AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8) _get_gcc_features(${CMAKE_CXX14_STANDARD_COMPILE_OPTION} CMAKE_CXX14_COMPILE_FEATURES) endif() - if (UNIX AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) if (_result EQUAL 0) _get_gcc_features(${CMAKE_CXX11_STANDARD_COMPILE_OPTION} CMAKE_CXX11_COMPILE_FEATURES) endif() diff --git a/Modules/Compiler/GNU-Fortran.cmake b/Modules/Compiler/GNU-Fortran.cmake index dfd7927..e9c8a59 100644 --- a/Modules/Compiler/GNU-Fortran.cmake +++ b/Modules/Compiler/GNU-Fortran.cmake @@ -8,5 +8,8 @@ set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form") set(CMAKE_Fortran_FLAGS_MINSIZEREL_INIT "-Os") set(CMAKE_Fortran_FLAGS_RELEASE_INIT "-O3") +# No -isystem for Fortran because it will not find .mod files. +unset(CMAKE_INCLUDE_SYSTEM_FLAG_Fortran) + # Fortran-specific feature flags. set(CMAKE_Fortran_MODDIR_FLAG -J) diff --git a/Modules/Compiler/SunPro-C.cmake b/Modules/Compiler/SunPro-C.cmake index c5b5203..92252cb 100644 --- a/Modules/Compiler/SunPro-C.cmake +++ b/Modules/Compiler/SunPro-C.cmake @@ -1,7 +1,6 @@ set(CMAKE_C_VERBOSE_FLAG "-#") set(CMAKE_C_COMPILE_OPTIONS_PIC -KPIC) -set(CMAKE_C_COMPILE_OPTIONS_PIE -KPIE) set(CMAKE_SHARED_LIBRARY_C_FLAGS "-KPIC") set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-G") set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-R") diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake index c7bc734..022b4d4 100644 --- a/Modules/Compiler/SunPro-CXX.cmake +++ b/Modules/Compiler/SunPro-CXX.cmake @@ -1,7 +1,6 @@ set(CMAKE_CXX_VERBOSE_FLAG "-v") set(CMAKE_CXX_COMPILE_OPTIONS_PIC -KPIC) -set(CMAKE_CXX_COMPILE_OPTIONS_PIE -KPIE) set(CMAKE_SHARED_LIBRARY_CXX_FLAGS "-KPIC") set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-G") set(CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG "-R") diff --git a/Modules/Compiler/SunPro-Fortran.cmake b/Modules/Compiler/SunPro-Fortran.cmake index e4db1e8..196aae4 100644 --- a/Modules/Compiler/SunPro-Fortran.cmake +++ b/Modules/Compiler/SunPro-Fortran.cmake @@ -2,6 +2,7 @@ set(CMAKE_Fortran_VERBOSE_FLAG "-v") set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixed") set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free") +set(CMAKE_Fortran_COMPILE_OPTIONS_PIC "-KPIC") set(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "-KPIC") set(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-G") set(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "-R") diff --git a/Modules/CompilerId/Xcode-3.pbxproj.in b/Modules/CompilerId/Xcode-3.pbxproj.in index 7f686a2..20f3da3 100644 --- a/Modules/CompilerId/Xcode-3.pbxproj.in +++ b/Modules/CompilerId/Xcode-3.pbxproj.in @@ -79,7 +79,6 @@ 1DEB928A08733DD80010E9CD = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; ONLY_ACTIVE_ARCH = YES; CODE_SIGNING_REQUIRED = NO; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; diff --git a/Modules/DeployQt4.cmake b/Modules/DeployQt4.cmake index b1a2370..de475e4 100644 --- a/Modules/DeployQt4.cmake +++ b/Modules/DeployQt4.cmake @@ -126,7 +126,10 @@ function(write_qt4_conf qt_conf_dir qt_conf_contents) endfunction() function(resolve_qt4_paths paths_var) - set(executable_path ${ARGV1}) + unset(executable_path) + if(ARGC GREATER 1) + set(executable_path ${ARGV1}) + endif() set(paths_resolved) foreach(path ${${paths_var}}) @@ -144,11 +147,26 @@ function(resolve_qt4_paths paths_var) endfunction() function(fixup_qt4_executable executable) - set(qtplugins ${ARGV1}) - set(libs ${ARGV2}) - set(dirs ${ARGV3}) - set(plugins_dir ${ARGV4}) - set(request_qt_conf ${ARGV5}) + unset(qtplugins) + if(ARGC GREATER 1) + set(qtplugins ${ARGV1}) + endif() + unset(libs) + if(ARGC GREATER 2) + set(libs ${ARGV2}) + endif() + unset(dirs) + if(ARGC GREATER 3) + set(dirs ${ARGV3}) + endif() + unset(plugins_dir) + if(ARGC GREATER 4) + set(plugins_dir ${ARGV4}) + endif() + unset(request_qt_conf) + if(ARGC GREATER 5) + set(request_qt_conf ${ARGV5}) + endif() message(STATUS "fixup_qt4_executable") message(STATUS " executable='${executable}'") @@ -169,7 +187,7 @@ function(fixup_qt4_executable executable) set(qt_conf_dir "${executable}/Contents/Resources") set(executable_path "${executable}") set(write_qt_conf TRUE) - if(NOT plugins_dir) + if(NOT DEFINED plugins_dir) set(plugins_dir "${DeployQt4_apple_plugins_dir}") endif() else() @@ -204,9 +222,19 @@ function(fixup_qt4_executable executable) endfunction() function(install_qt4_plugin_path plugin executable copy installed_plugin_path_var) - set(plugins_dir ${ARGV4}) - set(component ${ARGV5}) - set(configurations ${ARGV6}) + unset(plugins_dir) + if(ARGC GREATER 4) + set(plugins_dir ${ARGV4}) + endif() + unset(component) + if(ARGC GREATER 5) + set(component ${ARGV5}) + endif() + unset(configurations) + if(ARGC GREATER 6) + set(configurations ${ARGV6}) + endif() + if(EXISTS "${plugin}") if(APPLE) if(NOT plugins_dir) @@ -253,8 +281,15 @@ function(install_qt4_plugin_path plugin executable copy installed_plugin_path_va endfunction() function(install_qt4_plugin plugin executable copy installed_plugin_path_var) - set(plugins_dir ${ARGV4}) - set(component ${ARGV5}) + unset(plugins_dir) + if(ARGC GREATER 4) + set(plugins_dir ${ARGV4}) + endif() + unset(component) + if(ARGC GREATER 5) + set(component ${ARGV5}) + endif() + if(EXISTS "${plugin}") install_qt4_plugin_path("${plugin}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}") else() @@ -287,12 +322,31 @@ function(install_qt4_plugin plugin executable copy installed_plugin_path_var) endfunction() function(install_qt4_executable executable) - set(qtplugins ${ARGV1}) - set(libs ${ARGV2}) - set(dirs ${ARGV3}) - set(plugins_dir ${ARGV4}) - set(request_qt_conf ${ARGV5}) - set(component ${ARGV6}) + unset(qtplugins) + if(ARGC GREATER 1) + set(qtplugins ${ARGV1}) + endif() + unset(libs) + if(ARGC GREATER 2) + set(libs ${ARGV2}) + endif() + unset(dirs) + if(ARGC GREATER 3) + set(dirs ${ARGV3}) + endif() + unset(plugins_dir) + if(ARGC GREATER 4) + set(plugins_dir ${ARGV4}) + endif() + unset(request_qt_conf) + if(ARGC GREATER 5) + set(request_qt_conf ${ARGV5}) + endif() + unset(component) + if(ARGC GREATER 6) + set(component ${ARGV6}) + endif() + if(QT_LIBRARY_DIR) list(APPEND dirs "${QT_LIBRARY_DIR}") endif() diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 741db81..883ab69 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -155,13 +155,23 @@ calling any of the functions provided by this module. inactivity timeout, in seconds, with a default of ``60`` seconds. Set to ``0`` to disable enforcement. +.. variable:: ExternalData_URL_ALGO_<algo>_<key> + + Specify a custom URL component to be substituted for URL template + placeholders of the form ``%(algo:<key>)``, where ``<key>`` is a + valid C identifier, when fetching an object referenced via hash + algorithm ``<algo>``. If not defined, the default URL component + is just ``<algo>`` for any ``<key>``. + .. variable:: ExternalData_URL_TEMPLATES The ``ExternalData_URL_TEMPLATES`` may be set to provide a list of of URL templates using the placeholders ``%(algo)`` and ``%(hash)`` in each template. Data fetch rules try each URL template in order by substituting the hash algorithm name for ``%(algo)`` and the hash - value for ``%(hash)``. + value for ``%(hash)``. Alternatively one may use ``%(algo:<key>)`` + with ``ExternalData_URL_ALGO_<algo>_<key>`` variables to gain more + flexibility in remote URLs. Referencing Files ^^^^^^^^^^^^^^^^^ @@ -234,7 +244,8 @@ associated file options. For example, the argument ``DATA{MyDataDir/,REGEX:.*}`` will pass the full path to a ``MyDataDir`` directory on the command line and ensure that the directory contains files corresponding to every file or content link in the ``MyDataDir`` -source directory. +source directory. In order to match associated files in subdirectories, +specify a ``RECURSE:`` option, e.g. ``DATA{MyDataDir/,RECURSE:,REGEX:.*}``. Hash Algorithms ^^^^^^^^^^^^^^^ @@ -349,6 +360,25 @@ function(ExternalData_add_target target) "The key must be a valid C identifier.") endif() endif() + + # Store custom algorithm name to URL component maps. + if("${url_template}" MATCHES "%\\(algo:([^)]*)\\)") + set(key "${CMAKE_MATCH_1}") + if(key MATCHES "^[A-Za-z_][A-Za-z0-9_]*$") + string(REPLACE "|" ";" _algos "${_ExternalData_REGEX_ALGO}") + foreach(algo ${_algos}) + if(DEFINED ExternalData_URL_ALGO_${algo}_${key}) + string(CONCAT _ExternalData_CONFIG_CODE "${_ExternalData_CONFIG_CODE}\n" + "set(ExternalData_URL_ALGO_${algo}_${key} \"${ExternalData_URL_ALGO_${algo}_${key}}\")") + endif() + endforeach() + else() + message(FATAL_ERROR + "Bad %(algo:${key}) in URL template:\n" + " ${url_template}\n" + "The transform name must be a valid C identifier.") + endif() + endif() endforeach() # Store configuration for use by build-time script. @@ -568,6 +598,7 @@ function(_ExternalData_arg target arg options var_file) # Process options. set(series_option "") + set(recurse_option "") set(associated_files "") set(associated_regex "") foreach(opt ${options}) @@ -577,6 +608,9 @@ function(_ExternalData_arg target arg options var_file) elseif(opt STREQUAL ":") # Activate series matching. set(series_option "${opt}") + elseif(opt STREQUAL "RECURSE:") + # Activate recursive matching in directories. + set(recurse_option "${opt}") elseif("x${opt}" MATCHES "^[^][:/*?]+$") # Specific associated file. list(APPEND associated_files "${opt}") @@ -593,6 +627,9 @@ function(_ExternalData_arg target arg options var_file) if(associated_files OR associated_regex) message(FATAL_ERROR "Series option \"${series_option}\" not allowed with associated files.") endif() + if(recurse_option) + message(FATAL_ERROR "Recurse option \"${recurse_option}\" allowed only with directories.") + endif() # Load a whole file series. _ExternalData_arg_series() elseif(data_is_directory) @@ -605,6 +642,9 @@ function(_ExternalData_arg target arg options var_file) "must list associated files.") endif() else() + if(recurse_option) + message(FATAL_ERROR "Recurse option \"${recurse_option}\" allowed only with directories.") + endif() # Load the named data file. _ExternalData_arg_single() if(associated_files OR associated_regex) @@ -652,11 +692,18 @@ macro(_ExternalData_arg_associated) set(reldir "${reldir}/") endif() _ExternalData_exact_regex(reldir_regex "${reldir}") + if(recurse_option) + set(glob GLOB_RECURSE) + set(reldir_regex "${reldir_regex}(.+/)?") + else() + set(glob GLOB) + endif() # Find files named explicitly. foreach(file ${associated_files}) _ExternalData_exact_regex(file_regex "${file}") - _ExternalData_arg_find_files("${reldir}${file}" "${reldir_regex}${file_regex}") + _ExternalData_arg_find_files(${glob} "${reldir}${file}" + "${reldir_regex}${file_regex}") endforeach() # Find files matching the given regular expressions. @@ -666,13 +713,13 @@ macro(_ExternalData_arg_associated) set(all "${all}${sep}${reldir_regex}${regex}") set(sep "|") endforeach() - _ExternalData_arg_find_files("${reldir}" "${all}") + _ExternalData_arg_find_files(${glob} "${reldir}" "${all}") endmacro() macro(_ExternalData_arg_single) # Match only the named data by itself. _ExternalData_exact_regex(data_regex "${reldata}") - _ExternalData_arg_find_files("${reldata}" "${data_regex}") + _ExternalData_arg_find_files(GLOB "${reldata}" "${data_regex}") endmacro() macro(_ExternalData_arg_series) @@ -727,12 +774,15 @@ macro(_ExternalData_arg_series) # Then match base, number, and extension. _ExternalData_exact_regex(series_base "${relbase}") _ExternalData_exact_regex(series_ext "${ext}") - _ExternalData_arg_find_files("${relbase}*${ext}" + _ExternalData_arg_find_files(GLOB "${relbase}*${ext}" "${series_base}${series_match}${series_ext}") endmacro() -function(_ExternalData_arg_find_files pattern regex) - file(GLOB globbed RELATIVE "${top_src}" "${top_src}/${pattern}*") +function(_ExternalData_arg_find_files glob pattern regex) + cmake_policy(PUSH) + cmake_policy(SET CMP0009 NEW) + file(${glob} globbed RELATIVE "${top_src}" "${top_src}/${pattern}*") + cmake_policy(POP) foreach(entry IN LISTS globbed) if("x${entry}" MATCHES "^x(.*)(\\.(${_ExternalData_REGEX_EXT}))$") set(relname "${CMAKE_MATCH_1}") @@ -904,6 +954,16 @@ function(_ExternalData_download_object name hash algo var_obj) foreach(url_template IN LISTS ExternalData_URL_TEMPLATES) string(REPLACE "%(hash)" "${hash}" url_tmp "${url_template}") string(REPLACE "%(algo)" "${algo}" url "${url_tmp}") + if(url MATCHES "^(.*)%\\(algo:([A-Za-z_][A-Za-z0-9_]*)\\)(.*)$") + set(lhs "${CMAKE_MATCH_1}") + set(key "${CMAKE_MATCH_2}") + set(rhs "${CMAKE_MATCH_3}") + if(DEFINED ExternalData_URL_ALGO_${algo}_${key}) + set(url "${lhs}${ExternalData_URL_ALGO_${algo}_${key}}${rhs}") + else() + set(url "${lhs}${algo}${rhs}") + endif() + endif() message(STATUS "Fetching \"${url}\"") if(url MATCHES "^ExternalDataCustomScript://([A-Za-z_][A-Za-z0-9_]*)/(.*)$") _ExternalData_custom_fetch("${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}" "${tmp}" err errMsg) diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 74e8ae2..0c73d41 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -251,8 +251,8 @@ Create custom targets to build projects in external trees ``LOG 1`` Wrap step in script to log output - The command line, comment, and working directory of every standard and - custom step is processed to replace tokens ``<SOURCE_DIR>``, + The command line, comment, working directory, and byproducts of every + standard and custom step are processed to replace tokens ``<SOURCE_DIR>``, ``<BINARY_DIR>``, ``<INSTALL_DIR>``, and ``<TMP_DIR>`` with corresponding property values. @@ -1197,7 +1197,10 @@ function(_ep_get_build_command name step cmd_var) else() set(cmd "${CMAKE_COMMAND}") endif() - set(args --build ${binary_dir} --config ${CMAKE_CFG_INTDIR}) + set(args --build ".") + if (CMAKE_CFG_INTDIR AND NOT CMAKE_CFG_INTDIR STREQUAL ".") + list(APPEND args --config "${CMAKE_CFG_INTDIR}") + endif () if(step STREQUAL "INSTALL") list(APPEND args --target install) endif() @@ -1360,7 +1363,7 @@ endfunction() function(ExternalProject_Add_StepTargets name) set(steps ${ARGN}) - if("${ARGV1}" STREQUAL "NO_DEPENDS") + if(ARGC GREATER 1 AND "${ARGV1}" STREQUAL "NO_DEPENDS") set(no_deps 1) list(REMOVE_AT steps 0) endif() @@ -1443,7 +1446,7 @@ function(ExternalProject_Add_Step name step) endif() # Replace location tags. - _ep_replace_location_tags(${name} comment command work_dir) + _ep_replace_location_tags(${name} comment command work_dir byproducts) # Custom comment? get_property(comment_set TARGET ${name} PROPERTY _EP_${step}_COMMENT SET) diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake index 3eea9db..dc31086 100644 --- a/Modules/FeatureSummary.cmake +++ b/Modules/FeatureSummary.cmake @@ -379,6 +379,9 @@ function(_FS_GET_FEATURE_SUMMARY _property _var _includeQuiet) set(_currentFeatureText "") get_property(_EnabledFeatures GLOBAL PROPERTY ${_property}) + if(_EnabledFeatures) + list(REMOVE_DUPLICATES _EnabledFeatures) + endif(_EnabledFeatures) foreach(_currentFeature ${_EnabledFeatures}) @@ -559,8 +562,14 @@ endfunction() # The stuff below is only kept for compatibility function(SET_PACKAGE_INFO _name _desc) - set(_url "${ARGV2}") - set(_purpose "${ARGV3}") + unset(_url) + unset(_purpose) + if(ARGC GREATER 2) + set(_url "${ARGV2}") + endif() + if(ARGC GREATER 3) + set(_purpose "${ARGV3}") + endif() set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_desc}" ) if(NOT _url STREQUAL "") set_property(GLOBAL PROPERTY _CMAKE_${_name}_URL "${_url}" ) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index 99293c1..466090b 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -49,7 +49,8 @@ # and saves search results persistently in CMake cache entries:: # # Boost_INCLUDE_DIR - Directory containing Boost headers -# Boost_LIBRARY_DIR - Directory containing Boost libraries +# Boost_LIBRARY_DIR_RELEASE - Directory containing release Boost libraries +# Boost_LIBRARY_DIR_DEBUG - Directory containing debug Boost libraries # Boost_<C>_LIBRARY_DEBUG - Component <C> library debug variant # Boost_<C>_LIBRARY_RELEASE - Component <C> library release variant # @@ -65,7 +66,8 @@ # using the above hints (excluding BOOST_INCLUDEDIR and # Boost_ADDITIONAL_VERSIONS), "lib" directories near Boost_INCLUDE_DIR, # and the library name configuration settings below. It saves the -# library directory in Boost_LIBRARY_DIR and individual library +# library directories in Boost_LIBRARY_DIR_DEBUG and +# Boost_LIBRARY_DIR_RELEASE and individual library # locations in Boost_<C>_LIBRARY_DEBUG and Boost_<C>_LIBRARY_RELEASE. # When one changes settings used by previous searches in the same build # tree (excluding environment variables) this module discards previous @@ -118,6 +120,8 @@ # "/usr/lib/libboost_system.so". This does not # affect linking and should not be enabled unless # the user needs this information. +# Boost_LIBRARY_DIR - Default value for Boost_LIBRARY_DIR_RELEASE and +# Boost_LIBRARY_DIR_DEBUG. # # On Visual Studio and Borland compilers Boost headers request automatic # linking to corresponding libraries. This requires matching libraries @@ -283,6 +287,14 @@ macro(_Boost_ADJUST_LIB_VARS basename) ) endmacro() +# Detect changes in used variables. +# Compares the current variable value with the last one. +# In short form: +# v != v_LAST -> CHANGED = 1 +# v is defined, v_LAST not -> CHANGED = 1 +# v is not defined, but v_LAST is -> CHANGED = 1 +# otherwise -> CHANGED = 0 +# CHANGED is returned in variable named ${changed_var} macro(_Boost_CHANGE_DETECT changed_var) set(${changed_var} 0) foreach(v ${ARGN}) @@ -305,23 +317,33 @@ macro(_Boost_CHANGE_DETECT changed_var) endforeach() endmacro() -macro(_Boost_FIND_LIBRARY var) +# +# Find the given library (var). +# Use 'build_type' to support different lib paths for RELEASE or DEBUG builds +# +macro(_Boost_FIND_LIBRARY var build_type) + find_library(${var} ${ARGN}) if(${var}) - # If this is the first library found then save Boost_LIBRARY_DIR. - if(NOT Boost_LIBRARY_DIR) + # If this is the first library found then save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. + if(NOT Boost_LIBRARY_DIR_${build_type}) get_filename_component(_dir "${${var}}" PATH) - set(Boost_LIBRARY_DIR "${_dir}" CACHE PATH "Boost library directory" FORCE) + set(Boost_LIBRARY_DIR_${build_type} "${_dir}" CACHE PATH "Boost library directory ${build_type}" FORCE) endif() elseif(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - # Try component-specific hints but do not save Boost_LIBRARY_DIR. + # Try component-specific hints but do not save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. find_library(${var} HINTS ${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT} ${ARGN}) endif() - # If Boost_LIBRARY_DIR is known then search only there. - if(Boost_LIBRARY_DIR) - set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is known then search only there. + if(Boost_LIBRARY_DIR_${build_type}) + set(_boost_LIBRARY_SEARCH_DIRS_${build_type} ${Boost_LIBRARY_DIR_${build_type}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " Boost_LIBRARY_DIR_${build_type} = ${Boost_LIBRARY_DIR_${build_type}}" + " _boost_LIBRARY_SEARCH_DIRS_${build_type} = ${_boost_LIBRARY_SEARCH_DIRS_${build_type}}") + endif() endif() endmacro() @@ -456,6 +478,16 @@ endfunction() # main. #------------------------------------------------------------------------------- + +# If the user sets Boost_LIBRARY_DIR, use it as the default for both +# configurations. +if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR) + set(Boost_LIBRARY_DIR_RELEASE "${Boost_LIBRARY_DIR}") +endif() +if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR) + set(Boost_LIBRARY_DIR_DEBUG "${Boost_LIBRARY_DIR}") +endif() + if(NOT DEFINED Boost_USE_MULTITHREADED) set(Boost_USE_MULTITHREADED TRUE) endif() @@ -846,49 +878,54 @@ endif() # ------------------------------------------------------------------------ # Begin finding boost libraries # ------------------------------------------------------------------------ -set(_Boost_VARS_LIB BOOST_LIBRARYDIR Boost_LIBRARY_DIR) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR ${_Boost_VARS_DIR} ${_Boost_VARS_LIB} Boost_INCLUDE_DIR) -# Clear Boost_LIBRARY_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_LIBDIR AND NOT _Boost_LIBRARY_DIR_CHANGED) - unset(Boost_LIBRARY_DIR CACHE) -endif() -if(Boost_LIBRARY_DIR) - set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) -else() - set(_boost_LIBRARY_SEARCH_DIRS "") - if(BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_LIBRARYDIR}) - elseif(_ENV_BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_LIBRARYDIR}) - endif() - - if(BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) - elseif(_ENV_BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) +foreach(c DEBUG RELEASE) + set(_Boost_VARS_LIB_${c} BOOST_LIBRARYDIR Boost_LIBRARY_DIR_${c}) + _Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR_${c} ${_Boost_VARS_DIR} ${_Boost_VARS_LIB_${c}} Boost_INCLUDE_DIR) + # Clear Boost_LIBRARY_DIR_${c} if it did not change but other input affecting the + # location did. We will find a new one based on the new inputs. + if(_Boost_CHANGE_LIBDIR_${c} AND NOT _Boost_LIBRARY_DIR_${c}_CHANGED) + unset(Boost_LIBRARY_DIR_${c} CACHE) endif() - list(APPEND _boost_LIBRARY_SEARCH_DIRS - ${Boost_INCLUDE_DIR}/lib - ${Boost_INCLUDE_DIR}/../lib - ${Boost_INCLUDE_DIR}/stage/lib - ) - if( Boost_NO_SYSTEM_PATHS ) - list(APPEND _boost_LIBRARY_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) + # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is set, prefer its value. + if(Boost_LIBRARY_DIR_${c}) + set(_boost_LIBRARY_SEARCH_DIRS_${c} ${Boost_LIBRARY_DIR_${c}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) else() - list(APPEND _boost_LIBRARY_SEARCH_DIRS PATHS - C:/boost/lib - C:/boost - /sw/local/lib + set(_boost_LIBRARY_SEARCH_DIRS_${c} "") + if(BOOST_LIBRARYDIR) + list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_LIBRARYDIR}) + elseif(_ENV_BOOST_LIBRARYDIR) + list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_LIBRARYDIR}) + endif() + + if(BOOST_ROOT) + list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) + elseif(_ENV_BOOST_ROOT) + list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) + endif() + + list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} + ${Boost_INCLUDE_DIR}/lib + ${Boost_INCLUDE_DIR}/../lib + ${Boost_INCLUDE_DIR}/stage/lib ) + if( Boost_NO_SYSTEM_PATHS ) + list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH) + else() + list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS + C:/boost/lib + C:/boost + /sw/local/lib + ) + endif() endif() -endif() +endforeach() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_LIBRARY_SEARCH_DIRS = ${_boost_LIBRARY_SEARCH_DIRS}") + "_boost_LIBRARY_SEARCH_DIRS_RELEASE = ${_boost_LIBRARY_SEARCH_DIRS_RELEASE}" + "_boost_LIBRARY_SEARCH_DIRS_DEBUG = ${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") endif() # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES @@ -1002,10 +1039,16 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") endif() + # if Boost_LIBRARY_DIR_RELEASE is not defined, + # but Boost_LIBRARY_DIR_DEBUG is, look there first for RELEASE libs + if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR_DEBUG) + list(INSERT _boost_LIBRARY_SEARCH_DIRS_RELEASE 0 ${Boost_LIBRARY_DIR_DEBUG}) + endif() + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_RELEASE}") - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE RELEASE NAMES ${_boost_RELEASE_NAMES} HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} NAMES_PER_DIR @@ -1038,10 +1081,16 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") endif() + # if Boost_LIBRARY_DIR_DEBUG is not defined, + # but Boost_LIBRARY_DIR_RELEASE is, look there first for DEBUG libs + if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR_RELEASE) + list(INSERT _boost_LIBRARY_SEARCH_DIRS_DEBUG 0 ${Boost_LIBRARY_DIR_RELEASE}) + endif() + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG DEBUG NAMES ${_boost_DEBUG_NAMES} HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} NAMES_PER_DIR @@ -1067,7 +1116,16 @@ endif() # ------------------------------------------------------------------------ set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) -set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR}) +set(Boost_LIBRARY_DIRS) +if(Boost_LIBRARY_DIR_RELEASE) + list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_RELEASE}) +endif() +if(Boost_LIBRARY_DIR_DEBUG) + list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_DEBUG}) +endif() +if(Boost_LIBRARY_DIRS) + list(REMOVE_DUPLICATES Boost_LIBRARY_DIRS) +endif() # The above setting of Boost_FOUND was based only on the header files. # Update it for the requested component libraries. diff --git a/Modules/FindHg.cmake b/Modules/FindHg.cmake index 34d763e..bdbb79b 100644 --- a/Modules/FindHg.cmake +++ b/Modules/FindHg.cmake @@ -63,11 +63,21 @@ find_program(HG_EXECUTABLE mark_as_advanced(HG_EXECUTABLE) if(HG_EXECUTABLE) + set(_saved_lc_all "$ENV{LC_ALL}") + set(ENV{LC_ALL} "C") + + set(_saved_language "$ENV{LANGUAGE}") + set(ENV{LANGUAGE}) + execute_process(COMMAND ${HG_EXECUTABLE} --version OUTPUT_VARIABLE hg_version ERROR_QUIET RESULT_VARIABLE hg_result OUTPUT_STRIP_TRAILING_WHITESPACE) + + set(ENV{LC_ALL} ${_saved_lc_all}) + set(ENV{LANGUAGE} ${_saved_language}) + if(hg_result MATCHES "is not a valid Win32 application") set_property(CACHE HG_EXECUTABLE PROPERTY VALUE "HG_EXECUTABLE-NOTFOUND") endif() diff --git a/Modules/FindMFC.cmake b/Modules/FindMFC.cmake index 261ebdb..3547628 100644 --- a/Modules/FindMFC.cmake +++ b/Modules/FindMFC.cmake @@ -36,7 +36,7 @@ if(WIN32 AND NOT UNIX AND NOT BORLAND AND NOT MINGW) endif() if(MFC_ATTEMPT_TRY_COMPILE) - if("MFC_HAVE_MFC" MATCHES "^MFC_HAVE_MFC$") + if(NOT DEFINED MFC_HAVE_MFC) set(CHECK_INCLUDE_FILE_VAR "afxwin.h") configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx) diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 474556e..d08423b 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -2,20 +2,208 @@ # FindMatlab # ---------- # -# this module looks for Matlab +# Finds Matlab installations and provides Matlab tools and libraries to cmake. # -# Defines: +# This package first intention is to find the libraries associated with Matlab +# in order to be able to build Matlab extensions (mex files). It can also be +# used: # -# :: +# * run specific commands in Matlab +# * declare Matlab unit test +# * retrieve various information from Matlab (mex extensions, versions and +# release queries, ...) # -# MATLAB_INCLUDE_DIR: include path for mex.h, engine.h -# MATLAB_LIBRARIES: required libraries: libmex, etc -# MATLAB_MEX_LIBRARY: path to libmex.lib -# MATLAB_MX_LIBRARY: path to libmx.lib -# MATLAB_ENG_LIBRARY: path to libeng.lib +# The module supports the following components: +# +# * ``MX_LIBRARY`` and ``ENG_LIBRARY`` respectively the MX and ENG libraries of +# Matlab +# * ``MAIN_PROGRAM`` the Matlab binary program. +# +# .. note:: +# +# The version given to the :command:`find_package` directive is the Matlab +# **version**, which should not be confused with the Matlab *release* name +# (eg. `R2014`). +# The :command:`matlab_get_version_from_release_name` and +# :command:`matlab_get_release_name_from_version` allow a mapping +# from the release name to the version. +# +# The variable :variable:`Matlab_ROOT_DIR` may be specified in order to give +# the path of the desired Matlab version. Otherwise, the behaviour is platform +# specific: +# +# * Windows: The installed versions of Matlab are retrieved from the +# Windows registry +# * OS X: The installed versions of Matlab are given by the MATLAB +# paths in ``/Application``. If no such application is found, it falls back +# to the one that might be accessible from the PATH. +# * Unix: The desired Matlab should be accessible from the PATH. +# +# Additional information is provided when :variable:`MATLAB_FIND_DEBUG` is set. +# When a Matlab binary is found automatically and the ``MATLAB_VERSION`` +# is not given, the version is queried from Matlab directly. +# On Windows, it can make a window running Matlab appear. +# +# The mapping of the release names and the version of Matlab is performed by +# defining pairs (name, version). The variable +# :variable:`MATLAB_ADDITIONAL_VERSIONS` may be provided before the call to +# the :command:`find_package` in order to handle additional versions. +# +# A Matlab scripts can be added to the set of tests using the +# :command:`matlab_add_unit_test`. By default, the Matlab unit test framework +# will be used (>= 2013a) to run this script, but regular ``.m`` files +# returning an exit code can be used as well (0 indicating a success). +# +# Module Input Variables +# ---------------------- +# +# Users or projects may set the following variables to configure the module +# behaviour: +# +# :variable:`Matlab_ROOT_DIR` +# the root of the Matlab installation. +# :variable:`MATLAB_FIND_DEBUG` +# outputs debug information +# :variable:`MATLAB_ADDITIONAL_VERSIONS` +# additional versions of Matlab for the automatic retrieval of the installed +# versions. +# +# Variables defined by the module +# ------------------------------- +# +# Result variables +# ^^^^^^^^^^^^^^^^ +# +# ``Matlab_FOUND`` +# ``TRUE`` if the Matlab installation is found, ``FALSE`` +# otherwise. All variable below are defined if Matlab is found. +# ``Matlab_ROOT_DIR`` +# the final root of the Matlab installation determined by the FindMatlab +# module. +# ``Matlab_MAIN_PROGRAM`` +# the Matlab binary program. Available only if the component ``MAIN_PROGRAM`` +# is given in the :command:`find_package` directive. +# ``Matlab_INCLUDE_DIRS`` +# the path of the Matlab libraries headers +# ``Matlab_MEX_LIBRARY`` +# library for mex, always available. +# ``Matlab_MX_LIBRARY`` +# mx library of Matlab (arrays). Available only if the component +# ``MX_LIBRARY`` has been requested. +# ``Matlab_ENG_LIBRARY`` +# Matlab engine library. Available only if the component ``ENG_LIBRARY`` +# is requested. +# ``Matlab_LIBRARIES`` +# the whole set of libraries of Matlab +# ``Matlab_MEX_COMPILER`` +# the mex compiler of Matlab. Currently not used. +# Available only if the component ``MEX_COMPILER`` is asked +# +# Cached variables +# ^^^^^^^^^^^^^^^^ +# +# ``Matlab_MEX_EXTENSION`` +# the extension of the mex files for the current platform (given by Matlab). +# ``Matlab_ROOT_DIR`` +# the location of the root of the Matlab installation found. If this value +# is changed by the user, the result variables are recomputed. +# +# Provided macros +# --------------- +# +# :command:`matlab_get_version_from_release_name` +# returns the version from the release name +# :command:`matlab_get_release_name_from_version` +# returns the release name from the Matlab version +# +# Provided functions +# ------------------ +# +# :command:`matlab_add_mex` +# adds a target compiling a MEX file. +# :command:`matlab_add_unit_test` +# adds a Matlab unit test file as a test to the project. +# :command:`matlab_extract_all_installed_versions_from_registry` +# parses the registry for all Matlab versions. Available on Windows only. +# The part of the registry parsed is dependent on the host processor +# :command:`matlab_get_all_valid_matlab_roots_from_registry` +# returns all the possible Matlab paths, according to a previously +# given list. Only the existing/accessible paths are kept. This is mainly +# useful for the searching all possible Matlab installation. +# :command:`matlab_get_mex_suffix` +# returns the suffix to be used for the mex files +# (platform/architecture dependant) +# :command:`matlab_get_version_from_matlab_run` +# returns the version of Matlab, given the full directory of the Matlab program. +# +# +# Known issues +# ------------ +# +# **Symbol clash in a MEX target** +# By default, every symbols inside a MEX +# file defined with the command :command:`matlab_add_mex` have hidden +# visibility, except for the entry point. This is the default behaviour of +# the MEX compiler, which lowers the risk of symbol collision between the +# libraries shipped with Matlab, and the libraries to which the MEX file is +# linking to. This is also the default on Windows platforms. +# +# However, this is not sufficient in certain case, where for instance your +# MEX file is linking against libraries that are already loaded by Matlab, +# even if those libraries have different SONAMES. +# A possible solution is to hide the symbols of the libraries to which the +# MEX target is linking to. This can be achieved in GNU GCC compilers with +# the linker option ``-Wl,--exclude-libs,ALL``. +# +# **Tests using GPU resources** +# in case your MEX file is using the GPU and +# in order to be able to run unit tests on this MEX file, the GPU resources +# should be properly released by Matlab. A possible solution is to make +# Matlab aware of the use of the GPU resources in the session, which can be +# performed by a command such as ``D = gpuDevice()`` at the beginning of +# the test script (or via a fixture). +# +# +# Reference +# -------------- +# +# .. variable:: Matlab_ROOT_DIR +# +# The root folder of the Matlab installation. If set before the call to +# :command:`find_package`, the module will look for the components in that +# path. If not set, then an automatic search of Matlab +# will be performed. If set, it should point to a valid version of Matlab. +# +# .. variable:: MATLAB_FIND_DEBUG +# +# If set, the lookup of Matlab and the intermediate configuration steps are +# outputted to the console. +# +# .. variable:: MATLAB_ADDITIONAL_VERSIONS +# +# If set, specifies additional versions of Matlab that may be looked for. +# The variable should be a list of strings, organised by pairs of release +# name and versions, such as follows:: +# +# set(MATLAB_ADDITIONAL_VERSIONS +# "release_name1=corresponding_version1" +# "release_name2=corresponding_version2" +# ... +# ) +# +# Example:: +# +# set(MATLAB_ADDITIONAL_VERSIONS +# "R2013b=8.2" +# "R2013a=8.1" +# "R2012b=8.0") +# +# The order of entries in this list matters when several versions of +# Matlab are installed. The priority is set according to the ordering in +# this list. #============================================================================= -# Copyright 2005-2009 Kitware, Inc. +# Copyright 2014-2015 Raffi Enficiaud, Max Planck Society # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. @@ -27,102 +215,1247 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -set(MATLAB_FOUND 0) -if(WIN32) - if(${CMAKE_GENERATOR} MATCHES "Visual Studio 6") - set(MATLAB_ROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\7.0;MATLABROOT]/extern/lib/win32/microsoft/msvc60") +set(_FindMatlab_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}") + +include(FindPackageHandleStandardArgs) +include(CheckCXXCompilerFlag) + + +# The currently supported versions. Other version can be added by the user by +# providing MATLAB_ADDITIONAL_VERSIONS +if(NOT MATLAB_ADDITIONAL_VERSIONS) + set(MATLAB_ADDITIONAL_VERSIONS) +endif() + +set(MATLAB_VERSIONS_MAPPING + "R2014a=8.3" + "R2013b=8.2" + "R2013a=8.1" + "R2012b=8.0" + "R2012a=7.14" + + "R2011b=7.13" + "R2011a=7.12" + "R2010b=7.11" + + ${MATLAB_ADDITIONAL_VERSIONS} + ) + + +# temporary folder for all Matlab runs +set(_matlab_temporary_folder ${CMAKE_BINARY_DIR}/Matlab) + +if(NOT EXISTS "${_matlab_temporary_folder}") + file(MAKE_DIRECTORY "${_matlab_temporary_folder}") +endif() + +#.rst: +# .. command:: matlab_get_version_from_release_name +# +# Returns the version of Matlab (17.58) from a release name (R2017k) +macro (matlab_get_version_from_release_name release_name version_name) + + string(REGEX MATCHALL "${release_name}=([0-9]+\\.?[0-9]*)" _matched ${MATLAB_VERSIONS_MAPPING}) + + set(${version_name} "") + if(NOT _matched STREQUAL "") + set(${version_name} ${CMAKE_MATCH_1}) else() - if(${CMAKE_GENERATOR} MATCHES "Visual Studio 7") - # Assume people are generally using 7.1, - # if using 7.0 need to link to: ../extern/lib/win32/microsoft/msvc70 - set(MATLAB_ROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\7.0;MATLABROOT]/extern/lib/win32/microsoft/msvc71") - else() - if(${CMAKE_GENERATOR} MATCHES "Borland") - # Same here, there are also: bcc50 and bcc51 directories - set(MATLAB_ROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\7.0;MATLABROOT]/extern/lib/win32/microsoft/bcc54") - else() - if(MATLAB_FIND_REQUIRED) - message(FATAL_ERROR "Generator not compatible: ${CMAKE_GENERATOR}") - endif() + message(WARNING "The release name ${release_name} is not registered") + endif() + unset(_matched) + +endmacro() + + + + + +#.rst: +# .. command:: matlab_get_release_name_from_version +# +# Returns the release name (R2017k) from the version of Matlab (17.58) +macro (matlab_get_release_name_from_version version release_name) + + set(${release_name} "") + foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING) + string(REGEX MATCHALL "(.+)=${version}" _matched ${_var}) + if(NOT _matched STREQUAL "") + set(${release_name} ${CMAKE_MATCH_1}) + break() + endif() + endforeach(_var) + + unset(_var) + unset(_matched) + if(${release_name} STREQUAL "") + message(WARNING "The version ${version} is not registered") + endif() + +endmacro() + + + + + +# extracts all the supported release names (R2017k...) of Matlab +# internal use +macro(matlab_get_supported_releases list_releases) + set(${list_releases}) + foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING) + string(REGEX MATCHALL "(.+)=([0-9]+\\.?[0-9]*)" _matched ${_var}) + if(NOT _matched STREQUAL "") + list(APPEND ${list_releases} ${CMAKE_MATCH_1}) + endif() + unset(_matched) + unset(CMAKE_MATCH_1) + endforeach(_var) + unset(_var) +endmacro() + + + +# extracts all the supported versions of Matlab +# internal use +macro(matlab_get_supported_versions list_versions) + set(${list_versions}) + foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING) + string(REGEX MATCHALL "(.+)=([0-9]+\\.?[0-9]*)" _matched ${_var}) + if(NOT _matched STREQUAL "") + list(APPEND ${list_versions} ${CMAKE_MATCH_2}) + endif() + unset(_matched) + unset(CMAKE_MATCH_1) + endforeach(_var) + unset(_var) +endmacro() + + +#.rst: +# .. command:: matlab_extract_all_installed_versions_from_registry +# +# This function parses the registry and founds the Matlab versions that are +# installed. The found versions are returned in `matlab_versions`. +# Set `win64` to `TRUE` if the 64 bit version of Matlab should be looked for +# The returned list contains all versions under +# ``HKLM\\SOFTWARE\\Mathworks\\MATLAB`` or an empty list in case an error +# occurred (or nothing found). +# +# .. note:: +# +# Only the versions are provided. No check is made over the existence of the +# installation referenced in the registry, +# +function(matlab_extract_all_installed_versions_from_registry win64 matlab_versions) + + if(NOT CMAKE_HOST_WIN32) + message(FATAL_ERROR "This macro can only be called by a windows host (call to reg.exe") + endif() + + + if(${win64} AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "64") + set(APPEND_REG "/reg:64") + else() + set(APPEND_REG "/reg:32") + endif() + + # /reg:64 should be added on 64 bits capable OSs in order to enable the + # redirection of 64 bits applications + execute_process( + COMMAND reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\MATLAB /f * /k ${APPEND_REG} + RESULT_VARIABLE resultMatlab + OUTPUT_VARIABLE varMatlab + ERROR_VARIABLE errMatlab + INPUT_FILE NUL + ) + + + set(matlabs_from_registry) + if(${resultMatlab} EQUAL 0) + + string( + REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)" + matlab_versions_regex ${varMatlab}) + + foreach(match IN LISTS matlab_versions_regex) + string( + REGEX MATCH "MATLAB\\\\(([0-9]+)(\\.([0-9]+))?)" + current_match ${match}) + + set(_matlab_current_version ${CMAKE_MATCH_1}) + set(current_matlab_version_major ${CMAKE_MATCH_2}) + set(current_matlab_version_minor ${CMAKE_MATCH_4}) + if(NOT current_matlab_version_minor) + set(current_matlab_version_minor "0") endif() + + list(APPEND matlabs_from_registry ${_matlab_current_version}) + unset(_matlab_current_version) + endforeach(match) + + endif() + + if(matlabs_from_registry) + list(REMOVE_DUPLICATES matlabs_from_registry) + list(SORT matlabs_from_registry) + list(REVERSE matlabs_from_registry) + endif() + + set(${matlab_versions} ${matlabs_from_registry} PARENT_SCOPE) + +endfunction() + + + +# (internal) +macro(extract_matlab_versions_from_registry_brute_force matlab_versions) + # get the supported versions + set(matlab_supported_versions) + matlab_get_supported_versions(matlab_supported_versions) + + + # this is a manual population of the versions we want to look for + # this can be done as is, but preferably with the call to + # matlab_get_supported_versions and variable + + # populating the versions we want to look for + # set(matlab_supported_versions) + + # # Matlab 7 + # set(matlab_major 7) + # foreach(current_matlab_minor RANGE 4 20) + # list(APPEND matlab_supported_versions "${matlab_major}.${current_matlab_minor}") + # endforeach(current_matlab_minor) + + # # Matlab 8 + # set(matlab_major 8) + # foreach(current_matlab_minor RANGE 0 5) + # list(APPEND matlab_supported_versions "${matlab_major}.${current_matlab_minor}") + # endforeach(current_matlab_minor) + + # # taking into account the possible additional versions provided by the user + # if(DEFINED MATLAB_ADDITIONAL_VERSIONS) + # list(APPEND matlab_supported_versions MATLAB_ADDITIONAL_VERSIONS) + # endif() + + + # we order from more recent to older + if(matlab_supported_versions) + list(REMOVE_DUPLICATES matlab_supported_versions) + list(SORT matlab_supported_versions) + list(REVERSE matlab_supported_versions) + endif() + + + set(${matlab_versions} ${matlab_supported_versions}) + + +endmacro() + + + + +#.rst: +# .. command:: matlab_get_all_valid_matlab_roots_from_registry +# +# Populates the Matlab root with valid versions of Matlab. +# The returned matlab_roots is organized in pairs +# ``(version_number,matlab_root_path)``. +# +# :: +# +# matlab_get_all_valid_matlab_roots_from_registry( +# matlab_versions +# matlab_roots) +# +# ``matlab_versions`` +# the versions of each of the Matlab installations +# ``matlab_roots`` +# the location of each of the Matlab installations +function(matlab_get_all_valid_matlab_roots_from_registry matlab_versions matlab_roots) + + # The matlab_versions comes either from + # extract_matlab_versions_from_registry_brute_force or + # matlab_extract_all_installed_versions_from_registry. + + + set(_matlab_roots_list ) + foreach(_matlab_current_version ${matlab_versions}) + get_filename_component( + current_MATLAB_ROOT + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${_matlab_current_version};MATLABROOT]" + ABSOLUTE) + + if(EXISTS ${current_MATLAB_ROOT}) + list(APPEND _matlab_roots_list ${_matlab_current_version} ${current_MATLAB_ROOT}) endif() + + endforeach(_matlab_current_version) + unset(_matlab_current_version) + set(${matlab_roots} ${_matlab_roots_list} PARENT_SCOPE) + unset(_matlab_roots_list) +endfunction() + +#.rst: +# .. command:: matlab_get_mex_suffix +# +# Returns the extension of the mex files (the suffixes). +# This function should not be called before the appropriate Matlab root has +# been found. +# +# :: +# +# matlab_get_mex_suffix( +# matlab_root +# mex_suffix) +# +# ``matlab_root`` +# the root of the Matlab installation +# ``mex_suffix`` +# the variable name in which the suffix will be returned. +function(matlab_get_mex_suffix matlab_root mex_suffix) + + # todo setup the extension properly. Currently I do not know if this is + # sufficient for all win32 distributions. + # there is also CMAKE_EXECUTABLE_SUFFIX that could be tweaked + set(mexext_suffix "") + if(WIN32) + list(APPEND mexext_suffix ".bat") + endif() + + # we first try without suffix, since cmake does not understand a list with + # one empty string element + find_program( + Matlab_MEXEXTENSIONS_PROG + NAMES mexext + PATHS ${matlab_root}/bin + DOC "Matlab MEX extension provider" + NO_DEFAULT_PATH + ) + + foreach(current_mexext_suffix IN LISTS mexext_suffix) + if(NOT DEFINED Matlab_MEXEXTENSIONS_PROG OR NOT Matlab_MEXEXTENSIONS_PROG) + # this call should populate the cache automatically + find_program( + Matlab_MEXEXTENSIONS_PROG + "mexext${current_mexext_suffix}" + PATHS ${matlab_root}/bin + DOC "Matlab MEX extension provider" + NO_DEFAULT_PATH + ) + endif() + endforeach(current_mexext_suffix) + + + # the program has been found? + if((NOT Matlab_MEXEXTENSIONS_PROG) OR (NOT EXISTS ${Matlab_MEXEXTENSIONS_PROG})) + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Cannot found mexext program. Matlab root is ${matlab_root}") + endif() + unset(Matlab_MEXEXTENSIONS_PROG CACHE) + return() endif() - find_library(MATLAB_MEX_LIBRARY - libmex - ${MATLAB_ROOT} + + set(_matlab_mex_extension) + + set(devnull) + if(UNIX) + set(devnull INPUT_FILE /dev/null) + elseif(WIN32) + set(devnull INPUT_FILE NUL) + endif() + + execute_process( + COMMAND ${Matlab_MEXEXTENSIONS_PROG} + OUTPUT_VARIABLE _matlab_mex_extension + ERROR_VARIABLE _matlab_mex_extension_error + ${devnull}) + string(STRIP ${_matlab_mex_extension} _matlab_mex_extension) + + unset(Matlab_MEXEXTENSIONS_PROG CACHE) + set(${mex_suffix} ${_matlab_mex_extension} PARENT_SCOPE) +endfunction() + + + + +#.rst: +# .. command:: matlab_get_version_from_matlab_run +# +# This function runs Matlab program specified on arguments and extracts its +# version. +# +# :: +# +# matlab_get_version_from_matlab_run( +# matlab_binary_path +# matlab_list_versions) +# +# ``matlab_binary_path`` +# the location of the `matlab` binary executable +# ``matlab_list_versions`` +# the version extracted from Matlab +function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_versions) + + set(${matlab_list_versions} "" PARENT_SCOPE) + + + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Determining the version of Matlab from ${matlab_binary_program}") + endif() + + if(EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Removing previous ${_matlab_temporary_folder}/matlabVersionLog.cmaketmp file") + endif() + file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + endif() + + + # the log file is needed since on windows the command executes in a new + # window and it is not possible to get back the answer of Matlab + # the -wait command is needed on windows, otherwise the call returns + # immediately after the program launches itself. + if(WIN32) + set(_matlab_additional_commands "-wait") + endif() + + set(devnull) + if(UNIX) + set(devnull INPUT_FILE /dev/null) + elseif(WIN32) + set(devnull INPUT_FILE NUL) + endif() + + # timeout set to 30 seconds, in case it does not start + # note as said before OUTPUT_VARIABLE cannot be used in a platform + # independent manner however, not setting it would flush the output of Matlab + # in the current console (unix variant) + execute_process( + COMMAND "${matlab_binary_program}" -nosplash -nojvm ${_matlab_additional_commands} -logfile "matlabVersionLog.cmaketmp" -nodesktop -nodisplay -r "version, exit" + OUTPUT_VARIABLE _matlab_version_from_cmd_dummy + RESULT_VARIABLE _matlab_result_version_call + ERROR_VARIABLE _matlab_result_version_call_error + TIMEOUT 30 + WORKING_DIRECTORY "${_matlab_temporary_folder}" + ${devnull} ) - find_library(MATLAB_MX_LIBRARY - libmx - ${MATLAB_ROOT} + + + if(${_matlab_result_version_call}) + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call returned with error ${_matlab_result_version_call}.") + endif() + return() + elseif(NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab. The log file does not exist.") + endif() + return() + endif() + + # if successful, read back the log + file(READ "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp" _matlab_version_from_cmd) + file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + + set(index -1) + string(FIND ${_matlab_version_from_cmd} "ans" index) + if(index EQUAL -1) + + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Cannot find the version of Matlab returned by the run.") + endif() + + else() + set(matlab_list_of_all_versions_tmp) + + string(SUBSTRING ${_matlab_version_from_cmd} ${index} -1 substring_ans) + string( + REGEX MATCHALL "ans[\r\n\t ]*=[\r\n\t ]*([0-9]+(\\.[0-9]+)?)" + matlab_versions_regex + ${substring_ans}) + foreach(match IN LISTS matlab_versions_regex) + string( + REGEX MATCH "ans[\r\n\t ]*=[\r\n\t ]*(([0-9]+)(\\.([0-9]+))?)" + current_match ${match}) + + list(APPEND matlab_list_of_all_versions_tmp ${CMAKE_MATCH_1}) + endforeach() + if(matlab_list_of_all_versions_tmp) + list(REMOVE_DUPLICATES matlab_list_of_all_versions_tmp) + endif() + set(${matlab_list_versions} ${matlab_list_of_all_versions_tmp} PARENT_SCOPE) + + endif() + +endfunction() + + +#.rst: +# .. command:: matlab_add_unit_test +# +# Adds a Matlab unit test to the test set of cmake/ctest. +# This command requires the component ``MAIN_PROGRAM``. +# The unit test uses the Matlab unittest framework (default, available +# starting Matlab 2013b+) except if the option ``NO_UNITTEST_FRAMEWORK`` +# is given. +# +# The function expects one Matlab test script file to be given. +# In the case ``NO_UNITTEST_FRAMEWORK`` is given, the unittest script file +# should contain the script to be run, plus an exit command with the exit +# value. This exit value will be passed to the ctest framework (0 success, +# non 0 failure). Additional arguments accepted by :command:`add_test` can be +# passed through ``TEST_ARGS`` (eg. ``CONFIGURATION <config> ...``). +# +# :: +# +# matlab_add_unit_test( +# NAME <name> +# UNITTEST_FILE matlab_file_containing_unittest.m +# [UNITTEST_PRECOMMAND matlab_command_to_run] +# [TIMEOUT timeout] +# [ADDITIONAL_PATH path1 [path2 ...]] +# [MATLAB_ADDITIONAL_STARTUP_OPTIONS option1 [option2 ...]] +# [TEST_ARGS arg1 [arg2 ...]] +# [NO_UNITTEST_FRAMEWORK] +# ) +# +# The function arguments are: +# +# ``NAME`` +# name of the unittest in ctest. +# ``UNITTEST_FILE`` +# the matlab unittest file. Its path will be automatically +# added to the Matlab path. +# ``UNITTEST_PRECOMMAND`` +# Matlab script command to be ran before the file +# containing the test (eg. GPU device initialisation based on CMake +# variables). +# ``TIMEOUT`` +# the test timeout in seconds. Defaults to 180 seconds as the +# Matlab unit test may hang. +# ``ADDITIONAL_PATH`` +# a list of paths to add to the Matlab path prior to +# running the unit test. +# ``MATLAB_ADDITIONAL_STARTUP_OPTIONS`` +# a list of additional option in order +# to run Matlab from the command line. +# ``TEST_ARGS`` +# Additional options provided to the add_test command. These +# options are added to the default options (eg. "CONFIGURATIONS Release") +# ``NO_UNITTEST_FRAMEWORK`` +# when set, indicates that the test should not +# use the unittest framework of Matlab (available for versions >= R2013a). +# +function(matlab_add_unit_test) + + if(NOT Matlab_MAIN_PROGRAM) + message(FATAL_ERROR "[MATLAB] This functionality needs the MAIN_PROGRAM component (not default)") + endif() + + set(options NO_UNITTEST_FRAMEWORK) + set(oneValueArgs NAME UNITTEST_PRECOMMAND UNITTEST_FILE TIMEOUT) + set(multiValueArgs ADDITIONAL_PATH MATLAB_ADDITIONAL_STARTUP_OPTIONS TEST_ARGS) + + set(prefix _matlab_unittest_prefix) + cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if(NOT ${prefix}_NAME) + message(FATAL_ERROR "[MATLAB] The Matlab test name cannot be empty") + endif() + + add_test(NAME ${${prefix}_NAME} + COMMAND ${CMAKE_COMMAND} + -Dtest_name=${${prefix}_NAME} + -Dadditional_paths=${${prefix}_ADDITIONAL_PATH} + -Dtest_timeout=${${prefix}_TIMEOUT} + -Doutput_directory=${_matlab_temporary_folder} + -DMatlab_PROGRAM=${Matlab_MAIN_PROGRAM} + -Dno_unittest_framework=${${prefix}_NO_UNITTEST_FRAMEWORK} + -DMatlab_ADDITIONNAL_STARTUP_OPTIONS=${${prefix}_MATLAB_ADDITIONAL_STARTUP_OPTIONS} + -Dunittest_file_to_run=${${prefix}_UNITTEST_FILE} + -Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND} + -P ${_FindMatlab_SELF_DIR}/MatlabTestsRedirect.cmake + ${${prefix}_TEST_ARGS} + ${${prefix}_UNPARSED_ARGUMENTS} + ) +endfunction() + + +#.rst: +# .. command:: matlab_add_mex +# +# Adds a Matlab MEX target. +# This commands compiles the given sources with the current tool-chain in +# order to produce a MEX file. The final name of the produced output may be +# specified, as well as additional link libraries, and a documentation entry +# for the MEX file. Remaining arguments of the call are passed to the +# :command:`add_library` command. +# +# :: +# +# matlab_add_mex( +# NAME <name> +# SRC src1 [src2 ...] +# [OUTPUT_NAME output_name] +# [DOCUMENTATION file.txt] +# [LINK_TO target1 target2 ...] +# [...] +# ) +# +# ``NAME`` +# name of the target. +# ``SRC`` +# list of tje source files. +# ``LINK_TO`` +# a list of additional link dependencies. The target links to ``libmex`` +# by default. If ``Matlab_MX_LIBRARY`` is defined, it also +# links to ``libmx``. +# ``OUTPUT_NAME`` +# if given, overrides the default name. The default name is +# the name of the target without any prefix and +# with ``Matlab_MEX_EXTENSION`` suffix. +# ``DOCUMENTATION`` +# if given, the file ``file.txt`` will be considered as +# being the documentation file for the MEX file. This file is copied into +# the same folder without any processing, with the same name as the final +# mex file, and with extension `.m`. In that case, typing ``help <name>`` +# in Matlab prints the documentation contained in this file. +# +# The documentation file is not processed and should be in the following +# format: +# +# :: +# +# % This is the documentation +# function ret = mex_target_output_name(input1) +# +function(matlab_add_mex ) + + if(NOT WIN32) + # we do not need all this on Windows + # pthread options + check_cxx_compiler_flag(-pthread HAS_MINUS_PTHREAD) + # we should use try_compile instead, the link flags are discarded from + # this compiler_flag function. + #check_cxx_compiler_flag(-Wl,--exclude-libs,ALL HAS_SYMBOL_HIDING_CAPABILITY) + + endif() + + set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME) + set(multiValueArgs LINK_TO SRC) + + set(prefix _matlab_addmex_prefix) + cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if(NOT ${prefix}_NAME) + message(FATAL_ERROR "[MATLAB] The MEX target name cannot be empty") + endif() + + if(NOT ${prefix}_OUTPUT_NAME) + set(${prefix}_OUTPUT_NAME ${${prefix}_NAME}) + endif() + + add_library(${${prefix}_NAME} + SHARED + ${${prefix}_SRC} + ${${prefix}_DOCUMENTATION} + ${${prefix}_UNPARSED_ARGUMENTS}) + target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS}) + + if(DEFINED Matlab_MX_LIBRARY) + target_link_libraries(${${prefix}_NAME} ${Matlab_MX_LIBRARY}) + endif() + + target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${${prefix}_LINK_TO}) + set_target_properties(${${prefix}_NAME} + PROPERTIES + PREFIX "" + OUTPUT_NAME ${${prefix}_OUTPUT_NAME} + SUFFIX ".${Matlab_MEX_EXTENSION}") + + + # documentation + if(NOT ${${prefix}_DOCUMENTATION} STREQUAL "") + get_target_property(output_name ${${prefix}_NAME} OUTPUT_NAME) + add_custom_command( + TARGET ${${prefix}_NAME} + PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${${prefix}_DOCUMENTATION} $<TARGET_FILE_DIR:${${prefix}_NAME}>/${output_name}.m + COMMENT "Copy ${${prefix}_NAME} documentation file into the output folder" ) - find_library(MATLAB_ENG_LIBRARY - libeng - ${MATLAB_ROOT} + endif() # documentation + + # entry point in the mex file + taking care of visibility and symbol clashes. + if(WIN32) + set_target_properties(${${prefix}_NAME} + PROPERTIES + DEFINE_SYMBOL "DLL_EXPORT_SYM=__declspec(dllexport)") + else() + + if(HAS_MINUS_PTHREAD AND NOT APPLE) + # Apparently, compiling with -pthread generated the proper link flags + # and some defines at compilation + target_compile_options(${${prefix}_NAME} PRIVATE "-pthread") + endif() + + + # if we do not do that, the symbols linked from eg. boost remain weak and + # then clash with the ones defined in the matlab process. So by default + # the symbols are hidden. + # This also means that for shared libraries (like MEX), the entry point + # should be explicitly declared with default visibility, otherwise Matlab + # cannot find the entry point. + # Note that this is particularly meaningful if the MEX wrapper itself + # contains symbols that are clashing with Matlab (that are compiled in the + # MEX file). In order to propagate the visibility options to the libraries + # to which the MEX file is linked against, the -Wl,--exclude-libs,ALL + # option should also be specified. + + set_target_properties(${${prefix}_NAME} + PROPERTIES + CXX_VISIBILITY_PRESET "hidden" + C_VISIBILITY_PRESET "hidden" + VISIBILITY_INLINES_HIDDEN "hidden" ) - find_path(MATLAB_INCLUDE_DIR - "mex.h" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\7.0;MATLABROOT]/extern/include" + # get_target_property( + # _previous_link_flags + # ${${prefix}_NAME} + # LINK_FLAGS) + # if(NOT _previous_link_flags) + # set(_previous_link_flags) + # endif() + + # if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # set_target_properties(${${prefix}_NAME} + # PROPERTIES + # LINK_FLAGS "${_previous_link_flags} -Wl,--exclude-libs,ALL" + # # -Wl,--version-script=${_FindMatlab_SELF_DIR}/MatlabLinuxVisibility.map" + # ) + # elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # # in this case, all other symbols become hidden. + # set_target_properties(${${prefix}_NAME} + # PROPERTIES + # LINK_FLAGS "${_previous_link_flags} -Wl,-exported_symbol,_mexFunction" + # #-Wl,-exported_symbols_list,${_FindMatlab_SELF_DIR}/MatlabOSXVisilibity.map" + # ) + # endif() + + + + set_target_properties(${${prefix}_NAME} + PROPERTIES + DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__ ((visibility (\"default\")))" ) -else() - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - # Regular x86 - set(MATLAB_ROOT - /usr/local/matlab-7sp1/bin/glnx86/ - /opt/matlab-7sp1/bin/glnx86/ - $ENV{HOME}/matlab-7sp1/bin/glnx86/ - $ENV{HOME}/redhat-matlab/bin/glnx86/ + + + endif() + +endfunction() + + +# (internal) +# Used to get the version of matlab, using caching. This basically transforms the +# output of the root list, with possible unknown version, to a version +# +function(_Matlab_get_version_from_root matlab_root matlab_known_version matlab_final_version) + + # if the version is not trivial, we query matlab for that + # we keep track of the location of matlab that induced this version + #if(NOT DEFINED Matlab_PROG_VERSION_STRING_AUTO_DETECT) + # set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version") + #endif() + + if(NOT ${matlab_known_version} STREQUAL "NOTFOUND") + # the version is known, we just return it + set(${matlab_final_version} ${matlab_known_version} PARENT_SCOPE) + set(Matlab_VERSION_STRING_INTERNAL ${matlab_known_version} CACHE INTERNAL "Matlab version (automatically determined)" FORCE) + return() + endif() + + # + set(_matlab_current_program ${Matlab_MAIN_PROGRAM}) + + # do we already have a matlab program? + if(NOT _matlab_current_program) + + set(_find_matlab_options) + if(matlab_root AND EXISTS ${matlab_root}) + set(_find_matlab_options PATHS ${matlab_root} ${matlab_root}/bin NO_DEFAULT_PATH) + endif() + + find_program( + _matlab_current_program + matlab + ${_find_matlab_options} + DOC "Matlab main program" ) + endif() + + if(NOT _matlab_current_program OR NOT EXISTS ${_matlab_current_program}) + # if not found, clear the dependent variables + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Cannot find the main matlab program under ${matlab_root}") + endif() + set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE) + set(Matlab_VERSION_STRING_INTERNAL "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE) + unset(_matlab_current_program) + unset(_matlab_current_program CACHE) + return() + endif() + + # full real path for path comparison + get_filename_component(_matlab_main_real_path_tmp "${_matlab_current_program}" REALPATH) + unset(_matlab_current_program) + unset(_matlab_current_program CACHE) + + # is it the same as the previous one? + if(_matlab_main_real_path_tmp STREQUAL Matlab_PROG_VERSION_STRING_AUTO_DETECT) + set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE) + return() + endif() + + # update the location of the program + set(Matlab_PROG_VERSION_STRING_AUTO_DETECT ${_matlab_main_real_path_tmp} CACHE INTERNAL "internal matlab location for the discovered version" FORCE) + + set(matlab_list_of_all_versions) + matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions) + + list(GET matlab_list_of_all_versions 0 _matlab_version_tmp) + + # set the version into the cache + set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE) + + # warning, just in case several versions found (should not happen) + list(LENGTH matlab_list_of_all_versions list_of_all_versions_length) + if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})") + endif() + + # return the updated value + set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE) + +endfunction() + + + + + + + +# ################################### +# Exploring the possible Matlab_ROOTS + +# this variable will get all Matlab installations found in the current system. +set(_matlab_possible_roots) + + + +if(Matlab_ROOT_DIR) + # if the user specifies a possible root, we keep this one + + if(NOT EXISTS ${Matlab_ROOT_DIR}) + # if Matlab_ROOT_DIR specified but erroneous + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] the specified path for Matlab_ROOT_DIR does not exist (${Matlab_ROOT_DIR})") + endif() else() - # AMD64: - set(MATLAB_ROOT - /usr/local/matlab-7sp1/bin/glnxa64/ - /opt/matlab-7sp1/bin/glnxa64/ - $ENV{HOME}/matlab7_64/bin/glnxa64/ - $ENV{HOME}/matlab-7sp1/bin/glnxa64/ - $ENV{HOME}/redhat-matlab/bin/glnxa64/ - ) + # NOTFOUND indicates the code below to search for the version automatically + if(NOT DEFINED Matlab_VERSION_STRING_INTERNAL) + list(APPEND _matlab_possible_roots "NOTFOUND" ${Matlab_ROOT_DIR}) # empty version + else() + list(APPEND _matlab_possible_roots ${Matlab_VERSION_STRING_INTERNAL} ${Matlab_ROOT_DIR}) # cached version + endif() + endif() + + +else() + + # if the user does not specify the possible installation root, we look for + # one installation using the appropriate heuristics + + if(WIN32) + + # On WIN32, we look for Matlab installation in the registry + # if unsuccessful, we look for all known revision and filter the existing + # ones. + + # testing if we are able to extract the needed information from the registry + set(_matlab_versions_from_registry) + matlab_extract_all_installed_versions_from_registry(CMAKE_CL_64 _matlab_versions_from_registry) + + # the returned list is empty, doing the search on all known versions + if(NOT _matlab_versions_from_registry) + + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions") + endif() + + extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry) + endif() + + # filtering the results with the registry keys + matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots) + unset(_matlab_versions_from_registry) + + elseif(APPLE) + + # on mac, we look for the /Application paths + # this corresponds to the behaviour on Windows. On Linux, we do not have + # any other guess. + matlab_get_supported_releases(_matlab_releases) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Matlab supported versions ${_matlab_releases}. If more version should be supported " + "the variable MATLAB_ADDITIONAL_VERSIONS can be set according to the documentation") + endif() + + foreach(_matlab_current_release IN LISTS _matlab_releases) + set(_matlab_full_string "/Applications/MATLAB_${_matlab_current_release}.app") + if(EXISTS ${_matlab_full_string}) + set(_matlab_current_version) + matlab_get_version_from_release_name("${_matlab_current_release}" _matlab_current_version) + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Found version ${_matlab_current_release} (${_matlab_current_version}) in ${_matlab_full_string}") + endif() + list(APPEND _matlab_possible_roots ${_matlab_current_version} ${_matlab_full_string}) + unset(_matlab_current_version) + endif() + + unset(_matlab_full_string) + endforeach(_matlab_current_release) + + unset(_matlab_current_release) + unset(_matlab_releases) + endif() - find_library(MATLAB_MEX_LIBRARY - mex - ${MATLAB_ROOT} - ) - find_library(MATLAB_MX_LIBRARY - mx - ${MATLAB_ROOT} - ) - find_library(MATLAB_ENG_LIBRARY - eng - ${MATLAB_ROOT} - ) - find_path(MATLAB_INCLUDE_DIR - "mex.h" - "/usr/local/matlab-7sp1/extern/include/" - "/opt/matlab-7sp1/extern/include/" - "$ENV{HOME}/matlab-7sp1/extern/include/" - "$ENV{HOME}/redhat-matlab/extern/include/" - ) endif() -# This is common to UNIX and Win32: -set(MATLAB_LIBRARIES - ${MATLAB_MEX_LIBRARY} - ${MATLAB_MX_LIBRARY} - ${MATLAB_ENG_LIBRARY} + + +list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots) +if(_numbers_of_matlab_roots EQUAL 0) + # if we have not found anything, we fall back on the PATH + + + # At this point, we have no other choice than trying to find it from PATH. + # If set by the user, this wont change + find_program( + _matlab_main_tmp + NAMES matlab) + + + if(_matlab_main_tmp) + # we then populate the list of roots, with empty version + if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] matlab found from PATH: ${_matlab_main_tmp}") + endif() + + # resolve symlinks + get_filename_component(_matlab_current_location "${_matlab_main_tmp}" REALPATH) + + # get the directory (the command below has to be run twice) + # this will be the matlab root + get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY) + get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY) # Matlab should be in bin + + list(APPEND _matlab_possible_roots "NOTFOUND" ${_matlab_current_location}) + + unset(_matlab_current_location) + + endif() + unset(_matlab_main_tmp CACHE) + +endif() + + + + + +if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Matlab root folders are ${_matlab_possible_roots}") +endif() + + + + + +# take the first possible Matlab root +list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots) +set(Matlab_VERSION_STRING "NOTFOUND") +if(_numbers_of_matlab_roots GREATER 0) + list(GET _matlab_possible_roots 0 Matlab_VERSION_STRING) + list(GET _matlab_possible_roots 1 Matlab_ROOT_DIR) + + # adding a warning in case of ambiguity + if(_numbers_of_matlab_roots GREATER 2 AND MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})." + " If this is not the desired behaviour, provide the -DMatlab_ROOT_DIR=... on the command line") + endif() +endif() + + +# check if the root changed against the previous defined one, if so +# clear all the cached variables +if(DEFINED Matlab_ROOT_DIR_LAST_CACHED) + + if(NOT Matlab_ROOT_DIR_LAST_CACHED STREQUAL Matlab_ROOT_DIR) + set(_Matlab_cached_vars + Matlab_INCLUDE_DIRS + Matlab_MEX_LIBRARY + Matlab_MEX_COMPILER + Matlab_MAIN_PROGRAM + Matlab_MX_LIBRARY + Matlab_ENG_LIBRARY + Matlab_MEX_EXTENSION + + # internal + Matlab_MEXEXTENSIONS_PROG + Matlab_ROOT_DIR_LAST_CACHED + #Matlab_PROG_VERSION_STRING_AUTO_DETECT + Matlab_VERSION_STRING_INTERNAL + ) + foreach(_var IN LISTS _Matlab_cached_vars) + if(DEFINED ${_var}) + unset(${_var} CACHE) + endif() + endforeach() + endif() +endif() + +set(Matlab_ROOT_DIR_LAST_CACHED ${Matlab_ROOT_DIR} CACHE INTERNAL "last Matlab root dir location") +set(Matlab_ROOT_DIR ${Matlab_ROOT_DIR} CACHE PATH "Matlab installation root path" FORCE) + +# Fix the version, in case this one is NOTFOUND +_Matlab_get_version_from_root( + "${Matlab_ROOT_DIR}" + ${Matlab_VERSION_STRING} + Matlab_VERSION_STRING ) -if(MATLAB_INCLUDE_DIR AND MATLAB_LIBRARIES) - set(MATLAB_FOUND 1) + + + +if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] Current version is ${Matlab_VERSION_STRING} located ${Matlab_ROOT_DIR}") +endif() + + + +if(Matlab_ROOT_DIR) + file(TO_CMAKE_PATH ${Matlab_ROOT_DIR} Matlab_ROOT_DIR) endif() -mark_as_advanced( - MATLAB_LIBRARIES - MATLAB_MEX_LIBRARY - MATLAB_MX_LIBRARY - MATLAB_ENG_LIBRARY - MATLAB_INCLUDE_DIR - MATLAB_FOUND - MATLAB_ROOT +if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(_matlab_64Build FALSE) +else() + set(_matlab_64Build TRUE) +endif() + +if(APPLE) + set(_matlab_bin_prefix "mac") # i should be for intel + set(_matlab_bin_suffix_32bits "i") + set(_matlab_bin_suffix_64bits "i64") +elseif(UNIX) + set(_matlab_bin_prefix "gln") + set(_matlab_bin_suffix_32bits "x86") + set(_matlab_bin_suffix_64bits "xa64") +else() + set(_matlab_bin_prefix "win") + set(_matlab_bin_suffix_32bits "32") + set(_matlab_bin_suffix_64bits "64") +endif() + + + +set(MATLAB_INCLUDE_DIR_TO_LOOK ${Matlab_ROOT_DIR}/extern/include) +if(_matlab_64Build) + set(_matlab_current_suffix ${_matlab_bin_suffix_64bits}) +else() + set(_matlab_current_suffix ${_matlab_bin_suffix_32bits}) +endif() + +set(Matlab_BINARIES_DIR + ${Matlab_ROOT_DIR}/bin/${_matlab_bin_prefix}${_matlab_current_suffix}) +set(Matlab_EXTERN_LIBRARY_DIR + ${Matlab_ROOT_DIR}/extern/lib/${_matlab_bin_prefix}${_matlab_current_suffix}) + +if(WIN32) + set(_matlab_lib_dir_for_search ${Matlab_EXTERN_LIBRARY_DIR}/microsoft) + set(_matlab_lib_prefix_for_search "lib") +else() + set(_matlab_lib_dir_for_search ${Matlab_BINARIES_DIR}) + set(_matlab_lib_prefix_for_search "lib") +endif() + +unset(_matlab_64Build) + + +if(NOT DEFINED Matlab_MEX_EXTENSION) + set(_matlab_mex_extension "") + matlab_get_mex_suffix("${Matlab_ROOT_DIR}" _matlab_mex_extension) + + # This variable goes to the cache. + set(Matlab_MEX_EXTENSION ${_matlab_mex_extension} CACHE STRING "Extensions for the mex targets (automatically given by Matlab)") + unset(_matlab_mex_extension) +endif() + + +if(MATLAB_FIND_DEBUG) + message(STATUS "[MATLAB] [DEBUG]_matlab_lib_prefix_for_search = ${_matlab_lib_prefix_for_search} | _matlab_lib_dir_for_search = ${_matlab_lib_dir_for_search}") +endif() + + + +# internal +# This small stub around find_library is to prevent any pollution of CMAKE_FIND_LIBRARY_PREFIXES in the global scope. +# This is the function to be used below instead of the find_library directives. +function(_Matlab_find_library _matlab_library_prefix) + set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} ${_matlab_library_prefix}) + find_library(${ARGN}) +endfunction() + + +set(_matlab_required_variables) + + +# the MEX library/header are required +find_path( + Matlab_INCLUDE_DIRS + mex.h + PATHS ${MATLAB_INCLUDE_DIR_TO_LOOK} + NO_DEFAULT_PATH + ) +list(APPEND _matlab_required_variables Matlab_INCLUDE_DIRS) + +_Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_MEX_LIBRARY + mex + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH ) + +list(APPEND _matlab_required_variables Matlab_MEX_LIBRARY) + +# the MEX extension is required +list(APPEND _matlab_required_variables Matlab_MEX_EXTENSION) + +# the matlab root is required +list(APPEND _matlab_required_variables Matlab_ROOT_DIR) + + +# component Mex Compiler +list(FIND Matlab_FIND_COMPONENTS MEX_COMPILER _matlab_find_mex_compiler) +if(_matlab_find_mex_compiler GREATER -1) + find_program( + Matlab_MEX_COMPILER + "mex" + PATHS ${Matlab_BINARIES_DIR} + DOC "Matlab MEX compiler" + NO_DEFAULT_PATH + ) + + if(Matlab_MEX_COMPILER) + set(Matlab_MEX_COMPILER_FOUND TRUE) + endif() +endif() +unset(_matlab_find_mex_compiler) + +# component Matlab program +list(FIND Matlab_FIND_COMPONENTS MAIN_PROGRAM _matlab_find_matlab_program) +if(_matlab_find_matlab_program GREATER -1) + + find_program( + Matlab_MAIN_PROGRAM + matlab + PATHS ${Matlab_ROOT_DIR} ${Matlab_ROOT_DIR}/bin + DOC "Matlab main program" + NO_DEFAULT_PATH + ) + + if(Matlab_MAIN_PROGRAM) + set(Matlab_MAIN_PROGRAM_FOUND TRUE) + endif() + +endif() +unset(_matlab_find_matlab_program) + +# Component MX library +list(FIND Matlab_FIND_COMPONENTS MX_LIBRARY _matlab_find_mx) +if(_matlab_find_mx GREATER -1) + _Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_MX_LIBRARY + mx + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH + ) + + if(Matlab_MX_LIBRARY) + set(Matlab_MX_LIBRARY_FOUND TRUE) + endif() +endif() +unset(_matlab_find_mx) + + +# Component ENG library +list(FIND Matlab_FIND_COMPONENTS ENG_LIBRARY _matlab_find_eng) +if(_matlab_find_eng GREATER -1) + _Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_ENG_LIBRARY + eng + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH + ) + if(Matlab_ENG_LIBRARY) + set(Matlab_ENG_LIBRARY_FOUND TRUE) + endif() +endif() +unset(_matlab_find_eng) + + + + + +unset(_matlab_lib_dir_for_search) + + +set(Matlab_LIBRARIES ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${Matlab_ENG_LIBRARY}) + + +find_package_handle_standard_args( + Matlab + FOUND_VAR Matlab_FOUND + REQUIRED_VARS ${_matlab_required_variables} + VERSION_VAR Matlab_VERSION_STRING + HANDLE_COMPONENTS) + +unset(_matlab_required_variables) +unset(_matlab_bin_prefix) +unset(_matlab_bin_suffix_32bits) +unset(_matlab_bin_suffix_64bits) +unset(_matlab_current_suffix) +unset(_matlab_lib_dir_for_search) +unset(_matlab_lib_prefix_for_search) + +if(Matlab_INCLUDE_DIRS AND Matlab_LIBRARIES) + mark_as_advanced( + #Matlab_LIBRARIES + Matlab_MEX_LIBRARY + Matlab_MX_LIBRARY + Matlab_ENG_LIBRARY + Matlab_INCLUDE_DIRS + Matlab_FOUND + #Matlab_ROOT_DIR + #Matlab_VERSION_STRING + Matlab_MAIN_PROGRAM + #Matlab_MEX_EXTENSION + Matlab_MEXEXTENSIONS_PROG + Matlab_MEX_EXTENSION + #Matlab_BINARIES_DIR + ) +endif() diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake index 2de1fb3..bcbd17d 100644 --- a/Modules/FindPackageHandleStandardArgs.cmake +++ b/Modules/FindPackageHandleStandardArgs.cmake @@ -33,7 +33,7 @@ # # :: # -# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<NAME> # [FOUND_VAR <resultVar>] # [REQUIRED_VARS <var1>...<varN>] # [VERSION_VAR <versionvar>] diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index bf58ede..64ccde5 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -143,7 +143,7 @@ endmacro() # - _pkgconfig_add_extra_path(_extra_paths ENV VAR) function(_pkgconfig_add_extra_path _extra_paths_var _var) set(_is_env 0) - if(_var STREQUAL "ENV") + if(ARGC GREATER 2 AND _var STREQUAL "ENV") set(_var ${ARGV2}) set(_is_env 1) endif() diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index 4be16c9..e5ea210 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -234,11 +234,16 @@ if(WIN32) set( _RUBY_MSVC_RUNTIME "90" ) endif() + set(_RUBY_ARCH_PREFIX "") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_RUBY_ARCH_PREFIX "x64-") + endif() + list(APPEND _RUBY_POSSIBLE_LIB_NAMES - "msvcr${_RUBY_MSVC_RUNTIME}-ruby${_RUBY_NODOT_VERSION}" - "msvcr${_RUBY_MSVC_RUNTIME}-ruby${_RUBY_NODOT_VERSION}-static" - "msvcrt-ruby${_RUBY_NODOT_VERSION}" - "msvcrt-ruby${_RUBY_NODOT_VERSION}-static" ) + "${_RUBY_ARCH_PREFIX}msvcr${_RUBY_MSVC_RUNTIME}-ruby${_RUBY_NODOT_VERSION}" + "${_RUBY_ARCH_PREFIX}msvcr${_RUBY_MSVC_RUNTIME}-ruby${_RUBY_NODOT_VERSION}-static" + "${_RUBY_ARCH_PREFIX}msvcrt-ruby${_RUBY_NODOT_VERSION}" + "${_RUBY_ARCH_PREFIX}msvcrt-ruby${_RUBY_NODOT_VERSION}-static" ) endif() find_library(RUBY_LIBRARY NAMES ${_RUBY_POSSIBLE_LIB_NAMES} HINTS ${RUBY_POSSIBLE_LIB_DIR} ) diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake new file mode 100644 index 0000000..3cd9c22 --- /dev/null +++ b/Modules/FindXCTest.cmake @@ -0,0 +1,196 @@ +#[=======================================================================[.rst: +FindXCTest +---------- + +Functions to help creating and executing XCTest bundles. + +An XCTest bundle is a CFBundle with a special product-type +and bundle extension. The Mac Developer Library provides more +information in the `Testing with Xcode`_ document. + +.. _Testing with Xcode: http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/testing_with_xcode/ + +Module Functions +^^^^^^^^^^^^^^^^ + +.. command:: xctest_add_bundle + + The ``xctest_add_bundle`` function creates a XCTest bundle named + <target> which will test the target <testee>. Supported target types + for testee are Frameworks and App Bundles:: + + xctest_add_bundle( + <target> # Name of the XCTest bundle + <testee> # Target name of the testee + ) + +.. command:: xctest_add_test + + The ``xctest_add_test`` function adds an XCTest bundle to the + project to be run by :manual:`ctest(1)`. The test will be named + <name> and tests <bundle>:: + + xctest_add_test( + <name> # Test name + <bundle> # Target name of XCTest bundle + ) + +Module Variables +^^^^^^^^^^^^^^^^ + +The following variables are set by including this module: + +.. variable:: XCTest_FOUND + + True if the XCTest Framework and executable were found. + +.. variable:: XCTest_EXECUTABLE + + The path to the xctest command line tool used to execute XCTest bundles. + +.. variable:: XCTest_INCLUDE_DIRS + + The directory containing the XCTest Framework headers. + +.. variable:: XCTest_LIBRARIES + + The location of the XCTest Framework. + +#]=======================================================================] + +#============================================================================= +# Copyright 2015 Gregor Jasny +# +# 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.) + +find_path(XCTest_INCLUDE_DIR + NAMES "XCTest/XCTest.h" + DOC "XCTest include directory") +mark_as_advanced(XCTest_INCLUDE_DIR) + +find_library(XCTest_LIBRARY + NAMES XCTest + DOC "XCTest Framework library") +mark_as_advanced(XCTest_LIBRARY) + +execute_process( + COMMAND xcrun --find xctest + OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _xcrun_err) +if(_xcrun_out) + set(XCTest_EXECUTABLE "${_xcrun_out}" CACHE FILEPATH "XCTest executable") + mark_as_advanced(XCTest_EXECUTABLE) +endif() + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +find_package_handle_standard_args(XCTest + FOUND_VAR XCTest_FOUND + REQUIRED_VARS XCTest_LIBRARY XCTest_INCLUDE_DIR XCTest_EXECUTABLE) + +if(XCTest_FOUND) + set(XCTest_INCLUDE_DIRS "${XCTest_INCLUDE_DIR}") + set(XCTest_LIBRARIES "${XCTest_LIBRARY}") +endif(XCTest_FOUND) + + +function(xctest_add_bundle target testee) + if(NOT XCTest_FOUND) + message(FATAL_ERROR "XCTest is required to create a XCTest Bundle.") + endif(NOT XCTest_FOUND) + + if(NOT CMAKE_OSX_SYSROOT) + message(FATAL_ERROR "Adding XCTest bundles requires CMAKE_OSX_SYSROOT to be set.") + endif() + + add_library(${target} MODULE ${ARGN}) + + set_target_properties(${target} PROPERTIES + BUNDLE TRUE + XCTEST TRUE + XCTEST_TESTEE ${testee}) + + target_link_libraries(${target} PRIVATE "-framework Foundation") + target_link_libraries(${target} PRIVATE ${XCTest_LIBRARIES}) + target_include_directories(${target} PRIVATE ${XCTest_INCLUDE_DIRS}) + + # retrieve testee target type + if(NOT TARGET ${testee}) + message(FATAL_ERROR "${testee} is not a target.") + endif() + get_property(_testee_type TARGET ${testee} PROPERTY TYPE) + get_property(_testee_framework TARGET ${testee} PROPERTY FRAMEWORK) + get_property(_testee_macosx_bundle TARGET ${testee} PROPERTY MACOSX_BUNDLE) + + if(_testee_type STREQUAL "SHARED_LIBRARY" AND _testee_framework) + # testee is a Framework + target_link_libraries(${target} PRIVATE ${testee}) + + elseif(_testee_type STREQUAL "EXECUTABLE" AND _testee_macosx_bundle) + # testee is an App Bundle + add_dependencies(${target} ${testee}) + if(XCODE) + set_target_properties(${target} PROPERTIES + XCODE_ATTRIBUTE_BUNDLE_LOADER "$(TEST_HOST)" + XCODE_ATTRIBUTE_TEST_HOST "$<TARGET_FILE:${testee}>") + else(XCODE) + target_link_libraries(${target} + PRIVATE -bundle_loader $<TARGET_FILE:${testee}>) + endif(XCODE) + + else() + message(FATAL_ERROR "Testee ${testee} is of unsupported type.") + endif() +endfunction(xctest_add_bundle) + + +function(xctest_add_test name bundle) + if(NOT XCTest_EXECUTABLE) + message(FATAL_ERROR "XCTest executable is required to register a test.") + endif() + + # check that bundle is a XCTest Bundle + + if(NOT TARGET ${bundle}) + message(FATAL_ERROR "${bundle} is not a target.") + endif(NOT TARGET ${bundle}) + + get_property(_test_type TARGET ${bundle} PROPERTY TYPE) + get_property(_test_bundle TARGET ${bundle} PROPERTY BUNDLE) + get_property(_test_xctest TARGET ${bundle} PROPERTY XCTEST) + + if(NOT _test_type STREQUAL "MODULE_LIBRARY" + OR NOT _test_xctest OR NOT _test_bundle) + message(FATAL_ERROR "Test ${bundle} is not an XCTest Bundle") + endif() + + # get and check testee properties + + get_property(_testee TARGET ${bundle} PROPERTY XCTEST_TESTEE) + if(NOT TARGET ${_testee}) + message(FATAL_ERROR "${_testee} is not a target.") + endif() + + get_property(_testee_type TARGET ${_testee} PROPERTY TYPE) + get_property(_testee_framework TARGET ${_testee} PROPERTY FRAMEWORK) + + # register test + + add_test( + NAME ${name} + COMMAND ${XCTest_EXECUTABLE} $<TARGET_LINKER_FILE_DIR:${bundle}>/../..) + + # point loader to testee in case rpath is disabled + + if(_testee_type STREQUAL "SHARED_LIBRARY" AND _testee_framework) + set_property(TEST ${name} APPEND PROPERTY + ENVIRONMENT DYLD_FRAMEWORK_PATH=$<TARGET_LINKER_FILE_DIR:${_testee}>/..) + endif() +endfunction(xctest_add_test) diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake index 0c6256c..aab29ea 100644 --- a/Modules/GenerateExportHeader.cmake +++ b/Modules/GenerateExportHeader.cmake @@ -395,7 +395,7 @@ function(add_compiler_export_flags) # Either return the extra flags needed in the supplied argument, or to the # CMAKE_CXX_FLAGS if no argument is supplied. - if(ARGV0) + if(ARGC GREATER 0) set(${ARGV0} "${EXTRA_FLAGS}" PARENT_SCOPE) else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}" PARENT_SCOPE) diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 712a41c..23d486e 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -260,6 +260,13 @@ function(is_file_executable file result_var) return() endif() + # "file" version 5.22 does not print "(used shared libraries)" + # but uses "interpreter" + if("${file_ov}" MATCHES "shared object.*interpreter") + set(${result_var} 1 PARENT_SCOPE) + return() + endif() + else() message(STATUS "warning: No 'file' command, skipping execute_process...") endif() @@ -323,7 +330,11 @@ endfunction() function(gp_resolve_item context item exepath dirs resolved_item_var) set(resolved 0) set(resolved_item "${item}") - set(rpaths "${ARGV5}") + if(ARGC GREATER 5) + set(rpaths "${ARGV5}") + else() + set(rpaths "") + endif() # Is it already resolved? # @@ -474,7 +485,11 @@ endfunction() function(gp_resolved_file_type original_file file exepath dirs type_var) - set(rpaths "${ARGV5}") + if(ARGC GREATER 5) + set(rpaths "${ARGV5}") + else() + set(rpaths "") + endif() #message(STATUS "**") if(NOT IS_ABSOLUTE "${original_file}") @@ -616,7 +631,11 @@ endfunction() function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs) set(verbose 0) set(eol_char "E") - set(rpaths "${ARGV6}") + if(ARGC GREATER 6) + set(rpaths "${ARGV6}") + else() + set(rpaths "") + endif() if(NOT IS_ABSOLUTE "${target}") message("warning: target '${target}' is not absolute...") @@ -874,22 +893,22 @@ endfunction() function(list_prerequisites target) - if("${ARGV1}" STREQUAL "") - set(all 1) - else() + if(ARGC GREATER 1 AND NOT "${ARGV1}" STREQUAL "") set(all "${ARGV1}") + else() + set(all 1) endif() - if("${ARGV2}" STREQUAL "") - set(exclude_system 0) - else() + if(ARGC GREATER 2 AND NOT "${ARGV2}" STREQUAL "") set(exclude_system "${ARGV2}") + else() + set(exclude_system 0) endif() - if("${ARGV3}" STREQUAL "") - set(verbose 0) - else() + if(ARGC GREATER 3 AND NOT "${ARGV3}" STREQUAL "") set(verbose "${ARGV3}") + else() + set(verbose 0) endif() set(count 0) diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index 5afb517..c7e88ba 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -2,36 +2,49 @@ # InstallRequiredSystemLibraries # ------------------------------ # +# Include this module to search for compiler-provided system runtime +# libraries and add install rules for them. Some optional variables +# may be set prior to including the module to adjust behavior: # +# ``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS`` +# Specify additional runtime libraries that may not be detected. +# After inclusion any detected libraries will be appended to this. # -# By including this file, all library files listed in the variable -# CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS will be installed with -# install(PROGRAMS ...) into bin for WIN32 and lib for non-WIN32. If -# CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP is set to TRUE before including -# this file, then the INSTALL command is not called. The user can use -# the variable CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS to use a custom install -# command and install them however they want. If it is the MSVC -# compiler, then the microsoft run time libraries will be found and -# automatically added to the CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS, and -# installed. If CMAKE_INSTALL_DEBUG_LIBRARIES is set and it is the MSVC -# compiler, then the debug libraries are installed when available. If -# CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY is set then only the debug -# libraries are installed when both debug and release are available. If -# CMAKE_INSTALL_MFC_LIBRARIES is set then the MFC run time libraries are -# installed as well as the CRT run time libraries. If -# CMAKE_INSTALL_OPENMP_LIBRARIES is set then the OpenMP run time libraries -# are installed as well. If -# CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION is set then the libraries are -# installed to that directory rather than the default. If -# CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS is NOT set, then this -# file warns about required files that do not exist. You can set this -# variable to ON before including this file to avoid the warning. For -# example, the Visual Studio Express editions do not include the -# redistributable files, so if you include this file on a machine with -# only VS Express installed, you'll get the warning. +# ``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP`` +# Set to TRUE to skip calling the :command:`install(PROGRAMS)` command to +# allow the includer to specify its own install rule, using the value of +# ``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS`` to get the list of libraries. +# +# ``CMAKE_INSTALL_DEBUG_LIBRARIES`` +# Set to TRUE to install the debug runtime libraries when available +# with MSVC tools. +# +# ``CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY`` +# Set to TRUE to install only the debug runtime libraries with MSVC +# tools even if the release runtime libraries are also available. +# +# ``CMAKE_INSTALL_MFC_LIBRARIES`` +# Set to TRUE to install the MSVC MFC runtime libraries. +# +# ``CMAKE_INSTALL_OPENMP_LIBRARIES`` +# Set to TRUE to install the MSVC OpenMP runtime libraries +# +# ``CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION`` +# Specify the :command:`install(PROGRAMS)` command ``DESTINATION`` +# option. If not specified, the default is ``bin`` on Windows +# and ``lib`` elsewhere. +# +# ``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS`` +# Set to TRUE to disable warnings about required library files that +# do not exist. (For example, Visual Studio Express editions may +# not provide the redistributable files.) +# +# ``CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT`` +# Specify the :command:`install(PROGRAMS)` command ``COMPONENT`` +# option. If not specified, no such option will be used. #============================================================================= -# Copyright 2006-2009 Kitware, Inc. +# Copyright 2006-2015 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. @@ -477,7 +490,13 @@ if(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS) set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION lib) endif() endif() + if(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT) + set(_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT + COMPONENT ${CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT}) + endif() install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} - DESTINATION ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION}) + DESTINATION ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION} + ${_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} + ) endif() endif() diff --git a/Modules/MatlabTestsRedirect.cmake b/Modules/MatlabTestsRedirect.cmake new file mode 100644 index 0000000..ebccbf6 --- /dev/null +++ b/Modules/MatlabTestsRedirect.cmake @@ -0,0 +1,92 @@ +# This is an undocumented internal helper for the FindMatlab +# module ``matlab_add_unit_test`` command. + +#============================================================================= +# Copyright 2014-2015 Raffi Enficiaud, Max Planck Society +# +# 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.) + + +# Usage: cmake +# -Dtest_timeout=180 +# -Dworking_directory="." +# -Doutput_directory= +# -Dadditional_paths="" +# -Dno_unittest_framework="" +# -DMatlab_PROGRAM=matlab_exe_location +# -DMatlab_ADDITIONNAL_STARTUP_OPTIONS="" +# -Dtest_name=name_of_the_test +# -Dcmd_to_run_before_test="" +# -Dunittest_file_to_run +# -P FindMatlab_TestsRedirect.cmake + +set(Matlab_UNIT_TESTS_CMD -nosplash -nojvm -nodesktop -nodisplay ${Matlab_ADDITIONNAL_STARTUP_OPTIONS}) +if(WIN32) + set(Matlab_UNIT_TESTS_CMD ${Matlab_UNIT_TESTS_CMD} -wait) +endif() + +if(NOT test_timeout) + set(test_timeout 180) +endif() + +if(NOT cmd_to_run_before_test) + set(cmd_to_run_before_test) +endif() + +get_filename_component(unittest_file_directory "${unittest_file_to_run}" DIRECTORY) +get_filename_component(unittest_file_to_run_name "${unittest_file_to_run}" NAME_WE) + +set(concat_string '${unittest_file_directory}') +foreach(s IN LISTS additional_paths) + if(NOT "${s}" STREQUAL "") + set(concat_string "${concat_string}, '${s}'") + endif() +endforeach() + +set(unittest_to_run "runtests('${unittest_file_to_run_name}'), exit(max([ans(1,:).Failed]))") +if(no_unittest_framework) + set(unittest_to_run "try, ${unittest_file_to_run_name}, catch err, disp('An exception has been thrown during the execution'), disp(err), disp(err.stack), exit(1), end, exit(0)") +endif() + +set(Matlab_SCRIPT_TO_RUN + "addpath(${concat_string}), path, ${cmd_to_run_before_test}, ${unittest_to_run}" + ) + +set(Matlab_LOG_FILE "${output_directory}/${test_name}.log") + +set(devnull) +if(UNIX) + set(devnull INPUT_FILE /dev/null) +elseif(WIN32) + set(devnull INPUT_FILE NUL) +endif() + +execute_process( + COMMAND "${Matlab_PROGRAM}" ${Matlab_UNIT_TESTS_CMD} -logfile "${test_name}.log" -r "${Matlab_SCRIPT_TO_RUN}" + RESULT_VARIABLE res + TIMEOUT ${test_timeout} + OUTPUT_QUIET # we do not want the output twice + WORKING_DIRECTORY "${output_directory}" + ${devnull} + ) + +if(NOT EXISTS ${Matlab_LOG_FILE}) + message( FATAL_ERROR "[MATLAB] ERROR: cannot find the log file ${Matlab_LOG_FILE}") +endif() + +# print the output in any case. +file(READ ${Matlab_LOG_FILE} matlab_log_content) +message("Matlab test ${name_of_the_test} output:\n${matlab_log_content}") # if we put FATAL_ERROR here, the file is indented. + + +if(NOT (res EQUAL 0)) + message( FATAL_ERROR "[MATLAB] TEST FAILED" ) +endif() diff --git a/Modules/Platform/BlueGeneQ-base.cmake b/Modules/Platform/BlueGeneQ-base.cmake new file mode 100644 index 0000000..fa8dc52 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-base.cmake @@ -0,0 +1,177 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +# +# Blue Gene/Q base platform file. +# +# NOTE: Do not set your platform to "BlueGeneQ-base". This file is +# included by the real platform files. Use one of these two platforms +# instead: +# +# BlueGeneQ-dynamic For dynamically linked executables +# BlueGeneQ-static For statically linked executables +# +# The platform you choose doesn't affect whether or not you can build +# shared or static libraries -- it ONLY changs whether exeuatbles are linked +# statically or dynamically. +# +# This platform file tries its best to adhere to the behavior of the MPI +# compiler wrappers included with the latest BG/P drivers. +# + +# +# This adds directories that find commands should specifically ignore +# for cross compiles. Most of these directories are the includeand +# lib directories for the frontend on BG/P systems. Not ignoring +# these can cause things like FindX11 to find a frontend PPC version +# mistakenly. We use this on BG instead of re-rooting because backend +# libraries are typically strewn about the filesystem, and we can't +# re-root ALL backend libraries to a single place. +# +set(CMAKE_SYSTEM_IGNORE_PATH + /lib /lib64 /include + /usr/lib /usr/lib64 /usr/include + /usr/local/lib /usr/local/lib64 /usr/local/include + /usr/X11/lib /usr/X11/lib64 /usr/X11/include + /usr/lib/X11 /usr/lib64/X11 /usr/include/X11 + /usr/X11R6/lib /usr/X11R6/lib64 /usr/X11R6/include + /usr/X11R7/lib /usr/X11R7/lib64 /usr/X11R7/include +) + +# +# Indicate that this is a unix-like system +# +set(UNIX 1) + +# +# Library prefixes, suffixes, extra libs. +# +set(CMAKE_LINK_LIBRARY_SUFFIX "") +set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # lib +set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") # .a + +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib +set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so +set(CMAKE_EXECUTABLE_SUFFIX "") # .exe + +set(CMAKE_DL_LIBS "dl") + +# +# BG/Q supports dynamic libraries regardless of whether we're building +# static or dynamic *executables*. +# +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") + +# +# For BGQ builds, we're cross compiling, but we don't want to re-root things +# (e.g. with CMAKE_FIND_ROOT_PATH) because users may have libraries anywhere on +# the shared filesystems, and this may lie outside the root. Instead, we set the +# system directories so that the various system BG CNK library locations are +# searched first. This is not the clearest thing in the world, given IBM's driver +# layout, but this should cover all the standard ones. +# +macro(__BlueGeneQ_common_setup compiler_id lang) + # Need to use the version of the comm lib compiled with the right compiler. + set(__BlueGeneQ_commlib_dir gcc) + if (${compiler_id} STREQUAL XL) + set(__BlueGeneQ_commlib_dir xl) + endif() + + set(CMAKE_SYSTEM_LIBRARY_PATH + /bgsys/drivers/ppcfloor/comm/default/lib # default comm layer (used by mpi compiler wrappers) + /bgsys/drivers/ppcfloor/comm/${__BlueGeneQ_commlib_dir}/lib # PAMI, other lower-level comm libraries + /bgsys/drivers/ppcfloor/gnu-linux/lib # CNK python installation directory + /bgsys/drivers/ppcfloor/gnu-linux/powerpc64-bgq-linux/lib # CNK Linux image -- standard runtime libs, pthread, etc. + ) + + # Add all the system include paths. + set(CMAKE_SYSTEM_INCLUDE_PATH + /bgsys/drivers/ppcfloor/comm/sys/include + /bgsys/drivers/ppcfloor/ + /bgsys/drivers/ppcfloor/spi/include + /bgsys/drivers/ppcfloor/spi/include/kernel/cnk + /bgsys/drivers/ppcfloor/comm/${__BlueGeneQ_commlib_dir}/include + ) + + # Ensure that the system directories are included with the regular compilers, as users will expect this + # to do the same thing as the MPI compilers, which add these flags. + set(BGQ_SYSTEM_INCLUDES "") + foreach(dir ${CMAKE_SYSTEM_INCLUDE_PATH}) + set(BGQ_SYSTEM_INCLUDES "${BGQ_SYSTEM_INCLUDES} -I${dir}") + endforeach() + set(CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> ${BGQ_SYSTEM_INCLUDES} <FLAGS> -o <OBJECT> -c <SOURCE>") + set(CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> <DEFINES> ${BGQ_SYSTEM_INCLUDES} <FLAGS> -o <OBJECT> -c <SOURCE>") + + # + # Code below does setup for shared libraries. That this is done + # regardless of whether the platform is static or dynamic -- you can make + # shared libraries even if you intend to make static executables, you just + # can't make a dynamic executable if you use the static platform file. + # + if (${compiler_id} STREQUAL XL) + # Flags for XL compilers if we explicitly detected XL + set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-qpic") + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-qmkshrobj -qnostaticlink") + else() + # Assume flags for GNU compilers (if the ID is GNU *or* anything else). + set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") + endif() + + # Both toolchains use the GNU linker on BG/P, so these options are shared. + set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-rpath,") + set(CMAKE_SHARED_LIBRARY_RPATH_LINK_${lang}_FLAG "-Wl,-rpath-link,") + set(CMAKE_SHARED_LIBRARY_SONAME_${lang}_FLAG "-Wl,-soname,") + set(CMAKE_EXE_EXPORTS_${lang}_FLAG "-Wl,--export-dynamic") + set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "") # +s, flag for exe link to use shared lib + set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":") # : or empty + +endmacro() + +# +# This macro needs to be called for dynamic library support. Unfortunately on BG, +# We can't support both static and dynamic links in the same platform file. The +# dynamic link platform file needs to call this explicitly to set up dynamic linking. +# +macro(__BlueGeneQ_setup_dynamic compiler_id lang) + __BlueGeneQ_common_setup(${compiler_id} ${lang}) + + if (${compiler_id} STREQUAL XL) + set(BGQ_${lang}_DYNAMIC_EXE_FLAGS "-qnostaticlink -qnostaticlink=libgcc") + else() + set(BGQ_${lang}_DYNAMIC_EXE_FLAGS "-dynamic") + endif() + + # For dynamic executables, need to provide special BG/Q arguments. + set(BGQ_${lang}_DEFAULT_EXE_FLAGS + "<FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") + set(CMAKE_${lang}_LINK_EXECUTABLE + "<CMAKE_${lang}_COMPILER> -Wl,-relax ${BGQ_${lang}_DYNAMIC_EXE_FLAGS} ${BGQ_${lang}_DEFAULT_EXE_FLAGS}") +endmacro() + +# +# This macro needs to be called for static builds. Right now it just adds -Wl,-relax +# to the link line. +# +macro(__BlueGeneQ_setup_static compiler_id lang) + __BlueGeneQ_common_setup(${compiler_id} ${lang}) + + # For static executables, use default link settings. + set(BGQ_${lang}_DEFAULT_EXE_FLAGS + "<FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") + set(CMAKE_${lang}_LINK_EXECUTABLE + "<CMAKE_${lang}_COMPILER> -Wl,-relax ${BGQ_${lang}_DEFAULT_EXE_FLAGS}") +endmacro() diff --git a/Modules/Platform/BlueGeneQ-dynamic-GNU-C.cmake b/Modules/Platform/BlueGeneQ-dynamic-GNU-C.cmake new file mode 100644 index 0000000..102ac80 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-dynamic-GNU-C.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_dynamic(GNU C) diff --git a/Modules/Platform/BlueGeneQ-dynamic-GNU-CXX.cmake b/Modules/Platform/BlueGeneQ-dynamic-GNU-CXX.cmake new file mode 100644 index 0000000..cd8ab24 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-dynamic-GNU-CXX.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_dynamic(GNU CXX) diff --git a/Modules/Platform/BlueGeneQ-dynamic-GNU-Fortran.cmake b/Modules/Platform/BlueGeneQ-dynamic-GNU-Fortran.cmake new file mode 100644 index 0000000..c029f0f --- /dev/null +++ b/Modules/Platform/BlueGeneQ-dynamic-GNU-Fortran.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_dynamic(GNU Fortran) diff --git a/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake b/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake new file mode 100644 index 0000000..0077313 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_dynamic(XL C) diff --git a/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake b/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake new file mode 100644 index 0000000..0f43cb2 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_dynamic(XL CXX) diff --git a/Modules/Platform/BlueGeneQ-dynamic-XL-Fortran.cmake b/Modules/Platform/BlueGeneQ-dynamic-XL-Fortran.cmake new file mode 100644 index 0000000..12e446e --- /dev/null +++ b/Modules/Platform/BlueGeneQ-dynamic-XL-Fortran.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_dynamic(XL Fortran) diff --git a/Modules/Platform/BlueGeneQ-dynamic.cmake b/Modules/Platform/BlueGeneQ-dynamic.cmake new file mode 100644 index 0000000..0283900 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-dynamic.cmake @@ -0,0 +1,17 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +include(Platform/BlueGeneQ-base) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") diff --git a/Modules/Platform/BlueGeneQ-static-GNU-C.cmake b/Modules/Platform/BlueGeneQ-static-GNU-C.cmake new file mode 100644 index 0000000..70c84ba --- /dev/null +++ b/Modules/Platform/BlueGeneQ-static-GNU-C.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_static(GNU C) diff --git a/Modules/Platform/BlueGeneQ-static-GNU-CXX.cmake b/Modules/Platform/BlueGeneQ-static-GNU-CXX.cmake new file mode 100644 index 0000000..8f991de --- /dev/null +++ b/Modules/Platform/BlueGeneQ-static-GNU-CXX.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_static(GNU CXX) diff --git a/Modules/Platform/BlueGeneQ-static-GNU-Fortran.cmake b/Modules/Platform/BlueGeneQ-static-GNU-Fortran.cmake new file mode 100644 index 0000000..24dd9e7 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-static-GNU-Fortran.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_static(GNU Fortran) diff --git a/Modules/Platform/BlueGeneQ-static-XL-C.cmake b/Modules/Platform/BlueGeneQ-static-XL-C.cmake new file mode 100644 index 0000000..5555a68 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-static-XL-C.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_static(XL C) diff --git a/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake b/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake new file mode 100644 index 0000000..07c3c3d --- /dev/null +++ b/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_static(XL CXX) diff --git a/Modules/Platform/BlueGeneQ-static-XL-Fortran.cmake b/Modules/Platform/BlueGeneQ-static-XL-Fortran.cmake new file mode 100644 index 0000000..6f99933 --- /dev/null +++ b/Modules/Platform/BlueGeneQ-static-XL-Fortran.cmake @@ -0,0 +1,16 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +__BlueGeneQ_setup_static(XL Fortran) diff --git a/Modules/Platform/BlueGeneQ-static.cmake b/Modules/Platform/BlueGeneQ-static.cmake new file mode 100644 index 0000000..30b530d --- /dev/null +++ b/Modules/Platform/BlueGeneQ-static.cmake @@ -0,0 +1,17 @@ + +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2010 Todd Gamblin <tgamblin@llnl.gov> +# +# 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.) + +include(Platform/BlueGeneQ-base) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake index fe25ab2..3144ac4 100644 --- a/Modules/Platform/CYGWIN-GNU.cmake +++ b/Modules/Platform/CYGWIN-GNU.cmake @@ -25,7 +25,6 @@ set(CMAKE_CREATE_WIN32_EXE "-mwindows") set(CMAKE_GNULD_IMAGE_VERSION "-Wl,--major-image-version,<TARGET_VERSION_MAJOR>,--minor-image-version,<TARGET_VERSION_MINOR>") set(CMAKE_GENERATOR_RC windres) -enable_language(RC) macro(__cygwin_compiler_gnu lang) # Binary link rules. set(CMAKE_${lang}_CREATE_SHARED_MODULE @@ -53,4 +52,6 @@ macro(__cygwin_compiler_gnu lang) # TODO: Is -Wl,--enable-auto-import now always default? set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,--enable-auto-import") set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS}") + + enable_language(RC) endmacro() diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index e5c5f36..4e4810a 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -166,6 +166,21 @@ if(_CMAKE_OSX_SYSROOT_PATH) ${_CMAKE_OSX_SYSROOT_PATH}/Network/Library/Frameworks ${_CMAKE_OSX_SYSROOT_PATH}/System/Library/Frameworks ) + # add platform developer framework path if exists + foreach(_path + # Xcode 6 + ${_CMAKE_OSX_SYSROOT_PATH}/../../Library/Frameworks + # Xcode 5 iOS + ${_CMAKE_OSX_SYSROOT_PATH}/Developer/Library/Frameworks + # Xcode 5 OSX + ${_CMAKE_OSX_SYSROOT_PATH}/../../../../../Library/Frameworks + ) + get_filename_component(_abolute_path "${_path}" ABSOLUTE) + if(EXISTS "${_abolute_path}") + list(APPEND CMAKE_SYSTEM_FRAMEWORK_PATH "${_abolute_path}") + break() + endif() + endforeach() endif() list(APPEND CMAKE_SYSTEM_FRAMEWORK_PATH /Library/Frameworks diff --git a/Modules/Platform/Linux-PGI.cmake b/Modules/Platform/Linux-PGI.cmake index 3cbb35c..baa2248 100644 --- a/Modules/Platform/Linux-PGI.cmake +++ b/Modules/Platform/Linux-PGI.cmake @@ -21,7 +21,7 @@ set(__LINUX_COMPILER_PGI 1) macro(__linux_compiler_pgi lang) # Shared library compile and link flags. set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") - set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "") set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") endmacro() diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake index fe8e003..e40a74f 100644 --- a/Modules/Platform/Linux.cmake +++ b/Modules/Platform/Linux.cmake @@ -52,6 +52,6 @@ include(Platform/UnixPaths) # Debian has lib64 paths only for compatibility so they should not be # searched. -if(EXISTS "/etc/debian_version") +if(NOT CMAKE_CROSSCOMPILING AND EXISTS "/etc/debian_version") set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE) endif() diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index ffc5657..c827c32 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -35,7 +35,7 @@ endif() if(MINGW) set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll" ".dll.a" ".a" ".lib") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a" ".lib") set(CMAKE_C_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32") set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") endif() @@ -61,8 +61,6 @@ if(NOT CMAKE_GENERATOR_RC AND CMAKE_GENERATOR MATCHES "Unix Makefiles") set(CMAKE_GENERATOR_RC windres) endif() -enable_language(RC) - macro(__windows_compiler_gnu lang) if(MSYS OR MINGW) @@ -139,6 +137,8 @@ macro(__windows_compiler_gnu lang) ) endforeach() endif() + + enable_language(RC) endmacro() macro(__windows_compiler_gnu_abi lang) diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 2440f89..2905cee 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -53,10 +53,6 @@ if(NOT CMAKE_NO_BUILD_TYPE AND CMAKE_GENERATOR MATCHES "Visual Studio") set (CMAKE_NO_BUILD_TYPE 1) endif() -# make sure to enable languages after setting configuration types -enable_language(RC) -set(CMAKE_COMPILE_RESOURCE "rc <FLAGS> /fo<OBJECT> <SOURCE>") - if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") set(MSVC_IDE 1) else() @@ -131,14 +127,18 @@ endif() # default to Debug builds set(CMAKE_BUILD_TYPE_INIT Debug) +# Compute an architecture family from the architecture id. +foreach(lang C CXX) + set(_MSVC_${lang}_ARCHITECTURE_FAMILY "${MSVC_${lang}_ARCHITECTURE_ID}") + if(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^ARM") + set(_MSVC_${lang}_ARCHITECTURE_FAMILY "ARM") + elseif(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^SH") + set(_MSVC_${lang}_ARCHITECTURE_FAMILY "SHx") + endif() +endforeach() + if(WINCE) foreach(lang C CXX) - set(_MSVC_${lang}_ARCHITECTURE_FAMILY "${MSVC_${lang}_ARCHITECTURE_ID}") - if(_MSVC_${lang}_ARCHITECTURE_FAMILY STREQUAL "THUMB") - set(_MSVC_${lang}_ARCHITECTURE_FAMILY "ARM") - elseif(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^SH") - set(_MSVC_${lang}_ARCHITECTURE_FAMILY "SHx") - endif() string(TOUPPER "${_MSVC_${lang}_ARCHITECTURE_FAMILY}" _MSVC_${lang}_ARCHITECTURE_FAMILY_UPPER) endforeach() @@ -150,12 +150,23 @@ if(WINCE) message(FATAL_ERROR "Invalid Windows CE version: ${CMAKE_SYSTEM_VERSION}") endif() - set(_PLATFORM_DEFINES "/D_WIN32_WCE=0x${_CE_VERSION} /DUNDER_CE") + set(_PLATFORM_DEFINES "/D_WIN32_WCE=0x${_CE_VERSION} /DUNDER_CE /DWINCE") set(_PLATFORM_DEFINES_C " /D${_MSVC_C_ARCHITECTURE_FAMILY} /D_${_MSVC_C_ARCHITECTURE_FAMILY_UPPER}_") set(_PLATFORM_DEFINES_CXX " /D${_MSVC_CXX_ARCHITECTURE_FAMILY} /D_${_MSVC_CXX_ARCHITECTURE_FAMILY_UPPER}_") set(_RTC1 "") + set(_FLAGS_C "") set(_FLAGS_CXX " /GR /EHsc") + + foreach(lang C CXX) + if(_MSVC_${lang}_ARCHITECTURE_FAMILY STREQUAL "ARM") + set(_PLATFORM_DEFINES_${lang} "${_PLATFORM_DEFINES_${lang}} /D${MSVC_${lang}_ARCHITECTURE_ID}") + if(MSVC_${lang}_ARCHITECTURE_ID MATCHES "^ARMV([45])I$") + set(_FLAGS_${lang} "${_FLAGS_${lang}} /QRarch${CMAKE_MATCH_1}T") + endif() + endif() + endforeach() + set(CMAKE_C_STANDARD_LIBRARIES_INIT "coredll.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib") set(CMAKE_EXE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT} /NODEFAULTLIB:libc.lib /NODEFAULTLIB:oldnames.lib") @@ -168,7 +179,7 @@ elseif(WINDOWS_PHONE OR WINDOWS_STORE) set(_FLAGS_CXX " /DUNICODE /D_UNICODE /GR /EHsc") if(WINDOWS_PHONE) set(CMAKE_C_STANDARD_LIBRARIES_INIT "WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib") - elseif(MSVC_C_ARCHITECTURE_ID STREQUAL ARM OR MSVC_CXX_ARCHITECTURE_ID STREQUAL ARM) + elseif(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM") set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib") else() set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib") @@ -176,7 +187,7 @@ elseif(WINDOWS_PHONE OR WINDOWS_STORE) else() set(_PLATFORM_DEFINES "/DWIN32") - if(MSVC_C_ARCHITECTURE_ID STREQUAL ARM OR MSVC_CXX_ARCHITECTURE_ID STREQUAL ARM) + if(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM") set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib") elseif(MSVC_VERSION GREATER 1310) set(_RTC1 "/RTC1") @@ -200,9 +211,21 @@ set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") set (CMAKE_LINK_DEF_FILE_FLAG "/DEF:") # set the machine type if(MSVC_C_ARCHITECTURE_ID) - set(_MACHINE_ARCH_FLAG "/machine:${MSVC_C_ARCHITECTURE_ID}") + if(MSVC_C_ARCHITECTURE_ID MATCHES "^ARMV.I") + set(_MACHINE_ARCH_FLAG "/machine:THUMB") + elseif(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM") + set(_MACHINE_ARCH_FLAG "/machine:ARM") + else() + set(_MACHINE_ARCH_FLAG "/machine:${MSVC_C_ARCHITECTURE_ID}") + endif() elseif(MSVC_CXX_ARCHITECTURE_ID) - set(_MACHINE_ARCH_FLAG "/machine:${MSVC_CXX_ARCHITECTURE_ID}") + if(MSVC_CXX_ARCHITECTURE_ID MATCHES "^ARMV.I") + set(_MACHINE_ARCH_FLAG "/machine:THUMB") + elseif(_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM") + set(_MACHINE_ARCH_FLAG "/machine:ARM") + else() + set(_MACHINE_ARCH_FLAG "/machine:${MSVC_CXX_ARCHITECTURE_ID}") + endif() elseif(MSVC_Fortran_ARCHITECTURE_ID) set(_MACHINE_ARCH_FLAG "/machine:${MSVC_Fortran_ARCHITECTURE_ID}") endif() @@ -274,4 +297,10 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "/MD /Zi /O2 /Ob1 /D NDEBUG") set(CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "/MD /O1 /Ob1 /D NDEBUG") set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON) + + if(NOT CMAKE_RC_FLAGS_INIT) + set(CMAKE_RC_FLAGS_INIT "${_PLATFORM_DEFINES} ${_PLATFORM_DEFINES_${lang}}") + endif() + + enable_language(RC) endmacro() diff --git a/Modules/Platform/Windows-df.cmake b/Modules/Platform/Windows-df.cmake index 59d88a3..0beba73 100644 --- a/Modules/Platform/Windows-df.cmake +++ b/Modules/Platform/Windows-df.cmake @@ -24,8 +24,6 @@ set(CMAKE_Fortran_CREATE_STATIC_LIBRARY "lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /o set(CMAKE_Fortran_COMPILE_OBJECT "<CMAKE_Fortran_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /object:<OBJECT> <FLAGS> /compile_only <SOURCE>${CMAKE_END_TEMP_FILE}") -set(CMAKE_COMPILE_RESOURCE "rc <FLAGS> /fo<OBJECT> <SOURCE>") - set(CMAKE_Fortran_LINK_EXECUTABLE "<CMAKE_Fortran_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> /exe:<TARGET> <OBJECTS> /link <CMAKE_Fortran_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") diff --git a/Modules/Qt4Macros.cmake b/Modules/Qt4Macros.cmake index 6516b0a..3b0a6cc 100644 --- a/Modules/Qt4Macros.cmake +++ b/Modules/Qt4Macros.cmake @@ -158,7 +158,7 @@ macro (QT4_GENERATE_MOC infile outfile ) set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}") endif() - if ("x${ARGV2}" STREQUAL "xTARGET") + if (${ARGC} GREATER 3 AND "x${ARGV2}" STREQUAL "xTARGET") set(moc_target ${ARGV3}) endif() QT4_CREATE_MOC_COMMAND(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}") @@ -329,7 +329,10 @@ endmacro() macro(QT4_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optionalBasename _optionalClassName) get_filename_component(_infile ${_xml_file} ABSOLUTE) - set(_optionalBasename "${ARGV4}") + unset(_optionalBasename) + if(${ARGC} GREATER 4) + set(_optionalBasename "${ARGV4}") + endif() if (_optionalBasename) set(_basename ${_optionalBasename} ) else () @@ -337,7 +340,10 @@ macro(QT4_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optional string(TOLOWER ${_basename} _basename) endif () - set(_optionalClassName "${ARGV5}") + unset(_optionalClassName) + if(${ARGC} GREATER 5) + set(_optionalClassName "${ARGV5}") + endif() set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h") set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp") set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc") diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 3a6acd8..5eb0ca8 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -340,6 +340,13 @@ set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake) function(add_jar _TARGET_NAME) + cmake_parse_arguments(_add_jar + "" + "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT;MANIFEST" + "SOURCES;INCLUDE_JARS" + ${ARGN} + ) + # In CMake < 2.8.12, add_jar used variables which were set prior to calling # add_jar for customizing the behavior of add_jar. In order to be backwards # compatible, check if any of those variables are set, and use them to @@ -347,28 +354,21 @@ function(add_jar _TARGET_NAME) # argument will override the value set here.) # # New features should use named arguments only. - if(DEFINED CMAKE_JAVA_TARGET_VERSION) + if(NOT DEFINED _add_jar_VERSION AND DEFINED CMAKE_JAVA_TARGET_VERSION) set(_add_jar_VERSION "${CMAKE_JAVA_TARGET_VERSION}") endif() - if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) + if(NOT DEFINED _add_jar_OUTPUT_DIR AND DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) set(_add_jar_OUTPUT_DIR "${CMAKE_JAVA_TARGET_OUTPUT_DIR}") endif() - if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_NAME) + if(NOT DEFINED _add_jar_OUTPUT_NAME AND DEFINED CMAKE_JAVA_TARGET_OUTPUT_NAME) set(_add_jar_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}") # reset set(CMAKE_JAVA_TARGET_OUTPUT_NAME) endif() - if(DEFINED CMAKE_JAVA_JAR_ENTRY_POINT) + if(NOT DEFINED _add_jar_ENTRY_POINT AND DEFINED CMAKE_JAVA_JAR_ENTRY_POINT) set(_add_jar_ENTRY_POINT "${CMAKE_JAVA_JAR_ENTRY_POINT}") endif() - cmake_parse_arguments(_add_jar - "" - "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT;MANIFEST" - "SOURCES;INCLUDE_JARS" - ${ARGN} - ) - set(_JAVA_SOURCE_FILES ${_add_jar_SOURCES} ${_add_jar_UNPARSED_ARGUMENTS}) if (NOT DEFINED _add_jar_OUTPUT_DIR) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 7939b1f..7423418 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -204,8 +204,7 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) ${swig_include_dirs} -o "${swig_generated_file_fullname}" "${swig_source_file_fullname}" - MAIN_DEPENDENCY "${swig_source_file_fullname}" - DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS} + DEPENDS "${swig_source_file_fullname}" ${SWIG_MODULE_${name}_EXTRA_DEPS} COMMENT "Swig source") set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files} PROPERTIES GENERATED 1) diff --git a/Modules/WIX.template.in b/Modules/WIX.template.in index bbb7c88..c4fc83a 100644 --- a/Modules/WIX.template.in +++ b/Modules/WIX.template.in @@ -42,5 +42,6 @@ <UIRef Id="$(var.CPACK_WIX_UI_REF)" /> <?include "properties.wxi"?> + <?include "product_fragment.wxi"?> </Product> </Wix> diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index d18f47c..f4dcb21 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -586,7 +586,7 @@ function(write_compiler_detection_header # if ${def_name} # define ${def_value} nullptr # else -# define ${def_value} static_cast<void*>(0) +# define ${def_value} 0 # endif \n") endif() |