diff options
105 files changed, 1141 insertions, 394 deletions
diff --git a/CompileFlags.cmake b/CompileFlags.cmake index 32e7005..ec9b31b 100644 --- a/CompileFlags.cmake +++ b/CompileFlags.cmake @@ -82,3 +82,26 @@ endif () if (CMAKE_ANSI_CFLAGS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") endif () + +# Allow per-translation-unit parallel builds when using MSVC +if(CMAKE_GENERATOR MATCHES "Visual Studio" AND + (CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel" OR + CMAKE_CXX_COMPILER_ID MATCHES "MSVC|Intel")) + + set(CMake_MSVC_PARALLEL ON CACHE STRING "\ +Enables /MP flag for parallel builds using MSVC. Specify an \ +integer value to control the number of threads used (Only \ +works on some older versions of Visual Studio). Setting to \ +ON lets the toolchain decide how many threads to use. Set to \ +OFF to disable /MP completely." ) + + if(CMake_MSVC_PARALLEL) + if(CMake_MSVC_PARALLEL GREATER 0) + string(APPEND CMAKE_C_FLAGS " /MP${CMake_MSVC_PARALLEL}") + string(APPEND CMAKE_CXX_FLAGS " /MP${CMake_MSVC_PARALLEL}") + else() + string(APPEND CMAKE_C_FLAGS " /MP") + string(APPEND CMAKE_CXX_FLAGS " /MP") + endif() + endif() +endif() diff --git a/Help/command/file.rst b/Help/command/file.rst index 5ce86e5..5e18077 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -285,6 +285,23 @@ If neither ``TLS`` option is given CMake will check variables :: + file(TOUCH [<files>...]) + file(TOUCH_NOCREATE [<files>...]) + +Create a file with no content if it does not yet exist. If the file already +exists, its access and/or modification will be updated to the time when the +function call is executed. + +Use TOUCH_NOCREATE to touch a file if it exists but not create it. If a file +does not exist it will be silently ignored. + +With TOUCH and TOUCH_NOCREATE the contents of an existing file will not be +modified. + +------------------------------------------------------------------------------ + +:: + file(TIMESTAMP <filename> <variable> [<format>] [UTC]) Compute a string representation of the modification time of ``<filename>`` diff --git a/Help/command/string.rst b/Help/command/string.rst index fb3893f..cd94bb4 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -151,6 +151,16 @@ CONCAT Concatenate all the input arguments together and store the result in the named output variable. +JOIN +"""" + +:: + + string(JOIN <glue> <output variable> [<input>...]) + +Join all the input arguments together using the glue +string and store the result in the named output variable. + TOLOWER """"""" @@ -282,6 +292,18 @@ CONFIGURE Transform a string like :command:`configure_file` transforms a file. +MAKE_C_IDENTIFIER +""""""""""""""""" + +:: + + string(MAKE_C_IDENTIFIER <input string> <output variable>) + +Convert each non-alphanumeric character in the ``<input string>`` to an +underscore and store the result in the ``<output variable>``. If the first +character of the string is a digit, an underscore will also be prepended to +the result. + RANDOM """""" @@ -346,13 +368,6 @@ If no explicit ``<format string>`` is given it will default to: %Y-%m-%dT%H:%M:%S for local time. %Y-%m-%dT%H:%M:%SZ for UTC. - -:: - - string(MAKE_C_IDENTIFIER <input string> <output variable>) - -Write a string which can be used as an identifier in C. - .. note:: If the ``SOURCE_DATE_EPOCH`` environment variable is set, diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst index cd509ac..41fe90c 100644 --- a/Help/manual/cmake-developer.7.rst +++ b/Help/manual/cmake-developer.7.rst @@ -943,7 +943,7 @@ populated: endif() The ``RELEASE`` variant should be listed first in the property -so that that variant is chosen if the user uses a configuration which is +so that the variant is chosen if the user uses a configuration which is not an exact match for any listed ``IMPORTED_CONFIGURATIONS``. Most of the cache variables should be hidden in the ``ccmake`` interface unless diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 0f6d4cf..04cb1dc 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -57,6 +57,8 @@ Available logical expressions are: ``1`` if ``a`` is STREQUAL ``b``, else ``0`` ``$<EQUAL:a,b>`` ``1`` if ``a`` is EQUAL ``b`` in a numeric comparison, else ``0`` +``$<IN_LIST:a,b>`` + ``1`` if ``a`` is IN_LIST ``b``, else ``0`` ``$<CONFIG:cfg>`` ``1`` if config is ``cfg``, else ``0``. This is a case-insensitive comparison. The mapping in :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by @@ -289,7 +291,8 @@ Available output expressions are: ``$<UPPER_CASE:...>`` Content of ``...`` converted to upper case. ``$<MAKE_C_IDENTIFIER:...>`` - Content of ``...`` converted to a C identifier. + Content of ``...`` converted to a C identifier. The conversion follows the + same behavior as :command:`string(MAKE_C_IDENTIFIER)`. ``$<TARGET_OBJECTS:objLib>`` List of objects resulting from build of ``objLib``. ``objLib`` must be an object of type ``OBJECT_LIBRARY``. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 00a932f..d3e58d0 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -84,6 +84,7 @@ Properties on Directories /prop_dir/RULE_LAUNCH_LINK /prop_dir/SOURCE_DIR /prop_dir/SUBDIRECTORIES + /prop_dir/TESTS /prop_dir/TEST_INCLUDE_FILES /prop_dir/VARIABLES /prop_dir/VS_GLOBAL_SECTION_POST_section diff --git a/Help/prop_dir/TESTS.rst b/Help/prop_dir/TESTS.rst new file mode 100644 index 0000000..c6e1d88 --- /dev/null +++ b/Help/prop_dir/TESTS.rst @@ -0,0 +1,7 @@ +TESTS +----- + +List of tests. + +This read-only property holds a :ref:`;-list <CMake Language Lists>` of tests +defined so far by the :command:`add_test` command. diff --git a/Help/release/dev/UseSWIG-modernize-module.rst b/Help/release/dev/UseSWIG-modernize-module.rst new file mode 100644 index 0000000..925c119 --- /dev/null +++ b/Help/release/dev/UseSWIG-modernize-module.rst @@ -0,0 +1,6 @@ +UseSWIG-modernize-module +------------------------ + +* The :module:`UseSWIG` gained a whole refresh and is now more consistent with + standard CMake commands to generate libraries and is fully configurable through + properties. diff --git a/Help/release/dev/directory-property-TESTS.rst b/Help/release/dev/directory-property-TESTS.rst new file mode 100644 index 0000000..9de2531 --- /dev/null +++ b/Help/release/dev/directory-property-TESTS.rst @@ -0,0 +1,5 @@ +directory-property-TESTS +------------------------ + +* The :prop_dir:`TESTS` directory property was added to hold the list of tests defined by + command :command:`add_test`. diff --git a/Help/release/dev/file_cmd_touch.rst b/Help/release/dev/file_cmd_touch.rst new file mode 100644 index 0000000..b1b1e3c --- /dev/null +++ b/Help/release/dev/file_cmd_touch.rst @@ -0,0 +1,6 @@ +file_cmd_touch +------------------ + +* The :command:`file(TOUCH)` and :command:`file(TOUCH_NOCREATE)` commands + were added to expose TOUCH functionality without having to use CMake's + command-line tool mode with :command:`execute_process`. diff --git a/Help/release/dev/genex-IN_LIST-logical-operator.rst b/Help/release/dev/genex-IN_LIST-logical-operator.rst new file mode 100644 index 0000000..28fa7ce --- /dev/null +++ b/Help/release/dev/genex-IN_LIST-logical-operator.rst @@ -0,0 +1,5 @@ +genex-IN_LIST-logical-operator +------------------------------ + +* A new ``$<IN_LIST:...>`` :manual:`generator expression <cmake-generator-expressions(7)>` + has been added. diff --git a/Help/release/dev/string-join.rst b/Help/release/dev/string-join.rst new file mode 100644 index 0000000..5cca711 --- /dev/null +++ b/Help/release/dev/string-join.rst @@ -0,0 +1,5 @@ +string-join +----------- + +* The :command:`string` command learned a ``JOIN`` sub-command + to concatenate input strings separated by a glue string. diff --git a/Help/variable/CMAKE_NETRC.rst b/Help/variable/CMAKE_NETRC.rst index 52f857e..903ec31 100644 --- a/Help/variable/CMAKE_NETRC.rst +++ b/Help/variable/CMAKE_NETRC.rst @@ -2,7 +2,7 @@ CMAKE_NETRC ----------- This variable is used to initialize the ``NETRC`` option for -:command:`file(DOWNLOAD)` and :command:`file(DOWNLOAD)` commands and the +:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands and the module :module:`ExternalProject`. See those commands for additional information. diff --git a/Help/variable/CMAKE_NETRC_FILE.rst b/Help/variable/CMAKE_NETRC_FILE.rst index 1508f1e..0f09afe 100644 --- a/Help/variable/CMAKE_NETRC_FILE.rst +++ b/Help/variable/CMAKE_NETRC_FILE.rst @@ -2,7 +2,7 @@ CMAKE_NETRC_FILE ---------------- This variable is used to initialize the ``NETRC_FILE`` option for -:command:`file(DOWNLOAD)` and :command:`file(DOWNLOAD)` commands and the +:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands and the module :module:`ExternalProject`. See those commands for additional information. diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake index f3b95fd..6715c30 100644 --- a/Modules/CMakeTestCSharpCompiler.cmake +++ b/Modules/CMakeTestCSharpCompiler.cmake @@ -15,7 +15,7 @@ unset(CMAKE_CSharp_COMPILER_WORKS CACHE) set(test_compile_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs") # This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected C# compiler can actually compile +# determine that the selected C# compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index df5ec72..f0454da 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -15,7 +15,7 @@ include(CMakeTestCompilerCommon) unset(CMAKE_CUDA_COMPILER_WORKS CACHE) # This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected cuda compiler can actually compile +# determine that the selected cuda compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index 7b80dc0..e4d49ae 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -16,7 +16,7 @@ include(CMakeTestCompilerCommon) unset(CMAKE_CXX_COMPILER_WORKS CACHE) # This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected C++ compiler can actually compile +# determine that the selected C++ compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake index 3c150a8..e9860e9 100644 --- a/Modules/CMakeTestFortranCompiler.cmake +++ b/Modules/CMakeTestFortranCompiler.cmake @@ -16,7 +16,7 @@ include(CMakeTestCompilerCommon) unset(CMAKE_Fortran_COMPILER_WORKS CACHE) # This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected Fortran compiler can actually compile +# determine that the selected Fortran compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. diff --git a/Modules/CMakeTestJavaCompiler.cmake b/Modules/CMakeTestJavaCompiler.cmake index 23fdbdc..3c33573 100644 --- a/Modules/CMakeTestJavaCompiler.cmake +++ b/Modules/CMakeTestJavaCompiler.cmake @@ -3,7 +3,7 @@ # This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected Fortran compiler can actually compile +# determine that the selected Fortran compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. diff --git a/Modules/CMakeTestRCCompiler.cmake b/Modules/CMakeTestRCCompiler.cmake index c510d3a..3123a6c 100644 --- a/Modules/CMakeTestRCCompiler.cmake +++ b/Modules/CMakeTestRCCompiler.cmake @@ -3,7 +3,7 @@ # This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected RC compiler can actually compile +# determine that the selected RC compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. diff --git a/Modules/CMakeTestSwiftCompiler.cmake b/Modules/CMakeTestSwiftCompiler.cmake index bcd5c33..858c1be 100644 --- a/Modules/CMakeTestSwiftCompiler.cmake +++ b/Modules/CMakeTestSwiftCompiler.cmake @@ -16,7 +16,7 @@ include(CMakeTestCompilerCommon) unset(CMAKE_Swift_COMPILER_WORKS CACHE) # This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected C++ compiler can actually compile +# determine that the selected C++ compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index bb5181f..258922c 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -1984,7 +1984,7 @@ function(cpack_rpm_generate_package) endif() if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER}) - # Prefix can be replaced by Prefixes but the old version stil works so we'll ignore it for now + # Prefix can be replaced by Prefixes but the old version still works so we'll ignore it for now # Requires* is a special case because it gets transformed to Requires(pre/post/preun/postun) # Auto* is a special case because the tags can not be queried by querytags rpmbuild flag set(special_case_tags_ PREFIX REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN AUTOPROV AUTOREQ AUTOREQPROV) diff --git a/Modules/CheckCSourceRuns.cmake b/Modules/CheckCSourceRuns.cmake index fa51346..7eb050c 100644 --- a/Modules/CheckCSourceRuns.cmake +++ b/Modules/CheckCSourceRuns.cmake @@ -92,7 +92,8 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" - COMPILE_OUTPUT_VARIABLE OUTPUT) + COMPILE_OUTPUT_VARIABLE OUTPUT + RUN_OUTPUT_VARIABLE RUN_OUTPUT) # if it did not compile make the return value fail code of 1 if(NOT ${VAR}_COMPILED) set(${VAR}_EXITCODE 1) @@ -104,8 +105,10 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) message(STATUS "Performing Test ${VAR} - Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n" + "Performing C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n" "${OUTPUT}\n" + "...and run output:\n" + "${RUN_OUTPUT}\n" "Return value: ${${VAR}}\n" "Source file was:\n${SOURCE}\n") else() @@ -119,8 +122,10 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) message(STATUS "Performing Test ${VAR} - Failed") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n" + "Performing C SOURCE FILE Test ${VAR} failed with the following compile output:\n" "${OUTPUT}\n" + "...and run output:\n" + "${RUN_OUTPUT}\n" "Return value: ${${VAR}_EXITCODE}\n" "Source file was:\n${SOURCE}\n") diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 7331fb2..e5dbcd9 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -1133,7 +1133,7 @@ if("${ExternalData_ACTION}" STREQUAL "fetch") if(file_up_to_date) # Touch the file to convince the build system it is up to date. - execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${file}") + file(TOUCH "${file}") else() _ExternalData_link_or_copy("${obj}" "${file}") endif() diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 0a31ac2..119fc13 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -175,7 +175,7 @@ # -- Same as CUDA_ADD_EXECUTABLE except that a library is created. # # CUDA_BUILD_CLEAN_TARGET() -# -- Creates a convience target that deletes all the dependency files +# -- Creates a convenience target that deletes all the dependency files # generated. You should make clean after running this target to ensure the # dependency files get regenerated. # @@ -1564,7 +1564,7 @@ macro(CUDA_WRAP_SRCS cuda_target format generated_files) # Bring in the dependencies. Creates a variable CUDA_NVCC_DEPEND ####### cuda_include_nvcc_dependencies(${cmake_dependency_file}) - # Convience string for output ########################################### + # Convenience string for output ######################################### if(CUDA_BUILD_EMULATION) set(cuda_build_type "Emulation") else() @@ -1975,9 +1975,9 @@ endmacro() ############################################################################### ############################################################################### macro(CUDA_BUILD_CLEAN_TARGET) - # Call this after you add all your CUDA targets, and you will get a convience - # target. You should also make clean after running this target to get the - # build system to generate all the code again. + # Call this after you add all your CUDA targets, and you will get a + # convenience target. You should also make clean after running this target + # to get the build system to generate all the code again. set(cuda_clean_target_name clean_cuda_depends) if (CMAKE_GENERATOR MATCHES "Visual Studio") diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake index c16bbf2..881bff1 100644 --- a/Modules/FindImageMagick.cmake +++ b/Modules/FindImageMagick.cmake @@ -206,7 +206,7 @@ foreach(component ${ImageMagick_FIND_COMPONENTS} list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY) elseif(component STREQUAL "MagickWand") FIND_IMAGEMAGICK_API(MagickWand "wand/MagickWand.h;MagickWand/MagickWand.h" - Wand MagickWand CORE_RL_wand_ + Wand MagickWand CORE_RL_wand_ CORE_RL_MagickWand_ MagickWand-6 MagickWand-7 MagickWand-Q16 MagickWand-Q8 MagickWand-Q16HDRI MagickWand-Q8HDRI MagickWand-6.Q64 MagickWand-6.Q32 MagickWand-6.Q64HDRI MagickWand-6.Q32HDRI @@ -217,7 +217,7 @@ foreach(component ${ImageMagick_FIND_COMPONENTS} list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY) elseif(component STREQUAL "MagickCore") FIND_IMAGEMAGICK_API(MagickCore "magick/MagickCore.h;MagickCore/MagickCore.h" - Magick MagickCore CORE_RL_magick_ + Magick MagickCore CORE_RL_magick_ CORE_RL_MagickCore_ MagickCore-6 MagickCore-7 MagickCore-Q16 MagickCore-Q8 MagickCore-Q16HDRI MagickCore-Q8HDRI MagickCore-6.Q64 MagickCore-6.Q32 MagickCore-6.Q64HDRI MagickCore-6.Q32HDRI diff --git a/Modules/FindZLIB.cmake b/Modules/FindZLIB.cmake index 4065999..a5c04ac 100644 --- a/Modules/FindZLIB.cmake +++ b/Modules/FindZLIB.cmake @@ -75,8 +75,8 @@ endforeach() # Allow ZLIB_LIBRARY to be set manually, as the location of the zlib library if(NOT ZLIB_LIBRARY) foreach(search ${_ZLIB_SEARCHES}) - find_library(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_NAMES} ${${search}} PATH_SUFFIXES lib) - find_library(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_NAMES_DEBUG} ${${search}} PATH_SUFFIXES lib) + find_library(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_NAMES} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib) + find_library(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_NAMES_DEBUG} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib) endforeach() include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 939bd7b..7b138f5 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -36,7 +36,7 @@ # The default OUTPUT_DIR can also be changed by setting the variable # CMAKE_JAVA_TARGET_OUTPUT_DIR. # -# Optionaly, using option GENERATE_NATIVE_HEADERS, native header files can be generated +# Optionally, using option GENERATE_NATIVE_HEADERS, native header files can be generated # for methods declared as native. These files provide the connective glue that allow your # Java and C code to interact. An INTERFACE target will be created for an easy usage # of generated files. Sub-option DESTINATION can be used to specify output directory for diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 959893f..6d35d1b 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -5,7 +5,7 @@ UseSWIG ------- -Defines the following macros for use with SWIG: +Defines the following command for use with SWIG: .. command:: swig_add_library @@ -14,20 +14,47 @@ Defines the following macros for use with SWIG: swig_add_library(<name> [TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>] LANGUAGE <language> + [NO_PROXY] + [OUTPUT_DIR <directory>] + [OUTFILE_DIR <directory>] SOURCES <file>... - ) + ) - The variable ``SWIG_MODULE_<name>_REAL_NAME`` will be set to the name - of the swig module target library. + Targets created with command ``swig_add_library`` have the same capabilities as targets + created with command :command:`add_library`, so can be used with any command accepting a target + especially command :command:`target_link_libraries`. -.. command:: swig_link_libraries + The arguments are: - Link libraries to swig module:: + ``TYPE`` + ``SHARED``, ``MODULE`` and ``STATIC`` have same semantic as command :command:`add_library`. + if ``USE_BUILD_SHARED_LIBS`` is specified, library type will be ``STATIC`` or ``SHARED`` + based on whether the current value of the variable :variable:`BUILD_SHARED_LIBS` is ``ON``. + If none is specified, ``MODULE`` will be used. - swig_link_libraries(<name> [ libraries ]) + ``LANGUAGE`` + Specify the target language. -Source file properties on module files can be set before the invocation -of the ``swig_add_library`` macro to specify special behavior of SWIG: + ``NO_PROXY`` + Prevent the generation of the wrapper layer (swig ``-noproxy`` option). + + ``OUTPUT_DIR`` + Specify where to write the language specific files (swig ``-outdir`` option). + If not specified, variable ``CMAKE_SWIG_OUTDIR`` will be used. If none is specified, + :variable:`CMAKE_CURRENT_BINARY_DIR` is used. + + ``OUTFILE_DIR`` + Specify an output directory name where the generated source file will be placed + (swig -o option). If not specified, variable ``SWIG_OUTFILE_DIR`` will be used. + If none is specified, option ``OUTPUT_DIR`` or variable ``CMAKE_SWIG_OUTDIR`` is used. + + ``SOURCES`` + List of sources for the library. Files with extension ``.i`` will be identified as sources + for ``SWIG`` tool. Other files will be handled in the standard way. + +Source files properties on module files **must** be set before the invocation +of the ``swig_add_library`` command to specify special behavior of SWIG and ensure +generated files will receive required settings. ``CPLUSPLUS`` Call SWIG in c++ mode. For example: @@ -37,9 +64,17 @@ of the ``swig_add_library`` macro to specify special behavior of SWIG: 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. +``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` and ``COMPILE_OPTIONS`` + Add custom flags to SWIG compiler and have same semantic as properties + :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and :prop_sf:`COMPILE_OPTIONS`. + +``GENERATED_INCLUDE_DIRECTORIES``, ``GENERATED_COMPILE_DEFINITIONS`` and ``GENERATED_COMPILE_OPTIONS`` + Add custom flags to the C/C++ generated source. They will fill, respectively, + properties :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and + :prop_sf:`COMPILE_OPTIONS` of generated C/C++ file. +``DEPENDS`` + Specify additional dependencies to the source file. ``SWIG_MODULE_NAME`` Specify the actual import name of the module in the target language. @@ -50,6 +85,34 @@ of the ``swig_add_library`` macro to specify special behavior of SWIG: set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname) +Target library properties can be set to apply same configuration to all SWIG input files. + +``SWIG_INCLUDE_DIRECTORIES``, ``SWIG_COMPILE_DEFINITIONS`` and ``SWIG_COMPILE_OPTIONS`` + These properties will be applied to all SWIG input files and have same semantic as + target properties :prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and + :prop_tgt:`COMPILE_OPTIONS`. + + .. code-block:: cmake + + swig_add_library(mymod LANGUAGE python SOURCES mymod.i) + set_property(TARGET mymod PROPERTY SWIG_COMPILE_DEFINITIONS MY_DEF1 MY_DEF2) + set_property(TARGET mymod PROPERTY SWIG_COMPILE_OPTIONS -bla -blb) + +``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS`` + These properties will populate, respectively, properties :prop_sf:`INCLUDE_DIRECTORIES`, + :prop_sf:`COMPILE_DEFINITIONS` and :prop_sf:`COMPILE_FLAGS` of all generated C/C++ files. + +``SWIG_DEPENDS`` + Add dependencies to all SWIG input files. + +``SWIG_SUPPORT_FILES`` + This output property list of wrapper files generated during SWIG compilation. + + .. code-block:: cmake + + swig_add_library(mymod LANGUAGE python SOURCES mymod.i) + get_property(support_files TARGET mymod PROPERTY SWIG_SUPPORT_FILES) + Some variables can be set to specify special behavior of SWIG: ``CMAKE_SWIG_FLAGS`` @@ -66,34 +129,56 @@ Some variables can be set to specify special behavior of SWIG: Specify extra dependencies for the generated module for ``<name>``. #]=======================================================================] + +cmake_policy (VERSION 3.11) + set(SWIG_CXX_EXTENSION "cxx") set(SWIG_EXTRA_LIBRARIES "") set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py") set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java") +## +## PRIVATE functions +## +function (__SWIG_COMPUTE_TIMESTAMP name language infile workingdir __timestamp) + get_filename_component(filename "${infile}" NAME_WE) + set(${__timestamp} + "${workingdir}/${filename}${language}.stamp" PARENT_SCOPE) + # get_filename_component(filename "${infile}" ABSOLUTE) + # string(UUID uuid NAMESPACE 9735D882-D2F8-4E1D-88C9-A0A4F1F6ECA4 + # NAME ${name}-${language}-${filename} TYPE SHA1) + # set(${__timestamp} "${workingdir}/${uuid}.stamp" PARENT_SCOPE) +endfunction() + # # For given swig module initialize variables associated with it # macro(SWIG_MODULE_INITIALIZE name language) - string(TOUPPER "${language}" swig_uppercase_language) - string(TOLOWER "${language}" swig_lowercase_language) - set(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}") - set(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}") + string(TOUPPER "${language}" SWIG_MODULE_${name}_LANGUAGE) + string(TOLOWER "${language}" SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG) - set(SWIG_MODULE_${name}_REAL_NAME "${name}") - if (";${CMAKE_SWIG_FLAGS};" MATCHES ";-noproxy;") + set(SWIG_MODULE_${name}_NAME "${name}") + set(SWIG_MODULE_${name}_EXTRA_FLAGS) + if (NOT DEFINED SWIG_MODULE_${name}_NOPROXY) + set (SWIG_MODULE_${name}_NOPROXY FALSE) + endif() + if ("-noproxy" IN_LIST CMAKE_SWIG_FLAGS) set (SWIG_MODULE_${name}_NOPROXY TRUE) endif () - if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xUNKNOWN") + + if (SWIG_MODULE_${name}_NOPROXY AND NOT "-noproxy" IN_LIST CMAKE_SWIG_FLAGS) + list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-noproxy") + endif() + if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "UNKNOWN") message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found") - elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY) + elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY) # swig will produce a module.py containing an 'import _modulename' statement, # which implies having a corresponding _modulename.so (*NIX), _modulename.pyd (Win32), # unless the -noproxy flag is used - set(SWIG_MODULE_${name}_REAL_NAME "_${name}") - elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPERL") - set(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow") + set(SWIG_MODULE_${name}_NAME "_${name}") + elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PERL") + list(APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow") endif() endmacro() @@ -102,79 +187,108 @@ endmacro() # will be generated. This is internal swig macro. # -macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile) - set(${outfiles} "") - get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename - ${infile} SWIG_MODULE_NAME) - if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND") +function(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile) + set(files) + get_source_file_property(module_basename + "${infile}" SWIG_MODULE_NAME) + if(NOT swig_module_basename) # try to get module name from "%module foo" syntax - if ( EXISTS ${infile} ) - file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" ) + if ( EXISTS "${infile}" ) + file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" ) endif () - if ( _MODULE_NAME ) - string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" ) - set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}") + if ( module_basename ) + string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" ) else () # try to get module name from "%module (options=...) foo" syntax - if ( EXISTS ${infile} ) - file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" ) + if ( EXISTS "${infile}" ) + file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" ) endif () - if ( _MODULE_NAME ) - string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" ) - set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}") + if ( module_basename ) + string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" ) else () # fallback to file basename - get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename ${infile} NAME_WE) + get_filename_component(module_basename "${infile}" NAME_WE) endif () endif () endif() foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSIONS}) - set(extra_file "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}${it}") - list(APPEND ${outfiles} ${extra_file}) - # Treat extra outputs as plain files regardless of language. - set_property(SOURCE "${extra_file}" PROPERTY LANGUAGE "") + set(extra_file "${generatedpath}/${module_basename}${it}") + list(APPEND files "${extra_file}") endforeach() -endmacro() + # Treat extra outputs as plain files regardless of language. + set_source_files_properties(${files} PROPERTIES LANGUAGE "") + + set (${outfiles} ${files} PARENT_SCOPE) +endfunction() # # Take swig (*.i) file and add proper custom commands for it # -macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) - set(swig_full_infile ${infile}) +function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) get_filename_component(swig_source_file_name_we "${infile}" NAME_WE) - get_source_file_property(swig_source_file_generated ${infile} GENERATED) - get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS) - get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS) - if("${swig_source_file_flags}" STREQUAL "NOTFOUND") - set(swig_source_file_flags "") - endif() - get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE) + get_source_file_property(swig_source_file_cplusplus "${infile}" CPLUSPLUS) # If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir if(CMAKE_SWIG_OUTDIR) - set(swig_outdir ${CMAKE_SWIG_OUTDIR}) + set(outdir ${CMAKE_SWIG_OUTDIR}) else() - set(swig_outdir ${CMAKE_CURRENT_BINARY_DIR}) + set(outdir ${CMAKE_CURRENT_BINARY_DIR}) endif() if(SWIG_OUTFILE_DIR) - set(swig_outfile_dir ${SWIG_OUTFILE_DIR}) + set(outfiledir ${SWIG_OUTFILE_DIR}) else() - set(swig_outfile_dir ${swig_outdir}) + set(outfiledir ${outdir}) + endif() + + if(SWIG_WORKING_DIR) + set (workingdir "${SWIG_WORKING_DIR}") + else() + set(workingdir "${outdir}") + endif() + + set (swig_source_file_flags ${CMAKE_SWIG_FLAGS}) + # handle various swig compile flags properties + get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES) + if (include_directories) + list (APPEND swig_source_file_flags "-I$<JOIN:${include_directories},$<SEMICOLON>-I>") + endif() + set (property "$<TARGET_PROPERTY:${name},SWIG_INCLUDE_DIRECTORIES>") + list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>") + + set (property "$<TARGET_PROPERTY:${name},SWIG_COMPILE_DEFINITIONS>") + list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:${property},$<SEMICOLON>-D>>") + get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS) + if (compile_definitions) + list (APPEND swig_source_file_flags "-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>") + endif() + + list (APPEND swig_source_file_flags "$<TARGET_PROPERTY:${name},SWIG_COMPILE_OPTIONS>") + get_source_file_property (compile_options "${infile}" COMPILE_OPTIONS) + if (compile_options) + list (APPEND swig_source_file_flags ${compile_options}) + endif() + + # legacy support + get_source_file_property (swig_flags "${infile}" SWIG_FLAGS) + if (swig_flags) + list (APPEND swig_source_file_flags ${swig_flags}) endif() + get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE) + if (NOT SWIG_MODULE_${name}_NOPROXY) SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE} swig_extra_generated_files - "${swig_outdir}" + "${outdir}" "${swig_source_file_fullname}") endif() set(swig_generated_file_fullname - "${swig_outfile_dir}/${swig_source_file_name_we}") + "${outfiledir}/${swig_source_file_name_we}") # add the language into the name of the file (i.e. TCL_wrap) # this allows for the same .i file to be wrapped into different languages string(APPEND swig_generated_file_fullname @@ -188,45 +302,47 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) ".c") endif() - #message("Full path to source file: ${swig_source_file_fullname}") - #message("Full path to the output file: ${swig_generated_file_fullname}") - get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES) - list(REMOVE_DUPLICATES cmake_include_directories) - set(swig_include_dirs) - foreach(it ${cmake_include_directories}) - set(swig_include_dirs ${swig_include_dirs} "-I${it}") - endforeach() + get_directory_property (cmake_include_directories INCLUDE_DIRECTORIES) + list (REMOVE_DUPLICATES cmake_include_directories) + set (swig_include_dirs) + if (cmake_include_directories) + set (swig_include_dirs "-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>") + endif() set(swig_special_flags) # default is c, so add c++ flag if it is c++ if(swig_source_file_cplusplus) - set(swig_special_flags ${swig_special_flags} "-c++") + list (APPEND swig_special_flags "-c++") endif() - if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xCSHARP") - if(NOT ";${swig_source_file_flags};${CMAKE_SWIG_FLAGS};" MATCHES ";-dllimport;") + + set (swig_extra_flags) + if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "CSHARP") + if(NOT ("-dllimport" IN_LIST swig_source_file_flags OR "-dllimport" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS)) # This makes sure that the name used in the generated DllImport # matches the library name created by CMake - set(SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport;${name}") + list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "${name}") endif() endif() - set(swig_extra_flags) - if(SWIG_MODULE_${name}_EXTRA_FLAGS) - set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS}) + list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS}) + + # dependencies + set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${name},SWIG_DEPENDS>) + get_source_file_property(file_depends "${infile}" DEPENDS) + if (file_depends) + list (APPEND swig_dependencies ${file_depends}) endif() + # IMPLICIT_DEPENDS below can not handle situations where a dependent file is # removed. We need an extra step with timestamp and custom target, see #16830 # As this is needed only for Makefile generator do it conditionally if(CMAKE_GENERATOR MATCHES "Make") - get_filename_component(swig_generated_timestamp - "${swig_generated_file_fullname}" NAME_WE) - set(swig_gen_target gen_${name}_${swig_generated_timestamp}) - set(swig_generated_timestamp - "${swig_outdir}/${swig_generated_timestamp}.stamp") - set(swig_custom_output ${swig_generated_timestamp}) + __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} + "${infile}" "${workingdir}" swig_generated_timestamp) + set(swig_custom_output "${swig_generated_timestamp}") set(swig_custom_products BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files}) set(swig_timestamp_command - COMMAND ${CMAKE_COMMAND} -E touch ${swig_generated_timestamp}) + COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}") else() set(swig_custom_output "${swig_generated_file_fullname}" ${swig_extra_generated_files}) @@ -236,34 +352,41 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) add_custom_command( OUTPUT ${swig_custom_output} ${swig_custom_products} - # Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir) - COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir} + # Let's create the ${outdir} at execution time, in case dir contains $(OutDir) + COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir} ${swig_timestamp_command} COMMAND "${SWIG_EXECUTABLE}" - ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" - ${swig_source_file_flags} - ${CMAKE_SWIG_FLAGS} - -outdir ${swig_outdir} + "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" + "${swig_source_file_flags}" + -outdir "${outdir}" ${swig_special_flags} ${swig_extra_flags} - ${swig_include_dirs} + "${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_dependencies} IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}" - COMMENT "Swig source") - if(CMAKE_GENERATOR MATCHES "Make") - add_custom_target(${swig_gen_target} DEPENDS ${swig_generated_timestamp}) - endif() - unset(swig_generated_timestamp) - unset(swig_custom_output) - unset(swig_custom_products) - unset(swig_timestamp_command) + COMMENT "Swig source" + COMMAND_EXPAND_LISTS) set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files} PROPERTIES GENERATED 1) - set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files}) -endmacro() + + ## add all properties for generated file to various properties + get_property (include_directories SOURCE "${infile}" PROPERTY GENERATED_INCLUDE_DIRECTORIES) + set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY INCLUDE_DIRECTORIES ${include_directories} $<TARGET_PROPERTY:${name},SWIG_GENERATED_INCLUDE_DIRECTORIES>) + + get_property (compile_definitions SOURCE "${infile}" PROPERTY GENERATED_COMPILE_DEFINITIONS) + set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_DEFINITIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_DEFINITIONS> ${compile_definitions}) + + get_property (compile_options SOURCE "${infile}" PROPERTY GENERATED_COMPILE_OPTIONS) + set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_OPTIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_OPTIONS> ${compile_options}) + + set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE) + + # legacy support + set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE) +endfunction() # # Create Swig module @@ -277,13 +400,26 @@ macro(SWIG_ADD_MODULE name language) endmacro() -macro(SWIG_ADD_LIBRARY name) - set(options "") +function(SWIG_ADD_LIBRARY name) + set(options NO_PROXY) set(oneValueArgs LANGUAGE - TYPE) + TYPE + OUTPUT_DIR + OUTFILE_DIR) set(multiValueArgs SOURCES) cmake_parse_arguments(_SAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if (TARGET ${name}) + # a target with same name is already defined. + # call NOW add_library command to raise the most useful error message + add_library(${name}) + return() + endif() + + if (_SAM_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "SWIG_ADD_LIBRARY: ${_SAM_UNPARSED_ARGUMENTS}: unexpected arguments") + endif() + if(NOT DEFINED _SAM_LANGUAGE) message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing LANGUAGE argument") endif() @@ -294,50 +430,83 @@ macro(SWIG_ADD_LIBRARY name) if(NOT DEFINED _SAM_TYPE) set(_SAM_TYPE MODULE) - elseif("${_SAM_TYPE}" STREQUAL "USE_BUILD_SHARED_LIBS") + elseif(_SAM_TYPE STREQUAL "USE_BUILD_SHARED_LIBS") unset(_SAM_TYPE) endif() - swig_module_initialize(${name} ${_SAM_LANGUAGE}) + set (workingdir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${name}.dir") + # set special variable to pass extra information to command SWIG_ADD_SOURCE_TO_MODULE + # which cannot be changed due to legacy compatibility + set (SWIG_WORKING_DIR "${workingdir}") - set(swig_dot_i_sources) - set(swig_other_sources) - foreach(it ${_SAM_SOURCES}) - if(${it} MATCHES "\\.i$") - set(swig_dot_i_sources ${swig_dot_i_sources} "${it}") + set (outputdir "${_SAM_OUTPUT_DIR}") + if (NOT _SAM_OUTPUT_DIR) + if (CMAKE_SWIG_OUTDIR) + set (outputdir "${CMAKE_SWIG_OUTDIR}") else() - set(swig_other_sources ${swig_other_sources} "${it}") + set (outputdir "${CMAKE_CURRENT_BINARY_DIR}") endif() - endforeach() + endif() + + set (outfiledir "${_SAM_OUTFILE_DIR}") + if(NOT _SAM_OUTFILE_DIR) + if (SWIG_OUTFILE_DIR) + set (outfiledir "${SWIG_OUTFILE_DIR}") + else() + if (_SAM_OUTPUT_DIR OR CMAKE_SWIG_OUTDIR) + set (outfiledir "${outputdir}") + else() + set (outfiledir "${workingdir}") + endif() + endif() + endif() + # set again, locally, predefined variables to ensure compatibility + # with command SWIG_ADD_SOURCE_TO_MODULE + set(CMAKE_SWIG_OUTDIR "${outputdir}") + set(SWIG_OUTFILE_DIR "${outfiledir}") + + set (SWIG_MODULE_${name}_NOPROXY ${_SAM_NO_PROXY}) + swig_module_initialize(${name} ${_SAM_LANGUAGE}) + + set(swig_dot_i_sources ${_SAM_SOURCES}) + list(FILTER swig_dot_i_sources INCLUDE REGEX "\\.i$") + set(swig_other_sources ${_SAM_SOURCES}) + list(REMOVE_ITEM swig_other_sources ${swig_dot_i_sources}) set(swig_generated_sources) - set(swig_generated_targets) - foreach(it ${swig_dot_i_sources}) - SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it}) - set(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}") - list(APPEND swig_generated_targets "${swig_gen_target}") + set(swig_generated_timestamps) + foreach(swig_it IN LISTS swig_dot_i_sources) + SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}") + list (APPEND swig_generated_sources "${swig_generated_source}") + if(CMAKE_GENERATOR MATCHES "Make") + __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} "${swig_it}" + "${workingdir}" swig_timestamp) + list (APPEND swig_generated_timestamps "${swig_timestamp}") + endif() endforeach() - get_directory_property(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES) - set_directory_properties(PROPERTIES - ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}") - add_library(${SWIG_MODULE_${name}_REAL_NAME} + set_property (DIRECTORY APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps}) + + add_library(${name} ${_SAM_TYPE} ${swig_generated_sources} ${swig_other_sources}) + set_target_properties(${name} PROPERTIES OUTPUT_NAME "${SWIG_MODULE_${name}_NAME}") if(CMAKE_GENERATOR MATCHES "Make") # see IMPLICIT_DEPENDS above - add_dependencies(${SWIG_MODULE_${name}_REAL_NAME} ${swig_generated_targets}) + add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps}) + add_dependencies(${name} ${name}_swig_compilation) endif() - if("${_SAM_TYPE}" STREQUAL "MODULE") - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES NO_SONAME ON) + if(_SAM_TYPE STREQUAL "MODULE") + set_target_properties(${name} PROPERTIES NO_SONAME ON) endif() string(TOLOWER "${_SAM_LANGUAGE}" swig_lowercase_language) - if ("${swig_lowercase_language}" STREQUAL "octave") - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".oct") - elseif ("${swig_lowercase_language}" STREQUAL "go") - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") - elseif ("${swig_lowercase_language}" STREQUAL "java") + if (swig_lowercase_language STREQUAL "octave") + set_target_properties(${name} PROPERTIES PREFIX "") + set_target_properties(${name} PROPERTIES SUFFIX ".oct") + elseif (swig_lowercase_language STREQUAL "go") + set_target_properties(${name} PROPERTIES PREFIX "") + elseif (swig_lowercase_language STREQUAL "java") if (APPLE) # In java you want: # System.loadLibrary("LIBRARY"); @@ -345,15 +514,15 @@ macro(SWIG_ADD_LIBRARY name) # MacOS : libLIBRARY.jnilib # Windows: LIBRARY.dll # Linux : libLIBRARY.so - set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".jnilib") + set_target_properties (${name} PROPERTIES SUFFIX ".jnilib") endif () - elseif ("${swig_lowercase_language}" STREQUAL "lua") - if("${_SAM_TYPE}" STREQUAL "MODULE") - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") + elseif (swig_lowercase_language STREQUAL "lua") + if(_SAM_TYPE STREQUAL "MODULE") + set_target_properties(${name} PROPERTIES PREFIX "") endif() - elseif ("${swig_lowercase_language}" STREQUAL "python") + elseif (swig_lowercase_language STREQUAL "python") # this is only needed for the python case where a _modulename.so is generated - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") + set_target_properties(${name} PROPERTIES PREFIX "") # Python extension modules on Windows must have the extension ".pyd" # instead of ".dll" as of Python 2.5. Older python versions do support # this suffix. @@ -363,34 +532,60 @@ macro(SWIG_ADD_LIBRARY name) # .pyd is now the only filename extension that will be searched for. # </quote> if(WIN32 AND NOT CYGWIN) - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".pyd") + set_target_properties(${name} PROPERTIES SUFFIX ".pyd") endif() - elseif ("${swig_lowercase_language}" STREQUAL "r") - set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") - elseif ("${swig_lowercase_language}" STREQUAL "ruby") + elseif (swig_lowercase_language STREQUAL "r") + set_target_properties(${name} PROPERTIES PREFIX "") + elseif (swig_lowercase_language STREQUAL "ruby") # In ruby you want: # require 'LIBRARY' # then ruby will look for a library whose name is platform dependent, namely # MacOS : LIBRARY.bundle # Windows: LIBRARY.dll # Linux : LIBRARY.so - set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") + set_target_properties (${name} PROPERTIES PREFIX "") + if (APPLE) + set_target_properties (${name} PROPERTIES SUFFIX ".bundle") + endif () + elseif (swig_lowercase_language STREQUAL "perl") + # assume empty prefix because we expect the module to be dynamically loaded + set_target_properties (${name} PROPERTIES PREFIX "") if (APPLE) - set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".bundle") + set_target_properties (${name} PROPERTIES SUFFIX ".dylib") endif () else() # assume empty prefix because we expect the module to be dynamically loaded - set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") + set_target_properties (${name} PROPERTIES PREFIX "") endif () -endmacro() + # target property SWIG_SUPPORT_FILES lists proxy support files + if (NOT SWIG_MODULE_${name}_NOPROXY) + string(TOUPPER "${_SAM_LANGUAGE}" swig_uppercase_language) + foreach (swig_it IN LISTS SWIG_${swig_uppercase_language}_EXTRA_FILE_EXTENSIONS) + set (swig_support_files ${swig_generated_sources}) + list (FILTER swig_support_files INCLUDE REGEX ".*${swig_it}$") + set_property (TARGET ${name} APPEND PROPERTY SWIG_SUPPORT_FILES ${swig_support_files}) + endforeach() + endif() + + # to ensure legacy behavior, export some variables + set (SWIG_MODULE_${name}_LANGUAGE "${SWIG_MODULE_${name}_LANGUAGE}" PARENT_SCOPE) + set (SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" PARENT_SCOPE) + set (SWIG_MODULE_${name}_REAL_NAME "${name}" PARENT_SCOPE) + set (SWIG_MODULE_${name}_NOPROXY "${SWIG_MODULE_${name}_NOPROXY}" PARENT_SCOPE) + set (SWIG_MODULE_${name}_EXTRA_FLAGS "${SWIG_MODULE_${name}_EXTRA_FLAGS}" PARENT_SCOPE) + # the last one is a bit crazy but it is documented, so... + # NOTA: works as expected if only ONE input file is specified + set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE) +endfunction() # # Like TARGET_LINK_LIBRARIES but for swig modules # -macro(SWIG_LINK_LIBRARIES name) +function(SWIG_LINK_LIBRARIES name) + message(DEPRECATION "SWIG_LINK_LIBRARIES is deprecated. Use TARGET_LINK_LIBRARIES instead.") if(SWIG_MODULE_${name}_REAL_NAME) - target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN}) + target_link_libraries(${name} ${ARGN}) else() message(SEND_ERROR "Cannot find Swig library \"${name}\".") endif() -endmacro() +endfunction() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a6e8503..1477f0d 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 20180205) +set(CMake_VERSION_MINOR 11) +set(CMake_VERSION_PATCH 20180220) #set(CMake_VERSION_RC 1) diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index 6f31a2d..817b5d9 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -8,6 +8,7 @@ #include <utility> #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorTarget.h" #include "cmLinkItem.h" #include "cmLocalGenerator.h" @@ -101,12 +102,21 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( os << "LOCAL_CPP_FEATURES += "; os << (property.second) << "\n"; } else if (property.first == "INTERFACE_LINK_LIBRARIES") { + // evaluate any generator expressions with the current + // build type of the makefile + cmGeneratorExpression ge; + cmGeneratorExpressionDAGChecker dagChecker( + target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr); + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(property.second); + std::string evaluated = cge->Evaluate( + target->GetLocalGenerator(), config, false, target, &dagChecker); // need to look at list in pi->second and see if static or shared // FindTargetToLink // target->GetLocalGenerator()->FindGeneratorTargetToUse() // then add to LOCAL_CPPFLAGS std::vector<std::string> libraries; - cmSystemTools::ExpandListArgument(property.second, libraries); + cmSystemTools::ExpandListArgument(evaluated, libraries); std::string staticLibs; std::string sharedLibs; std::string ldlibs; @@ -122,12 +132,6 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( staticLibs += " " + lib; } } else { - // evaluate any generator expressions with the current - // build type of the makefile - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(lib); - std::string evaluated = - cge->Evaluate(target->GetLocalGenerator(), config); bool relpath = false; if (type == cmExportBuildAndroidMKGenerator::INSTALL) { relpath = lib.substr(0, 3) == "../"; @@ -135,12 +139,12 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( // check for full path or if it already has a -l, or // in the case of an install check for relative paths // if it is full or a link library then use string directly - if (cmSystemTools::FileIsFullPath(evaluated) || - evaluated.substr(0, 2) == "-l" || relpath) { - ldlibs += " " + evaluated; + if (cmSystemTools::FileIsFullPath(lib) || + lib.substr(0, 2) == "-l" || relpath) { + ldlibs += " " + lib; // if it is not a path and does not have a -l then add -l - } else if (!evaluated.empty()) { - ldlibs += " -l" + evaluated; + } else if (!lib.empty()) { + ldlibs += " -l" + lib; } } } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index d3dcc01..8492c17 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -160,6 +160,12 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args, if (subCommand == "TO_NATIVE_PATH") { return this->HandleCMakePathCommand(args, true); } + if (subCommand == "TOUCH") { + return this->HandleTouchCommand(args, true); + } + if (subCommand == "TOUCH_NOCREATE") { + return this->HandleTouchCommand(args, false); + } if (subCommand == "TIMESTAMP") { return this->HandleTimestampCommand(args); } @@ -905,6 +911,38 @@ bool cmFileCommand::HandleMakeDirectoryCommand( return true; } +bool cmFileCommand::HandleTouchCommand(std::vector<std::string> const& args, + bool create) +{ + // File command has at least one argument + assert(args.size() > 1); + + std::vector<std::string>::const_iterator i = args.begin(); + + i++; // Get rid of subcommand + + for (; i != args.end(); ++i) { + std::string tfile = *i; + if (!cmsys::SystemTools::FileIsFullPath(tfile)) { + tfile = this->Makefile->GetCurrentSourceDirectory(); + tfile += "/" + *i; + } + if (!this->Makefile->CanIWriteThisFile(tfile)) { + std::string e = + "attempted to touch a file: " + tfile + " in a source directory."; + this->SetError(e); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + if (!cmSystemTools::Touch(tfile, create)) { + std::string error = "problem touching file: " + tfile; + this->SetError(error); + return false; + } + } + return true; +} + bool cmFileCommand::HandleDifferentCommand( std::vector<std::string> const& args) { diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 17269f3..719dca2 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -39,6 +39,7 @@ protected: bool HandleHashCommand(std::vector<std::string> const& args); bool HandleStringsCommand(std::vector<std::string> const& args); bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse); + bool HandleTouchCommand(std::vector<std::string> const& args, bool create); bool HandleMakeDirectoryCommand(std::vector<std::string> const& args); bool HandleRelativePathCommand(std::vector<std::string> const& args); diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 417cdd2..7069386 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -225,8 +225,8 @@ void cmFindBase::FillCMakeVariablePath() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake]; - // Add CMake varibles of the same name as the previous environment - // varibles CMAKE_*_PATH to be used most of the time with -D + // Add CMake variables of the same name as the previous environment + // variables CMAKE_*_PATH to be used most of the time with -D // command line options std::string var = "CMAKE_"; var += this->CMakePathName; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index c1f1ee4..0d22028 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -275,6 +275,31 @@ static const struct EqualNode : public cmGeneratorExpressionNode } } equalNode; +static const struct InListNode : public cmGeneratorExpressionNode +{ + InListNode() {} + + int NumExpectedParameters() const override { return 2; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* /*context*/, + const GeneratorExpressionContent* /*content*/, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + std::vector<std::string> values; + cmSystemTools::ExpandListArgument(parameters[1], values); + if (values.empty()) { + return "0"; + } + + return std::find(values.cbegin(), values.cend(), parameters.front()) == + values.cend() + ? "0" + : "1"; + } +} inListNode; + static const struct LowerCaseNode : public cmGeneratorExpressionNode { LowerCaseNode() {} @@ -1827,6 +1852,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode; nodeMap["STREQUAL"] = &strEqualNode; nodeMap["EQUAL"] = &equalNode; + nodeMap["IN_LIST"] = &inListNode; nodeMap["LOWER_CASE"] = &lowerCaseNode; nodeMap["UPPER_CASE"] = &upperCaseNode; nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index b251f86..8410609 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1384,8 +1384,14 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) /*explicitDeps=*/cmNinjaDeps(), implicitDeps, /*orderOnlyDeps=*/cmNinjaDeps(), variables); + cmNinjaDeps missingInputs; + std::set_difference(std::make_move_iterator(implicitDeps.begin()), + std::make_move_iterator(implicitDeps.end()), + CustomCommandOutputs.begin(), CustomCommandOutputs.end(), + std::back_inserter(missingInputs)); + this->WritePhonyBuild(os, "A missing CMake input file is not an error.", - implicitDeps, cmNinjaDeps()); + missingInputs, cmNinjaDeps()); } std::string cmGlobalNinjaGenerator::ninjaCmd() const diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index b1afdc9..2a38599 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -542,6 +542,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( makefileStream.SetCopyIfDifferent(true); makefileStream << "# Generated by CMake, DO NOT EDIT\n\n"; + makefileStream << "TARGETS:= \n"; makefileStream << "empty:= \n"; makefileStream << "space:= $(empty) $(empty)\n"; makefileStream << "spaceplus:= $(empty)\\ $(empty)\n\n"; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 8c889fc..c1af92f 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -10,6 +10,7 @@ #include <stdio.h> #include <utility> +#include "cmCryptoHash.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" #include "cmGeneratedFileStream.h" @@ -24,6 +25,7 @@ #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmake.h" +#include "cmsys/FStream.hxx" cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmMakefile* mf) @@ -286,8 +288,51 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps( } } +std::string cmLocalNinjaGenerator::WriteCommandScript( + std::vector<std::string> const& cmdLines, std::string const& customStep, + cmGeneratorTarget const* target) const +{ + std::string scriptPath; + if (target) { + scriptPath = target->GetSupportDirectory(); + } else { + scriptPath = this->GetCurrentBinaryDirectory(); + scriptPath += cmake::GetCMakeFilesDirectory(); + } + cmSystemTools::MakeDirectory(scriptPath); + scriptPath += '/'; + scriptPath += customStep; +#ifdef _WIN32 + scriptPath += ".bat"; +#else + scriptPath += ".sh"; +#endif + + cmsys::ofstream script(scriptPath.c_str()); + +#ifndef _WIN32 + script << "set -e\n\n"; +#endif + + for (auto const& i : cmdLines) { + std::string cmd = i; + // The command line was built assuming it would be written to + // the build.ninja file, so it uses '$$' for '$'. Remove this + // for the raw shell script. + cmSystemTools::ReplaceString(cmd, "$$", "$"); +#ifdef _WIN32 + script << cmd << " || exit /b" << '\n'; +#else + script << cmd << '\n'; +#endif + } + + return scriptPath; +} + std::string cmLocalNinjaGenerator::BuildCommandLine( - const std::vector<std::string>& cmdLines) + std::vector<std::string> const& cmdLines, std::string const& customStep, + cmGeneratorTarget const* target) const { // If we have no commands but we need to build a command anyway, use noop. // This happens when building a POST_BUILD value for link targets that @@ -296,6 +341,35 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( return cmGlobalNinjaGenerator::SHELL_NOOP; } + // If this is a custom step then we will have no '$VAR' ninja placeholders. + // This means we can deal with long command sequences by writing to a script. + // Do this if the command lines are on the scale of the OS limit. + if (!customStep.empty()) { + size_t cmdLinesTotal = 0; + for (std::string const& cmd : cmdLines) { + cmdLinesTotal += cmd.length() + 6; + } + if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) { + std::string const scriptPath = + this->WriteCommandScript(cmdLines, customStep, target); + std::string cmd +#ifndef _WIN32 + = "/bin/sh " +#endif + ; + cmd += this->ConvertToOutputFormat( + this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath), + cmOutputConverter::SHELL); + + // Add an unused argument based on script content so that Ninja + // knows when the command lines change. + cmd += " "; + cmCryptoHash hash(cmCryptoHash::AlgoSHA256); + cmd += hash.HashFile(scriptPath).substr(0, 16); + return cmd; + } + } + std::ostringstream cmd; for (std::vector<std::string>::const_iterator li = cmdLines.begin(); li != cmdLines.end(); ++li) @@ -406,10 +480,16 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( "Phony custom command for " + ninjaOutputs[0], ninjaOutputs, ninjaDeps, cmNinjaDeps(), orderOnlyDeps, cmNinjaVars()); } else { + std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]); + // Hash full path to make unique. + customStep += '-'; + cmCryptoHash hash(cmCryptoHash::AlgoSHA256); + customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7); + this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild( - this->BuildCommandLine(cmdLines), this->ConstructComment(ccg), - "Custom command for " + ninjaOutputs[0], cc->GetDepfile(), - cc->GetUsesTerminal(), + this->BuildCommandLine(cmdLines, customStep), + this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], + cc->GetDepfile(), cc->GetUsesTerminal(), /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps, orderOnlyDeps); } diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 95d8a61..f772fb0 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -59,7 +59,10 @@ public: return this->HomeRelativeOutputPath; } - std::string BuildCommandLine(const std::vector<std::string>& cmdLines); + std::string BuildCommandLine( + std::vector<std::string> const& cmdLines, + std::string const& customStep = std::string(), + cmGeneratorTarget const* target = nullptr) const; void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs); void AppendTargetDepends( @@ -98,6 +101,10 @@ private: std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); + std::string WriteCommandScript(std::vector<std::string> const& cmdLines, + std::string const& customStep, + cmGeneratorTarget const* target) const; + std::string HomeRelativeOutputPath; typedef std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*>> diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index b468208..82c6e81 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3641,6 +3641,20 @@ void cmMakefile::AppendProperty(const std::string& prop, const char* value, const char* cmMakefile::GetProperty(const std::string& prop) const { + // Check for computed properties. + static std::string output; + if (prop == "TESTS") { + std::vector<std::string> keys; + // get list of keys + std::transform(this->Tests.begin(), this->Tests.end(), + std::back_inserter(keys), + [](decltype(this->Tests)::value_type const& pair) { + return pair.first; + }); + output = cmJoin(keys, ";"); + return output.c_str(); + } + return this->StateSnapshot.GetDirectory().GetProperty(prop); } diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index ddbc772..f1fb2d2 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -976,8 +976,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() preLinkCmdLines.push_back("cd " + homeOutDir); } - vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines); - std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines); + vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link", + this->GeneratorTarget); + std::string postBuildCmdLine = localGen.BuildCommandLine( + postBuildCmdLines, "post-build", this->GeneratorTarget); cmNinjaVars symlinkVars; bool const symlinkNeeded = diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 7adeb8e..cc6d4b9 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -96,8 +96,8 @@ void cmNinjaUtilityTargetGenerator::Generate() this->GetBuildFileStream(), "Utility command for " + this->GetTargetName(), outputs, deps); } else { - std::string command = - this->GetLocalGenerator()->BuildCommandLine(commands); + std::string command = this->GetLocalGenerator()->BuildCommandLine( + commands, "utility", this->GeneratorTarget); const char* echoStr = this->GetGeneratorTarget()->GetProperty("EchoString"); std::string desc; diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 41142e5..93c78b5 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -8,6 +8,7 @@ #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmFilePathChecksum.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" @@ -22,7 +23,6 @@ #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cm_sys_stat.h" #include "cmake.h" #include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" @@ -867,34 +867,6 @@ void cmQtAutoGenInitializer::SetupCustomTargets() dir += cfg; } - auto OpenInfoFile = [](cmsys::ofstream& ofs, - std::string const& fileName) -> bool { - // Ensure we have write permission - if (cmSystemTools::FileExists(fileName)) { - mode_t perm = 0; -#if defined(_WIN32) && !defined(__CYGWIN__) - mode_t mode_write = S_IWRITE; -#else - mode_t mode_write = S_IWUSR; -#endif - cmSystemTools::GetPermissions(fileName, perm); - if (!(perm & mode_write)) { - cmSystemTools::SetPermissions(fileName, perm | mode_write); - } - } - - ofs.open(fileName.c_str(), - (std::ios::out | std::ios::binary | std::ios::trunc)); - if (!ofs) { - // File open error - std::string error = "Internal CMake error when trying to open file: "; - error += Quoted(fileName); - error += " for writing."; - cmSystemTools::Error(error.c_str()); - } - return static_cast<bool>(ofs); - }; - // Generate autogen target info file if (this->MocEnabled || this->UicEnabled) { if (this->MocEnabled) { @@ -911,8 +883,10 @@ void cmQtAutoGenInitializer::SetupCustomTargets() this->Parallel = std::to_string(GetParallelCPUCount()); } - cmsys::ofstream ofs; - if (OpenInfoFile(ofs, this->AutogenInfoFile)) { + cmGeneratedFileStream ofs; + ofs.SetCopyIfDifferent(true); + ofs.Open(this->AutogenInfoFile.c_str(), false, true); + if (ofs) { // Utility lambdas auto CWrite = [&ofs](const char* key, std::string const& value) { ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) @@ -1012,14 +986,18 @@ void cmQtAutoGenInitializer::SetupCustomTargets() CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->UicFileOptions); CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths); } + } else { + return; } } // Generate auto RCC info files if (this->RccEnabled) { for (Qrc const& qrc : this->Qrcs) { - cmsys::ofstream ofs; - if (OpenInfoFile(ofs, qrc.InfoFile)) { + cmGeneratedFileStream ofs; + ofs.SetCopyIfDifferent(true); + ofs.Open(qrc.InfoFile.c_str(), false, true); + if (ofs) { // Utility lambdas auto CWrite = [&ofs](const char* key, std::string const& value) { ofs << "set(" << key << " " @@ -1069,7 +1047,7 @@ void cmQtAutoGenInitializer::SetupCustomTargets() CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); } else { - break; + return; } } } diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index 6be65ee..37cf0f8 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -434,7 +434,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, JobHandleT jobHandle(new JobMocT(std::move(jobPre.SourceFile), FileName, std::move(jobPre.IncludeString))); if (jobPre.self) { - // Read depdendencies from this source + // Read dependencies from this source static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content); } if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) { @@ -452,7 +452,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(WorkerT& wrk, if (!macroName.empty()) { JobHandleT jobHandle( new JobMocT(std::string(FileName), std::string(), std::string())); - // Read depdendencies from this source + // Read dependencies from this source static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content); success = wrk.Gen().ParallelJobPushMoc(jobHandle); } @@ -1373,7 +1373,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) // Compare list sizes if (sources.size() != options.size()) { std::ostringstream ost; - ost << "files/options lists sizes missmatch (" << sources.size() << "/" + ost << "files/options lists sizes mismatch (" << sources.size() << "/" << options.size() << ")"; Log().ErrorFile(GeneratorT::UIC, InfoFile(), ost.str()); return false; diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index 7b19210..a7d8cee 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -24,7 +24,7 @@ public: this->TargetImpLib = targetImpLib; } - // Create a struct to hold the varibles passed into + // Create a struct to hold the variables passed into // ExpandRuleVariables struct RuleVariables { diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 55af078..9631912 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -68,6 +68,9 @@ bool cmStringCommand::InitialPass(std::vector<std::string> const& args, if (subCommand == "CONCAT") { return this->HandleConcatCommand(args); } + if (subCommand == "JOIN") { + return this->HandleJoinCommand(args); + } if (subCommand == "SUBSTRING") { return this->HandleSubstringCommand(args); } @@ -677,8 +680,26 @@ bool cmStringCommand::HandleConcatCommand(std::vector<std::string> const& args) return false; } - std::string const& variableName = args[1]; - std::string value = cmJoin(cmMakeRange(args).advance(2), std::string()); + return this->joinImpl(args, std::string(), 1); +} + +bool cmStringCommand::HandleJoinCommand(std::vector<std::string> const& args) +{ + if (args.size() < 3) { + this->SetError("sub-command JOIN requires at least two arguments."); + return false; + } + + return this->joinImpl(args, args[1], 2); +} + +bool cmStringCommand::joinImpl(std::vector<std::string> const& args, + std::string const& glue, const size_t varIdx) +{ + std::string const& variableName = args[varIdx]; + // NOTE Items to concat/join placed right after the variable for + // both `CONCAT` and `JOIN` sub-commands. + std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue); this->Makefile->AddDefinition(variableName, value.c_str()); return true; diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index b287e37..569ed83 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <string> #include <vector> @@ -48,6 +49,7 @@ protected: bool HandleAppendCommand(std::vector<std::string> const& args); bool HandlePrependCommand(std::vector<std::string> const& args); bool HandleConcatCommand(std::vector<std::string> const& args); + bool HandleJoinCommand(std::vector<std::string> const& args); bool HandleStripCommand(std::vector<std::string> const& args); bool HandleRandomCommand(std::vector<std::string> const& args); bool HandleFindCommand(std::vector<std::string> const& args); @@ -56,6 +58,9 @@ protected: bool HandleGenexStripCommand(std::vector<std::string> const& args); bool HandleUuidCommand(std::vector<std::string> const& args); + bool joinImpl(std::vector<std::string> const& args, std::string const& glue, + size_t varIdx); + class RegexReplacement { public: diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index cd11c4b..734ac93 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -509,7 +509,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) { std::string src = s; - // For backwards compatibility replace varibles in source names. + // For backwards compatibility replace variables in source names. // This should eventually be removed. this->Makefile->ExpandVariablesInString(src); if (src != s) { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ec31bd6..92d67db 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -84,16 +84,15 @@ static std::string computeProjectFileExtension(cmGeneratorTarget const* t, cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg) + : GeneratorTarget(target) + , Makefile(target->Target->GetMakefile()) + , Platform(gg->GetPlatformName()) + , Name(target->GetName()) + , GUID(gg->GetGUID(this->Name)) + , GlobalGenerator(gg) + , LocalGenerator((cmLocalVisualStudio7Generator*)target->GetLocalGenerator()) { - this->GlobalGenerator = gg; - this->GeneratorTarget = target; - this->Makefile = target->Target->GetMakefile(); this->Makefile->GetConfigurations(this->Configurations); - this->LocalGenerator = - (cmLocalVisualStudio7Generator*)this->GeneratorTarget->GetLocalGenerator(); - this->Name = this->GeneratorTarget->GetName(); - this->GUID = this->GlobalGenerator->GetGUID(this->Name); - this->Platform = gg->GetPlatformName(); this->NsightTegra = gg->IsNsightTegra(); for (int i = 0; i < 4; ++i) { this->NsightTegraVersion[i] = 0; @@ -602,8 +601,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences() if (!name.empty()) { std::string path = i.second.GetValue(); if (!cmsys::SystemTools::FileIsFullPath(path)) { - path = std::string(this->GeneratorTarget->Target->GetMakefile() - ->GetCurrentSourceDirectory()) + + path = std::string(this->Makefile->GetCurrentSourceDirectory()) + "/" + path; } ConvertToWindowsSlash(path); @@ -994,11 +992,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( std::string const& config) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); - const char* mfcFlag = - this->GeneratorTarget->Target->GetMakefile()->GetDefinition( - "CMAKE_MFC_FLAG"); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; + const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); if (mfcFlag) { std::string const mfcFlagValue = mfcFlag; @@ -1046,8 +1041,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( std::string const& config) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; Options& o = *(this->ClOptions[config]); @@ -1100,8 +1094,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues( std::string const&) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; const char* toolset = gg->GetPlatformToolset(); std::string ntv = "<NdkToolchainVersion>"; ntv += toolset ? toolset : "Default"; @@ -1226,7 +1219,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( for (std::vector<std::string>::const_iterator i = this->Configurations.begin(); i != this->Configurations.end(); ++i) { - cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator); + cmCustomCommandGenerator ccg(command, *i, lg); std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg)); @@ -1236,7 +1229,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin(); d != ccg.GetDepends().end(); ++d) { std::string dep; - if (this->LocalGenerator->GetRealDependency(*d, *i, dep)) { + if (lg->GetRealDependency(*d, *i, dep)) { ConvertToWindowsSlash(dep); inputs << ";" << cmVS10EscapeXML(dep); } @@ -1334,6 +1327,7 @@ static void ConvertToWindowsSlash(std::string& s) pos++; } } + void cmVisualStudio10TargetGenerator::WriteGroups() { if (this->ProjectType == csproj) { @@ -2110,8 +2104,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( (*this->BuildFileStream) << firstString; firstString = ""; // only do firstString once hasFlags = true; - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; cmIDEFlagTable const* flagtable = nullptr; const std::string& srclang = source->GetLanguage(); if (srclang == "C" || srclang == "CXX") { @@ -2374,8 +2367,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( // copied from cmLocalVisualStudio7Generator.cxx 805 // TODO: Integrate code below with cmLocalVisualStudio7Generator. - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; std::unique_ptr<Options> pOptions; switch (this->ProjectType) { case vcxproj: @@ -2422,15 +2414,11 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( std::string baseFlagVar = "CMAKE_"; baseFlagVar += langForClCompile; baseFlagVar += "_FLAGS"; - flags = - this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition( - baseFlagVar); + flags = this->Makefile->GetRequiredDefinition(baseFlagVar); std::string flagVar = baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName); flags += " "; - flags += - this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition( - flagVar); + flags += this->Makefile->GetRequiredDefinition(flagVar); this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, langForClCompile, configName); } @@ -2446,8 +2434,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName); // Get preprocessor definitions for this directory. - std::string defineFlags = - this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags(); + std::string defineFlags = this->Makefile->GetDefineFlags(); if (this->MSTools) { if (this->ProjectType == vcxproj) { clOptions.FixExceptionHandlingDefault(); @@ -2605,8 +2592,7 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions() bool cmVisualStudio10TargetGenerator::ComputeRcOptions( std::string const& configName) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; auto pOptions = cm::make_unique<Options>( this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable()); Options& rcOptions = *pOptions; @@ -2666,8 +2652,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions() bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( std::string const& configName) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; auto pOptions = cm::make_unique<Options>( this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable()); Options& cudaOptions = *pOptions; @@ -2683,8 +2668,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( configName); // Get preprocessor definitions for this directory. - std::string defineFlags = - this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags(); + std::string defineFlags = this->Makefile->GetDefineFlags(); cudaOptions.Parse(flags.c_str()); cudaOptions.Parse(defineFlags.c_str()); @@ -2804,8 +2788,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions() bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( std::string const& configName) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; auto pOptions = cm::make_unique<Options>( this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable()); Options& cudaLinkOptions = *pOptions; @@ -2873,8 +2856,7 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions() bool cmVisualStudio10TargetGenerator::ComputeMasmOptions( std::string const& configName) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; auto pOptions = cm::make_unique<Options>( this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable()); Options& masmOptions = *pOptions; @@ -2933,8 +2915,7 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions() bool cmVisualStudio10TargetGenerator::ComputeNasmOptions( std::string const& configName) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; auto pOptions = cm::make_unique<Options>( this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable()); Options& nasmOptions = *pOptions; @@ -2994,8 +2975,7 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget); if (!libflags.empty()) { this->WriteString("<Lib>\n", 2); - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; cmVisualStudioGeneratorOptions libOptions( this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker, gg->GetLibFlagTable(), 0, this); @@ -3185,8 +3165,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions() bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( std::string const& config) { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; auto pOptions = cm::make_unique<Options>(this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), nullptr, this); @@ -3217,12 +3196,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( linkFlagVarBase += linkType; linkFlagVarBase += "_LINKER_FLAGS"; flags += " "; - flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition( - linkFlagVarBase); + flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase); std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG; flags += " "; - flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition( - linkFlagVar); + flags += this->Makefile->GetRequiredDefinition(linkFlagVar); const char* targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { @@ -3679,8 +3656,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() } // skip fortran targets as they can not be processed by MSBuild // the only reference will be in the .sln file - if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator) - ->TargetIsFortranOnly(dt)) { + if (this->GlobalGenerator->TargetIsFortranOnly(dt)) { continue; } this->WriteString("<ProjectReference Include=\"", 2); @@ -3706,8 +3682,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() (*this->BuildFileStream) << name << "</Name>\n"; this->WriteDotNetReferenceCustomTags(name); if (csproj == this->ProjectType) { - if (!static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator) - ->TargetCanBeReferenced(dt)) { + if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) { this->WriteString( "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3); } @@ -3921,8 +3896,7 @@ bool cmVisualStudio10TargetGenerator::IsXamlSource( void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; bool isAppContainer = false; bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone(); bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore(); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 33d4fb7..adef127 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -190,19 +190,19 @@ private: bool InSourceBuild; std::vector<std::string> Configurations; std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec; - cmGeneratorTarget* GeneratorTarget; - cmMakefile* Makefile; - std::string Platform; - std::string GUID; - std::string Name; + cmGeneratorTarget* const GeneratorTarget; + cmMakefile* const Makefile; + std::string const Platform; + std::string const Name; + std::string const GUID; bool MSTools; bool Managed; bool NsightTegra; int NsightTegraVersion[4]; bool TargetCompileAsWinRT; - cmGlobalVisualStudio10Generator* GlobalGenerator; + cmGlobalVisualStudio10Generator* const GlobalGenerator; cmGeneratedFileStream* BuildFileStream; - cmLocalVisualStudio7Generator* LocalGenerator; + cmLocalVisualStudio7Generator* const LocalGenerator; std::set<cmSourceFile const*> SourcesVisited; std::set<std::string> CSharpCustomCommandNames; bool IsMissingFiles; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 0988c3c..e7d92d4 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -689,8 +689,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // Touch file if (args[1] == "touch_nocreate" && args.size() > 2) { for (std::string::size_type cc = 2; cc < args.size(); cc++) { - // Complain if the file could not be removed, still exists, - // and the -f option was not given. if (!cmSystemTools::Touch(args[cc], false)) { return 1; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 08bfebe..62157bb 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -816,6 +816,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release ADD_TEST_MACRO(CustomCommandByproducts CustomCommandByproducts) + ADD_TEST_MACRO(CommandLength CommandLength) + ADD_TEST_MACRO(EmptyDepends ${CMAKE_CTEST_COMMAND}) add_test(CustomCommandWorkingDirectory ${CMAKE_CTEST_COMMAND} diff --git a/Tests/CTestTest/test.cmake.in b/Tests/CTestTest/test.cmake.in index 589bd44..23166a7 100644 --- a/Tests/CTestTest/test.cmake.in +++ b/Tests/CTestTest/test.cmake.in @@ -62,7 +62,7 @@ COVERAGE_COMMAND:FILEPATH=@COVERAGE_COMMAND@ set (CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@/Tests/CTestTest") -# set any extra environment varibles here +# set any extra environment variables here set (CTEST_ENVIRONMENT ) diff --git a/Tests/CommandLength/CMakeLists.txt b/Tests/CommandLength/CMakeLists.txt new file mode 100644 index 0000000..6836051 --- /dev/null +++ b/Tests/CommandLength/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.10) +project(CommandLength C) + +add_executable(CommandLength test.c) +add_custom_command(TARGET CommandLength POST_BUILD VERBATIM + COMMAND ${CMAKE_COMMAND} -E make_directory log) + +set(msg "xxxx $$$$ yyyy") +set(msg "${msg} ${msg}") +set(msg "${msg} ${msg}") +set(msg "${msg} ${msg}") +set(msg "${msg} ${msg}") +foreach(i RANGE 1 1000) + add_custom_command(TARGET CommandLength POST_BUILD VERBATIM + COMMAND ${CMAKE_COMMAND} -E echo "${i} ${msg}" > log/${i} + ) +endforeach() diff --git a/Tests/CommandLength/test.c b/Tests/CommandLength/test.c new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/CommandLength/test.c @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/Complex/Cache/CMakeCache.txt b/Tests/Complex/Cache/CMakeCache.txt index 17c55aa..727faa2 100644 --- a/Tests/Complex/Cache/CMakeCache.txt +++ b/Tests/Complex/Cache/CMakeCache.txt @@ -5,7 +5,7 @@ # If you do want to change a value, simply edit, save, and exit the editor. # The syntax for the file is as follows: # KEY:TYPE=VALUE -# KEY is the name of a varible in the cache. +# KEY is the name of a variable in the cache. # TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!. # VALUE is the current value for the KEY. diff --git a/Tests/ComplexOneConfig/Cache/CMakeCache.txt b/Tests/ComplexOneConfig/Cache/CMakeCache.txt index 17c55aa..727faa2 100644 --- a/Tests/ComplexOneConfig/Cache/CMakeCache.txt +++ b/Tests/ComplexOneConfig/Cache/CMakeCache.txt @@ -5,7 +5,7 @@ # If you do want to change a value, simply edit, save, and exit the editor. # The syntax for the file is as follows: # KEY:TYPE=VALUE -# KEY is the name of a varible in the cache. +# KEY is the name of a variable in the cache. # TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!. # VALUE is the current value for the KEY. diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index 19d12e5..3d08704 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -57,6 +57,11 @@ add_custom_target(check-part1 ALL -Dtest_strequal_angle_r_comma=$<STREQUAL:$<ANGLE-R>,$<COMMA>> -Dtest_strequal_both_empty=$<STREQUAL:,> -Dtest_strequal_one_empty=$<STREQUAL:something,> + -Dtest_inlist_true=$<IN_LIST:a,a$<SEMICOLON>b> + -Dtest_inlist_false=$<IN_LIST:c,a$<SEMICOLON>b> + -Dtest_inlist_empty_1=$<IN_LIST:a,> + -Dtest_inlist_empty_2=$<IN_LIST:,a> + -Dtest_inlist_empty_3=$<IN_LIST:,> -Dtest_angle_r=$<ANGLE-R> -Dtest_comma=$<COMMA> -Dtest_semicolon=$<SEMICOLON> diff --git a/Tests/GeneratorExpression/check-part1.cmake b/Tests/GeneratorExpression/check-part1.cmake index 60b193f..41bcd6d 100644 --- a/Tests/GeneratorExpression/check-part1.cmake +++ b/Tests/GeneratorExpression/check-part1.cmake @@ -49,6 +49,11 @@ check(test_strequal_semicolon "1") check(test_strequal_angle_r_comma "0") check(test_strequal_both_empty "1") check(test_strequal_one_empty "0") +check(test_inlist_true "1") +check(test_inlist_false "0") +check(test_inlist_empty_1 "0") +check(test_inlist_empty_2 "0") +check(test_inlist_empty_3 "0") check(test_angle_r ">") check(test_comma ",") check(test_semicolon ";") diff --git a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt index 2e6a5bd..f9c52b7 100644 --- a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt +++ b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt @@ -45,8 +45,7 @@ file(TIMESTAMP "${rccDepBinGen}" rdGenBefore "${timeformat}") # - Change a resource files listed in the .qrc file # - Rebuild execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resPlain/input.txt") -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resGen/input.txt") +file(TOUCH "${rccDepBD}/resPlain/input.txt" "${rccDepBD}/resGen/input.txt") execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result) if (result) message(SEND_ERROR "Second build of rccDepends failed.") @@ -97,8 +96,7 @@ file(TIMESTAMP "${rccDepBinGen}" rdGenBefore "${timeformat}") # - Change a newly added resource files listed in the .qrc file # - Rebuild execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resPlain/inputAdded.txt") -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resGen/inputAdded.txt") +file(TOUCH "${rccDepBD}/resPlain/inputAdded.txt" "${rccDepBD}/resGen/inputAdded.txt") execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result) if (result) message(SEND_ERROR "Fourth build of rccDepends failed.") diff --git a/Tests/RunCMake/AndroidMK/AndroidMK.cmake b/Tests/RunCMake/AndroidMK/AndroidMK.cmake index 2596e8c..3fbb2cf 100644 --- a/Tests/RunCMake/AndroidMK/AndroidMK.cmake +++ b/Tests/RunCMake/AndroidMK/AndroidMK.cmake @@ -4,7 +4,7 @@ add_library(foo foo.cxx) add_library(car foo.cxx) add_library(bar bar.c) add_library(dog foo.cxx) -target_link_libraries(foo car bar dog debug -lm) +target_link_libraries(foo PRIVATE car bar dog debug -lm) export(TARGETS bar dog car foo ANDROID_MK ${build_BINARY_DIR}/Android.mk) install(TARGETS bar dog car foo DESTINATION lib EXPORT myexp) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index d5bd297..31069fa 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -358,6 +358,11 @@ if(CMake_TEST_FindMatlab) add_RunCMake_test(FindMatlab) endif() +# UseSWIG related tests +if(CMake_TEST_UseSWIG) + add_RunCMake_test(UseSWIG) +endif() + add_executable(pseudo_emulator pseudo_emulator.c) add_executable(pseudo_emulator_custom_command pseudo_emulator_custom_command.c) add_RunCMake_test(CrosscompilingEmulator diff --git a/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake b/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake new file mode 100644 index 0000000..94d8dd3 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake @@ -0,0 +1,68 @@ + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +unset(SWIG_LANG_TYPE) +unset(SWIG_LANG_INCLUDE_DIRECTORIES) +unset(SWIG_LANG_DEFINITIONS) +unset(SWIG_LANG_OPTIONS) +unset(SWIG_LANG_LIBRARIES) + +if(${language} MATCHES python) + find_package(PythonInterp REQUIRED) + find_package(PythonLibs REQUIRED) + set(SWIG_LANG_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES}) +endif() +if(${language} MATCHES perl) + find_package(Perl REQUIRED) + find_package(PerlLibs REQUIRED) + set(SWIG_LANG_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH}) + separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}") + set(SWIG_LANG_OPTIONS ${c_flags}) + set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY}) +endif() +if(${language} MATCHES tcl) + find_package(TCL REQUIRED) + set(SWIG_LANG_INCLUDE_DIRECTORIES ${TCL_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY}) +endif() +if(${language} MATCHES ruby) + find_package(Ruby REQUIRED) + set(SWIG_LANG_INCLUDE_DIRECTORIES ${RUBY_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY}) +endif() +if(${language} MATCHES php4) + find_package(PHP4 REQUIRED) + set(SWIG_LANG_INCLUDE_DIRECTORIES ${PHP4_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY}) +endif() +if(${language} MATCHES pike) + find_package(Pike REQUIRED) + set(SWIG_LANG_INCLUDE_DIRECTORIES ${PIKE_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY}) +endif() +if(${language} MATCHES lua) + find_package(Lua REQUIRED) + set(SWIG_LANG_INCLUDE_DIRECTORIES ${LUA_INCLUDE_DIR}) + set(SWIG_LANG_TYPE TYPE SHARED) + set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES}) +endif() + +unset(CMAKE_SWIG_FLAGS) + +set (CMAKE_INCLUDE_CURRENT_DIR ON) + +set_property(SOURCE example.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE example.i PROPERTY COMPILE_OPTIONS -includeall) + +set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${SWIG_LANG_INCLUDE_DIRECTORIES}) +set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_DEFINITIONS ${SWIG_LANG_DEFINITIONS}) +set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_OPTIONS ${SWIG_LANG_OPTIONS}) + + +SWIG_ADD_LIBRARY(example + LANGUAGE "${language}" + ${SWIG_LANG_TYPE} + SOURCES example.i example.cxx) +TARGET_LINK_LIBRARIES(example PRIVATE ${SWIG_LANG_LIBRARIES}) diff --git a/Tests/RunCMake/UseSWIG/BasicPerl.cmake b/Tests/RunCMake/UseSWIG/BasicPerl.cmake new file mode 100644 index 0000000..67ad6bc --- /dev/null +++ b/Tests/RunCMake/UseSWIG/BasicPerl.cmake @@ -0,0 +1,18 @@ + +set(language "perl") + +include (BasicConfiguration.cmake) + +if (WIN32) + file (TO_CMAKE_PATH "$ENV{PATH}" perl_path) + string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}") + set (perl_env "PATH=$<TARGET_FILE_DIR:example>$<SEMICOLON>${perl_path}") +else() + set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:example>") +endif() + +add_custom_target (RunTest + COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" + "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:example>" + "${CMAKE_CURRENT_SOURCE_DIR}/runme.pl" + DEPENDS example) diff --git a/Tests/RunCMake/UseSWIG/BasicPython.cmake b/Tests/RunCMake/UseSWIG/BasicPython.cmake new file mode 100644 index 0000000..0d8c824 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/BasicPython.cmake @@ -0,0 +1,9 @@ + +set(language "python") + +include (BasicConfiguration.cmake) + +add_custom_target (RunTest + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:example>" + "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py" + DEPENDS example) diff --git a/Tests/RunCMake/UseSWIG/CMakeLists.txt b/Tests/RunCMake/UseSWIG/CMakeLists.txt new file mode 100644 index 0000000..f452db1 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/SwigTest/CMakeLists.txt b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake index 65f5c93..3ce0790 100644 --- a/Tests/SwigTest/CMakeLists.txt +++ b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake @@ -1,54 +1,55 @@ -set(language "python") -cmake_minimum_required (VERSION 2.6) - -project(example_${language}_class) +# Prevent deprecated warnings from new UseSWIG module +set (CMAKE_WARN_DEPRECATED FALSE) find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) unset(SWIG_LANG_TYPE) if(${language} MATCHES python) - find_package(PythonLibs) + find_package(PythonInterp REQUIRED) + find_package(PythonLibs REQUIRED) include_directories(${PYTHON_INCLUDE_PATH}) set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES}) endif() if(${language} MATCHES perl) - find_package(PerlLibs) + find_package(Perl REQUIRED) + find_package(PerlLibs REQUIRED) include_directories(${PERL_INCLUDE_PATH}) - add_definitions(${PERL_EXTRA_C_FLAGS}) + separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}") + add_compile_options(${c_flags}) set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY}) endif() if(${language} MATCHES tcl) - find_package(TCL) + find_package(TCL REQUIRED) include_directories(${TCL_INCLUDE_PATH}) set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY}) endif() if(${language} MATCHES ruby) - find_package(Ruby) + find_package(Ruby REQUIRED) include_directories(${RUBY_INCLUDE_PATH}) set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY}) endif() if(${language} MATCHES php4) - find_package(PHP4) + find_package(PHP4 REQUIRED) include_directories(${PHP4_INCLUDE_PATH}) set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY}) endif() if(${language} MATCHES pike) - find_package(Pike) + find_package(Pike REQUIRED) include_directories(${PIKE_INCLUDE_PATH}) set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY}) endif() if(${language} MATCHES lua) - find_package(Lua) + find_package(Lua REQUIRED) include_directories(${LUA_INCLUDE_DIR}) set(SWIG_LANG_TYPE TYPE SHARED) set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES}) endif() -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +unset(CMAKE_SWIG_FLAGS) -set(CMAKE_SWIG_FLAGS "") +include_directories(${CMAKE_CURRENT_LIST_DIR}) set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON) set_source_files_properties(example.i PROPERTIES SWIG_FLAGS "-includeall") diff --git a/Tests/RunCMake/UseSWIG/LegacyPerl.cmake b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake new file mode 100644 index 0000000..3428c46 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake @@ -0,0 +1,18 @@ + +set(language "perl") + +include (LegacyConfiguration.cmake) + +if (WIN32) + file (TO_CMAKE_PATH "$ENV{PATH}" perl_path) + string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}") + set (perl_env "PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>$<SEMICOLON>${perl_path}") +else() + set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>") +endif() + +add_custom_target (RunTest + COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" + "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>" + "${CMAKE_CURRENT_SOURCE_DIR}/runme.pl" + DEPENDS ${SWIG_MODULE_example_REAL_NAME}) diff --git a/Tests/RunCMake/UseSWIG/LegacyPython.cmake b/Tests/RunCMake/UseSWIG/LegacyPython.cmake new file mode 100644 index 0000000..8b47aa2 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/LegacyPython.cmake @@ -0,0 +1,9 @@ + +set(language "python") + +include (LegacyConfiguration.cmake) + +add_custom_target (RunTest + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>" + "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py" + DEPENDS ${SWIG_MODULE_example_REAL_NAME}) diff --git a/Tests/RunCMake/UseSWIG/MultipleModules.cmake b/Tests/RunCMake/UseSWIG/MultipleModules.cmake new file mode 100644 index 0000000..e3d579f --- /dev/null +++ b/Tests/RunCMake/UseSWIG/MultipleModules.cmake @@ -0,0 +1,30 @@ + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +find_package(PythonLibs REQUIRED) +find_package(PerlLibs REQUIRED) + +unset(CMAKE_SWIG_FLAGS) + +set (CMAKE_INCLUDE_CURRENT_DIR ON) + +set_property(SOURCE example.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE example.i PROPERTY COMPILE_OPTIONS -includeall) + +set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_PATH}) + +swig_add_library(example1 + LANGUAGE python + SOURCES example.i example.cxx) +target_link_libraries(example1 PRIVATE ${PYTHON_LIBRARIES}) + +# re-use sample interface file for another plugin +set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH}) +separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}") +set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_OPTIONS ${c_flags}) + +swig_add_library(example2 + LANGUAGE perl + SOURCES example.i example.cxx) +target_link_libraries(example2 PRIVATE ${PERL_LIBRARY}) diff --git a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake new file mode 100644 index 0000000..c63ff2e --- /dev/null +++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake @@ -0,0 +1,23 @@ +include(RunCMake) + +function(run_SWIG test) + cmake_parse_arguments(_SWIG_TEST "" "TARGET" "" ${ARGN}) + if (_SWIG_TEST_TARGET) + list (INSERT _SWIG_TEST_TARGET 0 --target) + endif() + + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(${test}) + run_cmake_command(${test}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} ${_SWIG_TEST_TARGET}) +endfunction() + +run_SWIG(LegacyPython TARGET RunTest) +run_SWIG(LegacyPerl TARGET RunTest) + +run_SWIG(BasicPython TARGET RunTest) +run_SWIG(BasicPerl TARGET RunTest) + +run_SWIG(MultipleModules) diff --git a/Tests/SwigTest/example.cxx b/Tests/RunCMake/UseSWIG/example.cxx index 961d6dd..961d6dd 100644 --- a/Tests/SwigTest/example.cxx +++ b/Tests/RunCMake/UseSWIG/example.cxx diff --git a/Tests/SwigTest/example.h b/Tests/RunCMake/UseSWIG/example.h index 366deb0..366deb0 100644 --- a/Tests/SwigTest/example.h +++ b/Tests/RunCMake/UseSWIG/example.h diff --git a/Tests/SwigTest/example.i b/Tests/RunCMake/UseSWIG/example.i index 75700b3..fbdf724 100644 --- a/Tests/SwigTest/example.i +++ b/Tests/RunCMake/UseSWIG/example.i @@ -7,4 +7,3 @@ /* Let's just grab the original header file here */ %include "example.h" - diff --git a/Tests/SwigTest/runme.php4 b/Tests/RunCMake/UseSWIG/runme.php4 index 653ced2..653ced2 100644 --- a/Tests/SwigTest/runme.php4 +++ b/Tests/RunCMake/UseSWIG/runme.php4 diff --git a/Tests/SwigTest/runme.pike b/Tests/RunCMake/UseSWIG/runme.pike index ec28dd7..ec28dd7 100755..100644 --- a/Tests/SwigTest/runme.pike +++ b/Tests/RunCMake/UseSWIG/runme.pike diff --git a/Tests/SwigTest/runme.pl b/Tests/RunCMake/UseSWIG/runme.pl index 5bfb3d8..965e063 100644 --- a/Tests/SwigTest/runme.pl +++ b/Tests/RunCMake/UseSWIG/runme.pl @@ -54,4 +54,3 @@ examplec::delete_Shape($s); print $examplec::Shape_nshapes," shapes remain\n"; print "Goodbye\n"; - diff --git a/Tests/RunCMake/UseSWIG/runme.py b/Tests/RunCMake/UseSWIG/runme.py new file mode 100644 index 0000000..af5e07d --- /dev/null +++ b/Tests/RunCMake/UseSWIG/runme.py @@ -0,0 +1,52 @@ +# file: runme.py + +# This file illustrates the shadow-class C++ interface generated +# by SWIG. + +from __future__ import print_function + +import example + +# ----- Object creation ----- + +print ("Creating some objects:") +c = example.Circle(10) +print (" Created circle", c) +s = example.Square(10) +print (" Created square", s) + +# ----- Access a static member ----- + +print ("\nA total of", example.cvar.Shape_nshapes,"shapes were created") + +# ----- Member data access ----- + +# Set the location of the object + +c.x = 20 +c.y = 30 + +s.x = -10 +s.y = 5 + +print ("\nHere is their current position:") +print (" Circle = (%f, %f)" % (c.x,c.y)) +print (" Square = (%f, %f)" % (s.x,s.y)) + +# ----- Call some methods ----- + +print ("\nHere are some properties of the shapes:") +for o in [c,s]: + print (" ", o) + print (" area = ", o.area()) + print (" perimeter = ", o.perimeter()) + +print ("\nGuess I'll clean up now") + +# Note: this invokes the virtual destructor +del c +del s + +s = 3 +print (example.cvar.Shape_nshapes,"shapes remain") +print ("Goodbye") diff --git a/Tests/SwigTest/runme.rb b/Tests/RunCMake/UseSWIG/runme.rb index de73bcd..de73bcd 100644 --- a/Tests/SwigTest/runme.rb +++ b/Tests/RunCMake/UseSWIG/runme.rb diff --git a/Tests/SwigTest/runme.tcl b/Tests/RunCMake/UseSWIG/runme.tcl index c7f4725..6055cf6 100644 --- a/Tests/SwigTest/runme.tcl +++ b/Tests/RunCMake/UseSWIG/runme.tcl @@ -47,4 +47,3 @@ rename s "" puts "$Shape_nshapes shapes remain" puts "Goodbye" - diff --git a/Tests/SwigTest/runme2.tcl b/Tests/RunCMake/UseSWIG/runme2.tcl index 88ec2f6..d0b5c21 100644 --- a/Tests/SwigTest/runme2.tcl +++ b/Tests/RunCMake/UseSWIG/runme2.tcl @@ -67,4 +67,3 @@ delete_Shape $s puts "$Shape_nshapes shapes remain" puts "Goodbye" - diff --git a/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake b/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake index 45766a0..96be54b 100644 --- a/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake +++ b/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake @@ -16,8 +16,7 @@ set(fileNames) foreach(e ${fileExtensions}) set(currentFile "${CMAKE_CURRENT_BINARY_DIR}/foo.${e}") list(APPEND fileNames ${currentFile}) - execute_process(COMMAND ${CMAKE_COMMAND} -E touch - "${currentFile}") + file(TOUCH "${currentFile}") string(TOUPPER ${e} eUC) set_source_files_properties("${currentFile}" PROPERTIES diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 3be4fb7..9a72333 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -5,6 +5,9 @@ run_cmake(DOWNLOAD-unused-argument) run_cmake(DOWNLOAD-httpheader-not-set) run_cmake(DOWNLOAD-netrc-bad) run_cmake(DOWNLOAD-pass-not-set) +run_cmake(TOUCH) +run_cmake(TOUCH-error-in-source-directory) +run_cmake(TOUCH-error-missing-directory) run_cmake(UPLOAD-unused-argument) run_cmake(UPLOAD-httpheader-not-set) run_cmake(UPLOAD-netrc-bad) diff --git a/Tests/RunCMake/file/TOUCH-error-in-source-directory-result.txt b/Tests/RunCMake/file/TOUCH-error-in-source-directory-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-error-in-source-directory-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/TOUCH-error-in-source-directory-stderr.txt b/Tests/RunCMake/file/TOUCH-error-in-source-directory-stderr.txt new file mode 100644 index 0000000..f899c75 --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-error-in-source-directory-stderr.txt @@ -0,0 +1 @@ +.*file attempted to touch a file: diff --git a/Tests/RunCMake/file/TOUCH-error-in-source-directory.cmake b/Tests/RunCMake/file/TOUCH-error-in-source-directory.cmake new file mode 100644 index 0000000..9aa7c56 --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-error-in-source-directory.cmake @@ -0,0 +1,2 @@ +set(CMAKE_DISABLE_SOURCE_CHANGES ON) +file(TOUCH "${CMAKE_CURRENT_SOURCE_DIR}/touch_test") diff --git a/Tests/RunCMake/file/TOUCH-error-missing-directory-result.txt b/Tests/RunCMake/file/TOUCH-error-missing-directory-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-error-missing-directory-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/TOUCH-error-missing-directory-stderr.txt b/Tests/RunCMake/file/TOUCH-error-missing-directory-stderr.txt new file mode 100644 index 0000000..f52e11a --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-error-missing-directory-stderr.txt @@ -0,0 +1 @@ +.*file problem touching file: diff --git a/Tests/RunCMake/file/TOUCH-error-missing-directory.cmake b/Tests/RunCMake/file/TOUCH-error-missing-directory.cmake new file mode 100644 index 0000000..0cfb8d9 --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-error-missing-directory.cmake @@ -0,0 +1 @@ +file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/missing/directory/file.to-touch") diff --git a/Tests/RunCMake/file/TOUCH-result.txt b/Tests/RunCMake/file/TOUCH-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/TOUCH-stderr.txt b/Tests/RunCMake/file/TOUCH-stderr.txt new file mode 100644 index 0000000..9f31676 --- /dev/null +++ b/Tests/RunCMake/file/TOUCH-stderr.txt @@ -0,0 +1,9 @@ +^CMake Error at TOUCH\.cmake:[0-9]+ \(file\): + file must be called with at least two arguments\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) ++ +CMake Error at TOUCH\.cmake:[0-9]+ \(file\): + file must be called with at least two arguments\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file/TOUCH.cmake b/Tests/RunCMake/file/TOUCH.cmake new file mode 100644 index 0000000..8931eb5 --- /dev/null +++ b/Tests/RunCMake/file/TOUCH.cmake @@ -0,0 +1,16 @@ +set(file "${CMAKE_CURRENT_BINARY_DIR}/file-to-touch") + +file(REMOVE "${file}") +file(TOUCH_NOCREATE "${file}") +if(EXISTS "${file}") + message(FATAL_ERROR "error: TOUCH_NOCREATE created a file!") +endif() + +file(TOUCH "${file}") +if(NOT EXISTS "${file}") + message(FATAL_ERROR "error: TOUCH did not create a file!") +endif() +file(REMOVE "${file}") + +file(TOUCH) +file(TOUCH_NOCREATE) diff --git a/Tests/RunCMake/get_property/directory_properties-stderr.txt b/Tests/RunCMake/get_property/directory_properties-stderr.txt index 6d5bcdb..89f5618 100644 --- a/Tests/RunCMake/get_property/directory_properties-stderr.txt +++ b/Tests/RunCMake/get_property/directory_properties-stderr.txt @@ -19,4 +19,12 @@ get_property: -->[^<;]*/Tests/RunCMake/get_property<-- get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<-- get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<-- get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<-- -get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--$ +get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<-- +get_directory_property: --><-- +get_property: --><-- +get_directory_property: -->test1;test2<-- +get_property: -->test1;test2<-- +get_directory_property: -->test1;test2;test3<-- +get_property: -->test1;test2;test3<-- +get_directory_property: -->Sub/test1;Sub/test2<-- +get_property: -->Sub/test1;Sub/test2<--$ diff --git a/Tests/RunCMake/get_property/directory_properties.cmake b/Tests/RunCMake/get_property/directory_properties.cmake index 4e68738..9b978fd 100644 --- a/Tests/RunCMake/get_property/directory_properties.cmake +++ b/Tests/RunCMake/get_property/directory_properties.cmake @@ -28,3 +28,12 @@ check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" BINARY_DIR) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SOURCE_DIR) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" BINARY_DIR) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" SOURCE_DIR) + +check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS) +add_test(NAME test1 COMMAND "${CMAKE_COMMAND}" -E echo "test1") +add_test(NAME test2 COMMAND "${CMAKE_COMMAND}" -E echo "test2") +check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS) +add_test(NAME test3 COMMAND "${CMAKE_COMMAND}" -E echo "test3") +check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS) + +check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" TESTS) diff --git a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt index 7318b97..95106ad 100644 --- a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt +++ b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt @@ -4,3 +4,6 @@ subdirs(sub2) add_custom_target(CustomSub) add_library(InterfaceSub INTERFACE) add_library(my::InterfaceSub ALIAS InterfaceSub) + +add_test(Sub/test1 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test1") +add_test(Sub/test2 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test2") diff --git a/Tests/RunCMake/string/Join.cmake b/Tests/RunCMake/string/Join.cmake new file mode 100644 index 0000000..081f1e4 --- /dev/null +++ b/Tests/RunCMake/string/Join.cmake @@ -0,0 +1,16 @@ +string(JOIN % out) +if(NOT out STREQUAL "") + message(FATAL_ERROR "\"string(JOIN % out)\" set out to \"${out}\"") +endif() +string(JOIN % out a) +if(NOT out STREQUAL "a") + message(FATAL_ERROR "\"string(JOIN % out a)\" set out to \"${out}\"") +endif() +string(JOIN % out a "b") +if(NOT out STREQUAL "a%b") + message(FATAL_ERROR "\"string(JOIN % out a \"b\")\" set out to \"${out}\"") +endif() +string(JOIN :: out a "b") +if(NOT out STREQUAL "a::b") + message(FATAL_ERROR "\"string(JOIN :: out a \"b\")\" set out to \"${out}\"") +endif() diff --git a/Tests/RunCMake/string/JoinNoArgs-result.txt b/Tests/RunCMake/string/JoinNoArgs-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/string/JoinNoArgs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/string/JoinNoArgs-stderr.txt b/Tests/RunCMake/string/JoinNoArgs-stderr.txt new file mode 100644 index 0000000..d9dcec3 --- /dev/null +++ b/Tests/RunCMake/string/JoinNoArgs-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at JoinNoArgs.cmake:1 \(string\): + string sub-command JOIN requires at least two arguments. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/string/JoinNoArgs.cmake b/Tests/RunCMake/string/JoinNoArgs.cmake new file mode 100644 index 0000000..35ba4d9 --- /dev/null +++ b/Tests/RunCMake/string/JoinNoArgs.cmake @@ -0,0 +1 @@ +string(JOIN) diff --git a/Tests/RunCMake/string/JoinNoVar-result.txt b/Tests/RunCMake/string/JoinNoVar-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/string/JoinNoVar-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/string/JoinNoVar-stderr.txt b/Tests/RunCMake/string/JoinNoVar-stderr.txt new file mode 100644 index 0000000..90701a9 --- /dev/null +++ b/Tests/RunCMake/string/JoinNoVar-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at JoinNoVar.cmake:1 \(string\): + string sub-command JOIN requires at least two arguments. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/string/JoinNoVar.cmake b/Tests/RunCMake/string/JoinNoVar.cmake new file mode 100644 index 0000000..35f7b92 --- /dev/null +++ b/Tests/RunCMake/string/JoinNoVar.cmake @@ -0,0 +1 @@ +string(JOIN ";") diff --git a/Tests/RunCMake/string/RunCMakeTest.cmake b/Tests/RunCMake/string/RunCMakeTest.cmake index 513d1e3..211337a 100644 --- a/Tests/RunCMake/string/RunCMakeTest.cmake +++ b/Tests/RunCMake/string/RunCMakeTest.cmake @@ -9,6 +9,10 @@ run_cmake(PrependNoArgs) run_cmake(Concat) run_cmake(ConcatNoArgs) +run_cmake(Join) +run_cmake(JoinNoArgs) +run_cmake(JoinNoVar) + run_cmake(Timestamp) run_cmake(TimestampEmpty) run_cmake(TimestampInvalid) diff --git a/Tests/SwigTest/runme.py b/Tests/SwigTest/runme.py deleted file mode 100644 index ed3909e..0000000 --- a/Tests/SwigTest/runme.py +++ /dev/null @@ -1,51 +0,0 @@ -# file: runme.py - -# This file illustrates the shadow-class C++ interface generated -# by SWIG. - -import example - -# ----- Object creation ----- - -print "Creating some objects:" -c = example.Circle(10) -print " Created circle", c -s = example.Square(10) -print " Created square", s - -# ----- Access a static member ----- - -print "\nA total of", example.cvar.Shape_nshapes,"shapes were created" - -# ----- Member data access ----- - -# Set the location of the object - -c.x = 20 -c.y = 30 - -s.x = -10 -s.y = 5 - -print "\nHere is their current position:" -print " Circle = (%f, %f)" % (c.x,c.y) -print " Square = (%f, %f)" % (s.x,s.y) - -# ----- Call some methods ----- - -print "\nHere are some properties of the shapes:" -for o in [c,s]: - print " ", o - print " area = ", o.area() - print " perimeter = ", o.perimeter() - -print "\nGuess I'll clean up now" - -# Note: this invokes the virtual destructor -del c -del s - -s = 3 -print example.cvar.Shape_nshapes,"shapes remain" -print "Goodbye" - diff --git a/Utilities/Release/upload_release.cmake b/Utilities/Release/upload_release.cmake index 3c83957..f627966 100644 --- a/Utilities/Release/upload_release.cmake +++ b/Utilities/Release/upload_release.cmake @@ -1,6 +1,6 @@ set(CTEST_RUN_CURRENT_SCRIPT 0) if(NOT VERSION) - set(VERSION 3.10) + set(VERSION 3.11) endif() if(NOT DEFINED PROJECT_PREFIX) set(PROJECT_PREFIX cmake-${VERSION}) |