diff options
82 files changed, 722 insertions, 188 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 69d6e9a..9279748 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -68,6 +68,9 @@ The options are: order-only dependencies to ensure the byproducts will be available before their dependents build. + The :ref:`Makefile Generators` will remove ``BYPRODUCTS`` and other + :prop_sf:`GENERATED` files during ``make clean``. + ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst index 2d5f5f0..56ab414 100644 --- a/Help/command/add_custom_target.rst +++ b/Help/command/add_custom_target.rst @@ -49,6 +49,9 @@ The options are: order-only dependencies to ensure the byproducts will be available before their dependents build. + The :ref:`Makefile Generators` will remove ``BYPRODUCTS`` and other + :prop_sf:`GENERATED` files during ``make clean``. + ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 5197bb6..e552377 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -286,6 +286,8 @@ Properties on Targets /prop_tgt/LINK_WHAT_YOU_USE /prop_tgt/LOCATION_CONFIG /prop_tgt/LOCATION + /prop_tgt/MACHO_COMPATIBILITY_VERSION + /prop_tgt/MACHO_CURRENT_VERSION /prop_tgt/MACOSX_BUNDLE_INFO_PLIST /prop_tgt/MACOSX_BUNDLE /prop_tgt/MACOSX_FRAMEWORK_INFO_PLIST @@ -304,8 +306,6 @@ Properties on Targets /prop_tgt/OBJCXX_STANDARD_REQUIRED /prop_tgt/OSX_ARCHITECTURES_CONFIG /prop_tgt/OSX_ARCHITECTURES - /prop_tgt/OSX_CURRENT_VERSION - /prop_tgt/OSX_COMPATIBILITY_VERSION /prop_tgt/OUTPUT_NAME_CONFIG /prop_tgt/OUTPUT_NAME /prop_tgt/PDB_NAME_CONFIG diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 44b1f2f..429cba4 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -356,6 +356,20 @@ Options in :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR`. This flag tells CMake to warn about other files as well. +``--profiling-output=<path>`` + Used in conjuction with ``--profiling-format`` to output to a given path. + +``--profiling-format=<file>`` + Enable the output of profiling data of CMake script in the given format. + + This can aid performance analysis of CMake scripts executed. Third party + applications should be used to process the output into human readable format. + + Currently supported values are: + ``google-trace`` Outputs in Google Trace Format, which can be parsed by the + about:tracing tab of Google Chrome or using a plugin for a tool like Trace + Compass. + .. _`Build Tool Mode`: Build a Project diff --git a/Help/prop_sf/GENERATED.rst b/Help/prop_sf/GENERATED.rst index d430ee2..48ff70c 100644 --- a/Help/prop_sf/GENERATED.rst +++ b/Help/prop_sf/GENERATED.rst @@ -4,16 +4,29 @@ GENERATED Is this source file generated as part of the build or CMake process. Tells the internal CMake engine that a source file is generated by an outside -process such as another build step, or the execution of CMake itself. This -information is then used to exempt the file from any existence or validity -checks. Generated files are created by the execution of commands such as -:command:`add_custom_command` and :command:`file(GENERATE)`. - -When a generated file created by an :command:`add_custom_command` command -is explicitly listed as a source file for any target in the same -directory scope (which usually means the same ``CMakeLists.txt`` file), -CMake will automatically create a dependency to make sure the file is -generated before building that target. +process such as another build step, or the execution of CMake itself. +This information is then used to exempt the file from any existence or +validity checks. + +Any file that is + +- created by the execution of commands such as + :command:`add_custom_command` and :command:`file(GENERATE)` +- listed as one of the ``BYPRODUCTS`` of an :command:`add_custom_command` + or :command:`add_custom_target` command, or +- created by a CMake ``AUTOGEN`` operation such as :prop_tgt:`AUTOMOC`, + :prop_tgt:`AUTORCC`, or :prop_tgt:`AUTOUIC` + +will be marked with the ``GENERATED`` property. + +When a generated file created as the ``OUTPUT`` of an +:command:`add_custom_command` command is explicitly listed as a source file +for any target in the same directory scope (which usually means the same +``CMakeLists.txt`` file), CMake will automatically create a dependency to +make sure the file is generated before building that target. + +The :ref:`Makefile Generators` will remove ``GENERATED`` files during +``make clean``. Generated sources may be hidden in some IDE tools, while in others they might be shown. For the special case of sources generated by CMake's :prop_tgt:`AUTOMOC` diff --git a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst index d5c5e14..92b52a3 100644 --- a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst +++ b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst @@ -33,4 +33,4 @@ If :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` depends on a file that is either :prop_sf:`SKIP_AUTOUIC`, :prop_sf:`SKIP_AUTOGEN` or :policy:`CMP0071` or - a file that isn't in the origin target's sources -it must added to :prop_tgt:`AUTOGEN_TARGET_DEPENDS`. +it must be added to :prop_tgt:`AUTOGEN_TARGET_DEPENDS`. diff --git a/Help/prop_tgt/MACHO_COMPATIBILITY_VERSION.rst b/Help/prop_tgt/MACHO_COMPATIBILITY_VERSION.rst new file mode 100644 index 0000000..f3fedba --- /dev/null +++ b/Help/prop_tgt/MACHO_COMPATIBILITY_VERSION.rst @@ -0,0 +1,14 @@ +MACHO_COMPATIBILITY_VERSION +--------------------------- + +What compatibility version number is this target for Mach-O binaries. + +For shared libraries on Mach-O systems (e.g. macOS, iOS) +the ``MACHO_COMPATIBILITY_VERSION`` property correspond to +``compatibility version`` and :prop_tgt:`MACHO_CURRENT_VERSION` to +``current version``. +See the :prop_tgt:`FRAMEWORK` target property for an example. + +Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` +command. If ``MACHO_COMPATIBILITY_VERSION`` is not set, the value of +the :prop_tgt:`SOVERSION` property will be used. diff --git a/Help/prop_tgt/MACHO_CURRENT_VERSION.rst b/Help/prop_tgt/MACHO_CURRENT_VERSION.rst new file mode 100644 index 0000000..4a1d3f0 --- /dev/null +++ b/Help/prop_tgt/MACHO_CURRENT_VERSION.rst @@ -0,0 +1,13 @@ +MACHO_CURRENT_VERSION +--------------------- + +What current version number is this target for Mach-O binaries. + +For shared libraries on Mach-O systems (e.g. macOS, iOS) +the :prop_tgt:`MACHO_COMPATIBILITY_VERSION` property correspond to +``compatibility version`` and ``MACHO_CURRENT_VERSION`` to ``current version``. +See the :prop_tgt:`FRAMEWORK` target property for an example. + +Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` +command. If ``MACHO_CURRENT_VERSION`` is not set, the value of +the :prop_tgt:`VERSION` property will be used. diff --git a/Help/prop_tgt/OSX_COMPATIBILITY_VERSION.rst b/Help/prop_tgt/OSX_COMPATIBILITY_VERSION.rst deleted file mode 100644 index 5432b9a7..0000000 --- a/Help/prop_tgt/OSX_COMPATIBILITY_VERSION.rst +++ /dev/null @@ -1,14 +0,0 @@ -OSX_COMPATIBILITY_VERSION -------------------------- - -What compatibility version number is this target for OSX. - -For shared libraries on Mach-O systems (e.g. macOS, iOS) -the ``OSX_COMPATIBILITY_VERSION`` property correspond to -``compatibility version`` and :prop_tgt:`OSX_CURRENT_VERSION` to -``current version``. -See the :prop_tgt:`FRAMEWORK` target property for an example. - -Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` -command. If ``OSX_COMPATIBILITY_VERSION`` is not set, the value of -the :prop_tgt:``SOVERSION`` property will be used. diff --git a/Help/prop_tgt/OSX_CURRENT_VERSION.rst b/Help/prop_tgt/OSX_CURRENT_VERSION.rst deleted file mode 100644 index 609924d..0000000 --- a/Help/prop_tgt/OSX_CURRENT_VERSION.rst +++ /dev/null @@ -1,13 +0,0 @@ -OSX_CURRENT_VERSION -------------------- - -What current version number is this target for OSX. - -For shared libraries on Mach-O systems (e.g. macOS, iOS) -the :prop_tgt:`OSX_COMPATIBILITY_VERSION` property correspond to -``compatibility version`` and ``OSX_CURRENT_VERSION`` to ``current version``. -See the :prop_tgt:`FRAMEWORK` target property for an example. - -Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` -command. If ``OSX_CURRENT_VERSION`` is not set, the value of -the :prop_tgt:``VERSION`` property will be used. diff --git a/Help/prop_tgt/SOVERSION.rst b/Help/prop_tgt/SOVERSION.rst index 1a66c8f..d6f8a94 100644 --- a/Help/prop_tgt/SOVERSION.rst +++ b/Help/prop_tgt/SOVERSION.rst @@ -22,8 +22,8 @@ Mach-O Versions For shared libraries and executables on Mach-O systems (e.g. macOS, iOS), the ``SOVERSION`` property is a fallback to -:prop_tgt:`OSX_COMPATIBILITY_VERSION` property which corresponds to +:prop_tgt:`MACHO_COMPATIBILITY_VERSION` property which corresponds to *compatiblity version* and :prop_tgt:`VERSION` is a fallback to -:prop_tgt:`OSX_CURRENT_VERSION` which corresponds to *current version*. +:prop_tgt:`MACHO_CURRENT_VERSION` which corresponds to *current version*. See the :prop_tgt:`FRAMEWORK` target property for an example. Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` command. diff --git a/Help/prop_tgt/VERSION.rst b/Help/prop_tgt/VERSION.rst index a24b613..f592f4a 100644 --- a/Help/prop_tgt/VERSION.rst +++ b/Help/prop_tgt/VERSION.rst @@ -23,9 +23,9 @@ Mach-O Versions ^^^^^^^^^^^^^^^ For shared libraries and executables on Mach-O systems (e.g. macOS, iOS), -the ``VERSION`` property is a fallback to :prop_tgt:`OSX_CURRENT_VERSION` +the ``VERSION`` property is a fallback to :prop_tgt:`MACHO_CURRENT_VERSION` property which corresponds to *current version* and :prop_tgt:`SOVERSION` -is a fallback to :prop_tgt:`OSX_COMPATIBILITY_VERSION` which corresponds +is a fallback to :prop_tgt:`MACHO_COMPATIBILITY_VERSION` which corresponds to *compatiblity version*. See the :prop_tgt:`FRAMEWORK` target property for an example. Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` command. diff --git a/Help/release/3.17.rst b/Help/release/3.17.rst index f2c4d85..c2cfdf0 100644 --- a/Help/release/3.17.rst +++ b/Help/release/3.17.rst @@ -143,10 +143,10 @@ Properties In particular, the ``$<INSTALL_PREFIX>`` generator expression can be used to set the directory relative to the install-time prefix. -* Target properties :prop_tgt:`OSX_COMPATIBILITY_VERSION` and - :prop_tgt:`OSX_CURRENT_VERSION` were added to set the - ``compatibility_version`` and ``curent_version`` respectively - on macOS. For backwards compatibility, if these properties +* Target properties :prop_tgt:`MACHO_COMPATIBILITY_VERSION` and + :prop_tgt:`MACHO_CURRENT_VERSION` were added to set the + ``compatibility_version`` and ``curent_version``, respectively, + for Mach-O binaries. For backwards compatibility, if these properties are not set, :prop_tgt:`SOVERSION` and :prop_tgt:`VERSION` are used respectively as fallbacks. diff --git a/Help/release/dev/profiling.rst b/Help/release/dev/profiling.rst new file mode 100644 index 0000000..ab180f0 --- /dev/null +++ b/Help/release/dev/profiling.rst @@ -0,0 +1,9 @@ +cmake-profiling +--------------- + +* Add support for profiling of CMake scripts through the parameters + ``--profiling-output`` and ``--profiling-format``. These options can + be used by users to gain insight into the performance of their scripts. + + The first supported output format is ``google-trace`` which is a format + supported by Google Chrome's ``about:tracing`` tab. diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 974f5fa..f31713e 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -138,24 +138,24 @@ endif() #Specify how to compile when ptx has been requested if(NOT CMAKE_CUDA_COMPILE_PTX_COMPILATION) set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -ptx <SOURCE> -o <OBJECT>") endif() #Specify how to compile when separable compilation has been requested if(NOT CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION) set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -dc <SOURCE> -o <OBJECT>") endif() #Specify how to compile when whole compilation has been requested if(NOT CMAKE_CUDA_COMPILE_WHOLE_COMPILATION) set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT>") endif() -if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_DEPFILE_FLAGS_CUDA ) +if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_DEPFILE_FLAGS_CUDA) set(CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -M <SOURCE> -MT <OBJECT> -o $DEP_FILE") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M <SOURCE> -MT <OBJECT> -o $DEP_FILE") #The Ninja generator uses the make file dependency files to determine what #files need to be recompiled. Unfortunately, nvcc < 10.2 doesn't support building #a source file and generating the dependencies of said file in a single diff --git a/Modules/CMakeFindFrameworks.cmake b/Modules/CMakeFindFrameworks.cmake index 06c05fb..8906f48 100644 --- a/Modules/CMakeFindFrameworks.cmake +++ b/Modules/CMakeFindFrameworks.cmake @@ -17,13 +17,25 @@ if(NOT CMAKE_FIND_FRAMEWORKS_INCLUDED) macro(CMAKE_FIND_FRAMEWORKS fwk) set(${fwk}_FRAMEWORKS) if(APPLE) - foreach(dir - ~/Library/Frameworks/${fwk}.framework - /usr/local/Frameworks/${fwk}.framework - /Library/Frameworks/${fwk}.framework - /System/Library/Frameworks/${fwk}.framework - /Network/Library/Frameworks/${fwk}.framework - ${CMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS}) + file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _cmff_CMAKE_FRAMEWORK_PATH) + set(_cmff_search_paths + ${CMAKE_FRAMEWORK_PATH} + ${_cmff_CMAKE_FRAMEWORK_PATH} + ~/Library/Frameworks + /usr/local/Frameworks + /Library/Frameworks + /System/Library/Frameworks + /Network/Library/Frameworks + ${CMAKE_SYSTEM_FRAMEWORK_PATH}) + + # For backwards compatibility reasons, + # CMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS includes ${fwk}.framework + list(TRANSFORM _cmff_search_paths APPEND /${fwk}.framework) + list(APPEND _cmff_search_paths ${CMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS}) + + list(REMOVE_DUPLICATES _cmff_search_paths) + + foreach(dir IN LISTS _cmff_search_paths) if(EXISTS ${dir}) set(${fwk}_FRAMEWORKS ${${fwk}_FRAMEWORKS} ${dir}) endif() diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake index ba242ec..8f0909c 100644 --- a/Modules/CMakeSwiftInformation.cmake +++ b/Modules/CMakeSwiftInformation.cmake @@ -27,12 +27,14 @@ elseif(NOT CMAKE_SYSTEM_NAME STREQUAL Windows) endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows) + set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG "-Xlinker -rpath -Xlinker ") set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG "-Xlinker -rpath -Xlinker ") - set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG_SEP ":") - - if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin) - set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG "-Xlinker -rpath -Xlinker ") + if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG_SEP "") + set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG_SEP "") + else() set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG_SEP ":") + set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG_SEP ":") endif() endif() diff --git a/Modules/Compiler/AppleClang-CXX.cmake b/Modules/Compiler/AppleClang-CXX.cmake index 3fa6990..15edc21 100644 --- a/Modules/Compiler/AppleClang-CXX.cmake +++ b/Modules/Compiler/AppleClang-CXX.cmake @@ -25,7 +25,10 @@ elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1) set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON) endif() -if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.1) +if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17") +elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.1) set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++1z") set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() diff --git a/Modules/Compiler/AppleClang-OBJCXX.cmake b/Modules/Compiler/AppleClang-OBJCXX.cmake index 2c084af..409bd4a 100644 --- a/Modules/Compiler/AppleClang-OBJCXX.cmake +++ b/Modules/Compiler/AppleClang-OBJCXX.cmake @@ -22,7 +22,10 @@ elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 5.1) set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON) endif() -if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1) +if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 10.0) + set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17") +elseif (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1) set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z") set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index 1f4d54d..2a2564e 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -4,6 +4,8 @@ set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True) set(CMAKE_CUDA_VERBOSE_FLAG "-v") set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") +set(_CMAKE_COMPILE_AS_CUDA_FLAG "-x cu") + if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) # The -forward-unknown-to-host-compiler flag was only # added to nvcc in 10.2 so before that we had no good diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index e903f2a..77b6562 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -95,8 +95,9 @@ endmacro() macro (_PYTHON_FIND_FRAMEWORKS) set (${_PYTHON_PREFIX}_FRAMEWORKS) if (CMAKE_HOST_APPLE OR APPLE) + file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _pff_CMAKE_FRAMEWORK_PATH) set (_pff_frameworks ${CMAKE_FRAMEWORK_PATH} - $ENV{CMAKE_FRAMEWORK_PATH} + ${_pff_CMAKE_FRAMEWORK_PATH} ~/Library/Frameworks /usr/local/Frameworks ${CMAKE_SYSTEM_FRAMEWORK_PATH}) diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake index 4f52ad2..73e55ea 100644 --- a/Modules/GoogleTestAddTests.cmake +++ b/Modules/GoogleTestAddTests.cmake @@ -13,11 +13,13 @@ set(tests) set(tests_buffer) # Overwrite possibly existing ${CTEST_FILE} with empty file -file(WRITE "${CTEST_FILE}" "") +set(flush_tests_MODE WRITE) # Flushes script to ${CTEST_FILE} macro(flush_script) - file(APPEND "${CTEST_FILE}" "${script}") + file(${flush_tests_MODE} "${CTEST_FILE}" "${script}") + set(flush_tests_MODE APPEND) + set(script "") endmacro() diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index af43f46..2f50280 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -1,11 +1,11 @@ include(Platform/Windows-MSVC) set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(__IMPLICT_LINKS ) foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) @@ -48,7 +48,7 @@ unset(__IMPLICT_DLINK_DIRS) set(CMAKE_CUDA_DEVICE_LINK_LIBRARY "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") unset(__IMPLICT_DLINK_FLAGS) string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 24370aa..467abe9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -354,6 +354,7 @@ set(SRCS cmMakefileTargetGenerator.cxx cmMakefileExecutableTargetGenerator.cxx cmMakefileLibraryTargetGenerator.cxx + cmMakefileProfilingData.cxx cmMakefileUtilityTargetGenerator.cxx cmMessageType.h cmMessenger.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ff03496..1b452f8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 17) -set(CMake_VERSION_PATCH 20200311) +set(CMake_VERSION_PATCH 20200313) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index 3ad4749..69c5793 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -55,7 +55,7 @@ size_t curlDebugCallback(CURL* /*unused*/, curl_infotype /*unused*/, char* chPtr, size_t size, void* data) { cm::append(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size); - return size; + return 0; } } diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 2192843..50c963d 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -12,13 +12,13 @@ #include <iomanip> #include <iostream> #include <list> -#include <memory> #include <sstream> #include <stack> #include <unordered_map> #include <utility> #include <vector> +#include <cm/memory> #include <cmext/algorithm> #include "cmsys/FStream.hxx" @@ -172,7 +172,8 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) this->EraseTest(test); this->RunningCount += GetProcessorsUsed(test); - cmCTestRunTest* testRun = new cmCTestRunTest(*this); + auto testRun = cm::make_unique<cmCTestRunTest>(*this); + if (this->RepeatMode != cmCTest::Repeat::Never) { testRun->SetRepeatMode(this->RepeatMode); testRun->SetNumberOfRuns(this->RepeatCount); @@ -229,28 +230,25 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) e << "\n"; } e << "Resource spec file:\n\n " << this->TestHandler->ResourceSpecFile; - testRun->StartFailure(e.str(), "Insufficient resources"); - this->FinishTestProcess(testRun, false); + cmCTestRunTest::StartFailure(std::move(testRun), e.str(), + "Insufficient resources"); return false; } cmWorkingDirectory workdir(this->Properties[test]->Directory); if (workdir.Failed()) { - testRun->StartFailure("Failed to change working directory to " + - this->Properties[test]->Directory + " : " + - std::strerror(workdir.GetLastResult()), - "Failed to change working directory"); - } else { - if (testRun->StartTest(this->Completed, this->Total)) { - // Ownership of 'testRun' has moved to another structure. - // When the test finishes, FinishTestProcess will be called. - return true; - } + cmCTestRunTest::StartFailure(std::move(testRun), + "Failed to change working directory to " + + this->Properties[test]->Directory + " : " + + std::strerror(workdir.GetLastResult()), + "Failed to change working directory"); + return false; } - // Pass ownership of 'testRun'. - this->FinishTestProcess(testRun, false); - return false; + // Ownership of 'testRun' has moved to another structure. + // When the test finishes, FinishTestProcess will be called. + return cmCTestRunTest::StartTest(std::move(testRun), this->Completed, + this->Total); } bool cmCTestMultiProcessHandler::AllocateResources(int index) @@ -540,7 +538,8 @@ void cmCTestMultiProcessHandler::StartNextTests() if (this->SerialTestRunning) { break; } - // We can only start a RUN_SERIAL test if no other tests are also running. + // We can only start a RUN_SERIAL test if no other tests are also + // running. if (this->Properties[test]->RunSerial && this->RunningCount > 0) { continue; } @@ -618,8 +617,8 @@ void cmCTestMultiProcessHandler::OnTestLoadRetryCB(uv_timer_t* timer) self->StartNextTests(); } -void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, - bool started) +void cmCTestMultiProcessHandler::FinishTestProcess( + std::unique_ptr<cmCTestRunTest> runner, bool started) { this->Completed++; @@ -631,7 +630,8 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, this->SetStopTimePassed(); } if (started) { - if (!this->StopTimePassed && runner->StartAgain(this->Completed)) { + if (!this->StopTimePassed && + cmCTestRunTest::StartAgain(std::move(runner), this->Completed)) { this->Completed--; // remove the completed test because run again return; } @@ -659,7 +659,7 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, } properties->Affinity.clear(); - delete runner; + runner.reset(); if (started) { this->StartNextTests(); } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 5b429d4..c3686bc 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -124,7 +125,7 @@ protected: // Removes the checkpoint file void MarkFinished(); void EraseTest(int index); - void FinishTestProcess(cmCTestRunTest* runner, bool started); + void FinishTestProcess(std::unique_ptr<cmCTestRunTest> runner, bool started); static void OnTestLoadRetryCB(uv_timer_t* timer); diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index ec54960..7d0f69b 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -314,23 +314,27 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) return passed || skipped; } -bool cmCTestRunTest::StartAgain(size_t completed) +bool cmCTestRunTest::StartAgain(std::unique_ptr<cmCTestRunTest> runner, + size_t completed) { - if (!this->RunAgain) { + auto* testRun = runner.get(); + + if (!testRun->RunAgain) { return false; } - this->RunAgain = false; // reset + testRun->RunAgain = false; // reset + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); // change to tests directory - cmWorkingDirectory workdir(this->TestProperties->Directory); + cmWorkingDirectory workdir(testRun->TestProperties->Directory); if (workdir.Failed()) { - this->StartFailure("Failed to change working directory to " + - this->TestProperties->Directory + " : " + - std::strerror(workdir.GetLastResult()), - "Failed to change working directory"); + testRun->StartFailure("Failed to change working directory to " + + testRun->TestProperties->Directory + " : " + + std::strerror(workdir.GetLastResult()), + "Failed to change working directory"); return true; } - this->StartTest(completed, this->TotalNumberOfTests); + testRun->StartTest(completed, testRun->TotalNumberOfTests); return true; } @@ -382,6 +386,18 @@ void cmCTestRunTest::MemCheckPostProcess() handler->PostProcessTest(this->TestResult, this->Index); } +void cmCTestRunTest::StartFailure(std::unique_ptr<cmCTestRunTest> runner, + std::string const& output, + std::string const& detail) +{ + auto* testRun = runner.get(); + + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); + testRun->StartFailure(output, detail); + + testRun->FinalizeTest(false); +} + void cmCTestRunTest::StartFailure(std::string const& output, std::string const& detail) { @@ -413,7 +429,6 @@ void cmCTestRunTest::StartFailure(std::string const& output, this->TestResult.Path = this->TestProperties->Directory; this->TestResult.Output = output; this->TestResult.FullCommandLine.clear(); - this->TestProcess = cm::make_unique<cmProcess>(*this); } std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const @@ -437,6 +452,21 @@ std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const return outputStream.str(); } +bool cmCTestRunTest::StartTest(std::unique_ptr<cmCTestRunTest> runner, + size_t completed, size_t total) +{ + auto* testRun = runner.get(); + + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); + + if (!testRun->StartTest(completed, total)) { + testRun->FinalizeTest(false); + return false; + } + + return true; +} + // Starts the execution of a test. Returns once it has started bool cmCTestRunTest::StartTest(size_t completed, size_t total) { @@ -468,7 +498,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) if (this->TestProperties->Disabled) { this->TestResult.CompletionStatus = "Disabled"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; - this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestResult.Output = "Disabled"; this->TestResult.FullCommandLine.clear(); return false; @@ -482,7 +511,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) // its arguments are irrelevant. This matters for the case where a fixture // dependency might be creating the executable we want to run. if (!this->FailedDependencies.empty()) { - this->TestProcess = cm::make_unique<cmProcess>(*this); std::string msg = "Failed test dependencies:"; for (std::string const& failedDep : this->FailedDependencies) { msg += " " + failedDep; @@ -499,7 +527,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) this->ComputeArguments(); std::vector<std::string>& args = this->TestProperties->Args; if (args.size() >= 2 && args[1] == "NOT_AVAILABLE") { - this->TestProcess = cm::make_unique<cmProcess>(*this); std::string msg; if (this->CTest->GetConfigType().empty()) { msg = "Test not available without configuration. (Missing \"-C " @@ -521,7 +548,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) for (std::string const& file : this->TestProperties->RequiredFiles) { if (!cmSystemTools::FileExists(file)) { // Required file was not found - this->TestProcess = cm::make_unique<cmProcess>(*this); *this->TestHandler->LogFile << "Unable to find required file: " << file << std::endl; cmCTestLog(this->CTest, ERROR_MESSAGE, @@ -537,7 +563,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) if (this->ActualCommand.empty()) { // if the command was not found create a TestResult object // that has that information - this->TestProcess = cm::make_unique<cmProcess>(*this); *this->TestHandler->LogFile << "Unable to find executable: " << args[1] << std::endl; cmCTestLog(this->CTest, ERROR_MESSAGE, @@ -649,7 +674,6 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, std::vector<std::string>* environment, std::vector<size_t>* affinity) { - this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestProcess->SetId(this->Index); this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory); this->TestProcess->SetCommand(this->ActualCommand); @@ -816,7 +840,8 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) "Testing " << this->TestProperties->Name << " ... "); } -void cmCTestRunTest::FinalizeTest() +void cmCTestRunTest::FinalizeTest(bool started) { - this->MultiTestHandler.FinishTestProcess(this, true); + this->MultiTestHandler.FinishTestProcess(this->TestProcess->GetRunner(), + started); } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 4988839..b1d188a 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -65,6 +65,15 @@ public: // Read and store output. Returns true if it must be called again. void CheckOutput(std::string const& line); + static bool StartTest(std::unique_ptr<cmCTestRunTest> runner, + size_t completed, size_t total); + static bool StartAgain(std::unique_ptr<cmCTestRunTest> runner, + size_t completed); + + static void StartFailure(std::unique_ptr<cmCTestRunTest> runner, + std::string const& output, + std::string const& detail); + // launch the test process, return whether it started correctly bool StartTest(size_t completed, size_t total); // capture and report the test results @@ -74,8 +83,6 @@ public: void ComputeWeightedCost(); - bool StartAgain(size_t completed); - void StartFailure(std::string const& output, std::string const& detail); cmCTest* GetCTest() const { return this->CTest; } @@ -84,7 +91,7 @@ public: const std::vector<std::string>& GetArguments() { return this->Arguments; } - void FinalizeTest(); + void FinalizeTest(bool started = true); bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; } diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index a8f201a..22ab48f 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -110,7 +110,7 @@ static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/, { cm::append(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, chPtr + size); - return size; + return 0; } cmCTestSubmitHandler::cmCTestSubmitHandler() diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index cdf899c..76ffb20 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -5,6 +5,7 @@ #include <csignal> #include <iostream> #include <string> +#include <utility> #include <cmext/algorithm> @@ -18,12 +19,11 @@ #if defined(_WIN32) # include "cm_kwiml.h" #endif -#include <utility> #define CM_PROCESS_BUF_SIZE 65536 -cmProcess::cmProcess(cmCTestRunTest& runner) - : Runner(runner) +cmProcess::cmProcess(std::unique_ptr<cmCTestRunTest> runner) + : Runner(std::move(runner)) , Conv(cmProcessOutput::UTF8, CM_PROCESS_BUF_SIZE) { this->Timeout = cmDuration::zero(); @@ -69,7 +69,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) cm::uv_timer_ptr timer; int status = timer.init(loop, this); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error initializing timer: " << uv_strerror(status) << std::endl); return false; @@ -84,7 +84,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) int fds[2] = { -1, -1 }; status = cmGetPipes(fds); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error initializing pipe: " << uv_strerror(status) << std::endl); return false; @@ -127,7 +127,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error starting read events: " << uv_strerror(status) << std::endl); return false; @@ -135,7 +135,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) status = this->Process.spawn(loop, options, this); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Process not started\n " << this->Command << "\n[" << uv_strerror(status) << "]\n"); return false; @@ -152,7 +152,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) void cmProcess::StartTimer() { - auto properties = this->Runner.GetTestProperties(); + auto properties = this->Runner->GetTestProperties(); auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(this->Timeout); @@ -222,7 +222,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) cm::append(this->Output, strdata); while (this->Output.GetLine(line)) { - this->Runner.CheckOutput(line); + this->Runner->CheckOutput(line); line.clear(); } @@ -236,20 +236,20 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) // The process will provide no more data. if (nread != UV_EOF) { auto error = static_cast<int>(nread); - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error reading stream: " << uv_strerror(error) << std::endl); } // Look for partial last lines. if (this->Output.GetLast(line)) { - this->Runner.CheckOutput(line); + this->Runner->CheckOutput(line); } this->ReadHandleClosed = true; this->PipeReader.reset(); if (this->ProcessHandleClosed) { uv_timer_stop(this->Timer); - this->Runner.FinalizeTest(); + this->Runner->FinalizeTest(); } } @@ -291,7 +291,7 @@ void cmProcess::OnTimeout() // Our on-exit handler already ran but did not finish the test // because we were still reading output. We've just dropped // our read handler, so we need to finish the test now. - this->Runner.FinalizeTest(); + this->Runner->FinalizeTest(); } } @@ -333,7 +333,7 @@ void cmProcess::OnExit(int64_t exit_status, int term_signal) this->ProcessHandleClosed = true; if (this->ReadHandleClosed) { uv_timer_stop(this->Timer); - this->Runner.FinalizeTest(); + this->Runner->FinalizeTest(); } } diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 2c24f2d..0f69f68 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -6,7 +6,9 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <chrono> +#include <memory> #include <string> +#include <utility> #include <vector> #include <stddef.h> @@ -28,7 +30,7 @@ class cmCTestRunTest; class cmProcess { public: - explicit cmProcess(cmCTestRunTest& runner); + explicit cmProcess(std::unique_ptr<cmCTestRunTest> runner); ~cmProcess(); void SetCommand(std::string const& command); void SetCommandArguments(std::vector<std::string> const& arg); @@ -70,6 +72,11 @@ public: Exception GetExitException(); std::string GetExitExceptionString(); + std::unique_ptr<cmCTestRunTest> GetRunner() + { + return std::move(this->Runner); + } + private: cmDuration Timeout; std::chrono::steady_clock::time_point StartTime; @@ -82,7 +89,7 @@ private: cm::uv_timer_ptr Timer; std::vector<char> Buf; - cmCTestRunTest& Runner; + std::unique_ptr<cmCTestRunTest> Runner; cmProcessOutput Conv; int Signal = 0; cmProcess::State ProcessState = cmProcess::State::Starting; diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 49c9439..b82fb9a 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -108,7 +108,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args, if (cacheValue) { return true; } - mf.AddCacheDefinition(define, makecommand.c_str(), + mf.AddCacheDefinition(define, makecommand, "Command used to build entire project " "from the command line.", cmStateEnums::STRING); diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 3e517dc..ad4d665 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -28,7 +28,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, std::replace(cv.begin(), cv.end(), '/', '_'); std::replace(cv.begin(), cv.end(), '(', '_'); std::replace(cv.begin(), cv.end(), ')', '_'); - mf.AddCacheDefinition(args[0], cv.c_str(), "Name of build.", + mf.AddCacheDefinition(args[0], cv, "Name of build.", cmStateEnums::STRING); } return true; @@ -54,7 +54,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, std::replace(buildname.begin(), buildname.end(), '(', '_'); std::replace(buildname.begin(), buildname.end(), ')', '_'); - mf.AddCacheDefinition(args[0], buildname.c_str(), "Name of build.", + mf.AddCacheDefinition(args[0], buildname, "Name of build.", cmStateEnums::STRING); return true; } diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 5ff6f8c..033cb60 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -248,7 +248,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, int major; int minor; int patch; - std::string prop = cmStrCat("OSX_", name, "_VERSION"); + std::string prop = cmStrCat("MACHO_", name, "_VERSION"); std::string fallback_prop = so ? "SOVERSION" : "VERSION"; this->GeneratorTarget->GetTargetVersionFallback(prop, fallback_prop, major, minor, patch); diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 78cabce..8ab30c0 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -255,8 +255,8 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, // The variable is in the env, but not in the cache. Use it and put it // in the cache valueToUse = envVarValue; - mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), - cacheEntryName.c_str(), cmStateEnums::STRING, true); + mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(), + cmStateEnums::STRING, true); mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); } else if (!envVarSet && cacheValue != nullptr) { // It is already in the cache, but not in the env, so use it from the cache @@ -270,7 +270,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, valueToUse = *cacheValue; if (valueToUse.find(envVarValue) == std::string::npos) { valueToUse = envVarValue; - mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), + mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(), cmStateEnums::STRING, true); mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 6f9f7a2..31f1201 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -76,13 +76,13 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) std::string const library = this->FindLibrary(); if (!library.empty()) { // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, library.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, library, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); return true; } std::string notfound = this->VariableName + "-NOTFOUND"; - this->Makefile->AddCacheDefinition(this->VariableName, notfound.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, notfound, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); if (this->Required) { diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 297c72b..f606002 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1060,8 +1060,8 @@ bool cmFindPackageCommand::FindConfig() cmStrCat("The directory containing a CMake configuration file for ", this->Name, '.'); // We force the value since we do not get here if it was already set. - this->Makefile->AddCacheDefinition(this->Variable, init.c_str(), - help.c_str(), cmStateEnums::PATH, true); + this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(), + cmStateEnums::PATH, true); return found; } diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index f5b52c2..4bab469 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -44,12 +44,12 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn) std::string result = this->FindHeader(); if (!result.empty()) { this->Makefile->AddCacheDefinition( - this->VariableName, result.c_str(), this->VariableDocumentation.c_str(), + this->VariableName, result, this->VariableDocumentation.c_str(), (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); return true; } this->Makefile->AddCacheDefinition( - this->VariableName, (this->VariableName + "-NOTFOUND").c_str(), + this->VariableName, this->VariableName + "-NOTFOUND", this->VariableDocumentation.c_str(), (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); if (this->Required) { diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index cbc3c78..4b88bea 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -128,14 +128,14 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) std::string const result = FindProgram(); if (!result.empty()) { // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, result.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, result, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); return true; } this->Makefile->AddCacheDefinition( - this->VariableName, (this->VariableName + "-NOTFOUND").c_str(), + this->VariableName, this->VariableName + "-NOTFOUND", this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); if (this->Required) { this->Makefile->IssueMessage( diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ad142d7..cb80fe6 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1282,6 +1282,86 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( } namespace { +std::string AddSwiftInterfaceIncludeDirectories( + const cmGeneratorTarget* root, const cmGeneratorTarget* target, + const std::string& config, cmGeneratorExpressionDAGChecker* context) +{ + cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, + "Swift_MODULE_DIRECTORY", nullptr, + context }; + switch (dag.Check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dag.ReportError(nullptr, + "$<TARGET_PROPERTY:" + target->GetName() + + ",Swift_MODULE_DIRECTORY>"); + return ""; + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return ""; + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We have already seen this transitive property. + return ""; + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + std::string directories; + if (const auto* interface = + target->GetLinkInterfaceLibraries(config, root, true)) { + for (const cmLinkItem& library : interface->Libraries) { + if (const cmGeneratorTarget* dependency = library.Target) { + if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) { + std::string value = + dependency->GetSafeProperty("Swift_MODULE_DIRECTORY"); + if (value.empty()) { + value = + dependency->GetLocalGenerator()->GetCurrentBinaryDirectory(); + } + + if (!directories.empty()) { + directories += ";"; + } + directories += value; + } + } + } + } + return directories; +} + +void AddSwiftImplicitIncludeDirectories( + const cmGeneratorTarget* target, const std::string& config, + std::vector<EvaluatedTargetPropertyEntry>& entries) +{ + if (const auto* libraries = target->GetLinkImplementationLibraries(config)) { + cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, + "Swift_MODULE_DIRECTORY", nullptr, + nullptr }; + + for (const cmLinkImplItem& library : libraries->Libraries) { + if (const cmGeneratorTarget* dependency = library.Target) { + if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) { + EvaluatedTargetPropertyEntry entry{ library, library.Backtrace }; + + if (const char* val = + dependency->GetProperty("Swift_MODULE_DIRECTORY")) { + entry.Values.emplace_back(val); + } else { + entry.Values.emplace_back( + dependency->GetLocalGenerator()->GetCurrentBinaryDirectory()); + } + + cmExpandList(AddSwiftInterfaceIncludeDirectories(target, dependency, + config, &dag), + entry.Values); + + entries.emplace_back(std::move(entry)); + } + } + } + } +} + void AddInterfaceEntries(cmGeneratorTarget const* headTarget, std::string const& config, std::string const& prop, std::string const& lang, @@ -3177,6 +3257,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( EvaluateTargetPropertyEntries(this, config, lang, &dagChecker, this->IncludeDirectoriesEntries); + if (lang == "Swift") { + AddSwiftImplicitIncludeDirectories(this, config, entries); + } + AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang, &dagChecker, entries); diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 7d91a75..811421a 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -120,11 +120,11 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, if (args.size() >= 4 && args.back() == "CACHE") { if (!programArgs.empty() && !storeArgs.empty()) { status.GetMakefile().AddCacheDefinition( - storeArgs, programArgs.c_str(), "", + storeArgs, programArgs, "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } status.GetMakefile().AddCacheDefinition( - args.front(), result.c_str(), "", + args.front(), result, "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } else { if (!programArgs.empty() && !storeArgs.empty()) { diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0404715..0b9a3e5 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -446,8 +446,8 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) cmSystemTools::GetShortPath(makeProgram, makeProgram); cmSystemTools::SplitProgramPath(makeProgram, dir, file); makeProgram = cmStrCat(dir, '/', saveFile); - mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(), - "make program", cmStateEnums::FILEPATH); + mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram, "make program", + cmStateEnums::FILEPATH); } return true; } diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 78e3b43..9754fd5 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -91,7 +91,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, /* store the full toolset for later use * -- already done if -T<toolset> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp.c_str(), + mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp, "Location of generator toolset.", cmStateEnums::INTERNAL); } @@ -113,8 +113,8 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, } /* store the toolset that is being used for this build */ - mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(), - "build program to use", cmStateEnums::INTERNAL, true); + mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild, "build program to use", + cmStateEnums::INTERNAL, true); mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp); @@ -133,7 +133,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, /* store the platform name for later use * -- already done if -A<arch> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch.c_str(), + mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch, "Name of generator platform.", cmStateEnums::INTERNAL); } else { @@ -167,7 +167,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, if (cmIsOff(bspName) && platform.find("integrity") != std::string::npos) { bspName = "sim" + arch; /* write back the calculate name for next time */ - mf->AddCacheDefinition("GHS_BSP_NAME", bspName.c_str(), + mf->AddCacheDefinition("GHS_BSP_NAME", bspName, "Name of GHS target platform.", cmStateEnums::STRING, true); std::string m = cmStrCat( diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index eb33825..43d31bc 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -128,7 +128,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage( // does not know about. std::string extraPath; if (cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH", extraPath)) { - mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath.c_str(), + mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath, "Saved environment variable CMAKE_MSVCIDE_RUN_PATH", cmStateEnums::STATIC); } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index ac7d204..9db4817 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2369,8 +2369,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, int minor; int patch; - // OSX_CURRENT_VERSION or VERSION -> current_version - gtgt->GetTargetVersionFallback("OSX_CURRENT_VERSION", "VERSION", major, + // MACHO_CURRENT_VERSION or VERSION -> current_version + gtgt->GetTargetVersionFallback("MACHO_CURRENT_VERSION", "VERSION", major, minor, patch); std::ostringstream v; @@ -2381,8 +2381,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("DYLIB_CURRENT_VERSION", this->CreateString(v.str())); - // OSX_COMPATIBILITY_VERSION or SOVERSION -> compatibility_version - gtgt->GetTargetVersionFallback("OSX_COMPATIBILITY_VERSION", "SOVERSION", + // MACHO_COMPATIBILITY_VERSION or SOVERSION -> compatibility_version + gtgt->GetTargetVersionFallback("MACHO_COMPATIBILITY_VERSION", "SOVERSION", major, minor, patch); std::ostringstream vso; diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 86ee953..480c005 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -156,9 +156,11 @@ void cmLinkLineComputer::ComputeLinkPath( type = cmStateEnums::ImportLibraryArtifact; } - linkPathNoBT += cmStrCat( - " ", libPathFlag, item.Target->GetDirectory(cli.GetConfig(), type), - libPathTerminator, " "); + linkPathNoBT += + cmStrCat(" ", libPathFlag, + this->ConvertToOutputForExisting( + item.Target->GetDirectory(cli.GetConfig(), type)), + libPathTerminator, " "); } } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 94d99b7..76c559f 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -60,6 +60,7 @@ #include "cmake.h" #ifndef CMAKE_BOOTSTRAP +# include "cmMakefileProfilingData.h" # include "cmVariableWatch.h" #endif @@ -372,19 +373,30 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const class cmMakefileCall { public: - cmMakefileCall(cmMakefile* mf, cmCommandContext const& cc, + cmMakefileCall(cmMakefile* mf, cmListFileFunction const& lff, cmExecutionStatus& status) : Makefile(mf) { cmListFileContext const& lfc = cmListFileContext::FromCommandContext( - cc, this->Makefile->StateSnapshot.GetExecutionListFile()); + lff, this->Makefile->StateSnapshot.GetExecutionListFile()); this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc); ++this->Makefile->RecursionDepth; this->Makefile->ExecutionStatusStack.push_back(&status); +#if !defined(CMAKE_BOOTSTRAP) + if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { + this->Makefile->GetCMakeInstance()->GetProfilingOutput().StartEntry(lff, + lfc); + } +#endif } ~cmMakefileCall() { +#if !defined(CMAKE_BOOTSTRAP) + if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { + this->Makefile->GetCMakeInstance()->GetProfilingOutput().StopEntry(); + } +#endif this->Makefile->ExecutionStatusStack.pop_back(); --this->Makefile->RecursionDepth; this->Makefile->Backtrace = this->Makefile->Backtrace.Pop(); diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 9c6dca6..081e69d 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -317,6 +317,12 @@ public: void AddCacheDefinition(const std::string& name, const char* value, const char* doc, cmStateEnums::CacheEntryType type, bool force = false); + void AddCacheDefinition(const std::string& name, const std::string& value, + const char* doc, cmStateEnums::CacheEntryType type, + bool force = false) + { + AddCacheDefinition(name, value.c_str(), doc, type, force); + } /** * Remove a variable definition from the build. This is not valid diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx new file mode 100644 index 0000000..ea64132 --- /dev/null +++ b/Source/cmMakefileProfilingData.cxx @@ -0,0 +1,113 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmMakefileProfilingData.h" + +#include <chrono> +#include <cstdint> +#include <stdexcept> +#include <vector> + +#include "cmsys/FStream.hxx" +#include "cmsys/SystemInformation.hxx" + +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" + +#include "cmListFileCache.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +cmMakefileProfilingData::cmMakefileProfilingData( + const std::string& profileStream) +{ + std::ios::openmode omode = std::ios::out | std::ios::trunc; + this->ProfileStream.open(profileStream.c_str(), omode); + Json::StreamWriterBuilder wbuilder; + this->JsonWriter = + std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter()); + if (!this->ProfileStream.good()) { + throw std::runtime_error(std::string("Unable to open: ") + profileStream); + } + + this->ProfileStream << "["; +}; + +cmMakefileProfilingData::~cmMakefileProfilingData() noexcept +{ + if (this->ProfileStream.good()) { + try { + this->ProfileStream << "]"; + this->ProfileStream.close(); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } + } +} + +void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff, + cmListFileContext const& lfc) +{ + /* Do not try again if we previously failed to write to output. */ + if (!this->ProfileStream.good()) { + return; + } + + try { + if (this->ProfileStream.tellp() > 1) { + this->ProfileStream << ","; + } + cmsys::SystemInformation info; + Json::Value v; + v["ph"] = "B"; + v["name"] = lff.Name.Original; + v["cat"] = "cmake"; + v["ts"] = uint64_t(std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count()); + v["pid"] = static_cast<int>(info.GetProcessId()); + v["tid"] = 0; + Json::Value argsValue; + if (!lff.Arguments.empty()) { + std::string args; + for (const auto& a : lff.Arguments) { + args += (args.empty() ? "" : " ") + a.Value; + } + argsValue["functionArgs"] = args; + } + argsValue["location"] = lfc.FilePath + ":" + std::to_string(lfc.Line); + v["args"] = argsValue; + + this->JsonWriter->write(v, &this->ProfileStream); + } catch (std::ios_base::failure& fail) { + cmSystemTools::Error( + cmStrCat("Failed to write to profiling output: ", fail.what())); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } +} + +void cmMakefileProfilingData::StopEntry() +{ + /* Do not try again if we previously failed to write to output. */ + if (!this->ProfileStream.good()) { + return; + } + + try { + this->ProfileStream << ","; + cmsys::SystemInformation info; + Json::Value v; + v["ph"] = "E"; + v["ts"] = uint64_t(std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count()); + v["pid"] = static_cast<int>(info.GetProcessId()); + v["tid"] = 0; + this->JsonWriter->write(v, &this->ProfileStream); + } catch (std::ios_base::failure& fail) { + cmSystemTools::Error( + cmStrCat("Failed to write to profiling output:", fail.what())); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } +} diff --git a/Source/cmMakefileProfilingData.h b/Source/cmMakefileProfilingData.h new file mode 100644 index 0000000..1babd97 --- /dev/null +++ b/Source/cmMakefileProfilingData.h @@ -0,0 +1,29 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmMakefileProfilingData_h +#define cmMakefileProfilingData_h +#include <memory> +#include <string> + +#include "cmsys/FStream.hxx" + +namespace Json { +class StreamWriter; +} + +class cmListFileContext; +struct cmListFileFunction; + +class cmMakefileProfilingData +{ +public: + cmMakefileProfilingData(const std::string&); + ~cmMakefileProfilingData() noexcept; + void StartEntry(const cmListFileFunction& lff, cmListFileContext const& lfc); + void StopEntry(); + +private: + cmsys::ofstream ProfileStream; + std::unique_ptr<Json::StreamWriter> JsonWriter; +}; +#endif diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index a25fd42..2ec66d9 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -47,10 +47,10 @@ bool cmProjectCommand(std::vector<std::string> const& args, mf.SetProjectName(projectName); mf.AddCacheDefinition(projectName + "_BINARY_DIR", - mf.GetCurrentBinaryDirectory().c_str(), + mf.GetCurrentBinaryDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); mf.AddCacheDefinition(projectName + "_SOURCE_DIR", - mf.GetCurrentSourceDirectory().c_str(), + mf.GetCurrentSourceDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); mf.AddDefinition("PROJECT_BINARY_DIR", mf.GetCurrentBinaryDirectory()); @@ -66,7 +66,7 @@ bool cmProjectCommand(std::vector<std::string> const& args, // will work. if (!mf.GetDefinition("CMAKE_PROJECT_NAME") || mf.IsRootMakefile()) { mf.AddDefinition("CMAKE_PROJECT_NAME", projectName); - mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName.c_str(), + mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName, "Value Computed by CMake", cmStateEnums::STATIC); } @@ -379,7 +379,7 @@ static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name, // CMakeLists.txt file, then go with the last one. if (!mf.GetDefinition(name) || mf.IsRootMakefile()) { mf.AddDefinition(name, value); - mf.AddCacheDefinition(name, value.c_str(), "Value Computed by CMake", + mf.AddCacheDefinition(name, value, "Value Computed by CMake", cmStateEnums::STATIC); } } diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 5e2a146..d8927e8 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -149,8 +149,8 @@ bool cmSetCommand(std::vector<std::string> const& args, // if it is meant to be in the cache then define it in the cache if (cache) { - status.GetMakefile().AddCacheDefinition(variable, value.c_str(), docstring, - type, force); + status.GetMakefile().AddCacheDefinition(variable, value, docstring, type, + force); } else { // add the definition status.GetMakefile().AddDefinition(variable, value); diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index d47f121..b2d905e 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -72,8 +72,7 @@ bool cmSiteNameCommand(std::vector<std::string> const& args, } #endif status.GetMakefile().AddCacheDefinition( - args[0], siteName.c_str(), - "Name of the computer/site where compile is being run", + args[0], siteName, "Name of the computer/site where compile is being run", cmStateEnums::STRING); return true; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 987f526..10515c2 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1007,7 +1007,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, dependencies += ";"; dependencies += lib; dependencies += ";"; - mf.AddCacheDefinition(targetEntry, dependencies.c_str(), + mf.AddCacheDefinition(targetEntry, dependencies, "Dependencies for the target", cmStateEnums::STATIC); } } diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index a43165c..5865a19 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -102,15 +102,15 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, cmSystemTools::ReplaceString(utilityExecutable, "/./", "/"); // Enter the value into the cache. - status.GetMakefile().AddCacheDefinition( - cacheEntry, utilityExecutable.c_str(), "Path to an internal program.", - cmStateEnums::FILEPATH); + status.GetMakefile().AddCacheDefinition(cacheEntry, utilityExecutable, + "Path to an internal program.", + cmStateEnums::FILEPATH); // add a value into the cache that maps from the // full path to the name of the project cmSystemTools::ConvertToUnixSlashes(utilityExecutable); - status.GetMakefile().AddCacheDefinition( - utilityExecutable, utilityName.c_str(), "Executable to project name.", - cmStateEnums::INTERNAL); + status.GetMakefile().AddCacheDefinition(utilityExecutable, utilityName, + "Executable to project name.", + cmStateEnums::INTERNAL); return true; } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f4b9f16..29ed61d 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -9,6 +9,7 @@ #include <initializer_list> #include <iostream> #include <sstream> +#include <stdexcept> #include <utility> #include <cm/memory> @@ -39,6 +40,9 @@ #include "cmLinkLineComputer.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#if !defined(CMAKE_BOOTSTRAP) +# include "cmMakefileProfilingData.h" +#endif #include "cmMessenger.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -613,6 +617,10 @@ void cmake::SetArgs(const std::vector<std::string>& args) { bool haveToolset = false; bool havePlatform = false; +#if !defined(CMAKE_BOOTSTRAP) + std::string profilingFormat; + std::string profilingOutput; +#endif for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) { @@ -839,6 +847,20 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetGlobalGenerator(std::move(gen)); +#if !defined(CMAKE_BOOTSTRAP) + } else if (arg.find("--profiling-format", 0) == 0) { + profilingFormat = arg.substr(strlen("--profiling-format=")); + if (profilingFormat.empty()) { + cmSystemTools::Error("No format specified for --profiling-format"); + } + } else if (arg.find("--profiling-output", 0) == 0) { + profilingOutput = arg.substr(strlen("--profiling-output=")); + profilingOutput = cmSystemTools::CollapseFullPath(profilingOutput); + cmSystemTools::ConvertToUnixSlashes(profilingOutput); + if (profilingOutput.empty()) { + cmSystemTools::Error("No path specified for --profiling-output"); + } +#endif } // no option assume it is the path to the source or an existing build else { @@ -856,6 +878,29 @@ void cmake::SetArgs(const std::vector<std::string>& args) } } +#if !defined(CMAKE_BOOTSTRAP) + if (!profilingOutput.empty() || !profilingFormat.empty()) { + if (profilingOutput.empty()) { + cmSystemTools::Error( + "--profiling-format specified but no --profiling-output!"); + return; + } + if (profilingFormat == "google-trace") { + try { + this->ProfilingOutput = + cm::make_unique<cmMakefileProfilingData>(profilingOutput); + } catch (std::runtime_error& e) { + cmSystemTools::Error( + cmStrCat("Could not start profiling: ", e.what())); + return; + } + } else { + cmSystemTools::Error("Invalid format specified for --profiling-format"); + return; + } + } +#endif + const bool haveSourceDir = !this->GetHomeDirectory().empty(); const bool haveBinaryDir = !this->GetHomeOutputDirectory().empty(); @@ -2952,3 +2997,15 @@ void cmake::SetDeprecatedWarningsAsErrors(bool b) " and functions.", cmStateEnums::INTERNAL); } + +#if !defined(CMAKE_BOOTSTRAP) +cmMakefileProfilingData& cmake::GetProfilingOutput() +{ + return *(this->ProfilingOutput); +} + +bool cmake::IsProfilingEnabled() const +{ + return static_cast<bool>(this->ProfilingOutput); +} +#endif diff --git a/Source/cmake.h b/Source/cmake.h index 35425ec..58769fd 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -34,6 +34,9 @@ class cmFileTimeCache; class cmGlobalGenerator; class cmGlobalGeneratorFactory; class cmMakefile; +#if !defined(CMAKE_BOOTSTRAP) +class cmMakefileProfilingData; +#endif class cmMessenger; class cmVariableWatch; struct cmDocumentationEntry; @@ -549,6 +552,11 @@ public: bool GetRegenerateDuringBuild() const { return this->RegenerateDuringBuild; } +#if !defined(CMAKE_BOOTSTRAP) + cmMakefileProfilingData& GetProfilingOutput(); + bool IsProfilingEnabled() const; +#endif + protected: void RunCheckForUnusedVariables(); int HandleDeleteCacheVariables(const std::string& var); @@ -657,6 +665,10 @@ private: void AppendGlobalGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); + +#if !defined(CMAKE_BOOTSTRAP) + std::unique_ptr<cmMakefileProfilingData> ProfilingOutput; +#endif }; #define CMAKE_STANDARD_OPTIONS_TABLE \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 494d5d9..90d8ea6 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -93,6 +93,12 @@ const char* cmDocumentationOptions[][2] = { { "--check-system-vars", "Find problems with variable usage in system " "files." }, +# if !defined(CMAKE_BOOTSTRAP) + { "--profiling-format=<fmt>", "Output data for profiling CMake scripts." }, + { "--profiling-output=<file>", + "Select an output path for the profiling data enabled through " + "--profiling-format." }, +# endif { nullptr, nullptr } }; diff --git a/Tests/RunCMake/CommandLine/ProfilingTest-check.cmake b/Tests/RunCMake/CommandLine/ProfilingTest-check.cmake new file mode 100644 index 0000000..19ece86 --- /dev/null +++ b/Tests/RunCMake/CommandLine/ProfilingTest-check.cmake @@ -0,0 +1,18 @@ +if (NOT EXISTS ${ProfilingTestOutput}) + set(RunCMake_TEST_FAILED "Expected ${ProfilingTestOutput} to exists") +endif() + +file(READ "${ProfilingTestOutput}" JSON_HEADER LIMIT 2) +if (NOT JSON_HEADER MATCHES "^\\[{") + set(RunCMake_TEST_FAILED "Expected valid JSON start") + return() +endif() + +file(SIZE "${ProfilingTestOutput}" OUTPUT_SIZE) +math(EXPR END_OFFSET "${OUTPUT_SIZE} -2 ") + +file(READ "${ProfilingTestOutput}" JSON_TRAILER OFFSET ${END_OFFSET}) +if (NOT JSON_TRAILER MATCHES "^}]$") + set(RunCMake_TEST_FAILED "Expected valid JSON end") + return() +endif() diff --git a/Tests/RunCMake/CommandLine/ProfilingTest.cmake b/Tests/RunCMake/CommandLine/ProfilingTest.cmake new file mode 100644 index 0000000..837f4bf --- /dev/null +++ b/Tests/RunCMake/CommandLine/ProfilingTest.cmake @@ -0,0 +1 @@ +# This file is intentionally left blank diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 087ef21..41f13db 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -697,3 +697,25 @@ function(run_llvm_rc) unset(LLVMRC_RESULT) endfunction() run_llvm_rc() + +set(RunCMake_TEST_OPTIONS --profiling-output=/no/such/file.txt --profiling-format=google-trace) +run_cmake(profiling-all-params) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS --profiling-output=/no/such/file.txt --profiling-format=invalid-format) +run_cmake(profiling-invalid-format) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS --profiling-output=/no/such/file.txt) +run_cmake(profiling-missing-format) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS --profiling-format=google-trace) +run_cmake(profiling-missing-output) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/profiling-test") +set(ProfilingTestOutput ${RunCMake_TEST_BINARY_DIR}/output.json) +set(RunCMake_TEST_OPTIONS --profiling-format=google-trace --profiling-output=${ProfilingTestOutput}) +run_cmake(ProfilingTest) +unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/CommandLine/profiling-all-params-result.txt b/Tests/RunCMake/CommandLine/profiling-all-params-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-all-params-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-all-params-stderr.txt b/Tests/RunCMake/CommandLine/profiling-all-params-stderr.txt new file mode 100644 index 0000000..6b5c373 --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-all-params-stderr.txt @@ -0,0 +1 @@ +^.*Could not start profiling: Unable to open: /no/such/file.txt$ diff --git a/Tests/RunCMake/CommandLine/profiling-invalid-format-result.txt b/Tests/RunCMake/CommandLine/profiling-invalid-format-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-invalid-format-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-invalid-format-stderr.txt b/Tests/RunCMake/CommandLine/profiling-invalid-format-stderr.txt new file mode 100644 index 0000000..459bc3a --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-invalid-format-stderr.txt @@ -0,0 +1 @@ +^.*Invalid format specified for --profiling-format$ diff --git a/Tests/RunCMake/CommandLine/profiling-missing-format-result.txt b/Tests/RunCMake/CommandLine/profiling-missing-format-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-format-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-missing-format-stderr.txt b/Tests/RunCMake/CommandLine/profiling-missing-format-stderr.txt new file mode 100644 index 0000000..459bc3a --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-format-stderr.txt @@ -0,0 +1 @@ +^.*Invalid format specified for --profiling-format$ diff --git a/Tests/RunCMake/CommandLine/profiling-missing-output-result.txt b/Tests/RunCMake/CommandLine/profiling-missing-output-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-output-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-missing-output-stderr.txt b/Tests/RunCMake/CommandLine/profiling-missing-output-stderr.txt new file mode 100644 index 0000000..9ab0c8f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-output-stderr.txt @@ -0,0 +1 @@ +^.*--profiling-format specified but no --profiling-output!$ diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-result.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-result.txt index d197c91..d197c91 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-result.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-result.txt diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-stdout.txt index 3a6572c..3a6572c 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-stdout.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-stdout.txt diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-result.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stderr.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stderr.txt new file mode 100644 index 0000000..f6be939 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stderr.txt @@ -0,0 +1,2 @@ +Unable to find executable: discovery_timeout_test_NOT_BUILT +Errors while running CTest diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stdout.txt new file mode 100644 index 0000000..d4c4e7b --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stdout.txt @@ -0,0 +1,18 @@ +Test project .*GoogleTest-build +[ \t]*Start [0-9]+: discovery_timeout_test_NOT_BUILT +Could not find executable discovery_timeout_test_NOT_BUILT +Looked in the following places: +discovery_timeout_test_NOT_BUILT +discovery_timeout_test_NOT_BUILT(\.exe)? +Debug/discovery_timeout_test_NOT_BUILT +Debug/discovery_timeout_test_NOT_BUILT(\.exe)? +Debug/discovery_timeout_test_NOT_BUILT +Debug/discovery_timeout_test_NOT_BUILT(\.exe)? +[^\n]+discovery_timeout_test_NOT_BUILT +\.+\*\*\*Not Run +[0-9.]+ sec ++ +0% tests passed, 1 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests FAILED: +[^\n]+discovery_timeout_test_NOT_BUILT \(Not Run\) diff --git a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake index 0fa4e2a..8c6b507 100644 --- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake @@ -27,7 +27,7 @@ function(run_GoogleTest) ) set(RunCMake_TEST_OUTPUT_MERGE 1) - run_cmake_command(GoogleTest-discovery-timeout + run_cmake_command(GoogleTest-discovery-timeout-build ${CMAKE_COMMAND} --build . --config Debug @@ -69,6 +69,13 @@ function(run_GoogleTest) -R property_timeout\\.case_with_discovery --no-label-summary ) + + run_cmake_command(GoogleTest-discovery-timeout-test + ${CMAKE_CTEST_COMMAND} + -C Debug + -R discovery_timeout_test + --no-label-summary + ) endfunction() run_GoogleTest() diff --git a/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake b/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake index 629e445..fc51bd8 100644 --- a/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake +++ b/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake @@ -4,6 +4,6 @@ add_library(foo SHARED foo.c) set_target_properties(foo PROPERTIES VERSION 1.0 SOVERSION 1 - OSX_COMPATIBILITY_VERSION 2.1.0 - OSX_CURRENT_VERSION 3.2.1 + MACHO_COMPATIBILITY_VERSION 2.1.0 + MACHO_CURRENT_VERSION 3.2.1 ) diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt index f4cbac2..e24279b 100644 --- a/Tests/SwiftOnly/CMakeLists.txt +++ b/Tests/SwiftOnly/CMakeLists.txt @@ -1,4 +1,16 @@ cmake_minimum_required(VERSION 3.3) + +# NOTE: Force the Release mode configuration as there are some issues with the +# debug information handling on macOS on certain Xcode builds. +if(NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build" FORCE) +endif() + +# NOTE: enable shared libraries by default. Older Xcode releases do not play +# well with static libraries, and Windows does not currently support static +# libraries in Swift. +set(BUILD_SHARED_LIBS YES) + project(SwiftOnly Swift) if(NOT XCODE_VERSION VERSION_LESS 10.2) @@ -7,7 +19,19 @@ elseif(NOT XCODE_VERSION VERSION_LESS 8.0) set(CMAKE_Swift_LANGUAGE_VERSION 3.0) endif() +set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift) + add_executable(SwiftOnly main.swift) +add_library(L L.swift) + +add_library(M M.swift) +target_link_libraries(M PUBLIC + L) + +add_library(N N.swift) +target_link_libraries(N PUBLIC + M) + # Dummy to make sure generation works with such targets. add_library(SwiftIface INTERFACE) diff --git a/Tests/SwiftOnly/L.swift b/Tests/SwiftOnly/L.swift new file mode 100644 index 0000000..79ff87e --- /dev/null +++ b/Tests/SwiftOnly/L.swift @@ -0,0 +1 @@ +public let ThirtyTwo: Int = 32 diff --git a/Tests/SwiftOnly/M.swift b/Tests/SwiftOnly/M.swift new file mode 100644 index 0000000..dd333fe --- /dev/null +++ b/Tests/SwiftOnly/M.swift @@ -0,0 +1,2 @@ +import L +public let SixtyFour: Int = ThirtyTwo * 2 diff --git a/Tests/SwiftOnly/N.swift b/Tests/SwiftOnly/N.swift new file mode 100644 index 0000000..990ddf9 --- /dev/null +++ b/Tests/SwiftOnly/N.swift @@ -0,0 +1,2 @@ +import M +public let OneTwentyEight = SixtyFour * 2 |