diff options
-rw-r--r-- | CompileFlags.cmake | 4 | ||||
-rw-r--r-- | Modules/FindMPI.cmake | 373 | ||||
-rw-r--r-- | Modules/UseSWIG.cmake | 116 | ||||
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/QtDialog/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Source/cmAddCustomCommandCommand.cxx | 148 | ||||
-rw-r--r-- | Source/cmExpandedCommandArgument.cxx | 5 | ||||
-rw-r--r-- | Source/cmExpandedCommandArgument.h | 1 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionLexer.cxx | 6 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 3 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 8 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 42 |
12 files changed, 499 insertions, 213 deletions
diff --git a/CompileFlags.cmake b/CompileFlags.cmake index 9834b04..32e7005 100644 --- a/CompileFlags.cmake +++ b/CompileFlags.cmake @@ -17,6 +17,10 @@ if(MSVC OR _INTEL_WINDOWS) else() endif() +if(MSVC) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stack:10000000") +endif() + #silence duplicate symbol warnings on AIX if(CMAKE_SYSTEM_NAME MATCHES "AIX") if(NOT CMAKE_COMPILER_IS_GNUCXX) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index c5eabbb..4bfbf03 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -357,7 +357,22 @@ function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE) set(${RESULT_VARIABLE} "${WRAPPER_RETURN}" PARENT_SCOPE) endfunction() -function (_MPI_interrogate_compiler lang) +macro(_MPI_env_set_ifnot VAR VALUE) + if(NOT DEFINED ENV{${VAR}}) + set(_MPI_${VAR}_WAS_SET FALSE) + set(ENV{${VAR}} ${${VALUE}}) + else() + set(_MPI_${VAR}_WAS_SET TRUE) + endif() +endmacro() + +macro(_MPI_env_unset_ifnot VAR) + if(NOT _MPI_${VAR}_WAS_SET) + unset(ENV{${VAR}}) + endif() +endmacro() + +function (_MPI_interrogate_compiler LANG) unset(MPI_COMPILE_CMDLINE) unset(MPI_LINK_CMDLINE) @@ -368,6 +383,41 @@ function (_MPI_interrogate_compiler lang) unset(MPI_LIB_NAMES_WORK) unset(MPI_LIB_FULLPATHS_WORK) + # Define the MPICH and Intel MPI compiler variables to the compilers set in CMake. + # It's possible to have a per-compiler configuration in these MPI implementations and + # a particular MPICH derivate might check compiler interoperability. + # Intel MPI in particular does this with I_MPI_CHECK_COMPILER. + file(TO_NATIVE_PATH "${CMAKE_${LANG}_COMPILER}" _MPI_UNDERLAYING_COMPILER) + # On Windows, the Intel MPI batch scripts can only work with filnames - Full paths will break them. + # Due to the lack of other MPICH-based wrappers for Visual C++, we may treat this as default. + if(MSVC) + get_filename_component(_MPI_UNDERLAYING_COMPILER "${_MPI_UNDERLAYING_COMPILER}" NAME) + endif() + if("${LANG}" STREQUAL "C") + _MPI_env_set_ifnot(I_MPI_CC _MPI_UNDERLAYING_COMPILER) + _MPI_env_set_ifnot(MPICH_CC _MPI_UNDERLAYING_COMPILER) + elseif("${LANG}" STREQUAL "CXX") + _MPI_env_set_ifnot(I_MPI_CXX _MPI_UNDERLAYING_COMPILER) + _MPI_env_set_ifnot(MPICH_CXX _MPI_UNDERLAYING_COMPILER) + elseif("${LANG}" STREQUAL "Fortran") + _MPI_env_set_ifnot(I_MPI_FC _MPI_UNDERLAYING_COMPILER) + _MPI_env_set_ifnot(MPICH_FC _MPI_UNDERLAYING_COMPILER) + _MPI_env_set_ifnot(I_MPI_F77 _MPI_UNDERLAYING_COMPILER) + _MPI_env_set_ifnot(MPICH_F77 _MPI_UNDERLAYING_COMPILER) + _MPI_env_set_ifnot(I_MPI_F90 _MPI_UNDERLAYING_COMPILER) + _MPI_env_set_ifnot(MPICH_F90 _MPI_UNDERLAYING_COMPILER) + endif() + + # Set these two variables for Intel MPI: + # - I_MPI_DEBUG_INFO_STRIP: It adds 'objcopy' lines to the compiler output. We support stripping them + # (see below), but if we can avoid them in the first place, we should. + # - I_MPI_FORT_BIND: By default Intel MPI makes the C/C++ compiler wrappers link Fortran bindings. + # This is so that mixed-language code doesn't require additional libraries when linking with mpicc. + # For our purposes, this makes little sense, since correct MPI usage from CMake already circumvenes this. + set(_MPI_ENV_VALUE "disable") + _MPI_env_set_ifnot(I_MPI_DEBUG_INFO_STRIP _MPI_ENV_VALUE) + _MPI_env_set_ifnot(I_MPI_FORT_BIND _MPI_ENV_VALUE) + # Check whether the -showme:compile option works. This indicates that we have either Open MPI # or a newer version of LAM/MPI, and implies that -showme:link will also work. # Open MPI also supports -show, but separates linker and compiler information @@ -408,6 +458,52 @@ function (_MPI_interrogate_compiler lang) _MPI_check_compiler(${LANG} "-showme" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) endif() + if (MPI_COMPILER_RETURN EQUAL 0 AND DEFINED MPI_COMPILE_CMDLINE) + # Intel MPI can be run with -compchk or I_MPI_CHECK_COMPILER set to 1. + # In this case, -show will be prepended with a line to the compiler checker. This is a script that performs + # compatibility checks and returns a non-zero exit code together with an error if something fails. + # It has to be called as "compchk.sh <arch> <compiler>". Here, <arch> is one out of 32 (i686), 64 (ia64) or 32e (x86_64). + # The compiler is identified by filename, and can be either the MPI compiler or the underlying compiler. + # NOTE: It is vital to run this script while the environment variables are set up, otherwise it can check the wrong compiler. + if("${MPI_COMPILE_CMDLINE}" MATCHES "^([^\" ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)") + # Now CMAKE_MATCH_1 contains the path to the compchk.sh file and CMAKE_MATCH_2 the architecture flag. + unset(COMPILER_CHECKER_OUTPUT) + execute_process( + COMMAND ${CMAKE_MATCH_1} ${CMAKE_MATCH_2} ${MPI_${LANG}_COMPILER} + OUTPUT_VARIABLE COMPILER_CHECKER_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE COMPILER_CHECKER_OUTPUT ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MPI_COMPILER_RETURN) + # If it returned a non-zero value, the check below will fail and cause the interrogation to be aborted. + if(NOT MPI_COMPILER_RETURN EQUAL 0) + if(NOT MPI_FIND_QUIETLY) + message(STATUS "Intel MPI compiler check failed: ${COMPILER_CHECKER_OUTPUT}") + endif() + else() + # Since the check passed, we can remove the compchk.sh script. + string(REGEX REPLACE "^([^\" ]+|\"[^\"]+\")/compchk.sh.*\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") + endif() + endif() + endif() + + # Revert changes to the environment made previously + if("${LANG}" STREQUAL "C") + _MPI_env_unset_ifnot(I_MPI_CC) + _MPI_env_unset_ifnot(MPICH_CC) + elseif("${LANG}" STREQUAL "CXX") + _MPI_env_unset_ifnot(I_MPI_CXX) + _MPI_env_unset_ifnot(MPICH_CXX) + elseif("${LANG}" STREQUAL "Fortran") + _MPI_env_unset_ifnot(I_MPI_FC) + _MPI_env_unset_ifnot(MPICH_FC) + _MPI_env_unset_ifnot(I_MPI_F77) + _MPI_env_unset_ifnot(MPICH_F77) + _MPI_env_unset_ifnot(I_MPI_F90) + _MPI_env_unset_ifnot(MPICH_F90) + endif() + + _MPI_env_unset_ifnot(I_MPI_DEBUG_INFO_STRIP) + _MPI_env_unset_ifnot(I_MPI_FORT_BIND) + if (NOT (MPI_COMPILER_RETURN EQUAL 0) OR NOT (DEFINED MPI_COMPILE_CMDLINE)) # Cannot interrogate this compiler, so exit. set(MPI_${LANG}_WRAPPER_FOUND FALSE PARENT_SCOPE) @@ -421,49 +517,92 @@ function (_MPI_interrogate_compiler lang) set(MPI_LINK_CMDLINE "${MPI_COMPILE_CMDLINE}") endif() - # At this point, we obtained some output from a compiler wrapper that works. - # We'll now try to parse it into variables with meaning to us. - if("${LANG}" STREQUAL "Fortran") - # Some MPICH-1 and MVAPICH-1 versions return a three command answer for Fortran, consisting - # out of a symlink command for mpif.h, the actual compiler command and a deletion of the - # created symlink. We need to detect that case, remember the include path and drop the - # symlink/deletion operation to obtain the link/compile lines we'd usually expect. - if("${MPI_COMPILE_CMDLINE}" MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h") - get_filename_component(MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY) - string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") - string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") - string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") - string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") + # Visual Studio parsers permit each flag prefixed by either / or -. + # We'll normalize this to the - syntax we use for CMake purposes anyways. + if(MSVC) + foreach(_MPI_VARIABLE IN ITEMS COMPILE LINK) + # The Intel MPI wrappers on Windows prefix their output with some copyright boilerplate. + # To prevent possible problems, we discard this text before proceeding with any further matching. + string(REGEX REPLACE "^[^ ]+ for the Intel\\(R\\) MPI Library [^\n]+ for Windows\\*\nCopyright\\(C\\) [^\n]+, Intel Corporation\\. All rights reserved\\.\n\n" "" + MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") + string(REGEX REPLACE "(^| )/" "\\1-" MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") + string(REPLACE "-libpath:" "-LIBPATH:" MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") + endforeach() + endif() + + # For MSVC and cl-compatible compilers, the keyword /link indicates a point after which + # everything following is passed to the linker. In this case, we drop all prior information + # from the link line and treat any unknown extra flags as linker flags. + set(_MPI_FILTERED_LINK_INFORMATION FALSE) + if(MSVC) + if(MPI_LINK_CMDLINE MATCHES " -(link|LINK) ") + string(REGEX REPLACE ".+-(link|LINK) +" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") + set(_MPI_FILTERED_LINK_INFORMATION TRUE) endif() + string(REGEX REPLACE " +-(link|LINK) .+" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") endif() - # The Intel MPI wrapper on Linux will emit some objcopy commands after its compile command - # if -static_mpi was passed to the wrapper. To avoid spurious matches, we need to drop these lines. if(UNIX) + # At this point, we obtained some output from a compiler wrapper that works. + # We'll now try to parse it into variables with meaning to us. + if("${LANG}" STREQUAL "Fortran") + # If MPICH (and derivates) didn't recognize the Fortran compiler include flag during configuration, + # they'll return a set of three commands, consisting out of a symlink command for mpif.h, + # the actual compiler command and deletion of the created symlink. + # Especially with M(VA)PICH-1, this appears to happen erroneously, and therefore we should translate + # this output into an additional include directory and then drop it from the output. + if("${MPI_COMPILE_CMDLINE}" MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h") + get_filename_component(MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY) + string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") + string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") + string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") + string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") + endif() + endif() + + # If Intel MPI was configured for static linkage with -static_mpi, the wrapper will by default strip + # debug information from resulting binaries (see I_MPI_DEBUG_INFO_STRIP). + # Since we cannot process this information into CMake logic, we need to discard the resulting objcopy + # commands from the output. string(REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") string(REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") endif() - # Extract compile options from the compile command line. - string(REGEX MATCHALL "(^| )-f([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_OPTIONS "${MPI_COMPILE_CMDLINE}") - - foreach(_MPI_COMPILE_OPTION IN LISTS MPI_ALL_COMPILE_OPTIONS) - string(REGEX REPLACE "^ " "" _MPI_COMPILE_OPTION "${_MPI_COMPILE_OPTION}") - # Ignore -fstack-protector directives: These occur on MPICH and MVAPICH when the libraries - # themselves were built with this flag. However, this flag is unrelated to using MPI, and - # we won't match the accompanying --param-ssp-size and -Wp,-D_FORTIFY_SOURCE flags and therefore - # produce inconsistent results with the regularly flags. - # Similarly, aliasing flags do not belong into our flag array. - if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f(stack-protector|(no-|)strict-aliasing|PI[CE]|pi[ce])") - list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") - endif() - endforeach() + # For Visual C++, extracting compiler options in a generic fashion isn't easy. However, no MPI implementation + # on Windows seems to require any specific ones, either. + if(NOT MSVC) + # Extract compile options from the compile command line. + string(REGEX MATCHALL "(^| )-f([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_OPTIONS "${MPI_COMPILE_CMDLINE}") + + foreach(_MPI_COMPILE_OPTION IN LISTS MPI_ALL_COMPILE_OPTIONS) + string(REGEX REPLACE "^ " "" _MPI_COMPILE_OPTION "${_MPI_COMPILE_OPTION}") + + # Ignore -fstack-protector directives: These occur on MPICH and MVAPICH when the libraries + # themselves were built with this flag. However, this flag is unrelated to using MPI, and + # we won't match the accompanying --param-ssp-size and -Wp,-D_FORTIFY_SOURCE flags and therefore + # produce inconsistent results with the regularly flags. + # Similarly, aliasing flags do not belong into our flag array. + if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce])") + list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") + endif() + endforeach() + endif() + + # For GNU-style compilers, it's possible to prefix includes and definitions with certain flags to pass them + # only to the preprocessor. For CMake purposes, we need to treat, but ignore such scopings. + # Note that we do not support spaces between the arguments, i.e. -Wp,-I -Wp,/opt/mympi will not be parsed + # correctly. This form does not seem to occur in any common MPI implementation, however. + if(NOT MSVC) + set(_MPI_PREPROCESSOR_FLAG_REGEX "(-Wp,|-Xpreprocessor )?") + else() + set(_MPI_PREPROCESSOR_FLAG_REGEX "") + endif() - # Same deal, with the definitions. We also treat arguments passed to the preprocessor directly. - string(REGEX MATCHALL "(^| )(-Wp,|-Xpreprocessor |)[-/]D([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_DEFINITIONS "${MPI_COMPILE_CMDLINE}") + # Same deal as above, for the definitions. + string(REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}-D *([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_DEFINITIONS "${MPI_COMPILE_CMDLINE}") foreach(_MPI_COMPILE_DEFINITION IN LISTS MPI_ALL_COMPILE_DEFINITIONS) - string(REGEX REPLACE "^ ?(-Wp,|-Xpreprocessor )?[-/]D" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") + string(REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}-D *" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") string(REPLACE "\"" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") if(NOT "${_MPI_COMPILE_DEFINITION}" MATCHES "^_FORTIFY_SOURCE.*") list(APPEND MPI_COMPILE_DEFINITIONS_WORK "${_MPI_COMPILE_DEFINITION}") @@ -471,9 +610,12 @@ function (_MPI_interrogate_compiler lang) endforeach() # Extract include paths from compile command line - string(REGEX MATCHALL "(^| )[-/]I([^\" ]+|\"[^\"]+\")" MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}") + string(REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *([^\" ]+|\"[^\"]+\")" + MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}") # If extracting failed to work, we'll try using -showme:incdirs. + # Unlike before, we do this without the environment variables set up, but since only MPICH derivates are affected by any of them, and + # -showme:... is only supported by Open MPI and LAM/MPI, this isn't a concern. if (NOT MPI_ALL_INCLUDE_PATHS) _MPI_check_compiler(${LANG} "-showme:incdirs" MPI_INCDIRS_CMDLINE MPI_INCDIRS_COMPILER_RETURN) if(MPI_INCDIRS_COMPILER_RETURN) @@ -482,16 +624,66 @@ function (_MPI_interrogate_compiler lang) endif() foreach(_MPI_INCLUDE_PATH IN LISTS MPI_ALL_INCLUDE_PATHS) - string(REGEX REPLACE "^ ?[-/]I" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") + string(REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") string(REPLACE "\"" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") get_filename_component(_MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}" REALPATH) list(APPEND MPI_INCLUDE_DIRS_WORK "${_MPI_INCLUDE_PATH}") endforeach() - # Extract linker paths from the link command line - string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker |)(-L|[/-]LIBPATH:|[/-]libpath:)([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_PATHS "${MPI_LINK_CMDLINE}") + # The next step are linker flags and library directories. Here, we first take the flags given in raw -L or -LIBPATH: syntax. + string(REGEX MATCHALL "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\"[^\"]+\")" MPI_DIRECT_LINK_PATHS "${MPI_LINK_CMDLINE}") + foreach(_MPI_LPATH IN LISTS MPI_DIRECT_LINK_PATHS) + string(REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *" "" _MPI_LPATH "${_MPI_LPATH}") + list(APPEND MPI_ALL_LINK_PATHS "${_MPI_LPATH}") + endforeach() + + # If the link commandline hasn't been filtered (e.g. when using MSVC and /link), we need to extract the relevant parts first. + if(NOT _MPI_FILTERED_LINK_INFORMATION) + string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\"[^\"]+\")" MPI_LINK_FLAGS "${MPI_LINK_CMDLINE}") + + # In this case, we could also find some indirectly given linker paths, e.g. prefixed by -Xlinker or -Wl, + # Since syntaxes like -Wl,-L -Wl,/my/path/to/lib are also valid, we parse these paths by first removing -Wl, and -Xlinker + # from the list of filtered flags and then parse the remainder of the output. + string(REGEX REPLACE "(-Wl,|-Xlinker +)" "" MPI_LINK_FLAGS_RAW "${MPI_LINK_FLAGS}") + + # Now we can parse the leftover output. Note that spaces can now be handled since the above example would reduce to + # -L /my/path/to/lib and can be extracted correctly. + string(REGEX MATCHALL "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)([^\" ]+|\"[^\"]+\")" + MPI_INDIRECT_LINK_PATHS "${MPI_LINK_FLAGS_RAW}") + + foreach(_MPI_LPATH IN LISTS MPI_INDIRECT_LINK_PATHS) + string(REGEX REPLACE "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)" "" _MPI_LPATH "${_MPI_LPATH}") + list(APPEND MPI_ALL_LINK_PATHS "${_MPI_LPATH}") + endforeach() + + # We need to remove the flags we extracted from the linker flag list now. + string(REGEX REPLACE "(^| )(-Wl,|-Xlinker +)(${CMAKE_LIBRARY_PATH_FLAG},? *(-Wl,|-Xlinker +)?|--library-path=)([^\" ]+|\"[^\"]+\")" "" + MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}") + + # Some MPI implementations pass on options they themselves were built with. Since -z,noexecstack is a common + # hardening, we should strip it. In general, the -z options should be undesirable. + string(REGEX REPLACE "(^| )-Wl,-z(,[^ ]+| +-Wl,[^ ]+)" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE_FILTERED}") + string(REGEX REPLACE "(^| )-Xlinker +-z +-Xlinker +[^ ]+" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE_FILTERED}") - # If extracting failed to work, we'll try using -showme:libdirs. + # We only consider options of the form -Wl or -Xlinker: + string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE_FILTERED}") + + # As a next step, we assemble the linker flags extracted in a preliminary flags string + foreach(_MPI_LINK_FLAG IN LISTS MPI_ALL_LINK_FLAGS) + string(STRIP "${_MPI_LINK_FLAG}" _MPI_LINK_FLAG) + if (MPI_LINK_FLAGS_WORK) + string(APPEND MPI_LINK_FLAGS_WORK " ${_MPI_LINK_FLAG}") + else() + set(MPI_LINK_FLAGS_WORK "${_MPI_LINK_FLAG}") + endif() + endforeach() + else() + # In the filtered case, we obtain the link time flags by just stripping the library paths. + string(REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\"[^\"]+\")" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}") + endif() + + # If we failed to extract any linker paths, we'll try using the -showme:libdirs option with the MPI compiler. + # This will return a list of folders, not a set of flags! if (NOT MPI_ALL_LINK_PATHS) _MPI_check_compiler(${LANG} "-showme:libdirs" MPI_LIBDIRS_CMDLINE MPI_LIBDIRS_COMPILER_RETURN) if(MPI_LIBDIRS_COMPILER_RETURN) @@ -499,34 +691,43 @@ function (_MPI_interrogate_compiler lang) endif() endif() + # We need to remove potential quotes and convert the paths to CMake syntax while resolving them, too. foreach(_MPI_LPATH IN LISTS MPI_ALL_LINK_PATHS) - string(REGEX REPLACE "^ ?(-Wl,|-Xlinker )?(-L|[/-]LIBPATH:|[/-]libpath:)" "" _MPI_LPATH "${_MPI_LPATH}") string(REPLACE "\"" "" _MPI_LPATH "${_MPI_LPATH}") get_filename_component(_MPI_LPATH "${_MPI_LPATH}" REALPATH) list(APPEND MPI_LINK_DIRECTORIES_WORK "${_MPI_LPATH}") endforeach() - # Extract linker flags from the link command line - string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker )([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE}") + # Extract the set of libraries to link against from the link command line + # This only makes sense if CMAKE_LINK_LIBRARY_FLAG is defined, i.e. a -lxxxx syntax is supported by the compiler. + if(CMAKE_LINK_LIBRARY_FLAG) + string(REGEX MATCHALL "(^| )${CMAKE_LINK_LIBRARY_FLAG}([^\" ]+|\"[^\"]+\")" + MPI_LIBNAMES "${MPI_LINK_CMDLINE}") - foreach(_MPI_LINK_FLAG IN LISTS MPI_ALL_LINK_FLAGS) - string(STRIP "${_MPI_LINK_FLAG}" _MPI_LINK_FLAG) - # MPI might be marked to build with non-executable stacks but this should not propagate. - if (NOT "${_MPI_LINK_FLAG}" MATCHES "(-Wl,|-Xlinker )-z,noexecstack") - if (MPI_LINK_FLAGS_WORK) - string(APPEND MPI_LINK_FLAGS_WORK " ${_MPI_LINK_FLAG}") - else() - set(MPI_LINK_FLAGS_WORK "${_MPI_LINK_FLAG}") - endif() - endif() - endforeach() + foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) + string(REGEX REPLACE "^ ?${CMAKE_LINK_LIBRARY_FLAG}" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") + endforeach() + endif() - # Extract the set of libraries to link against from the link command - # line - string(REGEX MATCHALL "(^| )-l([^\" ]+|\"[^\"]+\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") + # Treat linker objects given by full path, for example static libraries, import libraries + # or shared libraries if there aren't any import libraries in use on the system. + # Note that we do not consider CMAKE_<TYPE>_LIBRARY_PREFIX intentionally here: The linker will for a given file + # decide how to link it based on file type, not based on a prefix like 'lib'. + set(_MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_STATIC_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_STATIC_LIBRARY_SUFFIX}\"") + if(DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX) + if(NOT ("${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}")) + string(APPEND _MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_IMPORT_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_IMPORT_LIBRARY_SUFFIX}\"") + endif() + else() + string(APPEND _MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_SHARED_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_SHARED_LIBRARY_SUFFIX}\"") + endif() + string(REPLACE "." "\\." _MPI_LIB_NAME_REGEX "${_MPI_LIB_NAME_REGEX}") + string(REGEX MATCHALL "(^| )(${_MPI_LIB_NAME_REGEX})" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) - string(REGEX REPLACE "^ ?-l" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + string(REGEX REPLACE "^ " "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) if(NOT "${_MPI_LIB_PATH}" STREQUAL "") @@ -536,34 +737,8 @@ function (_MPI_interrogate_compiler lang) endif() endforeach() - if(WIN32) - # A compiler wrapper on Windows will just have the name of the - # library to link on its link line, potentially with a full path - string(REGEX MATCHALL "(^| )([^\" ]+\\.lib|\"[^\"]+\\.lib\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") - foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) - string(REGEX REPLACE "^ " "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") - string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") - get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) - if(NOT "${_MPI_LIB_PATH}" STREQUAL "") - list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") - else() - list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") - endif() - endforeach() - else() - # On UNIX platforms, archive libraries can be given with full path. - string(REGEX MATCHALL "(^| )([^\" ]+\\.a|\"[^\"]+\\.a\")" MPI_LIBFULLPATHS "${MPI_LINK_CMDLINE}") - foreach(_MPI_LIB_NAME IN LISTS MPI_LIBFULLPATHS) - string(REGEX REPLACE "^ " "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") - string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") - get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) - if(NOT "${_MPI_LIB_PATH}" STREQUAL "") - list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") - else() - list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") - endif() - endforeach() - endif() + # Save the explicitly given link directories + set(MPI_LINK_DIRECTORIES_LEFTOVER "${MPI_LINK_DIRECTORIES_WORK}") # An MPI compiler wrapper could have its MPI libraries in the implictly # linked directories of the compiler itself. @@ -583,22 +758,36 @@ function (_MPI_interrogate_compiler lang) DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" ) mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) + # Remove the directory from the remainder list. + if(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) + get_filename_component(_MPI_TAKEN_DIRECTORY "${MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY}" DIRECTORY) + list(REMOVE_ITEM MPI_LINK_DIRECTORIES_LEFTOVER "${_MPI_TAKEN_DIRECTORY}") + endif() + endforeach() + + # Add the link directories given explicitly that we haven't used back as linker directories. + foreach(_MPI_LINK_DIRECTORY IN LISTS MPI_LINK_DIRECTORIES_LEFTOVER) + file(TO_NATIVE_PATH "${_MPI_LINK_DIRECTORY}" _MPI_LINK_DIRECTORY_ACTUAL) + string(FIND "${_MPI_LINK_DIRECTORY_ACTUAL}" " " _MPI_LINK_DIRECTORY_CONTAINS_SPACE) + if(NOT _MPI_LINK_DIRECTORY_CONTAINS_SPACE EQUAL -1) + set(_MPI_LINK_DIRECTORY_ACTUAL "\"${_MPI_LINK_DIRECTORY_ACTUAL}\"") + endif() + if(MPI_LINK_FLAGS_WORK) + string(APPEND MPI_LINK_FLAGS_WORK " ${CMAKE_LIBRARY_PATH_FLAG}${_MPI_LINK_DIRECTORY_ACTUAL}") + else() + set(MPI_LINK_FLAGS_WORK "${CMAKE_LIBRARY_PATH_FLAG}${_MPI_LINK_DIRECTORY_ACTUAL}") + endif() endforeach() # Deal with the libraries given with full path next unset(MPI_DIRECT_LIB_NAMES_WORK) foreach(_MPI_LIB_FULLPATH IN LISTS MPI_LIB_FULLPATHS_WORK) get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB_FULLPATH}" NAME_WE) - get_filename_component(_MPI_LIB_NAME "${_MPI_LIB_FULLPATH}" NAME) - get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_FULLPATH}" DIRECTORY) list(APPEND MPI_DIRECT_LIB_NAMES_WORK "${_MPI_PLAIN_LIB_NAME}") - find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY - NAMES "${_MPI_LIB_NAME}" - HINTS ${_MPI_LIB_PATH} - DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" - ) + set(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY "${_MPI_LIB_FULLPATH}" CACHE FILEPATH "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI") mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) endforeach() + # Directly linked objects should be linked first in case some generic linker flags are needed for them. if(MPI_DIRECT_LIB_NAMES_WORK) set(MPI_PLAIN_LIB_NAMES_WORK "${MPI_DIRECT_LIB_NAMES_WORK};${MPI_PLAIN_LIB_NAMES_WORK}") endif() @@ -1121,7 +1310,7 @@ if(NOT MPI_IGNORE_LEGACY_VARIABLES) if(MPI_${LANG}_COMPILE_FLAGS) separate_arguments(MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}") foreach(_MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS) - if("${_MPI_FLAG}" MATCHES "^ *[-/D]([^ ]+)") + if("${_MPI_FLAG}" MATCHES "^ *-D([^ ]+)") list(APPEND MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}") else() list(APPEND MPI_${LANG}_EXTRA_COMPILE_OPTIONS "${_MPI_FLAG}") diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index b8bcd92..b38e2b7 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -1,58 +1,70 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -#.rst: -# UseSWIG -# ------- -# -# Defines the following macros for use with SWIG: -# -# :: -# -# SWIG_ADD_LIBRARY(<name> -# [TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>] -# LANGUAGE <language> -# SOURCES <file>... -# ) -# - Define swig module with given name and specified language -# SWIG_LINK_LIBRARIES(name [ libraries ]) -# - Link libraries to swig module -# -# Source files properties on module files can be set before the invocation -# of the SWIG_ADD_LIBRARY macro to specify special behavior of SWIG. -# -# The source file property CPLUSPLUS calls SWIG in c++ mode, e.g.:: -# -# set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON) -# swig_add_library(mymod LANGUAGE python SOURCES mymod.i) -# -# The source file property SWIG_FLAGS adds custom flags to the SWIG executable. -# -# The source-file property SWIG_MODULE_NAME have to be provided to specify the actual -# import name of the module in the target language if it cannot be scanned automatically -# from source or different from the module file basename.:: -# -# set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname) -# -# To get the name of the swig module target library, use: ${SWIG_MODULE_${name}_REAL_NAME}. -# -# Also some variables can be set to specify special behavior of SWIG. -# -# CMAKE_SWIG_FLAGS can be used to add special flags to all swig calls. -# -# CMAKE_SWIG_OUTDIR allows one to specify where to write -# the language specific files (swig -outdir option). -# -# SWIG_OUTFILE_DIR allows one to specify where to write the output file -# (swig -o option). If not specified, CMAKE_SWIG_OUTDIR is used. -# -# The name-specific variable SWIG_MODULE_<name>_EXTRA_DEPS may be used to specify extra -# dependencies for the generated modules. -# -# If the source file generated by swig need some special flag you can use:: -# -# set_source_files_properties( ${swig_generated_file_fullname} -# PROPERTIES COMPILE_FLAGS "-bla") +#[=======================================================================[.rst: +UseSWIG +------- + +Defines the following macros for use with SWIG: + +.. command:: swig_add_library + + Define swig module with given name and specified language:: + + swig_add_library(<name> + [TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>] + LANGUAGE <language> + SOURCES <file>... + ) + + The variable ``SWIG_MODULE_<name>_REAL_NAME`` will be set to the name + of the swig module target library. + +.. command:: swig_link_libraries + + Link libraries to swig module:: + + swig_link_libraries(<name> [ libraries ]) + +Source file properties on module files can be set before the invocation +of the ``swig_add_library`` macro to specify special behavior of SWIG: + +``CPLUSPLUS`` + Call SWIG in c++ mode. For example: + + .. code-block:: cmake + + set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON) + swig_add_library(mymod LANGUAGE python SOURCES mymod.i) + +``SWIG_FLAGS`` + Add custom flags to the SWIG executable. + + +``SWIG_MODULE_NAME`` + Specify the actual import name of the module in the target language. + This is required if it cannot be scanned automatically from source + or different from the module file basename. For example: + + .. code-block:: cmake + + set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname) + +Some variables can be set to specify special behavior of SWIG: + +``CMAKE_SWIG_FLAGS`` + Add flags to all swig calls. + +``CMAKE_SWIG_OUTDIR`` + Specify where to write the language specific files (swig ``-outdir`` option). + +``SWIG_OUTFILE_DIR`` + Specify an output directory name where the generated source file will be + placed. If not specified, ``CMAKE_SWIG_OUTDIR`` is used. + +``SWIG_MODULE_<name>_EXTRA_DEPS`` + Specify extra dependencies for the generated module for ``<name>``. +#]=======================================================================] set(SWIG_CXX_EXTENSION "cxx") set(SWIG_EXTRA_LIBRARIES "") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3666d5c..7d735ea 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 10) -set(CMake_VERSION_PATCH 20180131) +set(CMake_VERSION_PATCH 20180201) #set(CMake_VERSION_RC 1) diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 06d13ba..330b747 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -166,6 +166,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) +if(WIN32) + target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>) +endif() + # cmake-gui has not been updated for `include-what-you-use`. # Block the tool until this is done. set_target_properties(cmake-gui PROPERTIES diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index a262f80..1e3faef 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -3,6 +3,7 @@ #include "cmAddCustomCommandCommand.h" #include <sstream> +#include <unordered_set> #include <utility> #include "cmCustomCommand.h" @@ -69,57 +70,106 @@ bool cmAddCustomCommandCommand::InitialPass( tdoing doing = doing_nothing; +#define MAKE_STATIC_KEYWORD(KEYWORD) \ + static const std::string key##KEYWORD = #KEYWORD + MAKE_STATIC_KEYWORD(APPEND); + MAKE_STATIC_KEYWORD(ARGS); + MAKE_STATIC_KEYWORD(BYPRODUCTS); + MAKE_STATIC_KEYWORD(COMMAND); + MAKE_STATIC_KEYWORD(COMMAND_EXPAND_LISTS); + MAKE_STATIC_KEYWORD(COMMENT); + MAKE_STATIC_KEYWORD(DEPENDS); + MAKE_STATIC_KEYWORD(DEPFILE); + MAKE_STATIC_KEYWORD(IMPLICIT_DEPENDS); + MAKE_STATIC_KEYWORD(MAIN_DEPENDENCY); + MAKE_STATIC_KEYWORD(OUTPUT); + MAKE_STATIC_KEYWORD(OUTPUTS); + MAKE_STATIC_KEYWORD(POST_BUILD); + MAKE_STATIC_KEYWORD(PRE_BUILD); + MAKE_STATIC_KEYWORD(PRE_LINK); + MAKE_STATIC_KEYWORD(SOURCE); + MAKE_STATIC_KEYWORD(TARGET); + MAKE_STATIC_KEYWORD(USES_TERMINAL); + MAKE_STATIC_KEYWORD(VERBATIM); + MAKE_STATIC_KEYWORD(WORKING_DIRECTORY); +#undef MAKE_STATIC_KEYWORD + static std::unordered_set<std::string> keywords; + if (keywords.empty()) { + keywords.insert(keyAPPEND); + keywords.insert(keyARGS); + keywords.insert(keyBYPRODUCTS); + keywords.insert(keyCOMMAND); + keywords.insert(keyCOMMAND_EXPAND_LISTS); + keywords.insert(keyCOMMENT); + keywords.insert(keyDEPENDS); + keywords.insert(keyDEPFILE); + keywords.insert(keyIMPLICIT_DEPENDS); + keywords.insert(keyMAIN_DEPENDENCY); + keywords.insert(keyOUTPUT); + keywords.insert(keyOUTPUTS); + keywords.insert(keyPOST_BUILD); + keywords.insert(keyPRE_BUILD); + keywords.insert(keyPRE_LINK); + keywords.insert(keySOURCE); + keywords.insert(keyTARGET); + keywords.insert(keyUSES_TERMINAL); + keywords.insert(keyVERBATIM); + keywords.insert(keyWORKING_DIRECTORY); + } + for (std::string const& copy : args) { - if (copy == "SOURCE") { - doing = doing_source; - } else if (copy == "COMMAND") { - doing = doing_command; + if (keywords.count(copy)) { + if (copy == keySOURCE) { + doing = doing_source; + } else if (copy == keyCOMMAND) { + doing = doing_command; - // Save the current command before starting the next command. - if (!currentLine.empty()) { - commandLines.push_back(currentLine); - currentLine.clear(); - } - } else if (copy == "PRE_BUILD") { - cctype = cmTarget::PRE_BUILD; - } else if (copy == "PRE_LINK") { - cctype = cmTarget::PRE_LINK; - } else if (copy == "POST_BUILD") { - cctype = cmTarget::POST_BUILD; - } else if (copy == "VERBATIM") { - verbatim = true; - } else if (copy == "APPEND") { - append = true; - } else if (copy == "USES_TERMINAL") { - uses_terminal = true; - } else if (copy == "COMMAND_EXPAND_LISTS") { - command_expand_lists = true; - } else if (copy == "TARGET") { - doing = doing_target; - } else if (copy == "ARGS") { - // Ignore this old keyword. - } else if (copy == "DEPENDS") { - doing = doing_depends; - } else if (copy == "OUTPUTS") { - doing = doing_outputs; - } else if (copy == "OUTPUT") { - doing = doing_output; - } else if (copy == "BYPRODUCTS") { - doing = doing_byproducts; - } else if (copy == "WORKING_DIRECTORY") { - doing = doing_working_directory; - } else if (copy == "MAIN_DEPENDENCY") { - doing = doing_main_dependency; - } else if (copy == "IMPLICIT_DEPENDS") { - doing = doing_implicit_depends_lang; - } else if (copy == "COMMENT") { - doing = doing_comment; - } else if (copy == "DEPFILE") { - doing = doing_depfile; - if (this->Makefile->GetGlobalGenerator()->GetName() != "Ninja") { - this->SetError("Option DEPFILE not supported by " + - this->Makefile->GetGlobalGenerator()->GetName()); - return false; + // Save the current command before starting the next command. + if (!currentLine.empty()) { + commandLines.push_back(currentLine); + currentLine.clear(); + } + } else if (copy == keyPRE_BUILD) { + cctype = cmTarget::PRE_BUILD; + } else if (copy == keyPRE_LINK) { + cctype = cmTarget::PRE_LINK; + } else if (copy == keyPOST_BUILD) { + cctype = cmTarget::POST_BUILD; + } else if (copy == keyVERBATIM) { + verbatim = true; + } else if (copy == keyAPPEND) { + append = true; + } else if (copy == keyUSES_TERMINAL) { + uses_terminal = true; + } else if (copy == keyCOMMAND_EXPAND_LISTS) { + command_expand_lists = true; + } else if (copy == keyTARGET) { + doing = doing_target; + } else if (copy == keyARGS) { + // Ignore this old keyword. + } else if (copy == keyDEPENDS) { + doing = doing_depends; + } else if (copy == keyOUTPUTS) { + doing = doing_outputs; + } else if (copy == keyOUTPUT) { + doing = doing_output; + } else if (copy == keyBYPRODUCTS) { + doing = doing_byproducts; + } else if (copy == keyWORKING_DIRECTORY) { + doing = doing_working_directory; + } else if (copy == keyMAIN_DEPENDENCY) { + doing = doing_main_dependency; + } else if (copy == keyIMPLICIT_DEPENDS) { + doing = doing_implicit_depends_lang; + } else if (copy == keyCOMMENT) { + doing = doing_comment; + } else if (copy == keyDEPFILE) { + doing = doing_depfile; + if (this->Makefile->GetGlobalGenerator()->GetName() != "Ninja") { + this->SetError("Option DEPFILE not supported by " + + this->Makefile->GetGlobalGenerator()->GetName()); + return false; + } } } else { std::string filename; diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx index 0bea65f..1c0a721 100644 --- a/Source/cmExpandedCommandArgument.cxx +++ b/Source/cmExpandedCommandArgument.cxx @@ -24,6 +24,11 @@ bool cmExpandedCommandArgument::WasQuoted() const return this->Quoted; } +bool cmExpandedCommandArgument::operator==(const char* value) const +{ + return this->Value == value; +} + bool cmExpandedCommandArgument::operator==(std::string const& value) const { return this->Value == value; diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h index fe86528..302e8db 100644 --- a/Source/cmExpandedCommandArgument.h +++ b/Source/cmExpandedCommandArgument.h @@ -24,6 +24,7 @@ public: bool WasQuoted() const; + bool operator==(const char* value) const; bool operator==(std::string const& value) const; bool empty() const; diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx index 95c79c1..e37f165 100644 --- a/Source/cmGeneratorExpressionLexer.cxx +++ b/Source/cmGeneratorExpressionLexer.cxx @@ -21,6 +21,12 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize( { std::vector<cmGeneratorExpressionToken> result; + if (input.find('$') == std::string::npos) { + result.push_back(cmGeneratorExpressionToken( + cmGeneratorExpressionToken::Text, input.c_str(), input.size())); + return result; + } + const char* c = input.c_str(); const char* upto = c; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index e2cac35..c1f1ee4 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -947,7 +947,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "Target name not supported."); return std::string(); } - if (propertyName == "ALIASED_TARGET") { + static const std::string propALIASED_TARGET = "ALIASED_TARGET"; + if (propertyName == propALIASED_TARGET) { if (context->LG->GetMakefile()->IsAlias(targetName)) { if (cmGeneratorTarget* tgt = context->LG->FindGeneratorTargetToUse(targetName)) { diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f97d8ef..e9b6daf 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3616,13 +3616,13 @@ void cmGeneratorTarget::CheckPropertyCompatibility( const cmComputeLinkInformation::ItemVector& deps = info->GetItems(); std::set<std::string> emittedBools; - static std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; + static const std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; std::set<std::string> emittedStrings; - static std::string strString = "COMPATIBLE_INTERFACE_STRING"; + static const std::string strString = "COMPATIBLE_INTERFACE_STRING"; std::set<std::string> emittedMinNumbers; - static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN"; + static const std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN"; std::set<std::string> emittedMaxNumbers; - static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; + static const std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; for (auto const& dep : deps) { if (!dep.Target) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 33437a1..cd11c4b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -861,39 +861,53 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Makefile->GetBacktrace())) { return; } - if (prop == "MANUALLY_ADDED_DEPENDENCIES") { +#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(COMPILE_DEFINITIONS); + MAKE_STATIC_PROP(COMPILE_FEATURES); + MAKE_STATIC_PROP(COMPILE_OPTIONS); + MAKE_STATIC_PROP(CUDA_PTX_COMPILATION); + MAKE_STATIC_PROP(EXPORT_NAME); + MAKE_STATIC_PROP(IMPORTED_GLOBAL); + MAKE_STATIC_PROP(INCLUDE_DIRECTORIES); + MAKE_STATIC_PROP(LINK_LIBRARIES); + MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); + MAKE_STATIC_PROP(NAME); + MAKE_STATIC_PROP(SOURCES); + MAKE_STATIC_PROP(TYPE); +#undef MAKE_STATIC_PROP + if (prop == propMANUALLY_ADDED_DEPENDENCIES) { std::ostringstream e; e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if (prop == "NAME") { + if (prop == propNAME) { std::ostringstream e; e << "NAME property is read-only\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if (prop == "TYPE") { + if (prop == propTYPE) { std::ostringstream e; e << "TYPE property is read-only\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if (prop == "EXPORT_NAME" && this->IsImported()) { + if (prop == propEXPORT_NAME && this->IsImported()) { std::ostringstream e; e << "EXPORT_NAME property can't be set on imported targets (\"" << this->Name << "\")\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if (prop == "SOURCES" && this->IsImported()) { + if (prop == propSOURCES && this->IsImported()) { std::ostringstream e; e << "SOURCES property can't be set on imported targets (\"" << this->Name << "\")\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if (prop == "IMPORTED_GLOBAL" && !this->IsImported()) { + if (prop == propIMPORTED_GLOBAL && !this->IsImported()) { std::ostringstream e; e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\"" << this->Name << "\")\n"; @@ -901,7 +915,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) return; } - if (prop == "INCLUDE_DIRECTORIES") { + if (prop == propINCLUDE_DIRECTORIES) { this->Internal->IncludeDirectoriesEntries.clear(); this->Internal->IncludeDirectoriesBacktraces.clear(); if (value) { @@ -909,7 +923,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt); } - } else if (prop == "COMPILE_OPTIONS") { + } else if (prop == propCOMPILE_OPTIONS) { this->Internal->CompileOptionsEntries.clear(); this->Internal->CompileOptionsBacktraces.clear(); if (value) { @@ -917,7 +931,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileOptionsBacktraces.push_back(lfbt); } - } else if (prop == "COMPILE_FEATURES") { + } else if (prop == propCOMPILE_FEATURES) { this->Internal->CompileFeaturesEntries.clear(); this->Internal->CompileFeaturesBacktraces.clear(); if (value) { @@ -925,7 +939,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileFeaturesBacktraces.push_back(lfbt); } - } else if (prop == "COMPILE_DEFINITIONS") { + } else if (prop == propCOMPILE_DEFINITIONS) { this->Internal->CompileDefinitionsEntries.clear(); this->Internal->CompileDefinitionsBacktraces.clear(); if (value) { @@ -933,7 +947,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } - } else if (prop == "LINK_LIBRARIES") { + } else if (prop == propLINK_LIBRARIES) { this->Internal->LinkImplementationPropertyEntries.clear(); this->Internal->LinkImplementationPropertyBacktraces.clear(); if (value) { @@ -941,7 +955,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkImplementationPropertyEntries.push_back(value); this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt); } - } else if (prop == "SOURCES") { + } else if (prop == propSOURCES) { this->Internal->SourceEntries.clear(); this->Internal->SourceBacktraces.clear(); if (value) { @@ -949,7 +963,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->SourceEntries.push_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } - } else if (prop == "IMPORTED_GLOBAL") { + } else if (prop == propIMPORTED_GLOBAL) { if (!cmSystemTools::IsOn(value)) { std::ostringstream e; e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\"" @@ -965,7 +979,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") && !this->CheckImportedLibName(prop, value ? value : "")) { /* error was reported by check method */ - } else if (prop == "CUDA_PTX_COMPILATION" && + } else if (prop == propCUDA_PTX_COMPILATION && this->GetType() != cmStateEnums::OBJECT_LIBRARY) { std::ostringstream e; e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT " |