diff options
367 files changed, 5053 insertions, 1455 deletions
diff --git a/.clang-format b/.clang-format index a7f049a..4bfce44 100644 --- a/.clang-format +++ b/.clang-format @@ -22,6 +22,8 @@ IncludeBlocks: Regroup IncludeCategories: - Regex: '^[<"]cmConfigure\.h' Priority: -1 + - Regex: '^<queue>' + Priority: 1 - Regex: '^(<|")cm(ext)?/' Priority: 2 - Regex: '^(<|")windows\.h' diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 31ec1d0..0676f7e 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -221,6 +221,7 @@ syn keyword cmakeProperty contained \ JOB_POOLS \ JOB_POOL_COMPILE \ JOB_POOL_LINK + \ JOB_POOL_PRECOMPILE_HEADER \ KEEP_EXTENSION \ LABELS \ LANGUAGE @@ -1066,6 +1067,7 @@ syn keyword cmakeVariable contained \ CMAKE_JOB_POOLS \ CMAKE_JOB_POOL_COMPILE \ CMAKE_JOB_POOL_LINK + \ CMAKE_JOB_POOL_PRECOMPILE_HEADER \ CMAKE_Java \ CMAKE_Java_ANDROID_TOOLCHAIN_MACHINE \ CMAKE_Java_ANDROID_TOOLCHAIN_PREFIX @@ -2864,6 +2866,11 @@ syn keyword cmakeKWtarget_link_options contained \ _LINKER_WRAPPER_FLAG \ _LINKER_WRAPPER_FLAG_SEP +syn keyword cmakeKWtarget_precompile_headers contained + \ INTERFACE + \ PRIVATE + \ PUBLIC + syn keyword cmakeKWtarget_sources contained \ ALIAS \ IMPORTED @@ -3168,6 +3175,7 @@ syn keyword cmakeCommand \ target_link_directories \ target_link_libraries \ target_link_options + \ target_precompile_headers \ target_sources \ try_compile \ try_run @@ -3324,6 +3332,7 @@ hi def link cmakeKWtarget_include_directories ModeMsg hi def link cmakeKWtarget_link_directories ModeMsg hi def link cmakeKWtarget_link_libraries ModeMsg hi def link cmakeKWtarget_link_options ModeMsg +hi def link cmakeKWtarget_precompile_headers ModeMsg hi def link cmakeKWtarget_sources ModeMsg hi def link cmakeKWtry_compile ModeMsg hi def link cmakeKWtry_run ModeMsg diff --git a/CMakeLists.txt b/CMakeLists.txt index da99a6e..6f4c111 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -671,10 +671,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) set(LIBRARY_OUTPUT_PATH "" CACHE INTERNAL "Where to put the libraries for CMake") - # The CMake executables usually do not need any rpath to run in the build or - # install tree. - set(CMAKE_SKIP_RPATH ON CACHE INTERNAL "CMake does not need RPATHs.") - # Load install destinations. include(Source/CMakeInstallDestinations.cmake) @@ -714,19 +710,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) # build the utilities (a macro defined in this file) CMAKE_BUILD_UTILITIES() - # On NetBSD ncurses is required, since curses doesn't have the wsyncup() - # function. ncurses is installed via pkgsrc, so the library is in /usr/pkg/lib, - # which isn't in the default linker search path. So without RPATH ccmake - # doesn't run and the build doesn't succeed since ccmake is executed for - # generating the documentation. - if(BUILD_CursesDialog) - get_filename_component(_CURSES_DIR "${CURSES_LIBRARY}" PATH) - set(CURSES_NEED_RPATH FALSE) - if(NOT "${_CURSES_DIR}" STREQUAL "/lib" AND NOT "${_CURSES_DIR}" STREQUAL "/usr/lib" AND NOT "${_CURSES_DIR}" STREQUAL "/lib64" AND NOT "${_CURSES_DIR}" STREQUAL "/usr/lib64") - set(CURSES_NEED_RPATH TRUE) - endif() - endif() - if(BUILD_QtDialog) if(APPLE) set(CMAKE_BUNDLE_VERSION @@ -739,28 +722,15 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}CMake.app/Contents") endif() - - set(QT_NEED_RPATH FALSE) - if(NOT "${QT_LIBRARY_DIR}" STREQUAL "/lib" AND NOT "${QT_LIBRARY_DIR}" STREQUAL "/usr/lib" AND NOT "${QT_LIBRARY_DIR}" STREQUAL "/lib64" AND NOT "${QT_LIBRARY_DIR}" STREQUAL "/usr/lib64") - set(QT_NEED_RPATH TRUE) - endif() endif() - - # The same might be true on other systems for other libraries. - # Then only enable RPATH if we have are building at least with cmake 2.4, - # since this one has much better RPATH features than cmake 2.2. - # The executables are then built with the RPATH for the libraries outside - # the build tree, which is both the build and the install RPATH. - if (UNIX) - if( CMAKE_USE_SYSTEM_CURL OR CMAKE_USE_SYSTEM_ZLIB - OR CMAKE_USE_SYSTEM_EXPAT OR CURSES_NEED_RPATH OR QT_NEED_RPATH) - set(CMAKE_SKIP_RPATH OFF CACHE INTERNAL "CMake built with RPATH.") - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - endif() - endif () - + if(UNIX) + # Install executables with the RPATH set for libraries outside the build tree. + # This is also suitable for binaries in the build tree. Avoid re-link on install. + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON CACHE BOOL "Install with RPATH set to find custom-built libraries.") + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "Build with RPATH set to match install-tree RPATH.") + mark_as_advanced(CMAKE_INSTALL_RPATH_USE_LINK_PATH CMAKE_BUILD_WITH_INSTALL_RPATH) + endif() # add the uninstall support configure_file( diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst index 1e37889..35320c2 100644 --- a/Help/cpack_gen/dmg.rst +++ b/Help/cpack_gen/dmg.rst @@ -81,6 +81,13 @@ on macOS: ``<language>.menu.txt`` and ``<language>.license.txt`` in the directory specified by the :variable:`CPACK_DMG_SLA_DIR` variable. +.. variable:: CPACK_DMG_<component>_FILE_NAME + + File name when packaging ``<component>`` as its own DMG + (``CPACK_COMPONENTS_GROUPING`` set to IGNORE). + + - Default: ``CPACK_PACKAGE_FILE_NAME-<component>`` + .. variable:: CPACK_COMMAND_HDIUTIL Path to the ``hdiutil(1)`` command used to operate on disk image files on diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst index dc65249..a310e9f 100644 --- a/Help/cpack_gen/nsis.rst +++ b/Help/cpack_gen/nsis.rst @@ -149,3 +149,7 @@ on Windows Nullsoft Scriptable Install System. .. variable:: CPACK_NSIS_FINISH_TITLE_3LINES Display the title in the finish page on 3 lines instead of 2. + +.. variable:: CPACK_NSIS_MUI_HEADERIMAGE + + The image to display on the header of installers pages. diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst index 71cc392..248eb05 100644 --- a/Help/generator/Ninja Multi-Config.rst +++ b/Help/generator/Ninja Multi-Config.rst @@ -19,9 +19,10 @@ the desired ``build-<Config>.ninja`` file with ``ninja -f``. Running ``build-<Config>.ninja`` as the ``-f`` file and ``<target>`` as the build target. -Executables and libraries of any configuration can be built regardless of which +If :variable:`CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE` is turned on, executables +and libraries of any configuration can be built regardless of which ``build-<Config>.ninja`` file is used, simply by specifying -``<target>:<Config>`` as the Ninja target. You can also specify +``<target>:<OtherConfig>`` as the Ninja target. You can also specify ``<target>:all`` to build a target in all configurations. Each ``build-<Config>.ninja`` file will additionally have ``<target>`` targets which are aliases for ``<target>:<Config>``. However, custom commands and custom @@ -30,6 +31,11 @@ targets will always use the configuration specified in Ninja for the same file to be output with different commands in the same build graph. +If :variable:`CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE` is not enabled, you can +still build any target in ``build-<Config>.ninja`` by specifying +``<target>:<Config>`` or ``<target>``, but not ``<target>:<OtherConfig>`` or +``<target>:all``. + Consider the following example: .. code-block:: cmake @@ -54,7 +60,8 @@ This would build the ``Debug`` configuration of ``generator``, which would be used to generate ``generated.c``, which would be used to build the ``Debug`` configuration of ``generated``. -But if you run the following instead: +But if :variable:`CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE` is enabled, and you +run the following instead: .. code-block:: shell diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt index eca79d9..4d8a3ad 100644 --- a/Help/guide/tutorial/Complete/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) +set(CMAKE_DEBUG_POSTFIX d) + add_library(tutorial_compiler_flags INTERFACE) target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) @@ -37,6 +39,8 @@ add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) +set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) + target_link_libraries(Tutorial PUBLIC MathFunctions) # add the binary tree to the search path for include files diff --git a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt index dfa84c9..c911625 100644 --- a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt @@ -17,7 +17,7 @@ if(USE_MYMATH) # first we add the executable that generates the table add_executable(MakeTable MakeTable.cxx) - target_link_libraries(MakeTable tutorial_compiler_flags) + target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags) # add the command to generate the source code add_custom_command( diff --git a/Help/guide/tutorial/MultiPackage/MultiCPackConfig.cmake b/Help/guide/tutorial/Complete/MultiCPackConfig.cmake index 403b633..c2583df 100644 --- a/Help/guide/tutorial/MultiPackage/MultiCPackConfig.cmake +++ b/Help/guide/tutorial/Complete/MultiCPackConfig.cmake @@ -1,4 +1,3 @@ - include("release/CPackConfig.cmake") set(CPACK_INSTALL_CMAKE_PROJECTS diff --git a/Help/guide/tutorial/Complete/tutorial.cxx b/Help/guide/tutorial/Complete/tutorial.cxx index 586d183..a4f44d5 100644 --- a/Help/guide/tutorial/Complete/tutorial.cxx +++ b/Help/guide/tutorial/Complete/tutorial.cxx @@ -1,6 +1,5 @@ // A simple program that computes the square root of a number #include <iostream> -#include <sstream> #include <string> #include "MathFunctions.h" @@ -9,6 +8,7 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; @@ -18,8 +18,8 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // calculate square root const double outputValue = mathfunctions::sqrt(inputValue); + std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0; diff --git a/Help/guide/tutorial/Consumer/CMakeLists.txt b/Help/guide/tutorial/Consumer/CMakeLists.txt deleted file mode 100644 index a0e4598..0000000 --- a/Help/guide/tutorial/Consumer/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -if(NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED True) -endif() - - -function(find_external_dependency name) - set(${name}_ROOT "" CACHE PATH "Root directory to find ${name}") - mark_as_advanced(${name}_DIR) - find_package(${name} PATHS ${${name}_ROOT} REQUIRED) -endfunction() - - -project(Consumer) - -find_external_dependency(MathFunctions) - -add_library(consumer consumer.cxx) -target_link_libraries(consumer PUBLIC MathFunctions) - -# install the consumer library -install(TARGETS consumer DESTINATION bin EXPORT ConsumerTargets) - -# install the configuration targets -install(EXPORT ConsumerTargets - FILE ConsumerTargets.cmake - DESTINATION lib/cmake/Consumer -) - -include(CMakePackageConfigHelpers) -# generate the config file that is includes the exports -configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in - "${CMAKE_CURRENT_BINARY_DIR}/ConsumerConfig.cmake" - INSTALL_DESTINATION "lib/cmake/example" - NO_SET_AND_CHECK_MACRO - NO_CHECK_REQUIRED_COMPONENTS_MACRO - ) - -# install the configuration file -install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/ConsumerConfig.cmake - DESTINATION lib/cmake/Consumer - ) - -# generate the export targets for the build tree -# needs to be after the install(TARGETS ) command -export(EXPORT ConsumerTargets - FILE "${CMAKE_CURRENT_BINARY_DIR}/ConsumerTargets.cmake" -) diff --git a/Help/guide/tutorial/Consumer/Config.cmake.in b/Help/guide/tutorial/Consumer/Config.cmake.in deleted file mode 100644 index 0b3f1e4..0000000 --- a/Help/guide/tutorial/Consumer/Config.cmake.in +++ /dev/null @@ -1,14 +0,0 @@ - -@PACKAGE_INIT@ - -include(CMakeFindDependencyMacro) - -function(find_external_dependency name) - set(${name}_ROOT "" CACHE PATH "Root directory to find ${name}") - mark_as_advanced(${name}_DIR) - find_dependency(${name} PATHS ${${name}_ROOT} REQUIRED) -endfunction() - -find_external_dependency(MathFunctions) - -include ( "${CMAKE_CURRENT_LIST_DIR}/ConsumerTargets.cmake" ) diff --git a/Help/guide/tutorial/Consumer/consumer.cxx b/Help/guide/tutorial/Consumer/consumer.cxx deleted file mode 100644 index ae7877b..0000000 --- a/Help/guide/tutorial/Consumer/consumer.cxx +++ /dev/null @@ -1,11 +0,0 @@ -// A simple function that computes the square root of a number -#include <iostream> -#include <sstream> -#include <string> - -#include "MathFunctions.h" - -double string_square_root(std::string const& value) -{ - return mathfunctions::sqrt(std::stod(value)); -} diff --git a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt index e6cb8ba..32f5e08 100644 --- a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt @@ -15,7 +15,7 @@ if(USE_MYMATH) # first we add the executable that generates the table add_executable(MakeTable MakeTable.cxx) - target_link_libraries(MakeTable tutorial_compiler_flags) + target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags) # add the command to generate the source code add_custom_command( diff --git a/Help/guide/tutorial/MultiPackage/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt index 01d417a..eca79d9 100644 --- a/Help/guide/tutorial/MultiPackage/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/CMakeLists.txt @@ -1,11 +1,19 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # control where the static and shared libraries are built so that on windows # we don't need to tinker with the path to run the executable diff --git a/Help/guide/tutorial/Step12/CTestConfig.cmake b/Help/guide/tutorial/Step12/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step12/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Help/guide/tutorial/MultiPackage/Config.cmake.in b/Help/guide/tutorial/Step12/Config.cmake.in index 17cbabd..17cbabd 100644 --- a/Help/guide/tutorial/MultiPackage/Config.cmake.in +++ b/Help/guide/tutorial/Step12/Config.cmake.in diff --git a/Help/guide/tutorial/MultiPackage/License.txt b/Help/guide/tutorial/Step12/License.txt index c62d00b..c62d00b 100644 --- a/Help/guide/tutorial/MultiPackage/License.txt +++ b/Help/guide/tutorial/Step12/License.txt diff --git a/Help/guide/tutorial/MultiPackage/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt index a2df2a7..720ee64 100644 --- a/Help/guide/tutorial/MultiPackage/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt @@ -17,6 +17,7 @@ if(USE_MYMATH) # first we add the executable that generates the table add_executable(MakeTable MakeTable.cxx) + target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags) # add the command to generate the source code add_custom_command( @@ -41,19 +42,18 @@ if(USE_MYMATH) POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) + target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags) target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif() +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) + # define the symbol stating we are using the declspec(dllexport) when # building on windows target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") -# setup the version numbering -set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0") -set_property(TARGET MathFunctions PROPERTY SOVERSION "1") - # install rules -install(TARGETS MathFunctions +install(TARGETS MathFunctions tutorial_compiler_flags DESTINATION lib EXPORT MathFunctionsTargets) install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/MultiPackage/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step12/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Help/guide/tutorial/MultiPackage/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step12/MathFunctions/MakeTable.cxx diff --git a/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.cxx index 0145300..0145300 100644 --- a/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.cxx diff --git a/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.h index 3fb547b..3fb547b 100644 --- a/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.h diff --git a/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step12/MathFunctions/mysqrt.cxx index 5e622be..8153f18 100644 --- a/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step12/MathFunctions/mysqrt.cxx @@ -17,11 +17,10 @@ double mysqrt(double x) // use the table to help find an initial value double result = x; if (x >= 1 && x < 10) { + std::cout << "Use the table to help find an initial value " << std::endl; result = sqrtTable[static_cast<int>(x)]; } - // if we have both log and exp then use them - // do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { diff --git a/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step12/MathFunctions/mysqrt.h index e1c42ef..e1c42ef 100644 --- a/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.h +++ b/Help/guide/tutorial/Step12/MathFunctions/mysqrt.h diff --git a/Help/guide/tutorial/MultiPackage/TutorialConfig.h.in b/Help/guide/tutorial/Step12/TutorialConfig.h.in index 8cd2fc9..7e4d7fa 100644 --- a/Help/guide/tutorial/MultiPackage/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step12/TutorialConfig.h.in @@ -1,3 +1,3 @@ -// the configured version number +// the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/Help/guide/tutorial/MultiPackage/tutorial.cxx b/Help/guide/tutorial/Step12/tutorial.cxx index f97805b..a4f44d5 100644 --- a/Help/guide/tutorial/MultiPackage/tutorial.cxx +++ b/Help/guide/tutorial/Step12/tutorial.cxx @@ -8,6 +8,7 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; @@ -15,7 +16,7 @@ int main(int argc, char* argv[]) } // convert input to double - double inputValue = std::stod(argv[1]); + const double inputValue = std::stod(argv[1]); const double outputValue = mathfunctions::sqrt(inputValue); diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index d74d160..96f0486 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -45,7 +45,8 @@ The first feature we will add is to provide our executable and project with a version number. While we could do this exclusively in the source code, using ``CMakeLists.txt`` provides more flexibility. -First, modify the ``CMakeLists.txt`` file to set the version number. +First, modify the ``CMakeLists.txt`` file to use the :command:`project` command +to set the project name and version number. .. literalinclude:: Step2/CMakeLists.txt :language: cmake @@ -102,9 +103,10 @@ Next let's add some C++11 features to our project by replacing ``atof`` with We will need to explicitly state in the CMake code that it should use the correct flags. The easiest way to enable support for a specific C++ standard -in CMake is by using the ``CMAKE_CXX_STANDARD`` variable. For this tutorial, -set the ``CMAKE_CXX_STANDARD`` variable in the ``CMakeLists.txt`` file to 11 -and ``CMAKE_CXX_STANDARD_REQUIRED`` to True: +in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this +tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the +``CMakeLists.txt`` file to 11 and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to +True: .. literalinclude:: Step2/CMakeLists.txt :language: cmake @@ -113,7 +115,8 @@ and ``CMAKE_CXX_STANDARD_REQUIRED`` to True: Build and Test -------------- -Run **cmake** or **cmake-gui** to configure the project and then build it +Run the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool. For example, from the command line we could navigate to the @@ -156,11 +159,11 @@ directory: .. literalinclude:: Step3/MathFunctions/CMakeLists.txt :language: cmake -To make use of the new library we will add an ``add_subdirectory`` call in the -top-level ``CMakeLists.txt`` file so that the library will get built. We add -the new library to the executable, and add ``MathFunctions`` as an include -directory so that the ``mqsqrt.h`` header file can be found. The last few lines -of the top-level ``CMakeLists.txt`` file should now look like: +To make use of the new library we will add an :command:`add_subdirectory` +call in the top-level ``CMakeLists.txt`` file so that the library will get +built. We add the new library to the executable, and add ``MathFunctions`` as +an include directory so that the ``mqsqrt.h`` header file can be found. The +last few lines of the top-level ``CMakeLists.txt`` file should now look like: .. code-block:: cmake @@ -189,10 +192,11 @@ occurrence. The first step is to add an option to the top-level :start-after: # should we use our own math functions :end-before: # add the MathFunctions library -This option will be displayed in the CMake GUI and ccmake with a default -value of ON that can be changed by the user. This setting will be stored in -the cache so that the user does not need to set the value each time they run -CMake on a build directory. +This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and +:manual:`ccmake <ccmake(1)>` +with a default value of ON that can be changed by the user. This setting will +be stored in the cache so that the user does not need to set the value each +time they run CMake on a build directory. The next change is to make building and linking the MathFunctions library conditional. To do this we change the end of the top-level ``CMakeLists.txt`` @@ -234,11 +238,13 @@ Since the source code now requires ``USE_MYMATH`` we can add it to **Exercise**: Why is it important that we configure ``TutorialConfig.h.in`` after the option for ``USE_MYMATH``? What would happen if we inverted the two? -Run **cmake** or **cmake-gui** to configure the project and then build it +Run the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool. Then run the built Tutorial executable. -Use ccmake or the CMake GUI to update the value of ``USE_MYMATH``. Rebuild and -run the tutorial again. Which function gives better results, sqrt or mysqrt? +Use the :manual:`ccmake <ccmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` +to update the value of ``USE_MYMATH``. Rebuild and run the tutorial again. +Which function gives better results, sqrt or mysqrt? Adding Usage Requirements for Library (Step 3) ============================================== @@ -248,19 +254,20 @@ link and include line while also giving more control over the transitive property of targets inside CMake. The primary commands that leverage usage requirements are: - - ``target_compile_definitions`` - - ``target_compile_options`` - - ``target_include_directories`` - - ``target_link_libraries`` + - :command:`target_compile_definitions` + - :command:`target_compile_options` + - :command:`target_include_directories` + - :command:`target_link_libraries` Let's refactor our code from `Adding a Library (Step 2)`_ to use the modern CMake approach of usage requirements. We first state that anybody linking to MathFunctions needs to include the current source directory, while -MathFunctions itself doesn't. So this can become an ``INTERFACE`` usage +MathFunctions itself doesn't. So this can become an ``INTERFACE`` usage requirement. Remember ``INTERFACE`` means things that consumers require but the producer -doesn't. Add the following lines to the end of ``MathFunctions/CMakeLists.txt``: +doesn't. Add the following lines to the end of +``MathFunctions/CMakeLists.txt``: .. literalinclude:: Step4/MathFunctions/CMakeLists.txt :language: cmake @@ -281,9 +288,10 @@ And here: :language: cmake :start-after: # so that we will find TutorialConfig.h -Once this is done, run **cmake** or **cmake-gui** to configure the project -and then build it with your chosen build tool or by using ``cmake --build .`` -from the build directory. +Once this is done, run the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it +with your chosen build tool or by using ``cmake --build .`` from the build +directory. Installing and Testing (Step 4) =============================== @@ -312,16 +320,17 @@ And to the end of the top-level ``CMakeLists.txt`` we add: That is all that is needed to create a basic local install of the tutorial. -Run **cmake** or **cmake-gui** to configure the project and then build it -with your chosen build tool. Run the install step by typing -``cmake --install .`` (introduced in 3.15, older versions of CMake must use -``make install``) from the command line, or build the ``INSTALL`` target from -an IDE. This will install the appropriate header files, libraries, and -executables. - -The CMake variable ``CMAKE_INSTALL_PREFIX`` is used to determine the root of -where the files will be installed. If using ``cmake --install`` a custom -installation directory can be given via ``--prefix`` argument. For +Run the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it +with your chosen build tool. Run the install step by using the ``install`` +option of the :manual:`cmake <cmake(1)>` command (introduced in 3.15, older +versions of CMake must use ``make install``) from the command line, or build +the ``INSTALL`` target from an IDE. This will install the appropriate header +files, libraries, and executables. + +The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the +root of where the files will be installed. If using ``cmake --install`` a +custom installation directory can be given via the ``--prefix`` argument. For multi-configuration tools, use the ``--config`` argument to specify the configuration. @@ -339,25 +348,25 @@ the application is working correctly. :start-after: # enable testing The first test simply verifies that the application runs, does not segfault or -otherwise crash, and has a zero return value. This is the basic form of a CTest -test. +otherwise crash, and has a zero return value. This is the basic form of a +CTest test. -The next test makes use of the ``PASS_REGULAR_EXPRESSION`` test property to -verify that the output of the test contains certain strings. In this case, -verifying that the usage message is printed when an incorrect number of -arguments are provided. +The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test +property to verify that the output of the test contains certain strings. In +this case, verifying that the usage message is printed when an incorrect number +of arguments are provided. Lastly, we have a function called ``do_test`` that runs the application and verifies that the computed square root is correct for given input. For each invocation of ``do_test``, another test is added to the project with a name, input, and expected results based on the passed arguments. -Rebuild the application and then cd to the binary directory and run -``ctest -N`` and ``ctest -VV``. For multi-config generators (e.g. Visual -Studio), the configuration type must be specified. To run tests in Debug mode, -for example, use ``ctest -C Debug -VV`` from the build directory (not the -Debug subdirectory!). Alternatively, build the ``RUN_TESTS`` target from the -IDE. +Rebuild the application and then cd to the binary directory and run the +:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For +multi-config generators (e.g. Visual Studio), the configuration type must be +specified. To run tests in Debug mode, for example, use ``ctest -C Debug -VV`` +from the build directory (not the Debug subdirectory!). Alternatively, build +the ``RUN_TESTS`` target from the IDE. Adding System Introspection (Step 5) ==================================== @@ -370,7 +379,7 @@ tutorial assume that they are not common. If the platform has ``log`` and ``exp`` then we will use them to compute the square root in the ``mysqrt`` function. We first test for the availability of -these functions using the ``CheckSymbolExists`` module in the top-level +these functions using the :module:`CheckSymbolExists` module in the top-level ``CMakeLists.txt``. We're going to use the new defines in ``TutorialConfig.h.in``, so be sure to set them before that file is configured. @@ -388,22 +397,29 @@ from ``mysqrt.cxx``: #cmakedefine HAVE_LOG #cmakedefine HAVE_EXP -Modify ``mysqrt.cxx`` to include cmath. Next, in that same file in the -``mysqrt`` function we can provide an alternate implementation based on -``log`` and ``exp`` if they are available on the system using the following -code (don't forget the ``#endif`` before returning the result!): +If ``log`` and ``exp`` are available on the system, then we will use them to +compute the square root in the ``mysqrt`` function. Add the following code to +the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the +``#endif`` before returning the result!): .. literalinclude:: Step6/MathFunctions/mysqrt.cxx :language: c++ :start-after: // if we have both log and exp then use them :end-before: // do ten iterations -Run **cmake** or **cmake-gui** to configure the project and then build it +We will also need to modify ``mysqrt.cxx`` to include ``cmath``. + +.. literalinclude:: Step6/MathFunctions/mysqrt.cxx + :language: c++ + :end-before: #include <iostream> + +Run the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool and run the Tutorial executable. You will notice that we're not using ``log`` and ``exp``, even if we think they -should be available. We should realize quickly that we have forgotten to include -``TutorialConfig.h`` in ``mysqrt.cxx``. +should be available. We should realize quickly that we have forgotten to +include ``TutorialConfig.h`` in ``mysqrt.cxx``. We will also need to update ``MathFunctions/CMakeLists.txt`` so ``mysqrt.cxx`` knows where this file is located: @@ -415,10 +431,10 @@ knows where this file is located: PRIVATE ${CMAKE_BINARY_DIR} ) -After making this update, go ahead and build the project again and run the built -Tutorial executable. If ``log`` and ``exp`` are still not being used, open the -generated ``TutorialConfig.h`` file from the build directory. Maybe they aren't -available on the current system? +After making this update, go ahead and build the project again and run the +built Tutorial executable. If ``log`` and ``exp`` are still not being used, +open the generated ``TutorialConfig.h`` file from the build directory. Maybe +they aren't available on the current system? Which function gives better results now, sqrt or mysqrt? @@ -427,7 +443,7 @@ Specify Compile Definition Is there a better place for us to save the ``HAVE_LOG`` and ``HAVE_EXP`` values other than in ``TutorialConfig.h``? Let's try to use -``target_compile_definitions``. +:command:`target_compile_definitions`. First, remove the defines from ``TutorialConfig.h.in``. We no longer need to include ``TutorialConfig.h`` from ``mysqrt.cxx`` or the extra include in @@ -460,8 +476,8 @@ First, let's remove the check for the ``log`` and ``exp`` functions in ``HAVE_EXP`` from ``mysqrt.cxx``. At the same time, we can remove :code:`#include <cmath>`. -In the ``MathFunctions`` subdirectory, a new source file named ``MakeTable.cxx`` -has been provided to generate the table. +In the ``MathFunctions`` subdirectory, a new source file named +``MakeTable.cxx`` has been provided to generate the table. After reviewing the file, we can see that the table is produced as valid C++ code and that the output filename is passed in as an argument. @@ -510,7 +526,8 @@ Now let's use the generated table. First, modify ``mysqrt.cxx`` to include :language: c++ :start-after: // a hack square root calculation using simple operations -Run **cmake** or **cmake-gui** to configure the project and then build it +Run the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool. When this project is built it will first build the ``MakeTable`` executable. @@ -530,26 +547,28 @@ previously in `Installing and Testing (Step 4)`_ , where we were installing the binaries that we had built from the source code. In this example we will be building installation packages that support binary installations and package management features. To accomplish this we will use -CPack to create platform specific installers. Specifically we need to add -a few lines to the bottom of our top-level ``CMakeLists.txt`` file. +CPack to create platform specific installers. Specifically we need to add a +few lines to the bottom of our top-level ``CMakeLists.txt`` file. .. literalinclude:: Step8/CMakeLists.txt :language: cmake :start-after: # setup installer That is all there is to it. We start by including -``InstallRequiredSystemLibraries``. This module will include any runtime -libraries that are needed by the project for the current platform. Next we -set some CPack variables to where we have stored the license and version +:module:`InstallRequiredSystemLibraries`. This module will include any runtime +libraries that are needed by the project for the current platform. Next we set +some CPack variables to where we have stored the license and version information for this project. The version information was set earlier in this tutorial and the ``license.txt`` has been included in the top-level source directory for this step. -Finally we include the CPack module which will use these variables and some -other properties of the current system to setup an installer. +Finally we include the :module:`CPack module <CPack>` which will use these +variables and some other properties of the current system to setup an +installer. -The next step is to build the project in the usual manner and then run -CPack on it. To build a binary distribution, from the binary directory run: +The next step is to build the project in the usual manner and then run the +:manual:`cpack <cpack(1)>` executable. To build a binary distribution, from the +binary directory run: .. code-block:: console @@ -571,16 +590,17 @@ To create a source distribution you would type: Alternatively, run ``make package`` or right click the ``Package`` target and ``Build Project`` from an IDE. -Run the installer found in the binary directory. Then run the -installed executable and verify that it works. +Run the installer found in the binary directory. Then run the installed +executable and verify that it works. Adding Support for a Dashboard (Step 8) ======================================= -Adding support for submitting our test results to a dashboard is very easy. We +Adding support for submitting our test results to a dashboard is simple. We already defined a number of tests for our project in `Testing Support`_. Now we just have to run those tests and submit them to a dashboard. To include support -for dashboards we include the CTest module in our top-level ``CMakeLists.txt``. +for dashboards we include the :module:`CTest` module in our top-level +``CMakeLists.txt``. Replace: @@ -596,8 +616,8 @@ With: # enable dashboard scripting include(CTest) -The CTest module will automatically call ``enable_testing()``, so -we can remove it from our CMake files. +The :module:`CTest` module will automatically call ``enable_testing()``, so we +can remove it from our CMake files. We will also need to create a ``CTestConfig.cmake`` file in the top-level directory where we can specify the name of the project and where to submit the @@ -606,9 +626,11 @@ dashboard. .. literalinclude:: Step9/CTestConfig.cmake :language: cmake -CTest will read in this file when it runs. To create a simple dashboard you can -run **cmake** or **cmake-gui** to configure the project, but do not build it -yet. Instead, change directory to the binary tree, and then run:: +The :manual:`ctest <ctest(1)>` executable will read in this file when it runs. +To create a simple dashboard you can run the :manual:`cmake <cmake(1)>` +executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project, +but do not build it yet. Instead, change directory to the binary tree, and then +run: ctest [-VV] -D Experimental @@ -619,26 +641,26 @@ type must be specified:: Or, from an IDE, build the ``Experimental`` target. -``ctest`` will build and test the project and submit the results to the Kitware -public dashboard. The results of your dashboard will be uploaded to Kitware's -public dashboard here: https://my.cdash.org/index.php?project=CMakeTutorial. +The :manual:`ctest <ctest(1)>` executable will build and test the project and +submit the results to Kitware's public dashboard: +https://my.cdash.org/index.php?project=CMakeTutorial. Mixing Static and Shared (Step 9) ================================= -In this section we will show how by using the ``BUILD_SHARED_LIBS`` variable -we can control the default behavior of ``add_library``, and allow control -over how libraries without an explicit type (``STATIC``, ``SHARED``, ``MODULE`` -or ``OBJECT``) are built. +In this section we will show how the :variable:`BUILD_SHARED_LIBS` variable can +be used to control the default behavior of :command:`add_library`, +and allow control over how libraries without an explicit type (``STATIC``, +``SHARED``, ``MODULE`` or ``OBJECT``) are built. -To accomplish this we need to add ``BUILD_SHARED_LIBS`` to the top-level -``CMakeLists.txt``. We use the ``option`` command as it allows users to -optionally select if the value should be On or Off. +To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the +top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows +users to optionally select if the value should be ON or OFF. Next we are going to refactor MathFunctions to become a real library that encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling code to do this logic. This will also mean that ``USE_MYMATH`` will not control -building MathFuctions, but instead will control the behavior of this library. +building MathFunctions, but instead will control the behavior of this library. The first step is to update the starting section of the top-level ``CMakeLists.txt`` to look like: @@ -680,8 +702,8 @@ Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: At this point, if you build everything, you will notice that linking fails as we are combining a static library without position independent code with a library that has position independent code. The solution to this is to -explicitly set the ``POSITION_INDEPENDENT_CODE`` target property of SqrtLibrary -to be True no matter the build type. +explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of +SqrtLibrary to be True no matter the build type. .. literalinclude:: Step10/MathFunctions/CMakeLists.txt :language: cmake @@ -694,35 +716,39 @@ Using CMake documentation can you find a helper module to simplify this? Adding Generator Expressions (Step 10) ====================================== -Generator expressions are evaluated during build system generation to produce -information specific to each build configuration. +:manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated +during build system generation to produce information specific to each build +configuration. -Generator expressions are allowed in the context of many target properties, -such as ``LINK_LIBRARIES``, ``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` -and others. They may also be used when using commands to populate those -properties, such as ``target_link_libraries()``, -``target_include_directories()``, -``target_compile_definitions()`` and others. +:manual:`Generator expressions <cmake-generator-expressions(7)>` are allowed in +the context of many target properties, such as :prop_tgt:`LINK_LIBRARIES`, +:prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and others. +They may also be used when using commands to populate those properties, such as +:command:`target_link_libraries`, :command:`target_include_directories`, +:command:`target_compile_definitions` and others. -Generator expressions may be used to enable conditional linking, conditional -definitions used when compiling, conditional include directories and more. -The conditions may be based on the build configuration, target properties, -platform information or any other queryable information. +:manual:`Generator expressions <cmake-generator-expressions(7)>` may be used +to enable conditional linking, conditional definitions used when compiling, +conditional include directories and more. The conditions may be based on the +build configuration, target properties, platform information or any other +queryable information. -There are different types of generator expressions including Logical, -Informational, and Output expressions. +There are different types of +:manual:`generator expressions <cmake-generator-expressions(7)>` including +Logical, Informational, and Output expressions. Logical expressions are used to create conditional output. The basic expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty string, and ``<1:...>`` results in the content of "...". They can also be nested. -A common usage of generator expressions is to conditionally add compiler -flags, such as those for language levels or warnings. A nice pattern is -to associate this information to an ``INTERFACE`` target allowing this -information to propagate. Lets start by constructing an ``INTERFACE`` -target and specifying the required C++ standard level of ``11`` instead -of using ``CMAKE_CXX_STANDARD``. +A common usage of +:manual:`generator expressions <cmake-generator-expressions(7)>` is to +conditionally add compiler flags, such as those for language levels or +warnings. A nice pattern is to associate this information to an ``INTERFACE`` +target allowing this information to propagate. Lets start by constructing an +``INTERFACE`` target and specifying the required C++ standard level of ``11`` +instead of using :variable:`CMAKE_CXX_STANDARD`. So the following code: @@ -739,11 +765,10 @@ Would be replaced with: :end-before: # add compiler warning flags just when building this project via -Next we add the desired compiler warning flags that we want for our -project. As warning flags vary based on the compiler we use -the ``COMPILE_LANG_AND_ID`` generator expression to control which -flags to apply given a language and a set of compiler ids as seen -below: +Next we add the desired compiler warning flags that we want for our project. As +warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID`` +generator expression to control which flags to apply given a language and a set +of compiler ids as seen below: .. literalinclude:: Step11/CMakeLists.txt :language: cmake @@ -755,8 +780,8 @@ Looking at this we see that the warning flags are encapsulated inside a project will not inherit our warning flags. -**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that -all targets have a ``target_link_libraries()`` call to ``tutorial_compiler_flags``. +**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have +a :command:`target_link_libraries` call to ``tutorial_compiler_flags``. Adding Export Configuration (Step 11) @@ -771,12 +796,12 @@ The next step is to add the necessary information so that other CMake projects can use our project, be it from a build directory, a local install or when packaged. -The first step is to update our ``install(TARGETS)`` commands to not only -specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword +The first step is to update our :command:`install(TARGETS)` commands to not +only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword generates and installs a CMake file containing code to import all targets -listed in the install command from the installation tree. So let's go ahead -and explicitly ``EXPORT`` the MathFunctions library by updating the -``install`` command in ``MathFunctions/CMakeLists.txt`` to look like: +listed in the install command from the installation tree. So let's go ahead and +explicitly ``EXPORT`` the MathFunctions library by updating the ``install`` +command in ``MathFunctions/CMakeLists.txt`` to look like: .. literalinclude:: Complete/MathFunctions/CMakeLists.txt :language: cmake @@ -806,12 +831,12 @@ you will see that CMake will generate an error that looks like: What CMake is trying to say is that during generating the export information it will export a path that is intrinsically tied to the current machine and will not be valid on other machines. The solution to this is to update the -MathFunctions ``target_include_directories`` to understand that it needs +MathFunctions :command:`target_include_directories` to understand that it needs different ``INTERFACE`` locations when being used from within the build directory and from an install / package. This means converting the -``target_include_directories`` call for MathFunctions to look like: +:command:`target_include_directories` call for MathFunctions to look like: -.. literalinclude:: Complete/MathFunctions/CMakeLists.txt +.. literalinclude:: Step12/MathFunctions/CMakeLists.txt :language: cmake :start-after: # to find MathFunctions.h, while we don't. :end-before: # should we use our own math functions @@ -821,16 +846,16 @@ warn anymore. At this point, we have CMake properly packaging the target information that is required but we will still need to generate a ``MathFunctionsConfig.cmake`` so -that the CMake ``find_package`` command can find our project. So let's go +that the CMake :command:`find_package` command can find our project. So let's go ahead and add a new file to the top-level of the project called ``Config.cmake.in`` with the following contents: -.. literalinclude:: Complete/Config.cmake.in +.. literalinclude:: Step12/Config.cmake.in Then, to properly configure and install that file, add the following to the bottom of the top-level ``CMakeLists.txt``: -.. literalinclude:: Complete/CMakeLists.txt +.. literalinclude:: Step12/CMakeLists.txt :language: cmake :start-after: # install the configuration targets :end-before: # generate the export @@ -840,7 +865,7 @@ project that can be used after the project has been installed or packaged. If we want our project to also be used from a build directory we only have to add the following to the bottom of the top level ``CMakeLists.txt``: -.. literalinclude:: Complete/CMakeLists.txt +.. literalinclude:: Step12/CMakeLists.txt :language: cmake :start-after: # needs to be after the install(TARGETS ) command @@ -848,55 +873,81 @@ With this export call we now generate a ``Targets.cmake``, allowing the configured ``MathFunctionsConfig.cmake`` in the build directory to be used by other projects, without needing it to be installed. -Import a CMake Project (Consumer) -================================= +Packaging Debug and Release (Step 12) +===================================== -This example shows how a project can find other CMake packages that -generate ``Config.cmake`` files. +**Note:** This example is valid for single-configuration generators and will +not work for multi-configuration generators (e.g. Visual Studio). -It also shows how to state a project's external dependencies when generating -a ``Config.cmake``. +By default, CMake's model is that a build directory only contains a single +configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is +possible, however, to setup CPack to bundle multiple build directories and +construct a package that contains multiple configurations of the same project. -Packaging Debug and Release (MultiPackage) -========================================== +First, we want to ensure that the debug and release builds use different names +for the executables and libraries that will be installed. Let's use `d` as the +postfix for the debug executable and libraries. -By default CMake's model is that a build directory only contains a single -configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. +Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level +``CMakeLists.txt`` file: -But it is possible to setup CPack to bundle multiple build directories at the -same time to build a package that contains multiple configurations of the -same project. +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: project(Tutorial VERSION 1.0) + :end-before: target_compile_features(tutorial_compiler_flags + +And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable: + +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: # add the executable + :end-before: # add the binary tree to the search path for include files + +Let's also add version numbering to the MathFunctions library. In +``MathFunctions/CMakeLists.txt``, set the :prop_tgt:`VERSION` and +:prop_tgt:`SOVERSION` properties: -First we need to construct a directory called ``multi_config``, which -will contain all the builds that we want to package together. +.. literalinclude:: Complete/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # setup the version numbering + :end-before: # install rules -Second create a ``debug`` and ``release`` directory underneath -``multi_config``. At the end you should have a layout that looks like: +From the ``Step12`` directory, create ``debug`` and ``release`` +subbdirectories. The layout will look like: .. code-block:: none - ─ multi_config - ├── debug - └── release + - Step12 + └── debug + └── release -Now we need to setup debug and release builds, which would roughly entail -the following: +Now we need to setup debug and release builds. We can use +:variable:`CMAKE_BUILD_TYPE` to set the configuration type: .. code-block:: console cd debug - cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/ + cmake -DCMAKE_BUILD_TYPE=Debug .. cmake --build . cd ../release - cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/ + cmake -DCMAKE_BUILD_TYPE=Release .. cmake --build . - cd .. +Now that both the debug and release builds are complete, we can use a custom +configuration file to package both builds into a single release. In the +``Step12`` directory, create a file called ``MultiCPackConfig.cmake``. In this +file, first include the default configuration file that was created by the +:manual:`cmake <cmake(1)>` executable. + +Next, use the ``CPACK_INSTALL_CMAKE_PROJECTS`` variable to specify which +projects to install. In this case, we want to install both debug and release. + +.. literalinclude:: Complete/MultiCPackConfig.cmake + :language: cmake -Now that both the debug and release builds are complete, we can use -a custom ``MultiCPackConfig.cmake`` file to package both builds into a single -release. +From the ``Step12`` directory, run :manual:`cpack <cpack(1)>` specifying our +custom configuration file with the ``config`` option: .. code-block:: console - cpack --config ../../MultiPackage/MultiCPackConfig.cmake + cpack --config MultiCPackConfig.cmake diff --git a/Help/guide/user-interaction/GUI-Add-Entry.png b/Help/guide/user-interaction/GUI-Add-Entry.png Binary files differnew file mode 100644 index 0000000..1e9be7e --- /dev/null +++ b/Help/guide/user-interaction/GUI-Add-Entry.png diff --git a/Help/guide/user-interaction/GUI-Choose-Generator.png b/Help/guide/user-interaction/GUI-Choose-Generator.png Binary files differnew file mode 100644 index 0000000..19ad2c0 --- /dev/null +++ b/Help/guide/user-interaction/GUI-Choose-Generator.png diff --git a/Help/guide/user-interaction/GUI-Configure-Dialog.png b/Help/guide/user-interaction/GUI-Configure-Dialog.png Binary files differnew file mode 100644 index 0000000..9839cac --- /dev/null +++ b/Help/guide/user-interaction/GUI-Configure-Dialog.png diff --git a/Help/guide/user-interaction/GUI-Source-Binary.png b/Help/guide/user-interaction/GUI-Source-Binary.png Binary files differnew file mode 100644 index 0000000..e338354 --- /dev/null +++ b/Help/guide/user-interaction/GUI-Source-Binary.png diff --git a/Help/guide/user-interaction/index.rst b/Help/guide/user-interaction/index.rst new file mode 100644 index 0000000..3a1038f --- /dev/null +++ b/Help/guide/user-interaction/index.rst @@ -0,0 +1,686 @@ +User Interaction Guide +********************** + +.. only:: html + + .. contents:: + +Introduction +============ + +Where a software package supplies a CMake-based buildsystem +with the source of their software, the consumer of the +software is required to run a CMake user interaction tool +in order to build it. + +Well-behaved CMake-based buildsystems do not create any +output in the source directory, so typically, the user +performs an out-of-source build and performs the build +there. First, CMake must be instructed to generate a +suitable buildsystem, then the user invokes a build tool +to process that generated buildsystem. The generated +buildsystem is specific to the machine used to generate +it and is not redistributable. Each consumer of a provided +source software package is required to use CMake to +generate a buildsystem specific to their system. + +Generated buildsystems should generally be treated as +read-only. The CMake files as a primary artifact should +completely specify the buildsystem and there should be no +reason to populate properties manually in an IDE for +example after generating the buildsystem. CMake will +periodically rewrite the generated buildsystem, so +modifications by users will be overwritten. + +The features and user interfaces described in this manual +are available for all CMake-based build systems by virtue +of providing CMake files. + +The CMake tooling may report errors to the user when +processing provided CMake files, such as reporting that +the compiler is not supported, or the compiler does not +support a required compile option, or a dependency can +not be found. These errors must be resolved by the user +by choosing a different compiler, +:guide:`installing dependencies <Using Dependencies Guide>`, +or instructing CMake where to find them, etc. + +Command Line cmake tool +----------------------- + +A simple but typical use of :manual:`cmake(1)` with a fresh +copy of software source code is to create a build directory +and invoke cmake there: + +.. code-block:: console + + $ cd some_software-1.4.2 + $ mkdir build + $ cd build + $ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/the/prefix + $ cmake --build . + $ cmake --build . --target install + +It is recommended to build in a separate directory to the +source because that keeps the source directory pristine, +allows for building a single source with multiple +toolchains, and allows easy clearing of build artifacts by +simply deleting the build directory. + +The CMake tooling may report warnings which are intended +for the provider of the software, not intended for the +consumer of the software. Such warnings end with "This +warning is for project developers". Users may disable +such warnings by passing the ``-Wno-dev`` flag to +:manual:`cmake(1)`. + +cmake-gui tool +-------------- + +Users more accustomed to GUI interfaces may use the +:manual:`cmake-gui(1)` tool to invoke CMake and generate +a buildsystem. + +The source and binary directories must first be +populated. It is always advised to use different +directories for the source and the build. + +.. image:: /guide/user-interaction/GUI-Source-Binary.png + +Generating a Buildsystem +======================== + +There are several user interface tools which may be used +to generate a buildsystem from CMake files. The +:manual:`ccmake(1)` and :manual:`cmake-gui(1)` tools guide +the user through setting the various necessary options. +The :manual:`cmake(1)` tool can be invoked to specify +options on the command line. This manual describes options +which may be set using any of the user interface tools, +though the mode of setting an option is different for each +tool. + +Command line environment +------------------------ + +When invoking :manual:`cmake(1)` with a command line +buildsystem such as ``Makefiles`` or ``Ninja``, it is +necessary to use the correct build environment to +ensure that build tools are available. CMake must be +able to find the appropriate +:variable:`build tool <CMAKE_MAKE_PROGRAM>`, +compiler, linker and other tools as needed. + +On Linux systems, the appropriate tools are often +provided in system-wide locations and may be readily +installed through the system package manager. Other +toolchains provided by the user or installed in +non-default locations can also be used. + +When cross-compiling, some platforms may require +environment variables to be set or may provide +scripts to set the environment. + +Visual Studio ships multiple command prompts and +``vcvarsall.bat`` scripts for setting up the +correct environments for command line buildsystems. While +not strictly necessary to use a corresponding +command line environment when using a Visual Studio +generator, doing so has no disadvantages. + +When using Xcode, there can be more than one Xcode +version installed. Which one to use can be selected +in a number of different ways, but the most common +methods are: + +* Setting the default version in the preferences + of the Xcode IDE. +* Setting the default version via the ``xcode-select`` + command line tool. +* Overriding the default version by setting the + ``DEVELOPER_DIR`` environment variable when running + CMake and the build tool. + +Command line ``-G`` option +-------------------------- + +CMake chooses a generator by default based on the +platform. Usually, the default generator is sufficient +to allow the user to proceed to build the software. + +The user may override the default generator with +the ``-G`` option: + +.. code-block:: console + + $ cmake .. -G Ninja + +The output of ``cmake --help`` includes a list of +:manual:`generators <cmake-generators(7)>` available +for the user to choose from. Note that generator +names are case sensitive. + +On Unix-like systems (including Mac OS X), the +:generator:`Unix Makefiles` generator is used by +default. A variant of that generator can also be used +on Windows in various environments, such as the +:generator:`NMake Makefiles` and +:generator:`MinGW Makefiles` generator. These generators +generate a ``Makefile`` variant which can be executed +with ``make``, ``gmake``, ``nmake`` or similar tools. +See the individual generator documentation for more +information on targeted environments and tools. + +The :generator:`Ninja` generator is available on all +major platforms. ``ninja`` is a build tool similar +in use-cases to ``make``, but with a focus on +performance and efficiency. + +On Windows, :manual:`cmake(1)` can be used to generate +solutions for the Visual Studio IDE. Visual Studio +versions may be specified by the product name of the +IDE, which includes a four-digit year. Aliases are +provided for other means by which Visual Studio +versions are sometimes referred to, such as two +digits which correspond to the product version of the +VisualC++ compiler, or a combination of the two: + +.. code-block:: console + + $ cmake .. -G "Visual Studio 2019" + $ cmake .. -G "Visual Studio 16" + $ cmake .. -G "Visual Studio 16 2019" + +Visual Studio generators can target different architectures. +One can specify the target architecture using the `-A` option: + +.. code-block:: console + + cmake .. -G "Visual Studio 2019" -A x64 + cmake .. -G "Visual Studio 16" -A ARM + cmake .. -G "Visual Studio 16 2019" -A ARM64 + +On Apple, the :generator:`Xcode` generator may be used to +generate project files for the Xcode IDE. + +Some IDEs such as KDevelop4, QtCreator and CLion have +native support for CMake-based buildsystems. Those IDEs +provide user interface for selecting an underlying +generator to use, typically a choice between a ``Makefile`` +or a ``Ninja`` based generator. + +Note that it is not possible to change the generator +with ``-G`` after the first invocation of CMake. To +change the generator, the build directory must be +deleted and the build must be started from scratch. + +When generating Visual Studio project and solutions +files several other options are available to use when +initially running :manual:`cmake(1)`. + +The Visual Studio toolset can be specified with the +``-T`` option: + +.. code-block:: console + + $ # Build with the clang-cl toolset + $ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T LLVM + $ # Build targeting Windows XP + $ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp + +Whereas the ``-A`` option specifies the _target_ +architecture, the ``-T`` option can be used to specify +details of the toolchain used. For example, `-Thost=x64` +can be given to select the 64-bit version of the host +tools. The following demonstrates how to use 64-bit +tools and also build for a 64-bit target architecture: + +.. code-block:: console + + $ cmake .. -G "Visual Studio 16 2019" -A x64 -Thost=x64 + +Choosing a generator in cmake-gui +--------------------------------- + +The "Configure" button triggers a new dialog to +select the CMake generator to use. + +.. image:: /guide/user-interaction/GUI-Configure-Dialog.png + +All generators available on the command line are also +available in :manual:`cmake-gui(1)`. + +.. image:: /guide/user-interaction/GUI-Choose-Generator.png + +When choosing a Visual Studio generator, further options +are available to set an architecture to generate for. + +.. image:: /manual/VS-Choose-Arch.png + +.. _`Setting Build Variables`: + +Setting Build Variables +======================= + +Software projects often require variables to be +set on the command line when invoking CMake. Some of +the most commonly used CMake variables are listed in +the table below: + +========================================== ============================================================ + Variable Meaning +========================================== ============================================================ + :variable:`CMAKE_PREFIX_PATH` Path to search for + :guide:`dependent packages <Using Dependencies Guide>` + :variable:`CMAKE_MODULE_PATH` Path to search for additional CMake modules + :variable:`CMAKE_BUILD_TYPE` Build configuration, such as + ``Debug`` or ``Release``, determining + debug/optimization flags. This is only + relevant for single-configuration buildsystems such + as ``Makefile`` and ``Ninja``. Multi-configuration + buildsystems such as those for Visual Studio and Xcode + ignore this setting. + :variable:`CMAKE_INSTALL_PREFIX` Location to install the + software to with the + ``install`` build target + :variable:`CMAKE_TOOLCHAIN_FILE` File containing cross-compiling + data such as + :manual:`toolchains and sysroots <cmake-toolchains(7)>`. + :variable:`BUILD_SHARED_LIBS` Whether to build shared + instead of static libraries + for :command:`add_library` + commands used without a type + :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` Generate a ``compile_commands.json`` + file for use with clang-based tools +========================================== ============================================================ + +Other project-specific variables may be available +to control builds, such as enabling or disabling +components of the project. + +There is no convention provided by CMake for how +such variables are named between different +provided buildsystems, except that variables with +the prefix ``CMAKE_`` usually refer to options +provided by CMake itself and should not be used +in third-party options, which should use +their own prefix instead. The +:manual:`cmake-gui(1)` tool can display options +in groups defined by their prefix, so it makes +sense for third parties to ensure that they use a +self-consistent prefix. + +Setting variables on the command line +------------------------------------- + +CMake variables can be set on the command line either +when creating the initial build: + +.. code-block:: console + + $ mkdir build + $ cd build + $ cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug + +or later on a subsequent invocation of +:manual:`cmake(1)`: + +.. code-block:: console + + $ cd build + $ cmake . -DCMAKE_BUILD_TYPE=Debug + +The ``-U`` flag may be used to unset variables +on the :manual:`cmake(1)` command line: + +.. code-block:: console + + $ cd build + $ cmake . -UMyPackage_DIR + +A CMake buildsystem which was initially created +on the command line can be modified using the +:manual:`cmake-gui(1)` and vice-versa. + +The :manual:`cmake(1)` tool allows specifying a +file to use to populate the initial cache using +the ``-C`` option. This can be useful to simplify +commands and scripts which repeatedly require the +same cache entries. + +Setting variables with cmake-gui +-------------------------------- + +Variables may be set in the cmake-gui using the "Add Entry" +button. This triggers a new dialog to set the value of +the variable. + +.. image:: /guide/user-interaction/GUI-Add-Entry.png + +The main view of the :manual:`cmake-gui(1)` user interface +can be used to edit existing variables. + +The CMake Cache +--------------- + +When CMake is executed, it needs to find the locations of +compilers, tools and dependencies. It also needs to be +able to consistently re-generate a buildsystem to use the +same compile/link flags and paths to dependencies. Such +parameters are also required to be configurable by the +user because they are paths and options specific to the +users system. + +When it is first executed, CMake generates a +``CMakeCache.txt`` file in the build directory containing +key-value pairs for such artifacts. The cache file can be +viewed or edited by the user by running the +:manual:`cmake-gui(1)` or :manual:`ccmake(1)` tool. The +tools provide an interactive interface for re-configuring +the provided software and re-generating the buildsystem, +as is needed after editing cached values. Each cache +entry may have an associated short help text which is +displayed in the user interface tools. + +The cache entries may also have a type to signify how it +should be presented in the user interface. For example, +a cache entry of type ``BOOL`` can be edited by a +checkbox in a user interface, a ``STRING`` can be edited +in a text field, and a ``FILEPATH`` while similar to a +``STRING`` should also provide a way to locate filesystem +paths using a file dialog. An entry of type ``STRING`` +may provide a restricted list of allowed values which are +then provided in a drop-down menu in the +:manual:`cmake-gui(1)` user interface (see the +:prop_cache:`STRINGS` cache property). + +The CMake files shipped with a software package may also +define boolean toggle options using the :command:`option` +command. The command creates a cache entry which has a +help text and a default value. Such cache entries are +typically specific to the provided software and affect +the configuration of the build, such as whether tests +and examples are built, whether to build with exceptions +enabled etc. + +Invoking the Buildsystem +======================== + +After generating the buildsystem, the software can be +built by invoking the particular build tool. In the +case of the IDE generators, this can involve loading +the generated project file into the IDE to invoke the +build. + +CMake is aware of the specific build tool needed to invoke +a build so in general, to build a buildsystem or project +from the command line after generating, the following +command may be invoked in the build directory: + +.. code-block:: console + + $ cmake --build . + +The ``--build`` flag enables a particular mode of +operation for the :manual:`cmake(1)` tool. It invokes +the :variable:`CMAKE_MAKE_PROGRAM` command associated +with the :manual:`generator <cmake-generators(7)>`, or +the build tool configured by the user. + +The ``--build`` mode also accepts the parameter +``--target`` to specify a particular target to build, +for example a particular library, executable or +custom target, or a particular special target like +``install``: + +.. code-block:: console + + $ cmake --build . --target myexe + +The ``--build`` mode also accepts a ``--config`` parameter +in the case of multi-config generators to specify which +particular configuration to build: + +.. code-block:: console + + $ cmake --build . --target myexe --config Release + +The ``--config`` option has no effect if the generator +generates a buildsystem specific to a configuration which +is chosen when invoking cmake with the +:variable:`CMAKE_BUILD_TYPE` variable. + +Some buildsystems omit details of command lines invoked +during the build. The ``--verbose`` flag can be used to +cause those command lines to be shown: + +.. code-block:: console + + $ cmake --build . --target myexe --verbose + +The ``--build`` mode can also pass particular command +line options to the underlying build tool by listing +them after ``--``. This can be useful to specify +options to the build tool, such as to continue the +build after a failed job, where CMake does not +provide a high-level user interface. + +For all generators, it is possible to run the underlying +build tool after invoking CMake. For example, ``make`` +may be executed after generating with the +:generator:`Unix Makefiles` generator to invoke the build, +or ``ninja`` after generating with the :generator:`Ninja` +generator etc. The IDE buildsystems usually provide +command line tooling for building a project which can +also be invoked. + +Selecting a Target +------------------ + +Each executable and library described in the CMake files +is a build target, and the buildsystem may describe +custom targets, either for internal use, or for user +consumption, for example to create documentation. + +CMake provides some built-in targets for all buildsystems +providing CMake files. + +``all`` + The default target used by ``Makefile`` and ``Ninja`` + generators. Builds all targets in the buildsystem, + except those which are excluded by their + :prop_tgt:`EXCLUDE_FROM_ALL` target property or + :prop_dir:`EXCLUDE_FROM_ALL` directory property. The + name ``ALL_BUILD`` is used for this purpose for the + Xcode and Visual Studio generators. +``help`` + Lists the targets available for build. This target is + available when using the :generator:`Unix Makefiles` or + :generator:`Ninja` generator, and the exact output is + tool-specific. +``clean`` + Delete built object files and other output files. The + ``Makefile`` based generators create a ``clean`` target + per directory, so that an individual directory can be + cleaned. The ``Ninja`` tool provides its own granular + ``-t clean`` system. +``test`` + Runs tests. This target is only automatically available + if the CMake files provide CTest-based tests. See also + `Running Tests`_. +``install`` + Installs the software. This target is only automatically + available if the software defines install rules with the + :command:`install` command. See also + `Software Installation`_. +``package`` + Creates a binary package. This target is only + automatically available if the CMake files provide + CPack-based packages. +``package_source`` + Creates a source package. This target is only + automatically available if the CMake files provide + CPack-based packages. + +For ``Makefile`` based systems, ``/fast`` variants of binary +build targets are provided. The ``/fast`` variants are used +to build the specified target without regard for its +dependencies. The dependencies are not checked and +are not rebuilt if out of date. The :generator:`Ninja` +generator is sufficiently fast at dependency checking that +such targets are not provided for that generator. + +``Makefile`` based systems also provide build-targets to +preprocess, assemble and compile individual files in a +particular directory. + +.. code-block:: console + + $ make foo.cpp.i + $ make foo.cpp.s + $ make foo.cpp.o + +The file extension is built into the name of the target +because another file with the same name but a different +extension may exist. However, build-targets without the +file extension are also provided. + +.. code-block:: console + + $ make foo.i + $ make foo.s + $ make foo.o + +In buildsystems which contain ``foo.c`` and ``foo.cpp``, +building the ``foo.i`` target will preprocess both files. + +Specifying a Build Program +-------------------------- + +The program invoked by the ``--build`` mode is determined +by the :variable:`CMAKE_MAKE_PROGRAM` variable. For most +generators, the particular program does not need to be +configured. + +===================== =========================== =========================== + Generator Default make program Alternatives +===================== =========================== =========================== + XCode ``xcodebuild`` + Unix Makefiles ``make`` + NMake Makefiles ``nmake`` ``jom`` + NMake Makefiles JOM ``jom`` ``nmake`` + MinGW Makefiles ``mingw32-make`` + MSYS Makefiles ``make`` + Ninja ``ninja`` + Visual Studio ``msbuild`` + Watcom WMake ``wmake`` +===================== =========================== =========================== + +The ``jom`` tool is capable of reading makefiles of the +``NMake`` flavor and building in parallel, while the +``nmake`` tool always builds serially. After generating +with the :generator:`NMake Makefiles` generator a user +can run ``jom`` instead of ``nmake``. The ``--build`` +mode would also use ``jom`` if the +:variable:`CMAKE_MAKE_PROGRAM` was set to ``jom`` while +using the :generator:`NMake Makefiles` generator, and +as a convenience, the :generator:`NMake Makefiles JOM` +generator is provided to find ``jom`` in the normal way +and use it as the :variable:`CMAKE_MAKE_PROGRAM`. For +completeness, ``nmake`` is an alternative tool which +can process the output of the +:generator:`NMake Makefiles JOM` generator, but doing +so would be a pessimisation. + +Software Installation +===================== + +The :variable:`CMAKE_INSTALL_PREFIX` variable can be +set in the CMake cache to specify where to install the +provided software. If the provided software has install +rules, specified using the :command:`install` command, +they will install artifacts into that prefix. On Windows, +the default installation location corresponds to the +``ProgramFiles`` system directory which may be +architecture specific. On Unix hosts, ``/usr/local`` is +the default installation location. + +The :variable:`CMAKE_INSTALL_PREFIX` variable always +refers to the installation prefix on the target +filesystem. + +In cross-compiling or packaging scenarios where the +sysroot is read-only or where the sysroot should otherwise +remain pristine, the :variable:`CMAKE_STAGING_PREFIX` +variable can be set to a location to actually install +the files. + +The commands: + +.. code-block:: console + + $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DCMAKE_SYSROOT=$HOME/root \ + -DCMAKE_STAGING_PREFIX=/tmp/package + $ cmake --build . + $ cmake --build . --target install + +result in files being installed to paths such +as ``/tmp/package/lib/libfoo.so`` on the host machine. +The ``/usr/local`` location on the host machine is +not affected. + +Some provided software may specify ``uninstall`` rules, +but CMake does not generate such rules by default itself. + +Running Tests +============= + +The :manual:`ctest(1)` tool is shipped with the CMake +distribution to execute provided tests and report +results. The ``test`` build-target is provided to run +all available tests, but the :manual:`ctest(1)` tool +allows granular control over which tests to run, how to +run them, and how to report results. Executing +:manual:`ctest(1)` in the build directory is equivalent +to running the ``test`` target: + +.. code-block:: console + + $ ctest + +A regular expression can be passed to run only tests +which match the expression. To run only tests with +``Qt`` in their name: + +.. code-block:: console + + $ ctest -R Qt + +Tests can be excluded by regular expression too. To +run only tests without ``Qt`` in their name: + +.. code-block:: console + + $ ctest -E Qt + +Tests can be run in parallel by passing ``-j`` arguments +to :manual:`ctest(1)`: + +.. code-block:: console + + $ ctest -R Qt -j8 + +The environment variable :envvar:`CTEST_PARALLEL_LEVEL` +can alternatively be set to avoid the need to pass +``-j``. + +By default :manual:`ctest(1)` does not print the output +from the tests. The command line argument ``-V`` (or +``--verbose``) enables verbose mode to print the +output from all tests. +The ``--output-on-failure`` option prints the test +output for failing tests only. The environment variable +:envvar:`CTEST_OUTPUT_ON_FAILURE` +can be set to ``1`` as an alternative to passing the +``--output-on-failure`` option to :manual:`ctest(1)`. diff --git a/Help/guide/using-dependencies/index.rst b/Help/guide/using-dependencies/index.rst new file mode 100644 index 0000000..6fdcc55 --- /dev/null +++ b/Help/guide/using-dependencies/index.rst @@ -0,0 +1,200 @@ +Using Dependencies Guide +************************ + +.. only:: html + + .. contents:: + +Introduction +============ + +For developers wishing to use CMake to consume a third +party binary package, there are multiple possibilities +regarding how to optimally do so, depending on how +CMake-aware the third-party library is. + +CMake files provided with a software package contain +instructions for finding each build dependency. Some +build dependencies are optional in that the build may +succeed with a different feature set if the dependency +is missing, and some dependencies are required. CMake +searches well-known locations for each dependency, and +the provided software may supply additional hints or +locations to CMake to find each dependency. + +If a required dependency is not found by +:manual:`cmake(1)`, the cache is populated with an entry +which contains a ``NOTFOUND`` value. This value can be +replaced by specifying it on the command line, or in +the :manual:`ccmake(1)` or :manual:`cmake-gui(1)` tool. +See the :guide:`User Interaction Guide` for +more about setting cache entries. + +Libraries providing Config-file packages +---------------------------------------- + +The most convenient way for a third-party to provide library +binaries for use with CMake is to provide +:ref:`Config File Packages`. These packages are text files +shipped with the library which instruct CMake how to use the +library binaries and associated headers, helper tools and +CMake macros provided by the library. + +The config files can usually be found in a directory whose +name matches the pattern ``lib/cmake/<PackageName>``, though +they may be in other locations instead. The +``<PackageName>`` corresponds to use in CMake code with the +:command:`find_package` command such as +``find_package(PackageName REQUIRED)``. + +The ``lib/cmake/<PackageName>`` directory will contain a +file which is either named ``<PackageName>Config.cmake`` +or ``<PackageName>-config.cmake``. This is the entry point +to the package for CMake. A separate optional file named +``<PackageName>ConfigVersion.cmake`` may also exist in the +directory. This file is used by CMake to determine whether +the version of the third party package satisfies uses of the +:command:`find_package` command which specify version +constraints. It is optional to specify a version when using +:command:`find_package`, even if a ``ConfigVersion`` file is +present. + +If the ``Config.cmake`` file is found and the +optionally-specified version is satisfied, then the CMake +:command:`find_package` command considers the package to be +found and the entire library package is assumed to be +complete as designed. + +There may be additional files providing CMake macros or +:ref:`imported targets` for you to use. CMake does not +enforce any naming convention for these +files. They are related to the primary ``Config`` file by +use of the CMake :command:`include` command. + +:guide:`Invoking CMake <User Interaction Guide>` with the +intent of using a package of third party binaries requires +that cmake :command:`find_package` commands succeed in finding +the package. If the location of the package is in a directory +known to CMake, the :command:`find_package` call should +succeed. The directories known to cmake are platform-specific. +For example, packages installed on Linux with a standard +system package manager will be found in the ``/usr`` prefix +automatically. Packages installed in ``Program Files`` on +Windows will similarly be found automatically. + +Packages which are not found automatically are in locations +not predictable to CMake such as ``/opt/mylib`` or +``$HOME/dev/prefix``. This is a normal situation and CMake +provides several ways for users to specify where to find +such libraries. + +The :variable:`CMAKE_PREFIX_PATH` variable may be +:ref:`set when invoking CMake <Setting Build Variables>`. +It is treated as a list of paths to search for +:ref:`Config File Packages`. A package installed in +``/opt/somepackage`` will typically install config files +such as +``/opt/somepackage/lib/cmake/somePackage/SomePackageConfig.cmake``. +In that case, ``/opt/somepackage`` should be added to +:variable:`CMAKE_PREFIX_PATH`. + +The environment variable ``CMAKE_PREFIX_PATH`` may also be +populated with prefixes to search for packages. Like the +``PATH`` environment variable, this is a list and needs to use +the platform-specific environment variable list item separator +(``:`` on Unix and ``;`` on Windows). + +The :variable:`CMAKE_PREFIX_PATH` variable provides convenience +in cases where multiple prefixes need to be specified, or when +multiple different package binaries are available in the same +prefix. Paths to packages may also be specified by setting +variables matching ``<PackageName>_DIR``, such as +``SomePackage_DIR``. Note that this is not a prefix but should +be a full path to a directory containing a config-style package +file, such as ``/opt/somepackage/lib/cmake/SomePackage/`` in +the above example. + +Imported Targets from Packages +------------------------------ + +A third-party package which provides config-file packages may +also provide :ref:`Imported targets`. These will be +specified in files containing configuration-specific file +paths relevant to the package, such as debug and release +versions of libraries. + +Often the third-party package documentation will point out the +names of imported targets available after a successful +``find_package`` for a library. Those imported target names +can be used with the :command:`target_link_libraries` command. + +A complete example which makes a simple use of a third party +library might look like: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.10) + project(MyExeProject VERSION 1.0.0) + + find_package(SomePackage REQUIRED) + add_executable(MyExe main.cpp) + target_link_libraries(MyExe PRIVATE SomePrefix::LibName) + +See :manual:`cmake-buildsystem(7)` for further information +about developing a CMake buildsystem. + +Libraries not Providing Config-file Packages +-------------------------------------------- + +Third-party libraries which do not provide config-file packages +can still be found with the :command:`find_package` command, if +a ``FindSomePackage.cmake`` file is available. + +These module-file packages are different to config-file packages +in that: + +#. They should not be provided by the third party, except + perhaps in the form of documentation +#. The availability of a ``Find<PackageName>.cmake`` file does + not indicate the availability of the binaries themselves. +#. CMake does not search the :variable:`CMAKE_PREFIX_PATH` for + ``Find<PackageName>.cmake`` files. Instead CMake searches + for such files in the :variable:`CMAKE_MODULE_PATH` + variable. It is common for users to set the + :variable:`CMAKE_MODULE_PATH` when running CMake, and it is + common for CMake projects to append to + :variable:`CMAKE_MODULE_PATH` to allow use of local + module-file packages. +#. CMake ships ``Find<PackageName>.cmake`` files for some + :manual:`third party packages <cmake-modules(7)>` + for convenience in cases where the third party does + not provide config-file packages directly. These files are + a maintenance burden for CMake, so new Find modules are + generally not added to CMake anymore. Third-parties should + provide config file packages instead of relying on a Find + module to be provided by CMake. + +Module-file packages may also provide :ref:`Imported targets`. +A complete example which finds such a package might look +like: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.10) + project(MyExeProject VERSION 1.0.0) + + find_package(PNG REQUIRED) + + # Add path to a FindSomePackage.cmake file + list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + find_package(SomePackage REQUIRED) + + add_executable(MyExe main.cpp) + target_link_libraries(MyExe PRIVATE + PNG::PNG + SomePrefix::LibName + ) + +The :variable:`<PackageName>_ROOT` variable is also +searched as a prefix for :command:`find_package` calls using +module-file packages such as ``FindSomePackage``. diff --git a/Help/index.rst b/Help/index.rst index cc6cee6..4d9a9c8 100644 --- a/Help/index.rst +++ b/Help/index.rst @@ -1,5 +1,34 @@ .. title:: CMake Reference Documentation +Introduction +############ + +CMake is a tool to manage building of source code. Originally, CMake was +designed as a generator for various dialects of ``Makefile``, today +CMake generates modern buildsystems such as ``Ninja`` as well as project +files for IDEs such as Visual Studio and Xcode. + +CMake is widely used for the C and C++ languages, but it may be used to +build source code of other languages too. + +People encountering CMake for the first time may have different initial +goals. To learn how to build a source code package downloaded from the +internet, start with the :guide:`User Interaction Guide`. +This will detail the steps needed to run the :manual:`cmake(1)` or +:manual:`cmake-gui(1)` executable and how to choose a generator, and +how to complete the build. + +The :guide:`Using Dependencies Guide` is aimed at developers +wishing to get started using a third-party library. + +For developers starting a project using CMake, the :guide:`CMake Tutorial` +is a suitable starting point. The :manual:`cmake-buildsystem(7)` +manual is aimed at developers expanding their knowledge of maintaining +a buildsystem and becoming familiar with the build targets that +can be represented in CMake. The :manual:`cmake-packages(7)` manual +explains how to create packages which can easily be consumed by +third-party CMake-based buildsystems. + Command-Line Tools ################## @@ -53,6 +82,8 @@ Reference Manuals :maxdepth: 1 /guide/tutorial/index + /guide/user-interaction/index + /guide/using-dependencies/index .. only:: html or text diff --git a/Help/manual/VS-Choose-Arch.png b/Help/manual/VS-Choose-Arch.png Binary files differnew file mode 100644 index 0000000..816b0f4 --- /dev/null +++ b/Help/manual/VS-Choose-Arch.png diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 2118031..53cf264 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,8 @@ Policies Introduced by CMake 3.17 .. toctree:: :maxdepth: 1 + CMP0101: target_compile_options honors BEFORE keyword in all scopes. </policy/CMP0101> + CMP0100: Let AUTOMOC and AUTOUIC process .hh header files. </policy/CMP0100> CMP0099: Link properties are transitive over private dependency on static libraries. </policy/CMP0099> CMP0098: FindFLEX runs flex in CMAKE_CURRENT_BINARY_DIR when executing. </policy/CMP0098> diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index b9db12d..393735e 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -27,6 +27,8 @@ Properties of Global Scope /prop_gbl/CMAKE_ROLE /prop_gbl/DEBUG_CONFIGURATIONS /prop_gbl/DISABLED_FEATURES + /prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS + /prop_gbl/ECLIPSE_EXTRA_NATURES /prop_gbl/ENABLED_FEATURES /prop_gbl/ENABLED_LANGUAGES /prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS @@ -37,12 +39,10 @@ Properties of Global Scope /prop_gbl/GLOBAL_DEPENDS_DEBUG_MODE /prop_gbl/GLOBAL_DEPENDS_NO_CYCLES /prop_gbl/IN_TRY_COMPILE + /prop_gbl/JOB_POOLS /prop_gbl/PACKAGES_FOUND /prop_gbl/PACKAGES_NOT_FOUND - /prop_gbl/JOB_POOLS /prop_gbl/PREDEFINED_TARGETS_FOLDER - /prop_gbl/ECLIPSE_EXTRA_NATURES - /prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS /prop_gbl/REPORT_UNDEFINED_PROPERTIES /prop_gbl/RULE_LAUNCH_COMPILE /prop_gbl/RULE_LAUNCH_CUSTOM @@ -130,20 +130,20 @@ Properties on Targets /prop_tgt/AUTOGEN_ORIGIN_DEPENDS /prop_tgt/AUTOGEN_PARALLEL /prop_tgt/AUTOGEN_TARGET_DEPENDS + /prop_tgt/AUTOMOC /prop_tgt/AUTOMOC_COMPILER_PREDEFINES /prop_tgt/AUTOMOC_DEPEND_FILTERS /prop_tgt/AUTOMOC_EXECUTABLE /prop_tgt/AUTOMOC_MACRO_NAMES /prop_tgt/AUTOMOC_MOC_OPTIONS /prop_tgt/AUTOMOC_PATH_PREFIX - /prop_tgt/AUTOMOC + /prop_tgt/AUTORCC + /prop_tgt/AUTORCC_EXECUTABLE + /prop_tgt/AUTORCC_OPTIONS /prop_tgt/AUTOUIC /prop_tgt/AUTOUIC_EXECUTABLE /prop_tgt/AUTOUIC_OPTIONS /prop_tgt/AUTOUIC_SEARCH_PATHS - /prop_tgt/AUTORCC - /prop_tgt/AUTORCC_EXECUTABLE - /prop_tgt/AUTORCC_OPTIONS /prop_tgt/BINARY_DIR /prop_tgt/BUILD_RPATH /prop_tgt/BUILD_RPATH_USE_ORIGIN @@ -183,6 +183,7 @@ Properties on Targets /prop_tgt/DEFINE_SYMBOL /prop_tgt/DEPLOYMENT_REMOTE_DIRECTORY /prop_tgt/DEPLOYMENT_ADDITIONAL_FILES + /prop_tgt/DEPRECATION /prop_tgt/DISABLE_PRECOMPILE_HEADERS /prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION /prop_tgt/EchoString @@ -252,6 +253,7 @@ Properties on Targets /prop_tgt/IOS_INSTALL_COMBINED /prop_tgt/JOB_POOL_COMPILE /prop_tgt/JOB_POOL_LINK + /prop_tgt/JOB_POOL_PRECOMPILE_HEADER /prop_tgt/LABELS /prop_tgt/LANG_CLANG_TIDY /prop_tgt/LANG_COMPILER_LAUNCHER @@ -445,8 +447,8 @@ Properties on Source Files :maxdepth: 1 /prop_sf/ABSTRACT - /prop_sf/AUTOUIC_OPTIONS /prop_sf/AUTORCC_OPTIONS + /prop_sf/AUTOUIC_OPTIONS /prop_sf/COMPILE_DEFINITIONS /prop_sf/COMPILE_FLAGS /prop_sf/COMPILE_OPTIONS diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 74dd1fb..a8fbc09 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -65,6 +65,7 @@ Variables that Provide Information /variable/CMAKE_IMPORT_LIBRARY_SUFFIX /variable/CMAKE_JOB_POOL_COMPILE /variable/CMAKE_JOB_POOL_LINK + /variable/CMAKE_JOB_POOL_PRECOMPILE_HEADER /variable/CMAKE_JOB_POOLS /variable/CMAKE_LANG_COMPILER_AR /variable/CMAKE_LANG_COMPILER_RANLIB @@ -215,7 +216,6 @@ Variables that Change Behavior /variable/CMAKE_MESSAGE_INDENT /variable/CMAKE_MESSAGE_LOG_LEVEL /variable/CMAKE_MODULE_PATH - /variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE /variable/CMAKE_POLICY_DEFAULT_CMPNNNN /variable/CMAKE_POLICY_WARNING_CMPNNNN /variable/CMAKE_PREFIX_PATH @@ -369,6 +369,7 @@ Variables that Control the Build /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX + /variable/CMAKE_CTEST_ARGUMENTS /variable/CMAKE_CUDA_SEPARABLE_COMPILATION /variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS /variable/CMAKE_DEBUG_POSTFIX @@ -423,6 +424,8 @@ Variables that Control the Build /variable/CMAKE_MODULE_LINKER_FLAGS_INIT /variable/CMAKE_MSVCIDE_RUN_PATH /variable/CMAKE_MSVC_RUNTIME_LIBRARY + /variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE + /variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE /variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX /variable/CMAKE_NO_BUILTIN_CHRPATH /variable/CMAKE_NO_SYSTEM_FROM_IMPORTED diff --git a/Help/policy/CMP0100.rst b/Help/policy/CMP0100.rst new file mode 100644 index 0000000..b24d013 --- /dev/null +++ b/Help/policy/CMP0100.rst @@ -0,0 +1,40 @@ +CMP0100 +------- + +Let :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` process +header files that end with a ``.hh`` extension. + +Since version 3.17, CMake processes header files that end with a +``.hh`` extension in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`. +In earlier CMake versions, these header files were ignored by +:prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`. + +This policy affects how header files that end with a ``.hh`` extension +get treated in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`. + +The ``OLD`` behavior for this policy is to ignore ``.hh`` header files +in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`. + +The ``NEW`` behavior for this policy is to process ``.hh`` header files +in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` just like other header files. + +.. note:: + + To silence the ``CMP0100`` warning source files can be excluded from + :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` processing by setting the + source file properties :prop_sf:`SKIP_AUTOMOC`, :prop_sf:`SKIP_AUTOUIC` or + :prop_sf:`SKIP_AUTOGEN`. + + .. code-block:: cmake + + # Source skip example: + set_property(SOURCE /path/to/file1.hh PROPERTY SKIP_AUTOMOC ON) + set_property(SOURCE /path/to/file2.hh PROPERTY SKIP_AUTOUIC ON) + set_property(SOURCE /path/to/file3.hh PROPERTY SKIP_AUTOGEN ON) + +This policy was introduced in CMake version 3.17.0. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/policy/CMP0101.rst b/Help/policy/CMP0101.rst new file mode 100644 index 0000000..9941acf --- /dev/null +++ b/Help/policy/CMP0101.rst @@ -0,0 +1,20 @@ +CMP0101 +------- + +:command:`target_compile_options` now honors ``BEFORE`` keyword in all scopes. + +In CMake 3.16 and below the :command:`target_compile_options` ignores the +``BEFORE`` keyword in private scope. CMake 3.17 and later honors +``BEFORE`` keyword in all scopes. This policy provides compatibility for +projects that have not been updated to expect the new behavior. + +The ``OLD`` behavior for this policy is to not honor ``BEFORE`` keyword in +private scope. The ``NEW`` behavior of this policy is to honor +``BEFORE`` keyword in all scopes. + +This policy was introduced in CMake version 3.17. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_tgt/AUTOGEN_PARALLEL.rst b/Help/prop_tgt/AUTOGEN_PARALLEL.rst index 07fbc5a..968b619 100644 --- a/Help/prop_tgt/AUTOGEN_PARALLEL.rst +++ b/Help/prop_tgt/AUTOGEN_PARALLEL.rst @@ -4,9 +4,9 @@ AUTOGEN_PARALLEL Number of parallel ``moc`` or ``uic`` processes to start when using :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`. -The custom `<origin>_autogen` target starts a number of threads of which +The custom ``<origin>_autogen`` target starts a number of threads of which each one parses a source file and on demand starts a ``moc`` or ``uic`` -process. :prop_tgt:`AUTOGEN_PARALLEL` controls how many parallel threads +process. ``AUTOGEN_PARALLEL`` controls how many parallel threads (and therefore ``moc`` or ``uic`` processes) are started. - An empty (or unset) value or the string ``AUTO`` sets the number of @@ -14,7 +14,7 @@ process. :prop_tgt:`AUTOGEN_PARALLEL` controls how many parallel threads - A positive non zero integer value sets the exact thread/process count. - Otherwise a single thread/process is started. -By default :prop_tgt:`AUTOGEN_PARALLEL` is initialized from +By default ``AUTOGEN_PARALLEL`` is initialized from :variable:`CMAKE_AUTOGEN_PARALLEL`. See the :manual:`cmake-qt(7)` manual for more information on using CMake diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index f6dfabd..c18859b 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -172,7 +172,7 @@ variables. If the call is in a different context than the then the version variables might not be available to the :prop_tgt:`AUTOMOC` enabled target. In that case the version variables can be forwarded from the -`find_package(Qt[45]...)` calling context to the :command:`add_executable` +``find_package(Qt[45]...)`` calling context to the :command:`add_executable` or :command:`add_library` calling context as directory properties. The following Qt5 example demonstrates the procedure. diff --git a/Help/prop_tgt/AUTOMOC_MOC_OPTIONS.rst b/Help/prop_tgt/AUTOMOC_MOC_OPTIONS.rst index ebd5c49..330849b 100644 --- a/Help/prop_tgt/AUTOMOC_MOC_OPTIONS.rst +++ b/Help/prop_tgt/AUTOMOC_MOC_OPTIONS.rst @@ -1,7 +1,7 @@ AUTOMOC_MOC_OPTIONS ------------------- -Additional options for moc when using :prop_tgt:`AUTOMOC` +Additional options for ``moc`` when using :prop_tgt:`AUTOMOC` This property is only used if the :prop_tgt:`AUTOMOC` property is ``ON`` for this target. In this case, it holds additional command line @@ -9,7 +9,9 @@ options which will be used when ``moc`` is executed during the build, i.e. it is equivalent to the optional ``OPTIONS`` argument of the :module:`qt4_wrap_cpp() <FindQt4>` macro. -By default it is empty. +This property is initialized by the value of the +:variable:`CMAKE_AUTOMOC_MOC_OPTIONS` variable if it is set when a target +is created, or an empty string otherwise. See the :manual:`cmake-qt(7)` manual for more information on using CMake with Qt. diff --git a/Help/prop_tgt/AUTOMOC_PATH_PREFIX.rst b/Help/prop_tgt/AUTOMOC_PATH_PREFIX.rst index e2ebb3f..3e3059d 100644 --- a/Help/prop_tgt/AUTOMOC_PATH_PREFIX.rst +++ b/Help/prop_tgt/AUTOMOC_PATH_PREFIX.rst @@ -21,11 +21,11 @@ with Qt. Reproducible builds ^^^^^^^^^^^^^^^^^^^ -For reproducible builds is is recommended to keep headers that are ``moc`` +For reproducible builds it is recommended to keep headers that are ``moc`` compiled in one of the target :command:`include directories <target_include_directories>` and set :prop_tgt:`AUTOMOC_PATH_PREFIX` to ``ON`` (which is the default). This ensures -that +that: - ``moc`` output files are identical on different build setups, - ``moc`` output files will compile correctly when the source and/or diff --git a/Help/prop_tgt/AUTORCC.rst b/Help/prop_tgt/AUTORCC.rst index cca3e58..9a98f44 100644 --- a/Help/prop_tgt/AUTORCC.rst +++ b/Help/prop_tgt/AUTORCC.rst @@ -31,9 +31,10 @@ Modifiers The ``rcc`` executable will be detected automatically, but can be forced to a certain binary by setting this target property. -:prop_sf:`AUTORCC_OPTIONS`: -Additional command line options for ``rcc`` can be set via this ``.qrc`` -source file property. +:prop_tgt:`AUTORCC_OPTIONS`: +Additional command line options for ``rcc`` can be set via this target +property. The corresponding :prop_sf:`AUTORCC_OPTIONS` source file property +can be used to specify options to be applied only to a specific ``.qrc`` file. :prop_sf:`SKIP_AUTORCC`: ``.qrc`` files can be excluded from :prop_tgt:`AUTORCC` processing by diff --git a/Help/prop_tgt/AUTORCC_OPTIONS.rst b/Help/prop_tgt/AUTORCC_OPTIONS.rst index d6ade5a..5261aff 100644 --- a/Help/prop_tgt/AUTORCC_OPTIONS.rst +++ b/Help/prop_tgt/AUTORCC_OPTIONS.rst @@ -8,11 +8,9 @@ when ``rcc`` is executed during the build via :prop_tgt:`AUTORCC`, i.e. it is equivalent to the optional ``OPTIONS`` argument of the :module:`qt4_add_resources() <FindQt4>` macro. -By default it is empty. - This property is initialized by the value of the :variable:`CMAKE_AUTORCC_OPTIONS` variable if it is set when a target is -created. +created, or an empty string otherwise. The options set on the target may be overridden by :prop_sf:`AUTORCC_OPTIONS` set on the ``.qrc`` source file. diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst index 5cf8755..cd24f5e 100644 --- a/Help/prop_tgt/AUTOUIC.rst +++ b/Help/prop_tgt/AUTOUIC.rst @@ -52,8 +52,11 @@ Modifiers The ``uic`` executable will be detected automatically, but can be forced to a certain binary using this target property. -:prop_sf:`AUTOUIC_OPTIONS`: Additional command line options for ``uic`` can -be set via this source file property on a ``<base_name>.ui`` file. +:prop_tgt:`AUTOUIC_OPTIONS`: +Additional command line options for ``uic`` can be set via this target +property. The corresponding :prop_sf:`AUTOUIC_OPTIONS` source file property +can be used to specify options to be applied only to a specific +``<base_name>.ui`` file. :prop_sf:`SKIP_AUTOUIC`: Source files can be excluded from :prop_tgt:`AUTOUIC` processing by setting diff --git a/Help/prop_tgt/AUTOUIC_OPTIONS.rst b/Help/prop_tgt/AUTOUIC_OPTIONS.rst index 3f613b9..425ea1c 100644 --- a/Help/prop_tgt/AUTOUIC_OPTIONS.rst +++ b/Help/prop_tgt/AUTOUIC_OPTIONS.rst @@ -8,11 +8,9 @@ This property holds additional command line options which will be used when equivalent to the optional ``OPTIONS`` argument of the :module:`qt4_wrap_ui() <FindQt4>` macro. -By default it is empty. - This property is initialized by the value of the :variable:`CMAKE_AUTOUIC_OPTIONS` variable if it is set when a target is -created. +created, or an empty string otherwise. The options set on the target may be overridden by :prop_sf:`AUTOUIC_OPTIONS` set on the ``.ui`` source file. diff --git a/Help/prop_tgt/DEPRECATION.rst b/Help/prop_tgt/DEPRECATION.rst new file mode 100644 index 0000000..fef2e2e --- /dev/null +++ b/Help/prop_tgt/DEPRECATION.rst @@ -0,0 +1,7 @@ +DEPRECATION +----------- + +Deprecation message from imported target's developer. + +``DEPRECATION`` is the message regarding a deprecation status to be displayed +to downstream users of a target. diff --git a/Help/prop_tgt/JOB_POOL_PRECOMPILE_HEADER.rst b/Help/prop_tgt/JOB_POOL_PRECOMPILE_HEADER.rst new file mode 100644 index 0000000..ece28a4 --- /dev/null +++ b/Help/prop_tgt/JOB_POOL_PRECOMPILE_HEADER.rst @@ -0,0 +1,21 @@ +JOB_POOL_PRECOMPILE_HEADER +-------------------------- + +Ninja only: Pool used for generating pre-compiled headers. + +The number of parallel compile processes could be limited by defining +pools with the global :prop_gbl:`JOB_POOLS` +property and then specifying here the pool name. + +For instance: + +.. code-block:: cmake + + set_property(TARGET myexe PROPERTY JOB_POOL_PRECOMPILE_HEADER two_jobs) + +This property is initialized by the value of +:variable:`CMAKE_JOB_POOL_PRECOMPILE_HEADER`. + +If neither :prop_tgt:`JOB_POOL_PRECOMPILE_HEADER` nor +:variable:`CMAKE_JOB_POOL_PRECOMPILE_HEADER` are set then +:prop_tgt:`JOB_POOL_COMPILE` will be used for this task. diff --git a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst index 23af503..a6f2b24 100644 --- a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst +++ b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst @@ -2,7 +2,7 @@ ------------------------ This property is implemented only when ``<LANG>`` is ``C``, ``CXX``, -``Fortran``, or ``CUDA``. +``Fortran``, ``OBJC``, ``OBJCXX``, or ``CUDA``. Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing a command line for a compiler launching tool. The :ref:`Makefile Generators` and the diff --git a/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt b/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt index 1fdb6ad..476e4a6 100644 --- a/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt +++ b/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt @@ -1,9 +1,9 @@ .. note:: A call to :command:`target_link_libraries(<target> ...)` may update this property on ``<target>``. If ``<target>`` was not created in the same - directory as the call then :command:`target_link_libraries` will add a - suffix of the form ``::@<directory-id>`` to each entry, where the - ``::@`` is a separator and the ``<directory-id>`` is unspecified. + directory as the call then :command:`target_link_libraries` will wrap each + entry with the form ``::@(directory-id);...;::@``, where the ``::@`` is + literal and the ``(directory-id)`` is unspecified. This tells the generators that the named libraries must be looked up in the scope of the caller rather than in the scope in which the ``<target>`` was created. Valid directory ids are stripped on export diff --git a/Help/release/dev/FindPython-SOABI.rst b/Help/release/dev/FindPython-SOABI.rst new file mode 100644 index 0000000..29f7292 --- /dev/null +++ b/Help/release/dev/FindPython-SOABI.rst @@ -0,0 +1,6 @@ +FindPython-SOABI +---------------- + +* The :module:`FindPython3` and :module:`FindPython` modules gained, + respectively, variable ``Python3_SOABI`` and ``Python_SOABI`` giving + the standard extension suffix for modules. diff --git a/Help/release/dev/add_target_deprecation.rst b/Help/release/dev/add_target_deprecation.rst new file mode 100644 index 0000000..b91eca9 --- /dev/null +++ b/Help/release/dev/add_target_deprecation.rst @@ -0,0 +1,7 @@ +add_target_deprecation +---------------------- + +* A :prop_tgt:`DEPRECATION` target property was added to mark + a target as deprecated. If a linked target is marked as + deprecated, a warning with the deprecation message is issued + at generate time. diff --git a/Help/release/dev/autogen_hh_headers.rst b/Help/release/dev/autogen_hh_headers.rst new file mode 100644 index 0000000..35ccd61 --- /dev/null +++ b/Help/release/dev/autogen_hh_headers.rst @@ -0,0 +1,6 @@ +autogen_hh_headers +------------------ + +* :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` learned to process headers with + a ``.hh`` extension. The new behavior is enabled by policy + :policy:`CMP0100`. diff --git a/Help/release/dev/cmake-ctest-arguments.rst b/Help/release/dev/cmake-ctest-arguments.rst new file mode 100644 index 0000000..72a264a --- /dev/null +++ b/Help/release/dev/cmake-ctest-arguments.rst @@ -0,0 +1,6 @@ +cmake-ctest-arguments +--------------------- + +* A :variable:`CMAKE_CTEST_ARGUMENTS` variable was added to specify a list + of command-line arguments passed to CTest when running through the + ``test`` (or ``RUN_TESTS``) target of the generated build system. diff --git a/Help/release/dev/cpack-nsis-headerimage_var.rst b/Help/release/dev/cpack-nsis-headerimage_var.rst new file mode 100644 index 0000000..d44686b --- /dev/null +++ b/Help/release/dev/cpack-nsis-headerimage_var.rst @@ -0,0 +1,7 @@ +cpack-nsis-headerimage_var +-------------------------- + +* The :cpack_gen:`CPack NSIS Generator` gained a new variable + :variable:`CPACK_NSIS_MUI_HEADERIMAGE` to set the header image. + To not break existing setups, it still defaults to + :variable:`CPACK_PACKAGE_ICON` if the new variable is not set. diff --git a/Help/release/dev/custom-dmg-names.rst b/Help/release/dev/custom-dmg-names.rst new file mode 100644 index 0000000..73a70a1 --- /dev/null +++ b/Help/release/dev/custom-dmg-names.rst @@ -0,0 +1,7 @@ +custom-dmg-names +---------------- + +* The :cpack_gen:`CPack DragNDrop Generator` learned to use + the :variable:`CPACK_DMG_<component>_FILE_NAME` variable + to set a custom filename when packaging components into + their own DMGs. diff --git a/Help/release/dev/fphsa-detect-name-mismatch.rst b/Help/release/dev/fphsa-detect-name-mismatch.rst new file mode 100644 index 0000000..be51a43 --- /dev/null +++ b/Help/release/dev/fphsa-detect-name-mismatch.rst @@ -0,0 +1,5 @@ +fphsa-name-mismatch +------------------- + +* The :module:`FindPackageHandleStandardArgs` module learned to check the + package name passed in for typo mistakes. diff --git a/Help/release/dev/ninja-postgen-commands.rst b/Help/release/dev/ninja-postgen-commands.rst new file mode 100644 index 0000000..85b60dc --- /dev/null +++ b/Help/release/dev/ninja-postgen-commands.rst @@ -0,0 +1,5 @@ +ninja-postgen-commands +---------------------- + +* The :generator:`Ninja` generator learned to perform some post-processing on + the generated files for more consistent builds. diff --git a/Help/release/dev/target_compile_options-BEFORE-keyword.rst b/Help/release/dev/target_compile_options-BEFORE-keyword.rst new file mode 100644 index 0000000..8dafddd --- /dev/null +++ b/Help/release/dev/target_compile_options-BEFORE-keyword.rst @@ -0,0 +1,5 @@ +target_compile_options-BEFORE-keyword +------------------------------------- + +* :command:`target_compile_options` command learns to honor ``BEFORE`` keyword + in all scopes. See policy :policy:`CMP0101`. diff --git a/Help/release/dev/xcode-default-warnings.rst b/Help/release/dev/xcode-default-warnings.rst new file mode 100644 index 0000000..a9a2e49 --- /dev/null +++ b/Help/release/dev/xcode-default-warnings.rst @@ -0,0 +1,5 @@ +xcode-default-warnings +---------------------- + +* The :generator:`Xcode` generator no longer hard-codes ``-Wmost``, + ``-Wno-four-char-constants``, and ``-Wno-unknown-pragmas`` warning flags. diff --git a/Help/release/dev/xmllint-target.rst b/Help/release/dev/xmllint-target.rst new file mode 100644 index 0000000..19c69bf --- /dev/null +++ b/Help/release/dev/xmllint-target.rst @@ -0,0 +1,4 @@ +xmllint-target +-------------- + +* The :module:`FindLibXml2` module now provides an imported target for the xmllint executable diff --git a/Help/variable/CMAKE_CTEST_ARGUMENTS.rst b/Help/variable/CMAKE_CTEST_ARGUMENTS.rst new file mode 100644 index 0000000..0940b46 --- /dev/null +++ b/Help/variable/CMAKE_CTEST_ARGUMENTS.rst @@ -0,0 +1,6 @@ +CMAKE_CTEST_ARGUMENTS +--------------------- + +Set this to a :ref:`semicolon-separated list <CMake Language Lists>` of +command-line arguments to pass to :manual:`ctest(1)` when running tests +through the ``test`` (or ``RUN_TESTS``) target of the generated build system. diff --git a/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst b/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst index e82867d..8587742 100644 --- a/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst +++ b/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst @@ -3,7 +3,7 @@ CMAKE_GLOBAL_AUTOGEN_TARGET Switch to enable generation of a global ``autogen`` target. -When :variable:`CMAKE_GLOBAL_AUTORCC_TARGET` is enabled, a custom target +When :variable:`CMAKE_GLOBAL_AUTOGEN_TARGET` is enabled, a custom target ``autogen`` is generated. This target depends on all :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` generated ``<ORIGIN>_autogen`` targets in the project. By building the global ``autogen`` target, all :prop_tgt:`AUTOMOC` and diff --git a/Help/variable/CMAKE_JOB_POOL_PRECOMPILE_HEADER.rst b/Help/variable/CMAKE_JOB_POOL_PRECOMPILE_HEADER.rst new file mode 100644 index 0000000..f9467b3 --- /dev/null +++ b/Help/variable/CMAKE_JOB_POOL_PRECOMPILE_HEADER.rst @@ -0,0 +1,6 @@ +CMAKE_JOB_POOL_PRECOMPILE_HEADER +-------------------------------- + +This variable is used to initialize the :prop_tgt:`JOB_POOL_PRECOMPILE_HEADER` +property on all the targets. See :prop_tgt:`JOB_POOL_PRECOMPILE_HEADER` +for additional information. diff --git a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst index e5dda60..c76e2d0 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst @@ -4,7 +4,7 @@ CMAKE_<LANG>_COMPILER_LAUNCHER Default value for :prop_tgt:`<LANG>_COMPILER_LAUNCHER` target property. This variable is used to initialize the property on each target as it is created. This is done only when ``<LANG>`` is ``C``, ``CXX``, ``Fortran``, -or ``CUDA``. +``OBJC``, ``OBJCXX``, or ``CUDA``. This variable is initialized to the :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER` environment variable if it is set. diff --git a/Help/variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE.rst b/Help/variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE.rst new file mode 100644 index 0000000..0571d52 --- /dev/null +++ b/Help/variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE.rst @@ -0,0 +1,10 @@ +CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE +------------------------------------- + +If this variable is enabled, cross-configuration building is enabled in the +:generator:`Ninja Multi-Config` generator. See the generator's description for +more details. This variable is ``OFF`` by default. + +This variable is meant to be set from the command line (via +``-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE:BOOL=ON``) and should not be set from +project code. diff --git a/Modules/CMakeCSharpInformation.cmake b/Modules/CMakeCSharpInformation.cmake index 48e1a1e..41cd449 100644 --- a/Modules/CMakeCSharpInformation.cmake +++ b/Modules/CMakeCSharpInformation.cmake @@ -10,7 +10,7 @@ get_filename_component(CMAKE_BASE_NAME "${CMAKE_CSharp_COMPILER}" NAME_WE) set(CMAKE_BUILD_TYPE_INIT Debug) -set(CMAKE_CSharp_FLAGS_INIT "/define:TRACE /langversion:3") +set(CMAKE_CSharp_FLAGS_INIT "/define:TRACE") set(CMAKE_CSharp_FLAGS_DEBUG_INIT "/debug:full /optimize- /warn:3 /errorreport:prompt /define:DEBUG") set(CMAKE_CSharp_FLAGS_RELEASE_INIT "/debug:none /optimize /warn:1 /errorreport:queue") set(CMAKE_CSharp_FLAGS_RELWITHDEBINFO_INIT "/debug:full /optimize-") diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake index e1ce617..2dc75d6 100644 --- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake +++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake @@ -9,6 +9,7 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR) set(${_VAR} FAIL_REGEX "[Uu]nrecogni[sz]ed .*option" # GNU, NAG + FAIL_REGEX "switch .* is no longer supported" # GNU FAIL_REGEX "unknown .*option" # Clang FAIL_REGEX "optimization flag .* not supported" # Clang FAIL_REGEX "unknown argument ignored" # Clang (cl) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 490d659..7d7fb9a 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -186,33 +186,32 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) "Failed to parsed CUDA nvcc implicit link information:\n${_nvcc_log}\n\n") message(FATAL_ERROR "Failed to extract nvcc implicit link line.") endif() +endif() - set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES ) - if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n") - set(_nvcc_includes "${CMAKE_MATCH_1}") - string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n") - else() - set(_nvcc_includes "") - string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") - string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n") - endif() - if(_nvcc_includes) - # across all operating system each include directory is prefixed with -I - separate_arguments(_nvcc_output UNIX_COMMAND "${_nvcc_includes}") - foreach(line IN LISTS _nvcc_output) - string(REGEX REPLACE "^-I" "" line "${line}") - get_filename_component(line "${line}" ABSOLUTE) - list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}") - endforeach() - - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n") - else() - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") - endif() - - +set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES ) +string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") +if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n") + set(_nvcc_includes "${CMAKE_MATCH_1}") + string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n") +else() + set(_nvcc_includes "") + string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") + string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n") +endif() +if(_nvcc_includes) + # across all operating system each include directory is prefixed with -I + separate_arguments(_nvcc_output NATIVE_COMMAND "${_nvcc_includes}") + foreach(line IN LISTS _nvcc_output) + string(REGEX REPLACE "^-I" "" line "${line}") + get_filename_component(line "${line}" ABSOLUTE) + list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}") + endforeach() + + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n") +else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") endif() # configure all variables set in this file diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 52d8976..d125791 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -366,6 +366,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} endif() set(cuda_tools "CUDA ${CMAKE_VS_PLATFORM_TOOLSET_CUDA}") set(id_compile "CudaCompile") + set(id_ItemDefinitionGroup_entry "<CudaCompile><AdditionalOptions>%(AdditionalOptions)-v</AdditionalOptions></CudaCompile>") set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]]) if(CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR) set(id_CudaToolkitCustomDir "<CudaToolkitCustomDir>${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}nvcc</CudaToolkitCustomDir>") @@ -376,7 +377,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} string(CONCAT id_Import_targets [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.targets" />]]) endif() if(CMAKE_VS_PLATFORM_NAME STREQUAL x64) - set(id_ItemDefinitionGroup_entry "<CudaCompile><TargetMachinePlatform>64</TargetMachinePlatform></CudaCompile>") + set(id_ItemDefinitionGroup_entry "<CudaCompile><TargetMachinePlatform>64</TargetMachinePlatform><AdditionalOptions>%(AdditionalOptions)-v</AdditionalOptions></CudaCompile>") endif() set(id_Link_AdditionalDependencies "<AdditionalDependencies>cudart.lib</AdditionalDependencies>") endif() diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake index cb61cb8..15a3311 100644 --- a/Modules/CMakeOBJCInformation.cmake +++ b/Modules/CMakeOBJCInformation.cmake @@ -110,6 +110,11 @@ if(CMAKE_OBJC_STANDARD_LIBRARIES_INIT) mark_as_advanced(CMAKE_OBJC_STANDARD_LIBRARIES) endif() +if(NOT CMAKE_OBJC_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_OBJC_COMPILER_LAUNCHER}) + set(CMAKE_OBJC_COMPILER_LAUNCHER "$ENV{CMAKE_OBJC_COMPILER_LAUNCHER}" + CACHE STRING "Compiler launcher for OBJC.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rule variables diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake index 71ac26a..cb349d7 100644 --- a/Modules/CMakeOBJCXXInformation.cmake +++ b/Modules/CMakeOBJCXXInformation.cmake @@ -203,6 +203,11 @@ if(CMAKE_OBJCXX_STANDARD_LIBRARIES_INIT) mark_as_advanced(CMAKE_OBJCXX_STANDARD_LIBRARIES) endif() +if(NOT CMAKE_OBJCXX_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_OBJCXX_COMPILER_LAUNCHER}) + set(CMAKE_OBJCXX_COMPILER_LAUNCHER "$ENV{CMAKE_OBJCXX_COMPILER_LAUNCHER}" + CACHE STRING "Compiler launcher for OBJCXX.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rules: diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index cbb5323..e4f75d5 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -470,8 +470,10 @@ if(CMAKE_PROJECT_HOMEPAGE_URL) "${CMAKE_PROJECT_HOMEPAGE_URL}") endif() -_cpack_set_default(CPACK_PACKAGE_DESCRIPTION_FILE +set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "${CMAKE_ROOT}/Templates/CPack.GenericDescription.txt") +_cpack_set_default(CPACK_PACKAGE_DESCRIPTION_FILE + "${CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE}") _cpack_set_default(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_ROOT}/Templates/CPack.GenericLicense.txt") _cpack_set_default(CPACK_RESOURCE_FILE_README diff --git a/Modules/Compiler/AppleClang-OBJCXX.cmake b/Modules/Compiler/AppleClang-OBJCXX.cmake index 7c6f763..2c084af 100644 --- a/Modules/Compiler/AppleClang-OBJCXX.cmake +++ b/Modules/Compiler/AppleClang-OBJCXX.cmake @@ -1,5 +1,7 @@ include(Compiler/Clang-OBJCXX) +set(CMAKE_OBJCXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") + if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "-std=c++98") set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") diff --git a/Modules/Compiler/GNU-OBJC.cmake b/Modules/Compiler/GNU-OBJC.cmake index 5fba801..fb9b0b2 100644 --- a/Modules/Compiler/GNU-OBJC.cmake +++ b/Modules/Compiler/GNU-OBJC.cmake @@ -1,6 +1,2 @@ include(Compiler/GNU) __compiler_gnu(OBJC) - -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) - set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") -endif() diff --git a/Modules/Compiler/GNU-OBJCXX.cmake b/Modules/Compiler/GNU-OBJCXX.cmake index 66a547e..06f0244 100644 --- a/Modules/Compiler/GNU-OBJCXX.cmake +++ b/Modules/Compiler/GNU-OBJCXX.cmake @@ -1,8 +1,8 @@ include(Compiler/GNU) -__compiler_gnu(OBJC) +__compiler_gnu(OBJCXX) -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) - set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") +if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.2) + set(CMAKE_OBJCXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() if(NOT CMAKE_OBJCXX_LINK_FLAGS) diff --git a/Modules/Compiler/NAG-Fortran.cmake b/Modules/Compiler/NAG-Fortran.cmake index c54ab9d..2111c65 100644 --- a/Modules/Compiler/NAG-Fortran.cmake +++ b/Modules/Compiler/NAG-Fortran.cmake @@ -28,6 +28,8 @@ if(NOT CMAKE_Fortran_COMPILER_WORKS AND NOT CMAKE_Fortran_COMPILER_FORCED) endif() endif() +set(CMAKE_Fortran_SUBMODULE_SEP ".") +set(CMAKE_Fortran_SUBMODULE_EXT ".sub") set(CMAKE_Fortran_MODDIR_FLAG "-mdir ") set(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "-PIC") set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixed") diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index ad7f084..fb1fc20 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -4,7 +4,7 @@ set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True) set(CMAKE_CUDA_VERBOSE_FLAG "-v") set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") -if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 10.2) +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 # way to invoke the CUDA compiler and propagate unknown @@ -20,7 +20,7 @@ else() set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") endif() -if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 10.2) +if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) # The -MD flag was only added to nvcc in 10.2 so # before that we had to invoke the compiler twice # to get header dependency information diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 1837694..f7f68ca 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -122,7 +122,6 @@ CUDA Runtime Library The CUDA Runtime library (cudart) are what most applications will typically need to link against to make any calls such as `cudaMalloc`, and `cudaFree`. -They are an explicit dependency of almost every library. Targets Created: @@ -708,9 +707,13 @@ if(CUDAToolkit_FOUND) endfunction() function(add_cuda_link_dependency lib_name) - foreach(dependency IN LISTS ${ARGN}) - target_link_libraries(CUDA::${lib_name} INTERFACE CUDA::${dependency}) - endforeach() + if(TARGET CUDA::${lib_name}) + foreach(dependency IN LISTS ARGN) + if(TARGET CUDA::${dependency}) + target_link_libraries(CUDA::${lib_name} INTERFACE CUDA::${dependency}) + endif() + endforeach() + endif() endfunction() add_library(CUDA::toolkit IMPORTED INTERFACE) @@ -725,10 +728,8 @@ if(CUDAToolkit_FOUND) foreach (cuda_lib cublas cufft cufftw curand cusolver cusparse nvgraph nvjpeg) find_and_add_cuda_import_lib(${cuda_lib}) - add_cuda_link_dependency(${cuda_lib} cudart) find_and_add_cuda_import_lib(${cuda_lib}_static) - add_cuda_link_dependency(${cuda_lib}_static cudart_static) endforeach() # cuSOLVER depends on cuBLAS, and cuSPARSE @@ -742,9 +743,6 @@ if(CUDAToolkit_FOUND) find_and_add_cuda_import_lib(nppc) find_and_add_cuda_import_lib(nppc_static) - add_cuda_link_dependency(nppc cudart) - add_cuda_link_dependency(nppc_static cudart_static culibos) - # Process the majority of the NPP libraries. foreach (cuda_lib nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppicom nppisu) find_and_add_cuda_import_lib(${cuda_lib}) @@ -771,13 +769,11 @@ if(CUDAToolkit_FOUND) endif() find_and_add_cuda_import_lib(nvToolsExt nvToolsExt nvToolsExt64) - add_cuda_link_dependency(nvToolsExt cudart) - find_and_add_cuda_import_lib(OpenCL) find_and_add_cuda_import_lib(culibos) if(TARGET CUDA::culibos) - foreach (cuda_lib cublas cufft cusparse curand nvjpeg) + foreach (cuda_lib cublas cufft cusparse curand nppc nvjpeg) add_cuda_link_dependency(${cuda_lib}_static culibos) endforeach() endif() diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index 83091f3..9117321 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -881,6 +881,7 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS}) set(GTK2_${_COMPONENT_UPPER}_FIND_QUIETLY ${GTK2_FIND_QUIETLY}) + set(FPHSA_NAME_MISMATCHED 1) if(_GTK2_component STREQUAL "gtk") FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK2_${_COMPONENT_UPPER} "Some or all of the gtk libraries were not found." GTK2_GTK_LIBRARY @@ -923,6 +924,7 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS}) GTK2_GLADEMMCONFIG_INCLUDE_DIR ) endif() + unset(FPHSA_NAME_MISMATCHED) if(NOT GTK2_${_COMPONENT_UPPER}_FOUND) set(_GTK2_did_we_find_everything false) diff --git a/Modules/FindLibXml2.cmake b/Modules/FindLibXml2.cmake index da8bfe0..f551dfe 100644 --- a/Modules/FindLibXml2.cmake +++ b/Modules/FindLibXml2.cmake @@ -10,8 +10,12 @@ Find the XML processing library (libxml2). IMPORTED Targets ^^^^^^^^^^^^^^^^ -This module defines :prop_tgt:`IMPORTED` target ``LibXml2::LibXml2``, if -libxml2 has been found. +The following :prop_tgt:`IMPORTED` targets may be defined: + +``LibXml2::LibXml2`` + If the libxml2 library has been found +``LibXml2::xmllint`` + If the xmllint command-line executable has been found Result variables ^^^^^^^^^^^^^^^^ @@ -48,7 +52,6 @@ The following cache variables may also be set: # in the find_path() and find_library() calls find_package(PkgConfig QUIET) PKG_CHECK_MODULES(PC_LIBXML QUIET libxml-2.0) -set(LIBXML2_DEFINITIONS ${PC_LIBXML_CFLAGS_OTHER}) find_path(LIBXML2_INCLUDE_DIR NAMES libxml/xpath.h HINTS @@ -74,9 +77,7 @@ find_program(LIBXML2_XMLLINT_EXECUTABLE xmllint) # for backwards compat. with KDE 4.0.x: set(XMLLINT_EXECUTABLE "${LIBXML2_XMLLINT_EXECUTABLE}") -if(PC_LIBXML_VERSION) - set(LIBXML2_VERSION_STRING ${PC_LIBXML_VERSION}) -elseif(LIBXML2_INCLUDE_DIR AND EXISTS "${LIBXML2_INCLUDE_DIR}/libxml/xmlversion.h") +if(LIBXML2_INCLUDE_DIR AND EXISTS "${LIBXML2_INCLUDE_DIR}/libxml/xmlversion.h") file(STRINGS "${LIBXML2_INCLUDE_DIR}/libxml/xmlversion.h" libxml2_version_str REGEX "^#define[\t ]+LIBXML_DOTTED_VERSION[\t ]+\".*\"") @@ -85,9 +86,20 @@ elseif(LIBXML2_INCLUDE_DIR AND EXISTS "${LIBXML2_INCLUDE_DIR}/libxml/xmlversion. unset(libxml2_version_str) endif() -set(LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR} ${PC_LIBXML_INCLUDE_DIRS}) +set(LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR}) set(LIBXML2_LIBRARIES ${LIBXML2_LIBRARY}) +# Did we find the same installation as pkg-config? +# If so, use additional information from it. +unset(LIBXML2_DEFINITIONS) +foreach(libxml2_pc_lib_dir IN LISTS PC_LIBXML_LIBDIR PC_LIBXML_LIBRARY_DIRS) + if (LIBXML2_LIBRARY MATCHES "^${libxml2_pc_lib_dir}") + list(APPEND LIBXML2_INCLUDE_DIRS ${PC_LIBXML_INCLUDE_DIRS}) + set(LIBXML2_DEFINITIONS ${PC_LIBXML_CFLAGS_OTHER}) + break() + endif() +endforeach() + include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 REQUIRED_VARS LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR @@ -98,5 +110,11 @@ mark_as_advanced(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARY LIBXML2_XMLLINT_EXECUTABLE) if(LibXml2_FOUND AND NOT TARGET LibXml2::LibXml2) add_library(LibXml2::LibXml2 UNKNOWN IMPORTED) set_target_properties(LibXml2::LibXml2 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBXML2_INCLUDE_DIRS}") + set_target_properties(LibXml2::LibXml2 PROPERTIES INTERFACE_COMPILE_OPTIONS "${LIBXML2_DEFINITIONS}") set_property(TARGET LibXml2::LibXml2 APPEND PROPERTY IMPORTED_LOCATION "${LIBXML2_LIBRARY}") endif() + +if(LIBXML2_XMLLINT_EXECUTABLE AND NOT TARGET LibXml2::xmllint) + add_executable(LibXml2::xmllint IMPORTED) + set_target_properties(LibXml2::xmllint PROPERTIES IMPORTED_LOCATION "${LIBXML2_XMLLINT_EXECUTABLE}") +endif() diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 6b1da4b..f79ee63 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -1059,32 +1059,7 @@ macro(_MPI_assemble_libraries LANG) endif() endmacro() -macro(_MPI_assemble_include_dirs LANG) - if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") - set(MPI_${LANG}_INCLUDE_DIRS "") - else() - set(MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS}") - if("${LANG}" MATCHES "(C|CXX)") - if(MPI_${LANG}_HEADER_DIR) - list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}") - endif() - else() # Fortran - if(MPI_${LANG}_F77_HEADER_DIR) - list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_F77_HEADER_DIR}") - endif() - if(MPI_${LANG}_MODULE_DIR AND NOT "${MPI_${LANG}_MODULE_DIR}" IN_LIST MPI_${LANG}_INCLUDE_DIRS) - list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_MODULE_DIR}") - endif() - endif() - if(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) - foreach(MPI_ADDITIONAL_INC_DIR IN LISTS MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) - list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${MPI_ADDITIONAL_INC_DIR}_INCLUDE_DIR}") - endforeach() - endif() - endif() -endmacro() - -function(_MPI_split_include_dirs LANG) +macro(_MPI_split_include_dirs LANG) if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") return() endif() @@ -1093,6 +1068,9 @@ function(_MPI_split_include_dirs LANG) list(APPEND MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_INCLUDE_PATH}") endif() + # Preserve the include dirs before stripping out the components + set(MPI_${LANG}_INCLUDE_DIRS ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS}) + # We try to find the headers/modules among those paths (and system paths) # For C/C++, we just need to have a look for mpi.h. if("${LANG}" MATCHES "(C|CXX)") @@ -1103,6 +1081,7 @@ function(_MPI_split_include_dirs LANG) if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}") endif() + # Fortran is more complicated here: An implementation could provide # any of the Fortran 77/90/2008 APIs for MPI. For example, MSMPI # only provides Fortran 77 and - if mpi.f90 is built - potentially @@ -1123,6 +1102,7 @@ function(_MPI_split_include_dirs LANG) endif() mark_as_advanced(MPI_${LANG}_F77_HEADER_DIR MPI_${LANG}_MODULE_DIR) endif() + # Remove duplicates and default system directories from the list. if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) list(REMOVE_DUPLICATES MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) @@ -1130,8 +1110,9 @@ function(_MPI_split_include_dirs LANG) list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_IMPLICIT_INC_DIR}) endforeach() endif() + set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} additional include directories" FORCE) -endfunction() +endmacro() macro(_MPI_create_imported_target LANG) if(NOT TARGET MPI::MPI_${LANG}) @@ -1495,7 +1476,6 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() _MPI_split_include_dirs(${LANG}) - _MPI_assemble_include_dirs(${LANG}) _MPI_assemble_libraries(${LANG}) _MPI_adjust_compile_definitions(${LANG}) @@ -1664,7 +1644,8 @@ foreach(LANG IN ITEMS C CXX Fortran) list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_WORKS") endif() endif() - find_package_handle_standard_args(MPI_${LANG} REQUIRED_VARS ${MPI_${LANG}_REQUIRED_VARS} + find_package_handle_standard_args(MPI_${LANG} NAME_MISMATCHED + REQUIRED_VARS ${MPI_${LANG}_REQUIRED_VARS} VERSION_VAR MPI_${LANG}_VERSION) if(DEFINED MPI_${LANG}_VERSION) diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index c8cae2e..92ee729 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -241,6 +241,8 @@ if(NOT MATLAB_ADDITIONAL_VERSIONS) endif() set(MATLAB_VERSIONS_MAPPING + "R2019b=9.7" + "R2019a=9.6" "R2018b=9.5" "R2018a=9.4" "R2017b=9.3" @@ -974,10 +976,19 @@ function(matlab_add_mex) endif() if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file - # TODO: check the file extensions in ${${prefix}_SRC} to see if they're C or C++ files - # Currently, the C and C++ versions of the version files are identical, so this doesn't matter. - set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c") - #set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp") + # Add the correct version file depending on which languages are enabled in the project + if(CMAKE_C_COMPILER_LOADED) + # If C is enabled, use the .c file as it will work fine also with C++ + set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c") + elseif(CMAKE_CXX_COMPILER_LOADED) + # If C is not enabled, check if CXX is enabled and use the .cpp file + # to avoid that the .c file is silently ignored + set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp") + else() + # If neither C or CXX is enabled, warn because we cannot add the source. + # TODO: add support for fortran mex files + message(WARNING "[MATLAB] matlab_add_mex requires that at least C or CXX are enabled languages") + endif() endif() if(NOT Matlab_VERSION_STRING VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro diff --git a/Modules/FindOpenACC.cmake b/Modules/FindOpenACC.cmake index 743e0e2..398dcf5 100644 --- a/Modules/FindOpenACC.cmake +++ b/Modules/FindOpenACC.cmake @@ -254,6 +254,7 @@ foreach (LANG IN ITEMS C CXX Fortran) _OPENACC_SET_VERSION_BY_SPEC_DATE("${LANG}") find_package_handle_standard_args(OpenACC_${LANG} + NAME_MISMATCHED REQUIRED_VARS OpenACC_${LANG}_FLAGS VERSION_VAR OpenACC_${LANG}_VERSION ) diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index 90d1c3e..26fed41 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -509,6 +509,7 @@ foreach(LANG IN LISTS OpenMP_FINDLIST) endif() find_package_handle_standard_args(OpenMP_${LANG} + NAME_MISMATCHED REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS} VERSION_VAR OpenMP_${LANG}_VERSION ) diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 3688ae9..043fc6c 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -65,7 +65,7 @@ macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library) endif() endmacro() -function(_OpenSSL_add_dependencies libraries_var library) +function(_OpenSSL_add_dependencies libraries_var) if(CMAKE_THREAD_LIBS_INIT) list(APPEND ${libraries_var} ${CMAKE_THREAD_LIBS_INIT}) endif() @@ -341,13 +341,14 @@ else() endif() -# compat defines set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY}) set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) +set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES} ) _OpenSSL_test_and_find_dependencies("${OPENSSL_SSL_LIBRARY}" "${OPENSSL_CRYPTO_LIBRARY}") if(_OpenSSL_has_dependencies) - _OpenSSL_add_dependencies( OPENSSL_SSL_LIBRARIES "${OPENSSL_SSL_LIBRARY}" ) - _OpenSSL_add_dependencies( OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARY}" ) + _OpenSSL_add_dependencies( OPENSSL_SSL_LIBRARIES ) + _OpenSSL_add_dependencies( OPENSSL_CRYPTO_LIBRARIES ) + _OpenSSL_add_dependencies( OPENSSL_LIBRARIES ) endif() function(from_hex HEX DEC) @@ -417,9 +418,6 @@ if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h") endif () endif () -set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES} ) -list(REMOVE_DUPLICATES OPENSSL_LIBRARIES) - foreach(_comp IN LISTS OpenSSL_FIND_COMPONENTS) if(_comp STREQUAL "Crypto") if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake index d824ee8..a7c3eae 100644 --- a/Modules/FindPackageHandleStandardArgs.cmake +++ b/Modules/FindPackageHandleStandardArgs.cmake @@ -27,6 +27,7 @@ valid filepaths. [VERSION_VAR <version-var>] [HANDLE_COMPONENTS] [CONFIG_MODE] + [NAME_MISMATCHED] [REASON_FAILURE_MESSAGE <reason-failure-message>] [FAIL_MESSAGE <custom-failure-message>] ) @@ -90,6 +91,12 @@ valid filepaths. Specify a custom failure message instead of using the default generated message. Not recommended. + ``NAME_MISMATCHED`` + Indicate that the ``<PackageName>`` does not match + ``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a + warning, but it may be intentional for usage of the command for components + of a larger package. + Example for the simple signature: .. code-block:: cmake @@ -106,6 +113,17 @@ used or not. If it is found, success will be reported, including the content of the first ``<required-var>``. On repeated CMake runs, the same message will not be printed again. +.. note:: + + If ``<PackageName>`` does not match ``CMAKE_FIND_PACKAGE_NAME`` for the + calling module, a warning that there is a mismatch is given. The + ``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using + the old signature and the ``NAME_MISMATCHED`` argument using the new + signature. To avoid forcing the caller to require newer versions of CMake for + usage, the variable's value will be used if defined when the + ``NAME_MISMATCHED`` argument is not passed for the new signature (but using + both is an error).. + Example for the full signature: .. code-block:: cmake @@ -190,15 +208,32 @@ endmacro() function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) -# Set up the arguments for `cmake_parse_arguments`. - set(options CONFIG_MODE HANDLE_COMPONENTS) + # Set up the arguments for `cmake_parse_arguments`. + set(options CONFIG_MODE HANDLE_COMPONENTS NAME_MISMATCHED) set(oneValueArgs FAIL_MESSAGE REASON_FAILURE_MESSAGE VERSION_VAR FOUND_VAR) set(multiValueArgs REQUIRED_VARS) -# Check whether we are in 'simple' or 'extended' mode: + # Check whether we are in 'simple' or 'extended' mode: set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + unset(FPHSA_NAME_MISMATCHED_override) + if (DEFINED FPHSA_NAME_MISMATCHED) + # If the variable NAME_MISMATCHED variable is set, error if it is passed as + # an argument. The former is for old signatures, the latter is for new + # signatures. + list(FIND ARGN "NAME_MISMATCHED" name_mismatched_idx) + if (NOT name_mismatched_idx EQUAL "-1") + message(FATAL_ERROR + "The `NAME_MISMATCHED` argument may only be specified by the argument or " + "the variable, not both.") + endif () + + # But use the variable if it is not an argument to avoid forcing minimum + # CMake version bumps for calling modules. + set(FPHSA_NAME_MISMATCHED_override "${FPHSA_NAME_MISMATCHED}") + endif () + if(${INDEX} EQUAL -1) set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) set(FPHSA_REQUIRED_VARS ${ARGN}) @@ -227,6 +262,21 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) endif() endif() + if (DEFINED FPHSA_NAME_MISMATCHED_override) + set(FPHSA_NAME_MISMATCHED "${FPHSA_NAME_MISMATCHED_override}") + endif () + + if (DEFINED CMAKE_FIND_PACKAGE_NAME + AND NOT FPHSA_NAME_MISMATCHED + AND NOT _NAME STREQUAL CMAKE_FIND_PACKAGE_NAME) + message(AUTHOR_WARNING + "The package name passed to `find_package_handle_standard_args` " + "(${_NAME}) does not match the name of the calling package " + "(${CMAKE_FIND_PACKAGE_NAME}). This can lead to problems in calling " + "code that expects `find_package` result variables (e.g., `_FOUND`) " + "to follow a certain pattern.") + endif () + # now that we collected all arguments, process them if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG") diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index 177ed58..be272e1 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -93,6 +93,13 @@ This module will set the following variables in your project Information returned by ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``. +``Python_SOABI`` + Extension suffix for modules. + + Information returned by + ``distutils.sysconfig.get_config_flag('SOABI')`` or computed from + ``distutils.sysconfig.get_config_flag('EXT_SUFFIX')`` or + ``python-config --extension-suffix``. ``Python_Compiler_FOUND`` System has the Python compiler. ``Python_COMPILER`` diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index 0163d56..7483d72 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -23,7 +23,7 @@ if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) message (FATAL_ERROR "FindPython: INTERNAL ERROR") endif() if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 3) - set(_${_PYTHON_PREFIX}_VERSIONS 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) + set(_${_PYTHON_PREFIX}_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 2) set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) else() @@ -62,6 +62,9 @@ macro (_PYTHON_FIND_FRAMEWORKS) ${CMAKE_SYSTEM_FRAMEWORK_PATH}) list (REMOVE_DUPLICATES _pff_frameworks) foreach (_pff_framework IN LISTS _pff_frameworks) + if (EXISTS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework) + list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework) + endif() if (EXISTS ${_pff_framework}/Python.framework) list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python.framework) endif() @@ -244,12 +247,16 @@ endfunction() function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) unset (${_PYTHON_PGCV_VALUE} PARENT_SCOPE) - if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS)$") + if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS|SOABI)$") return() endif() if (_${_PYTHON_PREFIX}_CONFIG) - set (config_flag "--${NAME}") + if (NAME STREQUAL "SOABI") + set (config_flag "--extension-suffix") + else() + set (config_flag "--${NAME}") + endif() string (TOLOWER "${config_flag}" config_flag) execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" ${config_flag} RESULT_VARIABLE _result @@ -264,6 +271,9 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) string (REGEX MATCHALL "(-I|-iwithsysroot)[ ]*[^ ]+" _values "${_values}") string (REGEX REPLACE "(-I|-iwithsysroot)[ ]*" "" _values "${_values}") list (REMOVE_DUPLICATES _values) + elseif (NAME STREQUAL "SOABI") + # clean-up: remove prefix character and suffix + string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\.(so|pyd))$" "\\1" _values "${_values}") endif() endif() endif() @@ -289,6 +299,25 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (_result) unset (_values) endif() + elseif (NAME STREQUAL "SOABI") + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '']))" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _soabi + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_result) + unset (_values) + else() + list (GET _soabi 0 _values) + if (NOT _values) + # try to compute SOABI from EXT_SUFFIX + list (GET _soabi 1 _values) + if (_values) + # clean-up: remove prefix character and suffix + string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\.(so|pyd))$" "\\1" _values "${_values}") + endif() + endif() + endif() else() set (config_flag "${NAME}") if (NAME STREQUAL "CONFIGDIR") @@ -745,6 +774,7 @@ else() _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS) endif() endif() +unset (${_PYTHON_PREFIX}_SOABI) # Define lookup strategy if (_${_PYTHON_PREFIX}_LOOKUP_POLICY STREQUAL "NEW") @@ -1267,7 +1297,6 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # retrieve various package installation directories execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE _${_PYTHON_PREFIX}_LIBPATHS ERROR_QUIET) @@ -1282,6 +1311,10 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) unset (${_PYTHON_PREFIX}_SITELIB) unset (${_PYTHON_PREFIX}_SITEARCH) endif() + + if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL 3) + _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI) + endif() else() unset (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE CACHE) unset (${_PYTHON_PREFIX}_INTERPRETER_ID) @@ -1522,9 +1555,13 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS unset (_${_PYTHON_PREFIX}_LIBRARY_RELEASE CACHE) unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE) unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE) - unset (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE CACHE) endif() endif() + if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE CACHE) + endif() + if (DEFINED ${_PYTHON_PREFIX}_LIBRARY AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_LIBRARY}") set (_${_PYTHON_PREFIX}_LIBRARY_RELEASE "${${_PYTHON_PREFIX}_LIBRARY}" CACHE INTERNAL "") @@ -2148,6 +2185,11 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() endif() + if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL 3 + AND NOT DEFINED ${_PYTHON_PREFIX}_SOABI) + _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI) + endif() + if (${_PYTHON_PREFIX}_Development_FOUND) # compute and save development signature string (MD5 __${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:${_${_PYTHON_PREFIX}_INCLUDE_DIR}") @@ -2166,6 +2208,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG _${_PYTHON_PREFIX}_INCLUDE_DIR + _${_PYTHON_PREFIX}_CONFIG _${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE) endif() @@ -2425,5 +2468,3 @@ if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK) else() unset (CMAKE_FIND_FRAMEWORK) endif() - -unset (_${_PYTHON_PREFIX}_CONFIG CACHE) diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index 0a96fad..00c354e 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -94,6 +94,13 @@ This module will set the following variables in your project Information returned by ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``. +``Python3_SOABI`` + Extension suffix for modules. + + Information returned by + ``distutils.sysconfig.get_config_flag('SOABI')`` or computed from + ``distutils.sysconfig.get_config_flag('EXT_SUFFIX')`` or + ``python3-config --extension-suffix``. ``Python3_Compiler_FOUND`` System has the Python 3 compiler. ``Python3_COMPILER`` diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake index ccc7d5b..1e01a99 100644 --- a/Modules/FindPythonInterp.cmake +++ b/Modules/FindPythonInterp.cmake @@ -54,7 +54,7 @@ unset(_Python_NAMES) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonInterp_FIND_VERSION) if(PythonInterp_FIND_VERSION_COUNT GREATER 1) diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake index 1d62ac4..d3ec7be 100644 --- a/Modules/FindPythonLibs.cmake +++ b/Modules/FindPythonLibs.cmake @@ -79,7 +79,7 @@ set(CMAKE_FIND_FRAMEWORK LAST) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonLibs_FIND_VERSION) if(PythonLibs_FIND_VERSION_COUNT GREATER 1) diff --git a/Modules/FindTCL.cmake b/Modules/FindTCL.cmake index be47c39..960265f 100644 --- a/Modules/FindTCL.cmake +++ b/Modules/FindTCL.cmake @@ -224,12 +224,14 @@ find_path(TK_INCLUDE_PATH include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(TCL DEFAULT_MSG TCL_LIBRARY TCL_INCLUDE_PATH) +set(FPHSA_NAME_MISMATCHED 1) set(TCLTK_FIND_REQUIRED ${TCL_FIND_REQUIRED}) set(TCLTK_FIND_QUIETLY ${TCL_FIND_QUIETLY}) FIND_PACKAGE_HANDLE_STANDARD_ARGS(TCLTK DEFAULT_MSG TCL_LIBRARY TCL_INCLUDE_PATH TK_LIBRARY TK_INCLUDE_PATH) set(TK_FIND_REQUIRED ${TCL_FIND_REQUIRED}) set(TK_FIND_QUIETLY ${TCL_FIND_QUIETLY}) FIND_PACKAGE_HANDLE_STANDARD_ARGS(TK DEFAULT_MSG TK_LIBRARY TK_INCLUDE_PATH) +unset(FPHSA_NAME_MISMATCHED) mark_as_advanced( TCL_INCLUDE_PATH diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index fe0fe09..c74c324 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -498,6 +498,11 @@ function(cpack_deb_prepare_package_vars) # Description: (mandatory) # Try package description first + if(CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE) + set(_desc_fallback) + else() + set(_desc_fallback "CPACK_PACKAGE_DESCRIPTION") + endif() if(CPACK_DEB_PACKAGE_COMPONENT) cpack_deb_variable_fallback("CPACK_DEBIAN_PACKAGE_DESCRIPTION" "CPACK_DEBIAN_${_local_component_name}_DESCRIPTION" @@ -505,11 +510,13 @@ function(cpack_deb_prepare_package_vars) else() cpack_deb_variable_fallback("CPACK_DEBIAN_PACKAGE_DESCRIPTION" "CPACK_DEBIAN_PACKAGE_DESCRIPTION" - "CPACK_PACKAGE_DESCRIPTION") + ${_desc_fallback}) endif() # Still no description? ... and description file has set ... - if(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION AND CPACK_PACKAGE_DESCRIPTION_FILE) + if(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION + AND CPACK_PACKAGE_DESCRIPTION_FILE + AND NOT CPACK_PACKAGE_DESCRIPTION_FILE STREQUAL CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE) # Read `CPACK_PACKAGE_DESCRIPTION_FILE` then... file(READ ${CPACK_PACKAGE_DESCRIPTION_FILE} CPACK_DEBIAN_PACKAGE_DESCRIPTION) endif() diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index 23bb0018..660bfa3 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -524,14 +524,6 @@ FunctionEnd !endif ;-------------------------------- -; Installation types -@CPACK_NSIS_INSTALLATION_TYPES@ - -;-------------------------------- -; Component sections -@CPACK_NSIS_COMPONENT_SECTIONS@ - -;-------------------------------- ; Define some macro setting for the gui @CPACK_NSIS_INSTALLER_MUI_ICON_CODE@ @CPACK_NSIS_INSTALLER_ICON_CODE@ @@ -621,7 +613,6 @@ FunctionEnd !insertmacro MUI_LANGUAGE "Ukrainian" !insertmacro MUI_LANGUAGE "Welsh" - ;-------------------------------- ;Reserve Files @@ -632,6 +623,17 @@ FunctionEnd ReserveFile "NSIS.InstallOptions.ini" !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + ; for UserInfo::GetName and UserInfo::GetAccountType + ReserveFile /plugin 'UserInfo.dll' + +;-------------------------------- +; Installation types +@CPACK_NSIS_INSTALLATION_TYPES@ + +;-------------------------------- +; Component sections +@CPACK_NSIS_COMPONENT_SECTIONS@ + ;-------------------------------- ;Installer Sections diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index 1482d76..e5a57b5 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -157,6 +157,10 @@ if(_CMAKE_OSX_SYSROOT_PATH) endif() endforeach() endif() +if (OSX_DEVELOPER_ROOT AND EXISTS "${OSX_DEVELOPER_ROOT}/Library/Frameworks") + list(APPEND CMAKE_SYSTEM_FRAMEWORK_PATH + ${OSX_DEVELOPER_ROOT}/Library/Frameworks) +endif() list(APPEND CMAKE_SYSTEM_FRAMEWORK_PATH /Library/Frameworks /Network/Library/Frameworks diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index cf85367..235d9ce 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -152,7 +152,7 @@ macro(__windows_compiler_gnu_abi lang) # Query the VS Installer tool for locations of VS 2017 and above. set(_vs_installer_paths "") - foreach(vs RANGE 15 15 -1) # change the first number to the largest supported version + foreach(vs RANGE 16 15 -1) # change the first number to the largest supported version cmake_host_system_information(RESULT _vs_dir QUERY VS_${vs}_DIR) if(_vs_dir) list(APPEND _vs_installer_paths "${_vs_dir}/VC/Auxiliary/Build") diff --git a/Modules/Platform/Windows-PGI.cmake b/Modules/Platform/Windows-PGI.cmake index ad77e8a..8166240 100644 --- a/Modules/Platform/Windows-PGI.cmake +++ b/Modules/Platform/Windows-PGI.cmake @@ -9,9 +9,10 @@ endif() set(__WINDOWS_COMPILER_PGI 1) # PGI on Windows doesn't support parallel compile processes -if(NOT DEFINED CMAKE_JOB_POOL_LINK OR NOT DEFINED CMAKE_JOB_POOL_COMPILE) +if(NOT DEFINED CMAKE_JOB_POOL_LINK OR NOT DEFINED CMAKE_JOB_POOL_COMPILE OR NOT DEFINED CMAKE_JOB_POOL_PRECOMPILE_HEADER) set(CMAKE_JOB_POOL_LINK PGITaskPool) set(CMAKE_JOB_POOL_COMPILE PGITaskPool) + set(CMAKE_JOB_POOL_PRECOMPILE_HEADER PGITaskPool) get_property(_pgijp GLOBAL PROPERTY JOB_POOLS) if(NOT _pgijp MATCHES "PGITaskPool=") set_property(GLOBAL APPEND PROPERTY JOB_POOLS PGITaskPool=1) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8b8c711..58b8191 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 16) -set(CMake_VERSION_PATCH 20200101) +set(CMake_VERSION_PATCH 20200120) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index ea71007..3516235 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -775,6 +775,11 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( } } + std::string componentFileName = + "CPACK_DMG_" + cmSystemTools::UpperCase(componentName) + "_FILE_NAME"; + if (this->IsSet(componentFileName)) { + return this->GetOption(componentFileName); + } return GetComponentPackageFileName(package_file_name, componentName, false); } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 9530227..712eb77 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -125,7 +125,7 @@ int cmCPackGenerator::PrepareNames() cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl); const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); - if (descFileName) { + if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: " << descFileName << std::endl); if (!cmSystemTools::FileExists(descFileName)) { @@ -149,7 +149,12 @@ int cmCPackGenerator::PrepareNames() while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) { ostr << cmXMLSafe(line) << std::endl; } - this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str()); + this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str()); + const char* defFileName = + this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE"); + if (defFileName && !strcmp(defFileName, descFileName)) { + this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON"); + } } if (!this->GetOption("CPACK_PACKAGE_DESCRIPTION")) { cmCPackLogger( @@ -616,9 +621,9 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( buildConfigs.emplace_back(); } - std::unique_ptr<cmGlobalGenerator> globalGenerator( + std::unique_ptr<cmGlobalGenerator> globalGenerator = this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator( - cmakeGenerator)); + cmakeGenerator); if (!globalGenerator) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Specified package generator not found. " diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 4702639..363f536 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -139,10 +139,15 @@ int cmCPackNSISGenerator::PackageFiles() this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_ICON_CODE", installerIconCode.c_str()); } - if (this->IsSet("CPACK_PACKAGE_ICON")) { - std::string installerIconCode = - cmStrCat("!define MUI_HEADERIMAGE_BITMAP \"", - this->GetOption("CPACK_PACKAGE_ICON"), "\"\n"); + std::string installerHeaderImage; + if (this->IsSet("CPACK_NSIS_MUI_HEADERIMAGE")) { + installerHeaderImage = this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE"); + } else if (this->IsSet("CPACK_PACKAGE_ICON")) { + installerHeaderImage = this->GetOption("CPACK_PACKAGE_ICON"); + } + if (!installerHeaderImage.empty()) { + std::string installerIconCode = cmStrCat( + "!define MUI_HEADERIMAGE_BITMAP \"", installerHeaderImage, "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE", installerIconCode.c_str()); } diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 2ad661c..5e29386 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -215,11 +215,11 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) if (this->BuildNoCMake) { // Make the generator available for the Build call below. - cmGlobalGenerator* gen = cm.CreateGlobalGenerator(this->BuildGenerator); - cm.SetGlobalGenerator(gen); + cm.SetGlobalGenerator(cm.CreateGlobalGenerator(this->BuildGenerator)); if (!this->BuildGeneratorPlatform.empty()) { - cmMakefile mf(gen, cm.GetCurrentSnapshot()); - if (!gen->SetGeneratorPlatform(this->BuildGeneratorPlatform, &mf)) { + cmMakefile mf(cm.GetGlobalGenerator(), cm.GetCurrentSnapshot()); + if (!cm.GetGlobalGenerator()->SetGeneratorPlatform( + this->BuildGeneratorPlatform, &mf)) { return 1; } } diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 18df214..d1b7701 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -29,13 +29,7 @@ void cmCTestBuildCommand::BindArguments() this->Bind("PROJECT_NAME"_s, this->ProjectName); } -cmCTestBuildCommand::~cmCTestBuildCommand() -{ - if (this->GlobalGenerator) { - delete this->GlobalGenerator; - this->GlobalGenerator = nullptr; - } -} +cmCTestBuildCommand::~cmCTestBuildCommand() = default; cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() { @@ -79,8 +73,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() } if (this->GlobalGenerator) { if (this->GlobalGenerator->GetName() != cmakeGeneratorName) { - delete this->GlobalGenerator; - this->GlobalGenerator = nullptr; + this->GlobalGenerator.reset(); } } if (!this->GlobalGenerator) { diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index da00a43..0f82817 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -48,7 +48,7 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - cmGlobalGenerator* GlobalGenerator = nullptr; + std::unique_ptr<cmGlobalGenerator> GlobalGenerator; protected: cmCTestBuildHandler* Handler; diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index f2f42b4..3854710 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -69,12 +69,11 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() bool multiConfig = false; bool cmakeBuildTypeInOptions = false; - cmGlobalGenerator* gg = - this->Makefile->GetCMakeInstance()->CreateGlobalGenerator( - cmakeGeneratorName); + auto gg = this->Makefile->GetCMakeInstance()->CreateGlobalGenerator( + cmakeGeneratorName); if (gg) { multiConfig = gg->IsMultiConfig(); - delete gg; + gg.reset(); } std::string cmakeConfigureCommand = diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 46b00b1..acb75b2 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -7,6 +7,7 @@ #include <utility> #include <cm/memory> +#include <cm/vector> #include "cm_static_string_view.hxx" @@ -174,7 +175,7 @@ void cmCTestSubmitCommand::CheckArguments( this->PartsMentioned = !this->Parts.empty() || cmContains(keywords, "PARTS"); this->FilesMentioned = !this->Files.empty() || cmContains(keywords, "FILES"); - cmEraseIf(this->Parts, [this](std::string const& arg) -> bool { + cm::erase_if(this->Parts, [this](std::string const& arg) -> bool { cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str()); if (p == cmCTest::PartCount) { std::ostringstream e; @@ -185,7 +186,7 @@ void cmCTestSubmitCommand::CheckArguments( return false; }); - cmEraseIf(this->Files, [this](std::string const& arg) -> bool { + cm::erase_if(this->Files, [this](std::string const& arg) -> bool { if (!cmSystemTools::FileExists(arg)) { std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index d0e3848..eaef1ca 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -4,11 +4,11 @@ #include <set> #include <sstream> -#include <vector> + +#include <cm/vector> #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestUploadHandler.h" #include "cmMakefile.h" @@ -24,7 +24,7 @@ void cmCTestUploadCommand::BindArguments() void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&) { - cmEraseIf(this->Files, [this](std::string const& arg) -> bool { + cm::erase_if(this->Files, [this](std::string const& arg) -> bool { if (!cmSystemTools::FileExists(arg)) { std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 2ec9622..cdf899c 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -278,9 +278,6 @@ void cmProcess::OnTimeoutCB(uv_timer_t* timer) void cmProcess::OnTimeout() { - if (this->ProcessState != cmProcess::State::Executing) { - return; - } this->ProcessState = cmProcess::State::Expired; bool const was_still_reading = !this->ReadHandleClosed; if (!this->ReadHandleClosed) { diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index b608fcb..3b5dc04 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -6,6 +6,7 @@ #include <QDir> #include "cmExternalMakefileProjectGenerator.h" +#include "cmGlobalGenerator.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 995088c..5deba8b 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -215,7 +215,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, } if (cmSystemTools::FileIsFullPath(filename)) { - filename = cmSystemTools::CollapseFullPath(filename); + filename = cmSystemTools::CollapseFullPath( + filename, status.GetMakefile().GetHomeOutputDirectory()); } switch (doing) { case doing_depfile: diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index 6a1a514..35eabaf 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -53,7 +53,8 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, status.SetError(error); return false; } - srcPath = cmSystemTools::CollapseFullPath(srcPath); + srcPath = + cmSystemTools::CollapseFullPath(srcPath, mf.GetHomeOutputDirectory()); // Compute the full path to the binary directory. std::string binPath; diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index 8942113..205c1c7 100644 --- a/Source/cmAddTestCommand.cxx +++ b/Source/cmAddTestCommand.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddTestCommand.h" +#include <cm/memory> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -44,7 +46,7 @@ bool cmAddTestCommand(std::vector<std::string> const& args, } else { test = mf.CreateTest(args[0]); test->SetOldStyle(true); - mf.AddTestGenerator(new cmTestGenerator(test)); + mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test)); } test->SetCommand(command); @@ -141,7 +143,7 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args, test->SetProperty("WORKING_DIRECTORY", working_directory.c_str()); } test->SetCommandExpandLists(command_expand_lists); - mf.AddTestGenerator(new cmTestGenerator(test, configurations)); + mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test, configurations)); return true; } diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index a179acb..19da2a0 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -37,12 +37,6 @@ FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last) return first; } -template <typename Container, typename Predicate> -void cmEraseIf(Container& cont, Predicate pred) -{ - cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); -} - template <typename Range, typename Key> auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<2>) -> decltype(range.exists(key)) @@ -73,40 +67,6 @@ bool cmContains(Range const& range, Key const& key) namespace ContainerAlgorithms { -template <typename T> -struct cmIsPair -{ - enum - { - value = false - }; -}; - -template <typename K, typename V> -struct cmIsPair<std::pair<K, V>> -{ - enum - { - value = true - }; -}; - -template <typename Range, - bool valueTypeIsPair = cmIsPair<typename Range::value_type>::value> -struct DefaultDeleter -{ - void operator()(typename Range::value_type value) const { delete value; } -}; - -template <typename Range> -struct DefaultDeleter<Range, /* valueTypeIsPair = */ true> -{ - void operator()(typename Range::value_type value) const - { - delete value.second; - } -}; - template <typename FwdIt> FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n) { @@ -139,13 +99,6 @@ using cmBacktraceRange = cmRange<std::vector<cmListFileBacktrace>::const_iterator>; template <typename Range> -void cmDeleteAll(Range const& r) -{ - std::for_each(r.begin(), r.end(), - ContainerAlgorithms::DefaultDeleter<Range>()); -} - -template <typename Range> typename Range::const_iterator cmRemoveN(Range& r, size_t n) { return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n); diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index d627465..265941a 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -190,7 +190,7 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, if (entryKey.size() > plen && *(end - plen) == '-' && strcmp(end - plen + 1, *p) == 0) { std::string key = entryKey.substr(0, entryKey.size() - plen); - cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->GetCacheIterator(key); if (it.IsAtEnd()) { // Create an entry and store the property. CacheEntry& ne = this->Cache[key]; @@ -497,9 +497,15 @@ cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry( return nullptr; } -cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(const char* key) +cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator( + const std::string& key) { - return { *this, key }; + return { *this, key.c_str() }; +} + +cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator() +{ + return { *this, nullptr }; } const std::string* cmCacheManager::GetInitializedCacheValue( @@ -617,7 +623,7 @@ const char* cmCacheManager::CacheEntry::GetProperty( const std::string& prop) const { if (prop == "TYPE") { - return cmState::CacheEntryTypeToString(this->Type); + return cmState::CacheEntryTypeToString(this->Type).c_str(); } if (prop == "VALUE") { return this->Value.c_str(); @@ -638,20 +644,21 @@ void cmCacheManager::CacheEntry::SetProperty(const std::string& prop, } void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop, - const char* value, + const std::string& value, bool asString) { if (prop == "TYPE") { - this->Type = cmState::StringToCacheEntryType(value ? value : "STRING"); + this->Type = cmState::StringToCacheEntryType(!value.empty() ? value.c_str() + : "STRING"); } else if (prop == "VALUE") { - if (value) { - if (!this->Value.empty() && *value && !asString) { + if (!value.empty()) { + if (!this->Value.empty() && !asString) { this->Value += ";"; } this->Value += value; } } else { - this->Properties.AppendProperty(prop, value, asString); + this->Properties.AppendProperty(prop, value.c_str(), asString); } } @@ -673,7 +680,7 @@ void cmCacheManager::CacheIterator::SetProperty(const std::string& p, } void cmCacheManager::CacheIterator::AppendProperty(const std::string& p, - const char* v, + const std::string& v, bool asString) { if (!this->IsAtEnd()) { diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index faa60c5..d8be991 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -39,7 +39,7 @@ private: std::vector<std::string> GetPropertyList() const; const char* GetProperty(const std::string&) const; void SetProperty(const std::string& property, const char* value); - void AppendProperty(const std::string& property, const char* value, + void AppendProperty(const std::string& property, const std::string& value, bool asString = false); bool Initialized = false; }; @@ -58,10 +58,10 @@ public: bool GetPropertyAsBool(const std::string&) const; bool PropertyExists(const std::string&) const; void SetProperty(const std::string& property, const char* value); - void AppendProperty(const std::string& property, const char* value, + void AppendProperty(const std::string& property, const std::string& value, bool asString = false); void SetProperty(const std::string& property, bool value); - const char* GetValue() const { return this->GetEntry().Value.c_str(); } + const std::string& GetValue() const { return this->GetEntry().Value; } bool GetValueAsBool() const; void SetValue(const char*); cmStateEnums::CacheEntryType GetType() const @@ -111,7 +111,8 @@ public: void PrintCache(std::ostream&) const; //! Get the iterator for an entry with a given key. - cmCacheManager::CacheIterator GetCacheIterator(const char* key = nullptr); + cmCacheManager::CacheIterator GetCacheIterator(const std::string& key); + cmCacheManager::CacheIterator GetCacheIterator(); //! Remove an entry from the cache void RemoveCacheEntry(const std::string& key); @@ -124,52 +125,52 @@ public: const char* GetCacheEntryValue(const std::string& key) { - cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->GetCacheIterator(key); if (it.IsAtEnd()) { return nullptr; } - return it.GetValue(); + return it.GetValue().c_str(); } const char* GetCacheEntryProperty(std::string const& key, std::string const& propName) { - return this->GetCacheIterator(key.c_str()).GetProperty(propName); + return this->GetCacheIterator(key).GetProperty(propName); } cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) { - return this->GetCacheIterator(key.c_str()).GetType(); + return this->GetCacheIterator(key).GetType(); } bool GetCacheEntryPropertyAsBool(std::string const& key, std::string const& propName) { - return this->GetCacheIterator(key.c_str()).GetPropertyAsBool(propName); + return this->GetCacheIterator(key).GetPropertyAsBool(propName); } void SetCacheEntryProperty(std::string const& key, std::string const& propName, std::string const& value) { - this->GetCacheIterator(key.c_str()).SetProperty(propName, value.c_str()); + this->GetCacheIterator(key).SetProperty(propName, value.c_str()); } void SetCacheEntryBoolProperty(std::string const& key, std::string const& propName, bool value) { - this->GetCacheIterator(key.c_str()).SetProperty(propName, value); + this->GetCacheIterator(key).SetProperty(propName, value); } void SetCacheEntryValue(std::string const& key, std::string const& value) { - this->GetCacheIterator(key.c_str()).SetValue(value.c_str()); + this->GetCacheIterator(key).SetValue(value.c_str()); } void RemoveCacheEntryProperty(std::string const& key, std::string const& propName) { - this->GetCacheIterator(key.c_str()).SetProperty(propName, nullptr); + this->GetCacheIterator(key).SetProperty(propName, nullptr); } void AppendCacheEntryProperty(std::string const& key, @@ -177,8 +178,7 @@ public: std::string const& value, bool asString = false) { - this->GetCacheIterator(key.c_str()) - .AppendProperty(propName, value.c_str(), asString); + this->GetCacheIterator(key).AppendProperty(propName, value, asString); } std::vector<std::string> GetCacheEntryKeys() diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 645189a..47c821b 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -7,12 +7,11 @@ #include <map> #include <memory> +#include <queue> #include <set> #include <string> #include <vector> -#include <queue> - #include "cmGraphAdjacencyList.h" #include "cmLinkItem.h" #include "cmTargetLinkLibraryType.h" diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index c568253..34f815f 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -8,7 +8,6 @@ #include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmGeneratorExpression.h" @@ -30,11 +29,9 @@ void AppendPaths(const std::vector<std::string>& inputs, cmExpandedList(cge->Evaluate(lg, config)); for (std::string& it : result) { cmSystemTools::ConvertToUnixSlashes(it); - if (cmContains(it, '/') && !cmSystemTools::FileIsFullPath(it)) { - it = cmStrCat(lg->GetMakefile()->GetCurrentBinaryDirectory(), '/', it); - } if (cmSystemTools::FileIsFullPath(it)) { - it = cmSystemTools::CollapseFullPath(it); + it = cmSystemTools::CollapseFullPath( + it, lg->GetMakefile()->GetHomeOutputDirectory()); } } cm::append(output, result); diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index 3bb6e36..868c94a 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -7,12 +7,11 @@ #include <iosfwd> #include <map> +#include <queue> #include <set> #include <string> #include <vector> -#include <queue> - #include "cmsys/RegularExpression.hxx" #include "cmDepends.h" diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index ee43587..3692202 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -33,6 +33,8 @@ static void cmFortranModuleAppendUpperLower(std::string const& mod, ext_len = 4; } else if (cmHasLiteralSuffix(mod, ".smod")) { ext_len = 5; + } else if (cmHasLiteralSuffix(mod, ".sub")) { + ext_len = 4; } std::string const& name = mod.substr(0, mod.size() - ext_len); std::string const& ext = mod.substr(mod.size() - ext_len); @@ -284,7 +286,8 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin, if (doing_provides) { std::string mod = line; if (!cmHasLiteralSuffix(mod, ".mod") && - !cmHasLiteralSuffix(mod, ".smod")) { + !cmHasLiteralSuffix(mod, ".smod") && + !cmHasLiteralSuffix(mod, ".sub")) { // Support fortran.internal files left by older versions of CMake. // They do not include the ".mod" extension. mod += ".mod"; @@ -470,7 +473,8 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args) if (args.size() >= 5) { compilerId = args[4]; } - if (!cmHasLiteralSuffix(mod, ".mod") && !cmHasLiteralSuffix(mod, ".smod")) { + if (!cmHasLiteralSuffix(mod, ".mod") && !cmHasLiteralSuffix(mod, ".smod") && + !cmHasLiteralSuffix(mod, ".sub")) { // Support depend.make files left by older versions of CMake. // They do not include the ".mod" extension. mod += ".mod"; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index dbe5a5e..d22bd48 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -301,11 +301,10 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg, std::vector<std::string> exportFiles; std::string ns; - std::map<std::string, cmExportBuildFileGenerator*>& exportSets = - gg->GetBuildExportSets(); + auto& exportSets = gg->GetBuildExportSets(); for (auto const& exp : exportSets) { - const cmExportBuildFileGenerator* exportSet = exp.second; + const auto& exportSet = exp.second; std::vector<std::string> targets; exportSet->GetTargets(targets); if (cmContains(targets, name)) { diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 2a6bf5d..b7cc193 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -6,6 +6,8 @@ #include <sstream> #include <utility> +#include <cm/memory> + #include "cmsys/RegularExpression.hxx" #include "cm_static_string_view.hxx" @@ -182,11 +184,11 @@ bool cmExportCommand(std::vector<std::string> const& args, } // Setup export file generation. - cmExportBuildFileGenerator* ebfg = nullptr; + std::unique_ptr<cmExportBuildFileGenerator> ebfg = nullptr; if (android) { - ebfg = new cmExportBuildAndroidMKGenerator; + ebfg = cm::make_unique<cmExportBuildAndroidMKGenerator>(); } else { - ebfg = new cmExportBuildFileGenerator; + ebfg = cm::make_unique<cmExportBuildFileGenerator>(); } ebfg->SetExportFile(fname.c_str()); ebfg->SetNamespace(arguments.Namespace); @@ -196,7 +198,7 @@ bool cmExportCommand(std::vector<std::string> const& args, } else { ebfg->SetTargets(targets); } - mf.AddExportBuildFileGenerator(ebfg); + mf.AddExportBuildFileGenerator(ebfg.get()); ebfg->SetExportOld(arguments.ExportOld); // Compute the set of configurations exported. @@ -209,9 +211,9 @@ bool cmExportCommand(std::vector<std::string> const& args, ebfg->AddConfiguration(ct); } if (exportSet != nullptr) { - gg->AddBuildExportExportSet(ebfg); + gg->AddBuildExportExportSet(std::move(ebfg)); } else { - gg->AddBuildExportSet(ebfg); + gg->AddBuildExportSet(std::move(ebfg)); } return true; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index aeef602..27e9906 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -14,6 +14,7 @@ #include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -640,6 +641,9 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( std::string sep; input.clear(); for (std::string& li : parts) { + if (cmHasLiteralPrefix(li, CMAKE_DIRECTORY_ID_SEP)) { + continue; + } if (cmGeneratorExpression::Find(li) == std::string::npos) { this->AddTargetNamespace(li, target, missingTargets); } else { @@ -1062,6 +1066,12 @@ void cmExportFileGenerator::GenerateImportTargetCode( if (target->IsCFBundleOnApple()) { os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n"; } + + // generate DEPRECATION + if (target->IsDeprecated()) { + os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION " + << cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n"; + } os << "\n"; } diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index dfc8de5..6011ba4 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -49,11 +49,11 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename, // the project. cmake* cm = makefile.GetCMakeInstance(); cmGlobalGenerator* global = cm->GetGlobalGenerator(); - const std::vector<cmMakefile*>& locals = global->GetMakefiles(); + const auto& locals = global->GetMakefiles(); std::map<std::string, std::string> libDepsOld; std::map<std::string, std::string> libDepsNew; std::map<std::string, std::string> libTypes; - for (cmMakefile* local : locals) { + for (const auto& local : locals) { for (auto const& tgt : local->GetTargets()) { // Get the current target. cmTarget const& target = tgt.second; diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index a472a06..2b8d505 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <string> #include <vector> @@ -78,7 +79,7 @@ public: std::vector<std::string> GetSupportedGlobalGenerators() const; std::vector<std::string> Aliases; - virtual cmExternalMakefileProjectGenerator* + virtual std::unique_ptr<cmExternalMakefileProjectGenerator> CreateExternalMakefileProjectGenerator() const = 0; void AddSupportedGlobalGenerator(const std::string& base); @@ -100,10 +101,10 @@ public: { } - cmExternalMakefileProjectGenerator* CreateExternalMakefileProjectGenerator() - const override + std::unique_ptr<cmExternalMakefileProjectGenerator> + CreateExternalMakefileProjectGenerator() const override { - T* p = new T; + std::unique_ptr<cmExternalMakefileProjectGenerator> p(new T); p->SetName(GetName()); return p; } diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index e463420..3a22846 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -246,8 +246,7 @@ std::string cmExtraKateGenerator::GenerateFilesString( } } - const std::vector<cmSourceFile*>& sources = makefile->GetSourceFiles(); - for (cmSourceFile* sf : sources) { + for (const auto& sf : makefile->GetSourceFiles()) { if (sf->GetIsGenerated()) { continue; } diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 7a2d9d5..955195f 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -427,7 +427,7 @@ Json::Value Codemodel::DumpConfigurations() Json::Value configurations = Json::arrayValue; cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - auto makefiles = gg->GetMakefiles(); + const auto& makefiles = gg->GetMakefiles(); if (!makefiles.empty()) { std::vector<std::string> const& configs = makefiles[0]->GetGeneratorConfigs(); @@ -493,8 +493,9 @@ void CodemodelConfig::ProcessDirectories() Directory& d = *di; // Accumulate the presence of install rules on the way up. - for (auto gen : d.LocalGenerator->GetMakefile()->GetInstallGenerators()) { - if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) { + for (const auto& gen : + d.LocalGenerator->GetMakefile()->GetInstallGenerators()) { + if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen.get())) { d.HasInstallRule = true; break; } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 1fdfa87..d1775a7 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1707,7 +1707,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, // as we receive downloaded bits from curl... // std::string dir = cmSystemTools::GetFilenamePath(file); - if (!cmSystemTools::FileExists(dir) && !cmSystemTools::MakeDirectory(dir)) { + if (!dir.empty() && !cmSystemTools::FileExists(dir) && + !cmSystemTools::MakeDirectory(dir)) { std::string errstring = "DOWNLOAD error: cannot create directory '" + dir + "' - Specify file by full path name and verify that you " "have directory creation and file write privileges."; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 9eb256b..297c72b 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -161,6 +161,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } this->DebugMode = ComputeIfDebugModeWanted(); + this->DebugBuffer.clear(); // Lookup target architecture, if any. if (const char* arch = @@ -575,6 +576,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } this->AppendSuccessInformation(); + return loadedPackage; } @@ -708,7 +710,7 @@ bool cmFindPackageCommand::FindModule(bool& found) debugBuffer = cmStrCat(debugBuffer, "The file was found at\n ", mfile, "\n"); } - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } if (!mfile.empty()) { @@ -841,6 +843,11 @@ bool cmFindPackageCommand::HandlePackageMode( result = false; } + if (this->DebugMode) { + this->DebugMessage(this->DebugBuffer); + this->DebugBuffer.clear(); + } + // package not found if (result && !found) { // warn if package required or neither quiet nor in config mode @@ -1001,6 +1008,11 @@ bool cmFindPackageCommand::FindConfig() // Look for the project's configuration file. bool found = false; + if (this->DebugMode) { + this->DebugBuffer = cmStrCat(this->DebugBuffer, + "find_package considered the following " + "locations for the Config module:\n"); + } // Search for frameworks. if (!found && (this->SearchFrameworkFirst || this->SearchFrameworkOnly)) { @@ -1027,6 +1039,16 @@ bool cmFindPackageCommand::FindConfig() found = this->FindAppBundleConfig(); } + if (this->DebugMode) { + if (found) { + this->DebugBuffer = cmStrCat( + this->DebugBuffer, "The file was found at\n ", this->FileFound, "\n"); + } else { + this->DebugBuffer = + cmStrCat(this->DebugBuffer, "The file was not found.\n"); + } + } + // Store the entry in the cache so it can be set by the user. std::string init; if (found) { @@ -1040,6 +1062,7 @@ bool cmFindPackageCommand::FindConfig() // 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); + return found; } @@ -1244,7 +1267,7 @@ void cmFindPackageCommand::FillPrefixesPackageRoot() std::string debugBuffer = "<PackageName>_ROOT CMake variable " "[CMAKE_FIND_USE_PACKAGE_ROOT_PATH].\n"; collectPathsForDebug(debugBuffer, paths); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1280,7 +1303,7 @@ void cmFindPackageCommand::FillPrefixesCMakeEnvironment() "\nCMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH env " "variables [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n"); collectPathsForDebug(debugBuffer, paths, debugOffset); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1304,7 +1327,7 @@ void cmFindPackageCommand::FillPrefixesCMakeVariable() "\nCMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables " "[CMAKE_FIND_USE_CMAKE_PATH].\n"); collectPathsForDebug(debugBuffer, paths, debugOffset); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1329,7 +1352,7 @@ void cmFindPackageCommand::FillPrefixesSystemEnvironment() std::string debugBuffer = "Standard system environment variables " "[CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].\n"; collectPathsForDebug(debugBuffer, paths); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1359,7 +1382,7 @@ void cmFindPackageCommand::FillPrefixesUserRegistry() "CMake User Package Registry [CMAKE_FIND_USE_PACKAGE_REGISTRY].\n"; collectPathsForDebug(debugBuffer, this->LabeledPaths[PathLabel::UserRegistry]); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1379,7 +1402,7 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry() "[CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY].\n"; collectPathsForDebug(debugBuffer, this->LabeledPaths[PathLabel::SystemRegistry]); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1558,7 +1581,7 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() std::string debugBuffer = "CMake variables defined in the Platform file " "[CMAKE_FIND_USE_CMAKE_SYSTEM_PATH].\n"; collectPathsForDebug(debugBuffer, paths); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1573,7 +1596,7 @@ void cmFindPackageCommand::FillPrefixesUserGuess() std::string debugBuffer = "Paths specified by the find_package PATHS option.\n"; collectPathsForDebug(debugBuffer, paths); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1588,7 +1611,7 @@ void cmFindPackageCommand::FillPrefixesUserHints() std::string debugBuffer = "Paths specified by the find_package HINTS option.\n"; collectPathsForDebug(debugBuffer, paths); - this->DebugMessage(debugBuffer); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); } } @@ -1634,8 +1657,7 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir, for (std::string const& c : this->Configs) { file = cmStrCat(dir, '/', c); if (this->DebugMode) { - std::string msg = "Checking file [" + file + "]\n"; - this->DebugMessage(msg); + this->DebugBuffer = cmStrCat(this->DebugBuffer, " ", file, "\n"); } if (cmSystemTools::FileExists(file, true) && this->CheckVersion(file)) { // Allow resolving symlinks when the config file is found through a link diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index a65a292..ae9ade7 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -183,6 +183,7 @@ private: std::vector<std::string> Names; std::vector<std::string> Configs; std::set<std::string> IgnoredPaths; + std::string DebugBuffer; /*! the selected sortOrder (None by default)*/ SortOrderType SortOrder; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 19d5b4d..441515c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -10,6 +10,7 @@ #include <cstdlib> #include <cstring> #include <iterator> +#include <queue> #include <sstream> #include <unordered_set> #include <utility> @@ -17,8 +18,6 @@ #include <cm/memory> #include <cm/string_view> -#include <queue> - #include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" @@ -2714,6 +2713,17 @@ void cmTargetTraceDependencies::FollowName(std::string const& name) if (i == this->NameMap.end() || i->first != name) { // Check if we know how to generate this file. cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name); + // If we failed to find a target or source and we have a relative path, it + // might be a valid source if made relative to the current binary + // directory. + if (!sources.Target && !sources.Source && + !cmSystemTools::FileIsFullPath(name)) { + auto fullname = + cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', name); + fullname = cmSystemTools::CollapseFullPath( + fullname, this->Makefile->GetHomeOutputDirectory()); + sources = this->Makefile->GetSourcesWithOutput(fullname); + } i = this->NameMap.emplace_hint(i, name, sources); } if (cmTarget* t = i->second.Target) { @@ -3087,7 +3097,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( cmLinkImplementationLibraries const* impl = this->GetLinkImplementationLibraries(config); for (cmLinkImplItem const& lib : impl->Libraries) { - std::string libDir = cmSystemTools::CollapseFullPath(lib.AsStr()); + std::string libDir = cmSystemTools::CollapseFullPath( + lib.AsStr(), this->Makefile->GetHomeOutputDirectory()); static cmsys::RegularExpression frameworkCheck( "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); @@ -5407,16 +5418,39 @@ void cmGeneratorTarget::ReportPropertyOrigin( areport); } +bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n, + cmLocalGenerator const*& lg) const +{ + if (cmHasLiteralPrefix(n, CMAKE_DIRECTORY_ID_SEP)) { + cmDirectoryId const dirId = n.substr(sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); + if (dirId.String.empty()) { + lg = this->LocalGenerator; + return true; + } + if (cmLocalGenerator const* otherLG = + this->GlobalGenerator->FindLocalGenerator(dirId)) { + lg = otherLG; + return true; + } + } + return false; +} + void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const { + cmLocalGenerator const* lg = this->LocalGenerator; for (std::string const& n : names) { + if (this->IsLinkLookupScope(n, lg)) { + continue; + } + std::string name = this->CheckCMP0004(n); if (name == this->GetName() || name.empty()) { continue; } - items.push_back(this->ResolveLinkItem(name, bt)); + items.push_back(this->ResolveLinkItem(name, bt, lg)); } } @@ -5425,6 +5459,7 @@ void cmGeneratorTarget::ExpandLinkItems( cmGeneratorTarget const* headTarget, bool usage_requirements_only, std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const { + // Keep this logic in sync with ComputeLinkImplementationLibraries. cmGeneratorExpression ge; cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr); // The $<LINK_ONLY> expression may be in a link interface to specify private @@ -6354,6 +6389,21 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const return lib; } +bool cmGeneratorTarget::IsDeprecated() const +{ + const char* deprecation = this->GetProperty("DEPRECATION"); + return deprecation && *deprecation; +} + +std::string cmGeneratorTarget::GetDeprecation() const +{ + // find DEPRECATION property + if (const char* deprecation = this->GetProperty("DEPRECATION")) { + return deprecation; + } + return std::string(); +} + void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, const std::string& config) const { @@ -6485,6 +6535,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( const std::string& config, cmOptionalLinkImplementation& impl, cmGeneratorTarget const* head) const { + cmLocalGenerator const* lg = this->LocalGenerator; cmStringRange entryRange = this->Target->GetLinkImplementationEntries(); cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces(); cmBacktraceRange::const_iterator btIt = btRange.begin(); @@ -6493,6 +6544,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( end = entryRange.end(); le != end; ++le, ++btIt) { std::vector<std::string> llibs; + // Keep this logic in sync with ExpandLinkItems. cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, nullptr); cmGeneratorExpression ge(*btIt); @@ -6505,6 +6557,10 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } for (std::string const& lib : llibs) { + if (this->IsLinkLookupScope(lib, lg)) { + continue; + } + // Skip entries that resolve to the target itself or are empty. std::string name = this->CheckCMP0004(lib); if (name == this->GetName() || name.empty()) { @@ -6539,7 +6595,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt), + impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt, lg), evaluated != *le); } @@ -6576,38 +6632,16 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( std::string const& name) const { - cmLocalGenerator const* lg = this->LocalGenerator; - std::string const* lookupName = &name; - - // When target_link_libraries() is called with a LHS target that is - // not created in the calling directory it adds a directory id suffix - // that we can use to look up the calling directory. It is that scope - // in which the item name is meaningful. This case is relatively rare - // so we allocate a separate string only when the directory id is present. - std::string::size_type pos = name.find(CMAKE_DIRECTORY_ID_SEP); - std::string plainName; - if (pos != std::string::npos) { - // We will look up the plain name without the directory id suffix. - plainName = name.substr(0, pos); - - // We will look up in the scope of the directory id. - // If we do not recognize the id then leave the original - // syntax in place to produce an indicative error later. - cmDirectoryId const dirId = - name.substr(pos + sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); - if (cmLocalGenerator const* otherLG = - this->GlobalGenerator->FindLocalGenerator(dirId)) { - lg = otherLG; - lookupName = &plainName; - } - } + return this->ResolveTargetReference(name, this->LocalGenerator); +} +cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( + std::string const& name, cmLocalGenerator const* lg) const +{ TargetOrString resolved; - if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(*lookupName)) { + if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(name)) { resolved.Target = tgt; - } else if (lookupName == &plainName) { - resolved.String = std::move(plainName); } else { resolved.String = name; } @@ -6618,12 +6652,32 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( cmLinkItem cmGeneratorTarget::ResolveLinkItem( std::string const& name, cmListFileBacktrace const& bt) const { - TargetOrString resolved = this->ResolveTargetReference(name); + return this->ResolveLinkItem(name, bt, this->LocalGenerator); +} + +cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt, + cmLocalGenerator const* lg) const +{ + TargetOrString resolved = this->ResolveTargetReference(name, lg); if (!resolved.Target) { return cmLinkItem(resolved.String, bt); } + // Check deprecation, issue message with `bt` backtrace. + if (resolved.Target->IsDeprecated()) { + std::ostringstream w; + /* clang-format off */ + w << + "The library that is being linked to, " << resolved.Target->GetName() << + ", is marked as being deprecated by the owner. The message provided by " + "the developer is: \n" << resolved.Target->GetDeprecation() << "\n"; + /* clang-format on */ + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + MessageType::AUTHOR_WARNING, w.str(), bt); + } + // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable // within the project. diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index eabd3fa9..9d06104 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -250,6 +250,13 @@ public: std::string GetAppBundleDirectory(const std::string& config, BundleDirectoryLevel level) const; + /** Return whether this target is marked as deprecated by the + maintainer */ + bool IsDeprecated() const; + + /** Returns the deprecation message provided by the maintainer */ + std::string GetDeprecation() const; + /** Return whether this target is an executable Bundle, a framework or CFBundle on Apple. */ bool IsBundleOnApple() const; @@ -371,9 +378,14 @@ public: cmGeneratorTarget* Target = nullptr; }; TargetOrString ResolveTargetReference(std::string const& name) const; + TargetOrString ResolveTargetReference(std::string const& name, + cmLocalGenerator const* lg) const; cmLinkItem ResolveLinkItem(std::string const& name, cmListFileBacktrace const& bt) const; + cmLinkItem ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt, + cmLocalGenerator const* lg) const; // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change @@ -912,6 +924,9 @@ private: std::unordered_set<std::string> UnityBatchedSourceFiles; + bool IsLinkLookupScope(std::string const& n, + cmLocalGenerator const*& lg) const; + void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, const cmGeneratorTarget* headTarget, diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index f7c542f..5e2248e 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -279,10 +279,10 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, std::string frameworkPath; std::string linkPath; - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->GetGlobalGenerator()->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); this->LocalGenerator->GetTargetFlags( linkLineComputer.get(), config, linkLibraries, flags, linkFlags, diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index 291220c..9af0eac 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -17,10 +17,10 @@ class cmGlobalBorlandMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalBorlandMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalBorlandMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalBorlandMakefileGenerator>()); } //! Get the name for the generator. diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index c189ea5..38ff3ae 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -262,16 +262,17 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, } } -void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen) +void cmGlobalGenerator::AddBuildExportSet( + std::unique_ptr<cmExportBuildFileGenerator> gen) { - this->BuildExportSets[gen->GetMainExportFileName()] = gen; + this->BuildExportSets[gen->GetMainExportFileName()] = std::move(gen); } void cmGlobalGenerator::AddBuildExportExportSet( - cmExportBuildFileGenerator* gen) + std::unique_ptr<cmExportBuildFileGenerator> gen) { - this->BuildExportSets[gen->GetMainExportFileName()] = gen; - this->BuildExportExportSets[gen->GetMainExportFileName()] = gen; + this->BuildExportExportSets[gen->GetMainExportFileName()] = gen.get(); + this->AddBuildExportSet(std::move(gen)); } bool cmGlobalGenerator::GenerateImportFile(const std::string& file) @@ -281,13 +282,11 @@ bool cmGlobalGenerator::GenerateImportFile(const std::string& file) bool result = it->second->GenerateImportFile(); if (!this->ConfigureDoneCMP0026AndCMP0024) { - for (cmMakefile* m : this->Makefiles) { - m->RemoveExportBuildFileGeneratorCMP0024(it->second); + for (const auto& m : this->Makefiles) { + m->RemoveExportBuildFileGeneratorCMP0024(it->second.get()); } } - delete it->second; - it->second = nullptr; this->BuildExportSets.erase(it); return result; } @@ -1207,8 +1206,8 @@ void cmGlobalGenerator::CreateLocalGenerators() this->LocalGeneratorSearchIndex.clear(); this->LocalGenerators.clear(); this->LocalGenerators.reserve(this->Makefiles.size()); - for (cmMakefile* m : this->Makefiles) { - auto lg = this->CreateLocalGenerator(m); + for (const auto& m : this->Makefiles) { + auto lg = this->CreateLocalGenerator(m.get()); this->IndexLocalGenerator(lg.get()); this->LocalGenerators.push_back(std::move(lg)); } @@ -1226,9 +1225,10 @@ void cmGlobalGenerator::Configure() snapshot.GetDirectory().SetCurrentBinary( this->CMakeInstance->GetHomeOutputDirectory()); - cmMakefile* dirMf = new cmMakefile(this, snapshot); + auto dirMfu = cm::make_unique<cmMakefile>(this, snapshot); + auto dirMf = dirMfu.get(); + this->Makefiles.push_back(std::move(dirMfu)); dirMf->SetRecursionDepth(this->RecursionDepth); - this->Makefiles.push_back(dirMf); this->IndexMakefile(dirMf); this->BinaryDirectories.insert( @@ -1246,11 +1246,11 @@ void cmGlobalGenerator::Configure() std::vector<GlobalTargetInfo> globalTargets; this->CreateDefaultGlobalTargets(globalTargets); - for (cmMakefile* mf : this->Makefiles) { + for (const auto& mf : this->Makefiles) { auto& targets = mf->GetTargets(); for (GlobalTargetInfo const& globalTarget : globalTargets) { targets.emplace(globalTarget.Name, - this->CreateGlobalTarget(globalTarget, mf)); + this->CreateGlobalTarget(globalTarget, mf.get())); } } } @@ -1299,7 +1299,10 @@ void cmGlobalGenerator::CreateImportedGenerationObjects( { this->CreateGenerationObjects(ImportedOnly); auto const mfit = - std::find(this->Makefiles.begin(), this->Makefiles.end(), mf); + std::find_if(this->Makefiles.begin(), this->Makefiles.end(), + [mf](const std::unique_ptr<cmMakefile>& item) { + return item.get() == mf; + }); auto& lg = this->LocalGenerators[std::distance(this->Makefiles.begin(), mfit)]; for (std::string const& t : targets) { @@ -1314,7 +1317,7 @@ cmExportBuildFileGenerator* cmGlobalGenerator::GetExportedTargetsFile( const std::string& filename) const { auto const it = this->BuildExportSets.find(filename); - return it == this->BuildExportSets.end() ? nullptr : it->second; + return it == this->BuildExportSets.end() ? nullptr : it->second.get(); } void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target) @@ -1410,7 +1413,7 @@ bool cmGlobalGenerator::Compute() for (const auto& localGen : this->LocalGenerators) { cmMakefile* mf = localGen->GetMakefile(); - for (cmInstallGenerator* g : mf->GetInstallGenerators()) { + for (const auto& g : mf->GetInstallGenerators()) { if (!g->Compute(localGen.get())) { return false; } @@ -1587,16 +1590,18 @@ bool cmGlobalGenerator::AddAutomaticSources() return true; } -cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( +std::unique_ptr<cmLinkLineComputer> cmGlobalGenerator::CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const { - return new cmLinkLineComputer(outputConverter, stateDir); + return cm::make_unique<cmLinkLineComputer>(outputConverter, stateDir); } -cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer( +std::unique_ptr<cmLinkLineComputer> +cmGlobalGenerator::CreateMSVC60LinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const { - return new cmMSVC60LinkLineComputer(outputConverter, stateDir); + return std::unique_ptr<cmLinkLineComputer>( + cm::make_unique<cmMSVC60LinkLineComputer>(outputConverter, stateDir)); } void cmGlobalGenerator::FinalizeTargetCompileInfo() @@ -1605,7 +1610,7 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() this->CMakeInstance->GetState()->GetEnabledLanguages(); // Construct per-target generator information. - for (cmMakefile* mf : this->Makefiles) { + for (const auto& mf : this->Makefiles) { const cmStringRange noconfig_compile_definitions = mf->GetCompileDefinitionsEntries(); const cmBacktraceRange noconfig_compile_definitions_bts = @@ -1682,28 +1687,26 @@ void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes) { std::map<cmTarget*, cmGeneratorTarget*> importedMap; for (unsigned int i = 0; i < this->Makefiles.size(); ++i) { - cmMakefile* mf = this->Makefiles[i]; - for (cmTarget* ownedImpTgt : mf->GetOwnedImportedTargets()) { + auto& mf = this->Makefiles[i]; + for (const auto& ownedImpTgt : mf->GetOwnedImportedTargets()) { cmLocalGenerator* lg = this->LocalGenerators[i].get(); - auto gt = cm::make_unique<cmGeneratorTarget>(ownedImpTgt, lg); - importedMap[ownedImpTgt] = gt.get(); + auto gt = cm::make_unique<cmGeneratorTarget>(ownedImpTgt.get(), lg); + importedMap[ownedImpTgt.get()] = gt.get(); lg->AddOwnedImportedGeneratorTarget(std::move(gt)); } } // Construct per-target generator information. for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { - this->CreateGeneratorTargets(targetTypes, this->Makefiles[i], + this->CreateGeneratorTargets(targetTypes, this->Makefiles[i].get(), this->LocalGenerators[i].get(), importedMap); } } void cmGlobalGenerator::ClearGeneratorMembers() { - cmDeleteAll(this->BuildExportSets); this->BuildExportSets.clear(); - cmDeleteAll(this->Makefiles); this->Makefiles.clear(); this->LocalGenerators.clear(); @@ -2000,10 +2003,10 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand( return makeCommand; } -void cmGlobalGenerator::AddMakefile(cmMakefile* mf) +void cmGlobalGenerator::AddMakefile(std::unique_ptr<cmMakefile> mf) { - this->Makefiles.push_back(mf); - this->IndexMakefile(mf); + this->IndexMakefile(mf.get()); + this->Makefiles.push_back(std::move(mf)); // update progress // estimate how many lg there will be @@ -2355,7 +2358,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets( void cmGlobalGenerator::AddGlobalTarget_Package( std::vector<GlobalTargetInfo>& targets) { - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; std::string configFile = cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake"); if (!cmSystemTools::FileExists(configFile)) { @@ -2404,7 +2407,7 @@ void cmGlobalGenerator::AddGlobalTarget_PackageSource( return; } - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; std::string configFile = cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake"); if (!cmSystemTools::FileExists(configFile)) { @@ -2436,7 +2439,7 @@ void cmGlobalGenerator::AddGlobalTarget_PackageSource( void cmGlobalGenerator::AddGlobalTarget_Test( std::vector<GlobalTargetInfo>& targets) { - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; if (!mf->IsOn("CMAKE_TESTING_ENABLED")) { return; } @@ -2456,6 +2459,13 @@ void cmGlobalGenerator::AddGlobalTarget_Test( cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCTestCommand()); singleLine.push_back("--force-new-ctest-process"); + if (auto testArgs = mf->GetDefinition("CMAKE_CTEST_ARGUMENTS")) { + std::vector<std::string> args; + cmExpandList(testArgs, args); + for (auto const& arg : args) { + singleLine.push_back(arg); + } + } if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { singleLine.push_back("-C"); singleLine.push_back(cmakeCfgIntDir); @@ -2524,7 +2534,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache( void cmGlobalGenerator::AddGlobalTarget_Install( std::vector<GlobalTargetInfo>& targets) { - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES"); if (this->InstallTargetEnabled && skipInstallRules) { @@ -2574,7 +2584,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( singleLine.push_back(cmd); if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { std::string cfgArg = "-DBUILD_TYPE="; - bool useEPN = this->UseEffectivePlatformName(mf); + bool useEPN = this->UseEffectivePlatformName(mf.get()); if (useEPN) { cfgArg += "$(CONFIGURATION)"; singleLine.push_back(cfgArg); @@ -2741,9 +2751,9 @@ bool cmGlobalGenerator::IsReservedTarget(std::string const& name) } void cmGlobalGenerator::SetExternalMakefileProjectGenerator( - cmExternalMakefileProjectGenerator* extraGenerator) + std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator) { - this->ExtraGenerator.reset(extraGenerator); + this->ExtraGenerator = std::move(extraGenerator); if (this->ExtraGenerator) { this->ExtraGenerator->SetGlobalGenerator(this); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 4794853..51c8d06 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -162,11 +162,11 @@ public: */ virtual void Generate(); - virtual cmLinkLineComputer* CreateLinkLineComputer( + virtual std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const; - cmLinkLineComputer* CreateMSVC60LinkLineComputer( + std::unique_ptr<cmLinkLineComputer> CreateMSVC60LinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const; @@ -249,7 +249,7 @@ public: cmake* GetCMakeInstance() const { return this->CMakeInstance; } void SetConfiguredFilesPath(cmGlobalGenerator* gen); - const std::vector<cmMakefile*>& GetMakefiles() const + const std::vector<std::unique_ptr<cmMakefile>>& GetMakefiles() const { return this->Makefiles; } @@ -268,11 +268,11 @@ public: this->CurrentConfigureMakefile = mf; } - void AddMakefile(cmMakefile* mf); + void AddMakefile(std::unique_ptr<cmMakefile> mf); //! Set an generator for an "external makefile based project" void SetExternalMakefileProjectGenerator( - cmExternalMakefileProjectGenerator* extraGenerator); + std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator); std::string GetExtraGeneratorName() const; @@ -445,12 +445,13 @@ public: void ProcessEvaluationFiles(); - std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets() + std::map<std::string, std::unique_ptr<cmExportBuildFileGenerator>>& + GetBuildExportSets() { return this->BuildExportSets; } - void AddBuildExportSet(cmExportBuildFileGenerator*); - void AddBuildExportExportSet(cmExportBuildFileGenerator*); + void AddBuildExportSet(std::unique_ptr<cmExportBuildFileGenerator>); + void AddBuildExportExportSet(std::unique_ptr<cmExportBuildFileGenerator>); bool IsExportedTargetsFile(const std::string& filename) const; bool GenerateImportFile(const std::string& file); cmExportBuildFileGenerator* GetExportedTargetsFile( @@ -551,7 +552,7 @@ protected: std::string FindMakeProgramFile; std::string ConfiguredFilesPath; cmake* CMakeInstance; - std::vector<cmMakefile*> Makefiles; + std::vector<std::unique_ptr<cmMakefile>> Makefiles; LocalGeneratorVector LocalGenerators; cmMakefile* CurrentConfigureMakefile; // map from project name to vector of local generators in that project @@ -561,7 +562,8 @@ protected: std::set<std::string> InstallComponents; // Sets of named target exports cmExportSetMap ExportSets; - std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets; + std::map<std::string, std::unique_ptr<cmExportBuildFileGenerator>> + BuildExportSets; std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets; std::map<std::string, std::string> AliasTargets; diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index bb5f74c..3709365 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include <cm/memory> + class cmGlobalGenerator; class cmake; struct cmDocumentationEntry; @@ -23,8 +25,8 @@ public: virtual ~cmGlobalGeneratorFactory() = default; /** Create a GlobalGenerator */ - virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& n, - cmake* cm) const = 0; + virtual std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& n, cmake* cm) const = 0; /** Get the documentation entry for this factory */ virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0; @@ -51,13 +53,13 @@ class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory { public: /** Create a GlobalGenerator */ - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { if (name != T::GetActualName()) { - return nullptr; + return std::unique_ptr<cmGlobalGenerator>(); } - return new T(cm); + return std::unique_ptr<cmGlobalGenerator>(cm::make_unique<T>(cm)); } /** Get the documentation entry for this factory */ diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 989b12c..b82e9f5 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -29,9 +29,10 @@ public: cmGlobalGhsMultiGenerator(cmake* cm); ~cmGlobalGhsMultiGenerator() override; - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>()); } //! create the correct local generator diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index fc39ddf..9f1ec8b 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -4,6 +4,7 @@ #define cmGlobalJOMMakefileGenerator_h #include <iosfwd> +#include <memory> #include "cmGlobalUnixMakefileGenerator3.h" @@ -16,9 +17,10 @@ class cmGlobalJOMMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalJOMMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>()); } //! Get the name for the generator. std::string GetName() const override diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h index d6e4847..b2de4ff 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.h +++ b/Source/cmGlobalMSYSMakefileGenerator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalMSYSMakefileGenerator_h #define cmGlobalMSYSMakefileGenerator_h +#include <memory> + #include "cmGlobalUnixMakefileGenerator3.h" /** \class cmGlobalMSYSMakefileGenerator @@ -14,9 +16,10 @@ class cmGlobalMSYSMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalMSYSMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalMSYSMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalMSYSMakefileGenerator>()); } //! Get the name for the generator. diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h index 15297e3..a9f92a1 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.h +++ b/Source/cmGlobalMinGWMakefileGenerator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalMinGWMakefileGenerator_h #define cmGlobalMinGWMakefileGenerator_h +#include <memory> + #include "cmGlobalUnixMakefileGenerator3.h" /** \class cmGlobalMinGWMakefileGenerator @@ -14,10 +16,10 @@ class cmGlobalMinGWMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalMinGWMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalMinGWMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalMinGWMakefileGenerator>()); } //! Get the name for the generator. virtual std::string GetName() const diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index 4586b77..fdf6006 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -4,6 +4,7 @@ #define cmGlobalNMakeMakefileGenerator_h #include <iosfwd> +#include <memory> #include "cmGlobalUnixMakefileGenerator3.h" @@ -16,10 +17,10 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalNMakeMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalNMakeMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalNMakeMakefileGenerator>()); } //! Get the name for the generator. std::string GetName() const override diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 2a59708..0487ad1 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -25,6 +25,7 @@ #include "cmGeneratorExpressionEvaluationFile.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmLinkLineComputer.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" @@ -44,8 +45,6 @@ #include "cmVersion.h" #include "cmake.h" -class cmLinkLineComputer; - const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja"; const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja"; const char* cmGlobalNinjaGenerator::INDENT = " "; @@ -85,13 +84,15 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os, os << "# " << comment.substr(lpos) << "\n\n"; } -cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer( +std::unique_ptr<cmLinkLineComputer> +cmGlobalNinjaGenerator::CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& /* stateDir */) const { - return new cmNinjaLinkLineComputer( - outputConverter, - this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this); + return std::unique_ptr<cmLinkLineComputer>( + cm::make_unique<cmNinjaLinkLineComputer>( + outputConverter, + this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this)); } std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name) @@ -529,6 +530,35 @@ void cmGlobalNinjaGenerator::Generate() if (!this->WriteDefaultBuildFile()) { return; } + + auto run_ninja_tool = [this](char const* tool) { + std::vector<std::string> command; + command.push_back(this->NinjaCommand); + command.emplace_back("-t"); + command.emplace_back(tool); + std::string error; + if (!cmSystemTools::RunSingleCommand(command, nullptr, &error, nullptr, + nullptr, + cmSystemTools::OUTPUT_NONE)) { + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + "Running\n '" + + cmJoin(command, "' '") + + "'\n" + "failed with:\n " + + error); + cmSystemTools::SetFatalErrorOccured(); + } + }; + + if (this->NinjaSupportsCleanDeadTool) { + run_ninja_tool("cleandead"); + } + if (this->NinjaSupportsUnconditionalRecompactTool) { + run_ninja_tool("recompact"); + } + if (this->NinjaSupportsRestatTool) { + run_ninja_tool("restat"); + } } bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) @@ -592,6 +622,16 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() } } } + this->NinjaSupportsCleanDeadTool = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForCleanDeadTool().c_str()); + this->NinjaSupportsUnconditionalRecompactTool = + !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForUnconditionalRecompactTool().c_str()); + this->NinjaSupportsRestatTool = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForRestatTool().c_str()); } bool cmGlobalNinjaGenerator::CheckLanguages( @@ -1152,7 +1192,10 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps, ta.second.Config); } - this->WriteBuild(os, build); + this->WriteBuild(this->EnableCrossConfigBuild() + ? os + : *this->GetConfigFileStream(ta.second.Config), + build); } if (this->IsMultiConfig()) { @@ -1219,7 +1262,10 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) } } // Write target - this->WriteBuild(os, build); + this->WriteBuild(this->EnableCrossConfigBuild() + ? os + : *this->GetConfigFileStream(config), + build); } // Add shortcut target @@ -1234,7 +1280,7 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) } // Add target for all configs - if (this->IsMultiConfig()) { + if (this->EnableCrossConfigBuild()) { build.ExplicitDeps.clear(); for (auto const& config : configs) { build.ExplicitDeps.push_back(this->BuildAlias( @@ -1242,7 +1288,7 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) } build.Outputs.front() = this->BuildAlias( this->ConvertToNinjaPath(currentBinaryDir + "/all"), "all"); - this->WriteBuild(*this->GetCommonFileStream(), build); + this->WriteBuild(os, build); } } } @@ -1290,8 +1336,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) knownDependencies.insert(this->ConvertToNinjaPath(j)); } } - for (cmGeneratorExpressionEvaluationFile* li : - lg->GetMakefile()->GetEvaluationFiles()) { + for (const auto& li : lg->GetMakefile()->GetEvaluationFiles()) { // get all the files created by generator expressions and convert them // to ninja paths for (std::string const& evaluationFile : li->GetFiles()) { @@ -1670,6 +1715,9 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) config)); } for (auto const& fileConfig : configs) { + if (fileConfig != config && !this->EnableCrossConfigBuild()) { + continue; + } if (this->IsMultiConfig()) { build.Variables["FILE_ARG"] = cmStrCat( "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig)); @@ -1678,7 +1726,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) } } - if (this->IsMultiConfig()) { + if (this->EnableCrossConfigBuild()) { build.Outputs.front() = this->BuildAlias( this->NinjaOutputPath(this->GetCleanTargetName()), "all"); build.ExplicitDeps.clear(); @@ -2044,7 +2092,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str()); auto mfd = cm::make_unique<cmMakefile>(this, snapshot); auto lgd = this->CreateLocalGenerator(mfd.get()); - this->Makefiles.push_back(mfd.release()); + this->Makefiles.push_back(std::move(mfd)); this->LocalGenerators.push_back(std::move(lgd)); } @@ -2152,6 +2200,12 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( return true; } +bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const +{ + return this->IsMultiConfig() && + this->Makefiles.front()->IsOn("CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE"); +} + int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, std::vector<std::string>::const_iterator argEnd) { @@ -2222,12 +2276,11 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, cmake cm(cmake::RoleInternal, cmState::Unknown); cm.SetHomeDirectory(dir_top_src); cm.SetHomeOutputDirectory(dir_top_bld); - std::unique_ptr<cmGlobalNinjaGenerator> ggd( - static_cast<cmGlobalNinjaGenerator*>(cm.CreateGlobalGenerator("Ninja"))); + auto ggd = cm.CreateGlobalGenerator("Ninja"); if (!ggd || - !ggd->WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, - arg_dd, arg_ddis, module_dir, linked_target_dirs, - arg_lang)) { + !cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile( + dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis, + module_dir, linked_target_dirs, arg_lang)) { return 1; } return 0; diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 6ebb31d..3545f1e 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -77,7 +77,7 @@ public: std::string EncodeLiteral(const std::string& lit); std::string EncodePath(const std::string& path); - cmLinkLineComputer* CreateLinkLineComputer( + std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const override; @@ -153,9 +153,10 @@ public: public: cmGlobalNinjaGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>()); } std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( @@ -348,6 +349,12 @@ public: return "1.9"; } static std::string RequiredNinjaVersionForDyndeps() { return "1.10"; } + static std::string RequiredNinjaVersionForRestatTool() { return "1.10"; } + static std::string RequiredNinjaVersionForUnconditionalRecompactTool() + { + return "1.10"; + } + static std::string RequiredNinjaVersionForCleanDeadTool() { return "1.10"; } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; @@ -388,6 +395,8 @@ public: return this->Configs[config].ByproductsForCleanTarget; } + bool EnableCrossConfigBuild() const; + protected: void Generate() override; @@ -488,6 +497,9 @@ private: bool NinjaSupportsManifestRestat = false; bool NinjaSupportsMultilineDepfile = false; bool NinjaSupportsDyndeps = false; + bool NinjaSupportsRestatTool = false; + bool NinjaSupportsUnconditionalRecompactTool = false; + bool NinjaSupportsCleanDeadTool = false; private: void InitOutputPathPrefix(); @@ -524,9 +536,10 @@ public: cmGlobalNinjaMultiGenerator(cmake* cm); bool IsMultiConfig() const override { return true; } - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>()); } static void GetDocumentation(cmDocumentationEntry& entry); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index f2595ea..0591758 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -492,7 +492,7 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( std::unique_ptr<cmMakefile> mfu; cmMakefile* mf; if (!this->Makefiles.empty()) { - mf = this->Makefiles[0]; + mf = this->Makefiles[0].get(); } else { cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentSource( diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 5608baf..340a7ef 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -62,10 +62,10 @@ class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator { public: cmGlobalUnixMakefileGenerator3(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalUnixMakefileGenerator3>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>()); } //! Get the name for the generator. diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index bdf4cf2..a720cc3 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -57,27 +57,30 @@ class cmGlobalVisualStudio10Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS10GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio10Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio10Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio10Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio10Generator(cm, genName, "x64")); } if (strcmp(p, "IA64") == 0) { - return new cmGlobalVisualStudio10Generator(cm, genName, "Itanium"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio10Generator(cm, genName, "Itanium")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -117,9 +120,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio10Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index c991c76..2120785 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -16,7 +16,7 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 4b74ef1..a385375 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio11Generator.h" +#include <utility> + #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio10Generator.h" @@ -28,38 +30,41 @@ class cmGlobalVisualStudio11Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS11GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio11Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio11Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio11Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio11Generator(cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio11Generator(cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio11Generator(cm, genName, "ARM")); } std::set<std::string> installedSDKs = cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs(); if (installedSDKs.find(p) == installedSDKs.end()) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } - cmGlobalVisualStudio11Generator* ret = - new cmGlobalVisualStudio11Generator(cm, name, p); + auto ret = std::unique_ptr<cmGlobalVisualStudio11Generator>( + new cmGlobalVisualStudio11Generator(cm, name, p)); ret->WindowsCEVersion = "8.00"; - return ret; + return std::unique_ptr<cmGlobalGenerator>(std::move(ret)); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -113,9 +118,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio11Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index f8cce18..5f1ff73 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <set> #include <string> @@ -20,7 +21,7 @@ class cmake; class cmGlobalVisualStudio11Generator : public cmGlobalVisualStudio10Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index d9702c9..5a27994 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -28,27 +28,30 @@ class cmGlobalVisualStudio12Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS12GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio12Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio12Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio12Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio12Generator(cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio12Generator(cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio12Generator(cm, genName, "ARM")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -88,9 +91,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio12Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 53b7091..bdd40ff 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include "cmGlobalVisualStudio11Generator.h" @@ -18,7 +19,7 @@ class cmake; class cmGlobalVisualStudio12Generator : public cmGlobalVisualStudio11Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index cd48474..f549b6a 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -2,7 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio14Generator.h" -#include "cmAlgorithms.h" +#include <cm/vector> + #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" @@ -28,27 +29,30 @@ class cmGlobalVisualStudio14Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS14GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio14Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio14Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio14Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio14Generator(cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio14Generator(cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio14Generator(cm, genName, "ARM")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -88,9 +92,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio14Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( @@ -299,7 +304,7 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() // Skip SDKs that do not contain <um/windows.h> because that indicates that // only the UCRT MSIs were installed for them. - cmEraseIf(sdks, NoWindowsH()); + cm::erase_if(sdks, NoWindowsH()); // Only use the filename, which will be the SDK version. for (std::string& i : sdks) { @@ -309,7 +314,7 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() // Skip SDKs that cannot be used with our toolset. std::string maxVersion = this->GetWindows10SDKMaxVersion(); if (!maxVersion.empty()) { - cmEraseIf(sdks, WindowsSDKTooRecent(maxVersion)); + cm::erase_if(sdks, WindowsSDKTooRecent(maxVersion)); } // Sort the results to make sure we select the most recent one. diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 6e12d3e..ccc2917 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include "cmGlobalVisualStudio12Generator.h" @@ -18,7 +19,7 @@ class cmake; class cmGlobalVisualStudio14Generator : public cmGlobalVisualStudio12Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 6e61d26..9f73c15 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio9Generator.h" +#include <utility> + #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" @@ -13,43 +15,46 @@ static const char vs9generatorName[] = "Visual Studio 9 2008"; class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { if (strncmp(name.c_str(), vs9generatorName, sizeof(vs9generatorName) - 1) != 0) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } const char* p = name.c_str() + sizeof(vs9generatorName) - 1; if (p[0] == '\0') { - return new cmGlobalVisualStudio9Generator(cm, name, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio9Generator(cm, name, "")); } if (p[0] != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } ++p; if (!strcmp(p, "IA64")) { - return new cmGlobalVisualStudio9Generator(cm, name, "Itanium"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio9Generator(cm, name, "Itanium")); } if (!strcmp(p, "Win64")) { - return new cmGlobalVisualStudio9Generator(cm, name, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio9Generator(cm, name, "x64")); } cmVisualStudioWCEPlatformParser parser(p); parser.ParseVersion("9.0"); if (!parser.Found()) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } - cmGlobalVisualStudio9Generator* ret = - new cmGlobalVisualStudio9Generator(cm, name, p); + auto ret = std::unique_ptr<cmGlobalVisualStudio9Generator>( + new cmGlobalVisualStudio9Generator(cm, name, p)); ret->WindowsCEVersion = parser.GetOSVersion(); - return ret; + return std::unique_ptr<cmGlobalGenerator>(std::move(ret)); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -103,9 +108,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio9Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator( diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index 7bebfd6..53318a6 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalVisualStudio9Generator_h #define cmGlobalVisualStudio9Generator_h +#include <memory> + #include "cmGlobalVisualStudio8Generator.h" /** \class cmGlobalVisualStudio9Generator @@ -13,7 +15,7 @@ class cmGlobalVisualStudio9Generator : public cmGlobalVisualStudio8Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); /** * Where does this version of Visual Studio look for macros for the diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index a371633..13ae32a 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -121,30 +121,33 @@ class cmGlobalVisualStudioVersionedGenerator::Factory15 : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS15GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS15, cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -185,10 +188,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* +std::unique_ptr<cmGlobalGeneratorFactory> cmGlobalVisualStudioVersionedGenerator::NewFactory15() { - return new Factory15; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory15); } static const char vs16generatorName[] = "Visual Studio 16 2019"; @@ -212,19 +215,20 @@ class cmGlobalVisualStudioVersionedGenerator::Factory16 : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS16GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS16, cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS16, cm, genName, "")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -265,10 +269,10 @@ public: } }; -cmGlobalGeneratorFactory* +std::unique_ptr<cmGlobalGeneratorFactory> cmGlobalVisualStudioVersionedGenerator::NewFactory16() { - return new Factory16; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory16); } cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 466816b..abb6095 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include "cmGlobalVisualStudio14Generator.h" @@ -19,8 +20,8 @@ class cmGlobalVisualStudioVersionedGenerator : public cmGlobalVisualStudio14Generator { public: - static cmGlobalGeneratorFactory* NewFactory15(); - static cmGlobalGeneratorFactory* NewFactory16(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory15(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory16(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index 64ace13..c0daf8a 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include <vector> @@ -25,9 +26,10 @@ class cmGlobalWatcomWMakeGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalWatcomWMakeGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalWatcomWMakeGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalWatcomWMakeGenerator>()); } //! Get the name for the generator. std::string GetName() const override diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index dcd9705..f887284 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -131,8 +131,8 @@ public: class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override; + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override; void GetDocumentation(cmDocumentationEntry& entry) const override { @@ -181,16 +181,17 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( cm->GetState()->SetIsGeneratorMultiConfig(true); } -cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> cmGlobalXCodeGenerator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } -cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( - const std::string& name, cmake* cm) const +std::unique_ptr<cmGlobalGenerator> +cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(const std::string& name, + cmake* cm) const { if (name != GetActualName()) { - return nullptr; + return std::unique_ptr<cmGlobalGenerator>(); } #if !defined(CMAKE_BOOTSTRAP) cmXcodeVersionParser parser; @@ -226,16 +227,17 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( if (version_number < 50) { cm->IssueMessage(MessageType::FATAL_ERROR, "Xcode " + version_string + " not supported."); - return nullptr; + return std::unique_ptr<cmGlobalGenerator>(); } - auto gg = cm::make_unique<cmGlobalXCodeGenerator>(cm, version_string, - version_number); - return gg.release(); + return std::unique_ptr<cmGlobalGenerator>( + cm::make_unique<cmGlobalXCodeGenerator>(cm, version_string, + version_number)); #else std::cerr << "CMake should be built with cmake to use Xcode, " "default to Xcode 1.5\n"; - return new cmGlobalXCodeGenerator(cm); + return std::unique_ptr<cmGlobalGenerator>( + cm::make_unique<cmGlobalXCodeGenerator>(cm)); #endif } @@ -2355,9 +2357,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("SECTORDER_FLAGS", this->CreateString("")); buildSettings->AddAttribute("USE_HEADERMAP", this->CreateString("NO")); cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST); - group->AddObject(this->CreateString("-Wmost")); - group->AddObject(this->CreateString("-Wno-four-char-constants")); - group->AddObject(this->CreateString("-Wno-unknown-pragmas")); group->AddObject(this->CreateString("$(inherited)")); buildSettings->AddAttribute("WARNING_CFLAGS", group); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index a12021d..df68f80 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -35,7 +35,7 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator public: cmGlobalXCodeGenerator(cmake* cm, std::string const& version_string, unsigned int version_number); - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); //! Get the name for the generator. std::string GetName() const override diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 0c52cc5..54b85cd 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -85,7 +85,7 @@ public: std::string DefaultComponentName; }; -cmInstallTargetGenerator* CreateInstallTargetGenerator( +std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, cmListFileBacktrace const& backtrace, const std::string& destination, bool forceOpt = false, bool namelink = false) @@ -95,16 +95,16 @@ cmInstallTargetGenerator* CreateInstallTargetGenerator( target.SetHaveInstallRule(true); const char* component = namelink ? args.GetNamelinkComponent().c_str() : args.GetComponent().c_str(); - auto g = new cmInstallTargetGenerator( + auto g = cm::make_unique<cmInstallTargetGenerator>( target.GetName(), destination.c_str(), impLib, args.GetPermissions().c_str(), args.GetConfigurations(), component, message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt, backtrace); - target.AddInstallGenerator(g); + target.AddInstallGenerator(g.get()); return g; } -cmInstallTargetGenerator* CreateInstallTargetGenerator( +std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, cmListFileBacktrace const& backtrace, bool forceOpt = false, bool namelink = false) @@ -114,20 +114,20 @@ cmInstallTargetGenerator* CreateInstallTargetGenerator( namelink); } -cmInstallFilesGenerator* CreateInstallFilesGenerator( +std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs, const std::string& destination) { cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(mf); - return new cmInstallFilesGenerator( + return cm::make_unique<cmInstallFilesGenerator>( absFiles, destination.c_str(), programs, args.GetPermissions().c_str(), args.GetConfigurations(), args.GetComponent().c_str(), message, args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional()); } -cmInstallFilesGenerator* CreateInstallFilesGenerator( +std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs) { @@ -196,13 +196,15 @@ bool HandleScriptMode(std::vector<std::string> const& args, status.SetError("given a directory as value of SCRIPT argument."); return false; } - helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator( - script.c_str(), false, component.c_str(), exclude_from_all)); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallScriptGenerator>( + script.c_str(), false, component.c_str(), exclude_from_all)); } else if (doing_code) { doing_code = false; std::string const& code = arg; - helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator( - code.c_str(), true, component.c_str(), exclude_from_all)); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallScriptGenerator>( + code.c_str(), true, component.c_str(), exclude_from_all)); } } @@ -449,16 +451,16 @@ bool HandleTargetsMode(std::vector<std::string> const& args, for (cmTarget* ti : targets) { // Handle each target type. cmTarget& target = *ti; - cmInstallTargetGenerator* archiveGenerator = nullptr; - cmInstallTargetGenerator* libraryGenerator = nullptr; - cmInstallTargetGenerator* namelinkGenerator = nullptr; - cmInstallTargetGenerator* runtimeGenerator = nullptr; - cmInstallTargetGenerator* objectGenerator = nullptr; - cmInstallTargetGenerator* frameworkGenerator = nullptr; - cmInstallTargetGenerator* bundleGenerator = nullptr; - cmInstallFilesGenerator* privateHeaderGenerator = nullptr; - cmInstallFilesGenerator* publicHeaderGenerator = nullptr; - cmInstallFilesGenerator* resourceGenerator = nullptr; + std::unique_ptr<cmInstallTargetGenerator> archiveGenerator; + std::unique_ptr<cmInstallTargetGenerator> libraryGenerator; + std::unique_ptr<cmInstallTargetGenerator> namelinkGenerator; + std::unique_ptr<cmInstallTargetGenerator> runtimeGenerator; + std::unique_ptr<cmInstallTargetGenerator> objectGenerator; + std::unique_ptr<cmInstallTargetGenerator> frameworkGenerator; + std::unique_ptr<cmInstallTargetGenerator> bundleGenerator; + std::unique_ptr<cmInstallFilesGenerator> privateHeaderGenerator; + std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator; + std::unique_ptr<cmInstallFilesGenerator> resourceGenerator; // Track whether this is a namelink-only rule. bool namelinkOnly = false; @@ -485,7 +487,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, runtimeGenerator = CreateInstallTargetGenerator( target, runtimeArgs, false, helper.Makefile->GetBacktrace()); } - if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) { + if (!archiveGenerator && !runtimeGenerator) { archiveGenerator = CreateInstallTargetGenerator( target, archiveArgs, true, helper.Makefile->GetBacktrace(), helper.GetArchiveDestination(nullptr)); @@ -712,43 +714,18 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } } - // Keep track of whether we're installing anything in each category - installsArchive = installsArchive || archiveGenerator != nullptr; - installsLibrary = installsLibrary || libraryGenerator != nullptr; - installsNamelink = installsNamelink || namelinkGenerator != nullptr; - installsRuntime = installsRuntime || runtimeGenerator != nullptr; - installsObject = installsObject || objectGenerator != nullptr; - installsFramework = installsFramework || frameworkGenerator != nullptr; - installsBundle = installsBundle || bundleGenerator != nullptr; - installsPrivateHeader = - installsPrivateHeader || privateHeaderGenerator != nullptr; - installsPublicHeader = - installsPublicHeader || publicHeaderGenerator != nullptr; - installsResource = installsResource || resourceGenerator; - - helper.Makefile->AddInstallGenerator(archiveGenerator); - helper.Makefile->AddInstallGenerator(libraryGenerator); - helper.Makefile->AddInstallGenerator(namelinkGenerator); - helper.Makefile->AddInstallGenerator(runtimeGenerator); - helper.Makefile->AddInstallGenerator(objectGenerator); - helper.Makefile->AddInstallGenerator(frameworkGenerator); - helper.Makefile->AddInstallGenerator(bundleGenerator); - helper.Makefile->AddInstallGenerator(privateHeaderGenerator); - helper.Makefile->AddInstallGenerator(publicHeaderGenerator); - helper.Makefile->AddInstallGenerator(resourceGenerator); - // Add this install rule to an export if one was specified and // this is not a namelink-only rule. if (!exports.empty() && !namelinkOnly) { auto te = cm::make_unique<cmTargetExport>(); te->TargetName = target.GetName(); - te->ArchiveGenerator = archiveGenerator; - te->BundleGenerator = bundleGenerator; - te->FrameworkGenerator = frameworkGenerator; - te->HeaderGenerator = publicHeaderGenerator; - te->LibraryGenerator = libraryGenerator; - te->RuntimeGenerator = runtimeGenerator; - te->ObjectsGenerator = objectGenerator; + te->ArchiveGenerator = archiveGenerator.get(); + te->BundleGenerator = bundleGenerator.get(); + te->FrameworkGenerator = frameworkGenerator.get(); + te->HeaderGenerator = publicHeaderGenerator.get(); + te->LibraryGenerator = libraryGenerator.get(); + te->RuntimeGenerator = runtimeGenerator.get(); + te->ObjectsGenerator = objectGenerator.get(); te->InterfaceIncludeDirectories = cmJoin(includesArgs.GetIncludeDirs(), ";"); @@ -756,6 +733,29 @@ bool HandleTargetsMode(std::vector<std::string> const& args, ->GetExportSets()[exports] .AddTargetExport(std::move(te)); } + + // Keep track of whether we're installing anything in each category + installsArchive = installsArchive || archiveGenerator; + installsLibrary = installsLibrary || libraryGenerator; + installsNamelink = installsNamelink || namelinkGenerator; + installsRuntime = installsRuntime || runtimeGenerator; + installsObject = installsObject || objectGenerator; + installsFramework = installsFramework || frameworkGenerator; + installsBundle = installsBundle || bundleGenerator; + installsPrivateHeader = installsPrivateHeader || privateHeaderGenerator; + installsPublicHeader = installsPublicHeader || publicHeaderGenerator; + installsResource = installsResource || resourceGenerator; + + helper.Makefile->AddInstallGenerator(std::move(archiveGenerator)); + helper.Makefile->AddInstallGenerator(std::move(libraryGenerator)); + helper.Makefile->AddInstallGenerator(std::move(namelinkGenerator)); + helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator)); + helper.Makefile->AddInstallGenerator(std::move(objectGenerator)); + helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator)); + helper.Makefile->AddInstallGenerator(std::move(bundleGenerator)); + helper.Makefile->AddInstallGenerator(std::move(privateHeaderGenerator)); + helper.Makefile->AddInstallGenerator(std::move(publicHeaderGenerator)); + helper.Makefile->AddInstallGenerator(std::move(resourceGenerator)); } // Tell the global generator about any installation component names @@ -1200,10 +1200,11 @@ bool HandleDirectoryMode(std::vector<std::string> const& args, cmInstallGenerator::SelectMessageLevel(helper.Makefile, message_never); // Create the directory install generator. - helper.Makefile->AddInstallGenerator(new cmInstallDirectoryGenerator( - dirs, destination, permissions_file.c_str(), permissions_dir.c_str(), - configurations, component.c_str(), message, exclude_from_all, - literal_args.c_str(), optional)); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallDirectoryGenerator>( + dirs, destination, permissions_file.c_str(), permissions_dir.c_str(), + configurations, component.c_str(), message, exclude_from_all, + literal_args.c_str(), optional)); // Tell the global generator about any installation component names // specified. @@ -1291,12 +1292,12 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args, cmInstallGenerator::SelectMessageLevel(helper.Makefile); // Create the export install generator. - cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( - &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), - ica.GetConfigurations(), ica.GetComponent().c_str(), message, - ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, - true); - helper.Makefile->AddInstallGenerator(exportGenerator); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallExportGenerator>( + &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), + ica.GetConfigurations(), ica.GetComponent().c_str(), message, + ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, + true)); return true; #else @@ -1405,12 +1406,12 @@ bool HandleExportMode(std::vector<std::string> const& args, cmInstallGenerator::SelectMessageLevel(helper.Makefile); // Create the export install generator. - cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( - &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), - ica.GetConfigurations(), ica.GetComponent().c_str(), message, - ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, - false); - helper.Makefile->AddInstallGenerator(exportGenerator); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallExportGenerator>( + &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), + ica.GetConfigurations(), ica.GetComponent().c_str(), message, + ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, + false)); return true; } diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index efbcb98..bfc7359 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallFilesCommand.h" +#include <cm/memory> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -121,7 +123,7 @@ static void CreateInstallGenerator(cmMakefile& makefile, std::vector<std::string> no_configurations; cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(&makefile); - makefile.AddInstallGenerator(new cmInstallFilesGenerator( + makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>( files, destination.c_str(), false, no_permissions, no_configurations, no_component.c_str(), message, no_exclude_from_all, no_rename)); } diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 2088eae..2fd9bad 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallProgramsCommand.h" +#include <cm/memory> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -95,7 +97,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& dest, std::vector<std::string> no_configurations; cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(&makefile); - makefile.AddInstallGenerator(new cmInstallFilesGenerator( + makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>( files, destination.c_str(), true, no_permissions, no_configurations, no_component.c_str(), message, no_exclude_from_all, no_rename)); } diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx index 8a0fefa..5405b7c 100644 --- a/Source/cmInstallSubdirectoryGenerator.cxx +++ b/Source/cmInstallSubdirectoryGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallSubdirectoryGenerator.h" +#include <memory> #include <sstream> #include <vector> @@ -24,7 +25,7 @@ cmInstallSubdirectoryGenerator::~cmInstallSubdirectoryGenerator() = default; bool cmInstallSubdirectoryGenerator::HaveInstall() { - for (auto generator : this->Makefile->GetInstallGenerators()) { + for (const auto& generator : this->Makefile->GetInstallGenerators()) { if (generator->HaveInstall()) { return true; } diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index 5f86d85..dd36386 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -8,6 +8,7 @@ #include <functional> #include <limits> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -44,7 +45,7 @@ namespace { std::vector<std::string> getConfigurations(const cmake* cm) { std::vector<std::string> configurations; - auto makefiles = cm->GetGlobalGenerator()->GetMakefiles(); + const auto& makefiles = cm->GetGlobalGenerator()->GetMakefiles(); if (makefiles.empty()) { return configurations; } @@ -83,8 +84,8 @@ void cmGetCMakeInputs(const cmGlobalGenerator* gg, std::vector<std::string>* tmpFiles) { const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/'; - std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles(); - for (cmMakefile const* mf : makefiles) { + auto const& makefiles = gg->GetMakefiles(); + for (const auto& mf : makefiles) { for (std::string const& lf : mf->GetListFiles()) { const std::string startOfFile = lf.substr(0, cmakeRootDir.size()); @@ -486,10 +487,10 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, result[kHAS_INSTALL_RULE] = true; Json::Value installPaths = Json::arrayValue; - auto targetGenerators = target->Makefile->GetInstallGenerators(); - for (auto installGenerator : targetGenerators) { + for (const auto& installGenerator : + target->Makefile->GetInstallGenerators()) { auto installTargetGenerator = - dynamic_cast<cmInstallTargetGenerator*>(installGenerator); + dynamic_cast<cmInstallTargetGenerator*>(installGenerator.get()); if (installTargetGenerator != nullptr && installTargetGenerator->GetTarget()->Target == target->Target) { auto dest = installTargetGenerator->GetDestination(config); @@ -642,9 +643,9 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) // associated generators. bool hasInstallRule = false; for (const auto generator : projectIt.second) { - for (const auto installGen : + for (const auto& installGen : generator->GetMakefile()->GetInstallGenerators()) { - if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen)) { + if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen.get())) { hasInstallRule = true; break; } diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index d845652..847334b 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -183,29 +183,29 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, return cmIsOn(resolveDeviceSymbols); } - if (const char* separableCompilation = - target.GetProperty("CUDA_SEPARABLE_COMPILATION")) { - if (cmIsOn(separableCompilation)) { - bool doDeviceLinking = false; - switch (target.GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::EXECUTABLE: - doDeviceLinking = true; - break; - default: - break; - } - return doDeviceLinking; - } - } - // Determine if we have any dependencies that require // us to do a device link step cmGeneratorTarget::LinkClosure const* closure = target.GetLinkClosure(config); if (cmContains(closure->Languages, "CUDA")) { + if (const char* separableCompilation = + target.GetProperty("CUDA_SEPARABLE_COMPILATION")) { + if (cmIsOn(separableCompilation)) { + bool doDeviceLinking = false; + switch (target.GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::EXECUTABLE: + doDeviceLinking = true; + break; + default: + break; + } + return doDeviceLinking; + } + } + cmComputeLinkInformation* pcli = target.GetLinkInformation(config); if (pcli) { cmLinkLineDeviceComputer deviceLinkComputer( diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 5e39d9b..cedc3ad 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -315,9 +315,7 @@ void cmLocalGenerator::GenerateTestFiles() } // Ask each test generator to write its code. - std::vector<cmTestGenerator*> const& testers = - this->Makefile->GetTestGenerators(); - for (cmTestGenerator* tester : testers) { + for (const auto& tester : this->Makefile->GetTestGenerators()) { tester->Compute(this); tester->Generate(fout, config, configurationTypes); } @@ -363,9 +361,7 @@ void cmLocalGenerator::CreateEvaluationFileOutputs() void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config) { - std::vector<cmGeneratorExpressionEvaluationFile*> ef = - this->Makefile->GetEvaluationFiles(); - for (cmGeneratorExpressionEvaluationFile* geef : ef) { + for (const auto& geef : this->Makefile->GetEvaluationFiles()) { geef->CreateOutputFile(this, config); } } @@ -373,8 +369,7 @@ void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config) void cmLocalGenerator::ProcessEvaluationFiles( std::vector<std::string>& generatedFiles) { - for (cmGeneratorExpressionEvaluationFile* geef : - this->Makefile->GetEvaluationFiles()) { + for (const auto& geef : this->Makefile->GetEvaluationFiles()) { geef->Generate(this); if (cmSystemTools::GetFatalErrorOccured()) { return; @@ -557,18 +552,17 @@ void cmLocalGenerator::GenerateInstallRules() // Ask each install generator to write its code. cmPolicies::PolicyStatus status = this->GetPolicyStatus(cmPolicies::CMP0082); - std::vector<cmInstallGenerator*> const& installers = - this->Makefile->GetInstallGenerators(); + auto const& installers = this->Makefile->GetInstallGenerators(); bool haveSubdirectoryInstall = false; bool haveInstallAfterSubdirectory = false; if (status == cmPolicies::WARN) { - for (cmInstallGenerator* installer : installers) { + for (const auto& installer : installers) { installer->CheckCMP0082(haveSubdirectoryInstall, haveInstallAfterSubdirectory); installer->Generate(fout, config, configurationTypes); } } else { - for (cmInstallGenerator* installer : installers) { + for (const auto& installer : installers) { installer->Generate(fout, config, configurationTypes); } } @@ -2009,8 +2003,16 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName, // Treat the name as relative to the source directory in which it // was given. - dep = cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentSource(), '/', - inName); + dep = cmStrCat(this->GetCurrentSourceDirectory(), '/', inName); + + // If the in-source path does not exist, assume it instead lives in the + // binary directory. + if (!cmSystemTools::FileExists(dep)) { + dep = cmStrCat(this->GetCurrentBinaryDirectory(), '/', inName); + } + + dep = cmSystemTools::CollapseFullPath(dep, this->GetBinaryDirectory()); + return true; } @@ -2220,10 +2222,11 @@ static void AddVisibilityCompileOption(std::string& flags, static void AddInlineVisibilityCompileOption(std::string& flags, cmGeneratorTarget const* target, cmLocalGenerator* lg, - std::string* warnCMP0063) + std::string* warnCMP0063, + const std::string& lang) { std::string compileOption = - "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"; + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"); const char* opt = lg->GetMakefile()->GetDefinition(compileOption); if (!opt) { return; @@ -2265,8 +2268,8 @@ void cmLocalGenerator::AddVisibilityPresetFlags( AddVisibilityCompileOption(flags, target, this, lang, pWarnCMP0063); - if (lang == "CXX") { - AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063); + if (lang == "CXX" || lang == "OBJCXX") { + AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063, lang); } if (!warnCMP0063.empty() && this->WarnCMP0063.insert(target).second) { @@ -2632,7 +2635,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) chunk = std::min(itemsLeft, batchSize); std::string filename = cmStrCat(filename_base, "unity_", batch, - (lang == "C") ? ".c" : ".cxx"); + (lang == "C") ? "_c.c" : "_cxx.cxx"); const std::string filename_tmp = cmStrCat(filename, ".tmp"); { @@ -3281,7 +3284,8 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( // CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/generated_source_file.obj const char* unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE"); const char* pchExtension = source.GetProperty("PCH_EXTENSION"); - if (unitySourceFile || pchExtension) { + const bool isPchObject = objectName.find("cmake_pch") != std::string::npos; + if (unitySourceFile || pchExtension || isPchObject) { if (pchExtension) { customOutputExtension = pchExtension; } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index f6a0e34..dbdde48 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -9,12 +9,12 @@ #include <utility> #include <cm/memory> +#include <cm/vector> #include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/Terminal.h" -#include "cmAlgorithms.h" #include "cmCustomCommand.h" // IWYU pragma: keep #include "cmCustomCommandGenerator.h" #include "cmFileTimeCache.h" @@ -1876,7 +1876,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( std::string binaryDir = this->GetState()->GetBinaryDirectory(); if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) { std::string const& sourceDir = this->GetState()->GetSourceDirectory(); - cmEraseIf(includes, ::NotInProjectDir(sourceDir, binaryDir)); + cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir)); } for (std::string const& include : includes) { cmakefileStream << " \"" diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 7683855..55a9a72 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -530,6 +530,14 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranLinkFlagTable[] = { "linkIncrementalNo", 0 }, { "LinkIncremental", "INCREMENTAL:YES", "link incremental", "linkIncrementalYes", 0 }, + { "EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs", + "optNoFolding", 0 }, + { "EnableCOMDATFolding", "OPT:ICF", "Remove redundant COMDATs", "optFolding", + 0 }, + { "OptimizeReferences", "OPT:NOREF", "Keep unreferenced data", + "optNoReferences", 0 }, + { "OptimizeReferences", "OPT:REF", "Eliminate unreferenced data", + "optReferences", 0 }, { "", "", "", "", 0 } }; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 13a6ed7..dc741d3 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -15,7 +15,9 @@ #include <utility> #include <cm/iterator> +#include <cm/memory> #include <cm/optional> +#include <cm/vector> #include <cmext/algorithm> #include "cmsys/FStream.hxx" @@ -122,15 +124,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, #endif } -cmMakefile::~cmMakefile() -{ - cmDeleteAll(this->InstallGenerators); - cmDeleteAll(this->TestGenerators); - cmDeleteAll(this->SourceFiles); - cmDeleteAll(this->Tests); - cmDeleteAll(this->ImportedTargetsOwned); - cmDeleteAll(this->EvaluationFiles); -} +cmMakefile::~cmMakefile() = default; cmDirectoryId cmMakefile::GetDirectoryId() const { @@ -138,7 +132,7 @@ cmDirectoryId cmMakefile::GetDirectoryId() const // If we ever need to expose this to CMake language code we should // add a read-only property in cmMakefile::GetProperty. char buf[32]; - sprintf(buf, "<%p>", + sprintf(buf, "(%p)", static_cast<void const*>(this)); // cast avoids format warning return std::string(buf); } @@ -772,12 +766,13 @@ void cmMakefile::AddEvaluationFile( std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent) { - this->EvaluationFiles.push_back(new cmGeneratorExpressionEvaluationFile( - inputFile, std::move(outputName), std::move(condition), inputIsContent, - this->GetPolicyStatus(cmPolicies::CMP0070))); + this->EvaluationFiles.push_back( + cm::make_unique<cmGeneratorExpressionEvaluationFile>( + inputFile, std::move(outputName), std::move(condition), inputIsContent, + this->GetPolicyStatus(cmPolicies::CMP0070))); } -std::vector<cmGeneratorExpressionEvaluationFile*> +const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>& cmMakefile::GetEvaluationFiles() const { return this->EvaluationFiles; @@ -839,12 +834,12 @@ void cmMakefile::DoGenerate(cmLocalGenerator& lg) // we don't want cmake to re-run if a configured file is created and deleted // during processing as that would make it a transient file that can't // influence the build process - cmEraseIf(this->OutputFiles, file_not_persistent()); + cm::erase_if(this->OutputFiles, file_not_persistent()); // if a configured file is used as input for another configured file, // and then deleted it will show up in the input list files so we // need to scan those too - cmEraseIf(this->ListFiles, file_not_persistent()); + cm::erase_if(this->ListFiles, file_not_persistent()); } // Generate the output file @@ -1423,6 +1418,20 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) this->RecursionDepth = parent->RecursionDepth; } +void cmMakefile::AddInstallGenerator(std::unique_ptr<cmInstallGenerator> g) +{ + if (g) { + this->InstallGenerators.push_back(std::move(g)); + } +} + +void cmMakefile::AddTestGenerator(std::unique_ptr<cmTestGenerator> g) +{ + if (g) { + this->TestGenerators.push_back(std::move(g)); + } +} + void cmMakefile::PushFunctionScope(std::string const& fileName, const cmPolicies::PolicyMap& pm) { @@ -1723,8 +1732,10 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, cmSystemTools::MakeDirectory(binPath); - cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot); - this->GetGlobalGenerator()->AddMakefile(subMf); + auto subMfu = + cm::make_unique<cmMakefile>(this->GlobalGenerator, newSnapshot); + auto subMf = subMfu.get(); + this->GetGlobalGenerator()->AddMakefile(std::move(subMfu)); if (excludeFromAll) { subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); @@ -1736,7 +1747,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, this->UnConfiguredDirectories.push_back(subMf); } - this->AddInstallGenerator(new cmInstallSubdirectoryGenerator( + this->AddInstallGenerator(cm::make_unique<cmInstallSubdirectoryGenerator>( subMf, binPath.c_str(), excludeFromAll)); } @@ -2100,18 +2111,18 @@ cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput( // Look through all the source files that have custom commands and see if the // custom command has the passed source file as an output. - for (cmSourceFile* src : this->SourceFiles) { + for (const auto& src : this->SourceFiles) { // Does this source file have a custom command? if (src->GetCustomCommand()) { // Does the output of the custom command match the source file name? if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) { // Return the first matching output. - return src; + return src.get(); } if (kind == cmSourceOutputKind::OutputOrByproduct) { if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) { // Do not return the source yet as there might be a matching output. - fallback = src; + fallback = src.get(); } } } @@ -3469,24 +3480,25 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName, bool generated, cmSourceFileLocationKind kind) { - cmSourceFile* sf = new cmSourceFile(this, sourceName, kind); + auto sf = cm::make_unique<cmSourceFile>(this, sourceName, kind); if (generated) { sf->SetProperty("GENERATED", "1"); } - this->SourceFiles.push_back(sf); auto name = this->GetCMakeInstance()->StripExtension(sf->GetLocation().GetName()); #if defined(_WIN32) || defined(__APPLE__) name = cmSystemTools::LowerCase(name); #endif - this->SourceFileSearchIndex[name].push_back(sf); + this->SourceFileSearchIndex[name].push_back(sf.get()); // for "Known" paths add direct lookup (used for faster lookup in GetSource) if (kind == cmSourceFileLocationKind::Known) { - this->KnownFileSearchIndex[sourceName] = sf; + this->KnownFileSearchIndex[sourceName] = sf.get(); } - return sf; + this->SourceFiles.push_back(std::move(sf)); + + return this->SourceFiles.back().get(); } cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName, @@ -3615,8 +3627,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, // be run that way but the cmake object requires a vailid path cmake cm(cmake::RoleProject, cmState::Project); cm.SetIsInTryCompile(true); - cmGlobalGenerator* gg = - cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); + auto gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); if (!gg) { this->IssueMessage(MessageType::INTERNAL_ERROR, "Global generator '" + @@ -3627,7 +3638,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, return 1; } gg->RecursionDepth = this->RecursionDepth; - cm.SetGlobalGenerator(gg); + cm.SetGlobalGenerator(std::move(gg)); // do a configure cm.SetHomeDirectory(srcdir); @@ -3636,7 +3647,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetGeneratorPlatform(this->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM")); cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET")); cm.LoadCache(); - if (!gg->IsMultiConfig()) { + if (!cm.GetGlobalGenerator()->IsMultiConfig()) { if (const char* config = this->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION")) { // Tell the single-configuration generator which one to use. @@ -3682,7 +3693,8 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetCacheArgs(*cmakeArgs); } // to save time we pass the EnableLanguage info directly - gg->EnableLanguagesFromGenerator(this->GetGlobalGenerator(), this); + cm.GetGlobalGenerator()->EnableLanguagesFromGenerator( + this->GetGlobalGenerator(), this); if (this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE", "", cmStateEnums::INTERNAL); @@ -4080,9 +4092,10 @@ cmTest* cmMakefile::CreateTest(const std::string& testName) if (test) { return test; } - test = new cmTest(this); - test->SetName(testName); - this->Tests[testName] = test; + auto newTest = cm::make_unique<cmTest>(this); + test = newTest.get(); + newTest->SetName(testName); + this->Tests[testName] = std::move(newTest); return test; } @@ -4090,7 +4103,7 @@ cmTest* cmMakefile::GetTest(const std::string& testName) const { auto mi = this->Tests.find(testName); if (mi != this->Tests.end()) { - return mi->second; + return mi->second.get(); } return nullptr; } @@ -4098,7 +4111,7 @@ cmTest* cmMakefile::GetTest(const std::string& testName) const void cmMakefile::GetTests(const std::string& config, std::vector<cmTest*>& tests) { - for (auto generator : this->GetTestGenerators()) { + for (const auto& generator : this->GetTestGenerators()) { if (generator->TestsForConfig(config)) { tests.push_back(generator->GetTest()); } @@ -4211,8 +4224,8 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name, this->GetGlobalGenerator()->IndexTarget(target.get()); // Transfer ownership to this cmMakefile object. - this->ImportedTargetsOwned.push_back(target.get()); - return target.release(); + this->ImportedTargetsOwned.push_back(std::move(target)); + return this->ImportedTargetsOwned.back().get(); } cmTarget* cmMakefile::FindTargetToUse(const std::string& name, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 085c1d6..b13716b 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -431,7 +431,7 @@ public: /** Get the target map - const version */ cmTargetMap const& GetTargets() const { return this->Targets; } - const std::vector<cmTarget*>& GetOwnedImportedTargets() const + const std::vector<std::unique_ptr<cmTarget>>& GetOwnedImportedTargets() const { return this->ImportedTargetsOwned; } @@ -727,7 +727,7 @@ public: /** * Get all the source files this makefile knows about */ - const std::vector<cmSourceFile*>& GetSourceFiles() const + const std::vector<std::unique_ptr<cmSourceFile>>& GetSourceFiles() const { return this->SourceFiles; } @@ -794,28 +794,22 @@ public: //! Initialize a makefile from its parent void InitializeFromParent(cmMakefile* parent); - void AddInstallGenerator(cmInstallGenerator* g) - { - if (g) { - this->InstallGenerators.push_back(g); - } - } - std::vector<cmInstallGenerator*>& GetInstallGenerators() + void AddInstallGenerator(std::unique_ptr<cmInstallGenerator> g); + + std::vector<std::unique_ptr<cmInstallGenerator>>& GetInstallGenerators() { return this->InstallGenerators; } - const std::vector<cmInstallGenerator*>& GetInstallGenerators() const + const std::vector<std::unique_ptr<cmInstallGenerator>>& + GetInstallGenerators() const { return this->InstallGenerators; } - void AddTestGenerator(cmTestGenerator* g) - { - if (g) { - this->TestGenerators.push_back(g); - } - } - const std::vector<cmTestGenerator*>& GetTestGenerators() const + void AddTestGenerator(std::unique_ptr<cmTestGenerator> g); + + const std::vector<std::unique_ptr<cmTestGenerator>>& GetTestGenerators() + const { return this->TestGenerators; } @@ -948,7 +942,8 @@ public: std::unique_ptr<cmCompiledGeneratorExpression> outputName, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent); - std::vector<cmGeneratorExpressionEvaluationFile*> GetEvaluationFiles() const; + const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>& + GetEvaluationFiles() const; std::vector<cmExportBuildFileGenerator*> GetExportBuildFileGenerators() const; @@ -983,8 +978,7 @@ protected: using TargetsVec = std::vector<cmTarget*>; TargetsVec OrderedTargets; - using SourceFileVec = std::vector<cmSourceFile*>; - SourceFileVec SourceFiles; + std::vector<std::unique_ptr<cmSourceFile>> SourceFiles; // Because cmSourceFile names are compared in a fuzzy way (see // cmSourceFileLocation::Match()) we can't have a straight mapping from @@ -992,14 +986,15 @@ protected: // Name portion of the cmSourceFileLocation and then compare on the list of // cmSourceFiles that might match that name. Note that on platforms which // have a case-insensitive filesystem we store the key in all lowercase. - using SourceFileMap = std::unordered_map<std::string, SourceFileVec>; + using SourceFileMap = + std::unordered_map<std::string, std::vector<cmSourceFile*>>; SourceFileMap SourceFileSearchIndex; // For "Known" paths we can store a direct filename to cmSourceFile map std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex; // Tests - std::map<std::string, cmTest*> Tests; + std::map<std::string, std::unique_ptr<cmTest>> Tests; // The set of include directories that are marked as system include // directories. @@ -1008,8 +1003,8 @@ protected: std::vector<std::string> ListFiles; std::vector<std::string> OutputFiles; - std::vector<cmInstallGenerator*> InstallGenerators; - std::vector<cmTestGenerator*> TestGenerators; + std::vector<std::unique_ptr<cmInstallGenerator>> InstallGenerators; + std::vector<std::unique_ptr<cmTestGenerator>> TestGenerators; std::string ComplainFileRegularExpression; std::string DefineFlags; @@ -1060,13 +1055,14 @@ private: std::vector<cmMakefile*> UnConfiguredDirectories; std::vector<cmExportBuildFileGenerator*> ExportBuildFileGenerators; - std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles; + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>> + EvaluationFiles; std::vector<cmExecutionStatus*> ExecutionStatusStack; friend class cmMakefileCall; friend class cmParseFileScope; - std::vector<cmTarget*> ImportedTargetsOwned; + std::vector<std::unique_ptr<cmTarget>> ImportedTargetsOwned; using TargetMap = std::unordered_map<std::string, cmTarget*>; TargetMap ImportedTargets; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 5c9608c..1df5410 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -420,10 +420,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->GetTargetLinkFlags(linkFlags, linkLanguage); { - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags, this->GetConfigName()); @@ -509,10 +509,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Set path conversion for link script shells. this->LocalGenerator->SetLinkScriptShell(useLinkScript); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); linkLineComputer->SetForResponse(useResponseFileForLibs); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); linkLineComputer->SetRelink(relink); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index e728b67..357e273 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -172,10 +172,10 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) this->LocalGenerator->AddConfigVariableFlags( extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->GetConfigName()); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, this->GetConfigName()); @@ -207,10 +207,10 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) this->LocalGenerator->AddConfigVariableFlags( extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->GetConfigName()); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, this->GetConfigName()); @@ -700,10 +700,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string linkLibs; if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) { - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); linkLineComputer->SetForResponse(useResponseFileForLibs); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); linkLineComputer->SetRelink(relink); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4979da5..77b6bc2 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" +#include "cmLinkLineComputer.h" #include "cmLocalCommonGenerator.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" @@ -753,8 +754,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // See if we need to use a compiler launcher like ccache or distcc std::string compilerLauncher; if (!compileCommands.empty() && - (lang == "C" || lang == "CXX" || lang == "Fortran" || - lang == "CUDA")) { + (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || + lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); @@ -1634,7 +1635,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( return responseFileName; } -cmLinkLineComputer* cmMakefileTargetGenerator::CreateLinkLineComputer( +std::unique_ptr<cmLinkLineComputer> +cmMakefileTargetGenerator::CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) { if (this->Makefile->IsOn("MSVC60")) { diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 710ef89..fd62933 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -140,7 +140,7 @@ protected: std::vector<std::string>& makefile_commands, std::vector<std::string>& makefile_depends); - cmLinkLineComputer* CreateLinkLineComputer( + std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir); /** Create a response file with the given set of options. Returns diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 5a12855..f853ac5 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -11,8 +11,8 @@ #include <utility> #include <cm/memory> +#include <cm/vector> -#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" // IWYU pragma: keep #include "cmCustomCommandGenerator.h" @@ -72,6 +72,10 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config) // Write the build statements bool firstForConfig = true; for (auto const& fileConfig : this->GetConfigNames()) { + if (fileConfig != config && + !this->GetGlobalGenerator()->EnableCrossConfigBuild()) { + continue; + } this->WriteObjectBuildStatements(config, fileConfig, firstForConfig); firstForConfig = false; } @@ -79,17 +83,23 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config) if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) { this->WriteObjectLibStatement(config); } else { - // If this target has cuda language link inputs, and we need to do - // device linking - this->WriteDeviceLinkStatement(config); firstForConfig = true; for (auto const& fileConfig : this->GetConfigNames()) { + if (fileConfig != config && + !this->GetGlobalGenerator()->EnableCrossConfigBuild()) { + continue; + } + // If this target has cuda language link inputs, and we need to do + // device linking + this->WriteDeviceLinkStatement(config, fileConfig, firstForConfig); this->WriteLinkStatement(config, fileConfig, firstForConfig); firstForConfig = false; } } - this->GetGlobalGenerator()->AddTargetAlias( - this->GetTargetName(), this->GetGeneratorTarget(), "all"); + if (this->GetGlobalGenerator()->EnableCrossConfigBuild()) { + this->GetGlobalGenerator()->AddTargetAlias( + this->GetTargetName(), this->GetGeneratorTarget(), "all"); + } // Find ADDITIONAL_CLEAN_FILES this->AdditionalCleanFiles(config); @@ -243,7 +253,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule( } // If there is no ranlib the command will be ":". Skip it. - cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); + cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands()); rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); @@ -379,7 +389,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, } // If there is no ranlib the command will be ":". Skip it. - cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); + cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands()); linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); linkCmds.emplace_back("$POST_BUILD"); @@ -551,7 +561,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( } void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( - const std::string& config) + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); if (!globalGen->GetLanguageEnabled("CUDA")) { @@ -574,12 +585,42 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( std::string const& objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); - std::string const targetOutputReal = ConvertToNinjaPath( - genTarget->ObjectDirectory + "cmake_device_link" + objExt); + std::string targetOutputDir = + cmStrCat(this->GetLocalGenerator()->GetTargetDirectory(genTarget), + globalGen->ConfigDirectory(config), "/"); + targetOutputDir = globalGen->ExpandCFGIntDir(targetOutputDir, config); - std::string const targetOutputImplib = ConvertToNinjaPath( + std::string targetOutputReal = + ConvertToNinjaPath(targetOutputDir + "cmake_device_link" + objExt); + + std::string targetOutputImplib = ConvertToNinjaPath( genTarget->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + if (config != fileConfig) { + std::string targetOutputFileConfigDir = + cmStrCat(this->GetLocalGenerator()->GetTargetDirectory(genTarget), + globalGen->ConfigDirectory(fileConfig), "/"); + targetOutputFileConfigDir = + globalGen->ExpandCFGIntDir(targetOutputDir, fileConfig); + if (targetOutputDir == targetOutputFileConfigDir) { + return; + } + + if (!genTarget->GetFullName(config, cmStateEnums::ImportLibraryArtifact) + .empty() && + !genTarget + ->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact) + .empty() && + targetOutputImplib == + ConvertToNinjaPath(genTarget->GetFullPath( + fileConfig, cmStateEnums::ImportLibraryArtifact))) { + return; + } + } + + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutputReal); + } this->DeviceLinkObject = targetOutputReal; // Write comments. @@ -884,10 +925,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( vars["TARGET_FILE"] = localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = globalGen->CreateLinkLineComputer( this->GetLocalGenerator(), - this->GetLocalGenerator()->GetStateSnapshot().GetDirectory())); + this->GetLocalGenerator()->GetStateSnapshot().GetDirectory()); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig()); diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index cda76d8..9de99b9 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -31,7 +31,9 @@ private: void WriteLinkStatement(const std::string& config, const std::string& fileConfig, bool firstForConfig); - void WriteDeviceLinkStatement(const std::string& config); + void WriteDeviceLinkStatement(const std::string& config, + const std::string& fileConfig, + bool firstForConfig); void WriteObjectLibStatement(const std::string& config); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 3f1dbe8..5a8c144 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -724,7 +724,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, // See if we need to use a compiler launcher like ccache or distcc std::string compilerLauncher; if (!compileCmds.empty() && - (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) { + (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || + lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (clauncher && *clauncher) { @@ -1195,6 +1196,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), vars); + if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + if (source->GetFullPath() == pchSource) { + this->addPoolNinjaVariable("JOB_POOL_PRECOMPILE_HEADER", + this->GetGeneratorTarget(), vars); + } + } + this->SetMsvcTargetPdbVariable(vars, config); objBuild.RspFile = objectFileName + ".rsp"; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index ecf892b..eef41c0 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -297,7 +297,12 @@ class cmMakefile; SELECT(POLICY, CMP0099, \ "Link properties are transitive over private dependency on static " \ "libraries.", \ - 3, 17, 0, cmPolicies::WARN) + 3, 17, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0100, "Let AUTOMOC and AUTOUIC process .hh files.", 3, \ + 17, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0101, \ + "target_compile_options honors BEFORE keyword in all scopes.", 3, \ + 17, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index ab47f3f..ebb522b 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -42,6 +42,7 @@ #include "cmSourceGroup.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmString.hxx" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -354,24 +355,38 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } } - // Check status of policy CMP0071 - { - cmPolicies::PolicyStatus const CMP0071_status = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0071); - switch (CMP0071_status) { - case cmPolicies::WARN: - this->CMP0071Warn = true; - CM_FALLTHROUGH; - case cmPolicies::OLD: - // Ignore GENERATED file - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Process GENERATED file - this->CMP0071Accept = true; - break; - } + // Check status of policy CMP0071 regarding handling of GENERATED files + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0071)) { + case cmPolicies::WARN: + // Ignore GENERATED files but warn + this->CMP0071Warn = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + // Ignore GENERATED files + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Process GENERATED files + this->CMP0071Accept = true; + break; + } + + // Check status of policy CMP0100 regarding handling of .hh headers + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0100)) { + case cmPolicies::WARN: + // Ignore but .hh files but warn + this->CMP0100Warn = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + // Ignore .hh files + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Process .hh file + this->CMP0100Accept = true; + break; } // Common directories @@ -733,15 +748,26 @@ bool cmQtAutoGenInitializer::InitScanFiles() return muf; }; - auto addMUFile = [&](MUFileHandle&& muf, bool isHeader) { + auto addMUHeader = [this](MUFileHandle&& muf, cm::string_view extension) { + cmSourceFile* sf = muf->SF; + const bool muIt = (muf->MocIt || muf->UicIt); + if (this->CMP0100Accept || (extension != "hh")) { + // Accept + if (muIt && muf->Generated) { + this->AutogenTarget.FilesGenerated.emplace_back(muf.get()); + } + this->AutogenTarget.Headers.emplace(sf, std::move(muf)); + } else if (muIt && this->CMP0100Warn) { + // Store file for warning message + this->AutogenTarget.CMP0100HeadersWarn.push_back(sf); + } + }; + + auto addMUSource = [this](MUFileHandle&& muf) { if ((muf->MocIt || muf->UicIt) && muf->Generated) { this->AutogenTarget.FilesGenerated.emplace_back(muf.get()); } - if (isHeader) { - this->AutogenTarget.Headers.emplace(muf->SF, std::move(muf)); - } else { - this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf)); - } + this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf)); }; // Scan through target files @@ -763,11 +789,10 @@ bool cmQtAutoGenInitializer::InitScanFiles() // Register files that will be scanned by moc or uic if (this->MocOrUicEnabled()) { - // FIXME: Add a policy to include .hh files. - if (cm->IsHeaderExtension(extLower) && extLower != "hh") { - addMUFile(makeMUFile(sf, fullPath, true), true); + if (cm->IsHeaderExtension(extLower)) { + addMUHeader(makeMUFile(sf, fullPath, true), extLower); } else if (cm->IsSourceExtension(extLower)) { - addMUFile(makeMUFile(sf, fullPath, true), false); + addMUSource(makeMUFile(sf, fullPath, true)); } } @@ -801,8 +826,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() // For source files find additional headers and private headers if (this->MocOrUicEnabled()) { - std::vector<MUFileHandle> extraHeaders; - extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2); // Header search suffixes and extensions static std::initializer_list<cm::string_view> const suffixes{ "", "_p" }; auto const& exts = cm->GetHeaderExtensions(); @@ -847,16 +870,12 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!muf.UicIt) { eMuf->UicIt = false; } - extraHeaders.emplace_back(std::move(eMuf)); + addMUHeader(std::move(eMuf), ext); } } } } } - // Move generated files to main headers list - for (auto& eMuf : extraHeaders) { - addMUFile(std::move(eMuf), true); - } } // Scan through all source files in the makefile to extract moc and uic @@ -864,7 +883,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() // The reason is that their file names might be discovered from source files // at generation time. if (this->MocOrUicEnabled()) { - for (cmSourceFile* sf : this->Makefile->GetSourceFiles()) { + for (const auto& sf : this->Makefile->GetSourceFiles()) { // sf->GetExtension() is only valid after sf->ResolveFullPath() ... // Since we're iterating over source files that might be not in the // target we need to check for path errors (not existing files). @@ -876,19 +895,18 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::string const& extLower = cmSystemTools::LowerCase(sf->GetExtension()); - // FIXME: Add a policy to include .hh files. - if (cm->IsHeaderExtension(extLower) && extLower != "hh") { - if (!cmContains(this->AutogenTarget.Headers, sf)) { - auto muf = makeMUFile(sf, fullPath, false); + if (cm->IsHeaderExtension(extLower)) { + if (!cmContains(this->AutogenTarget.Headers, sf.get())) { + auto muf = makeMUFile(sf.get(), fullPath, false); if (muf->SkipMoc || muf->SkipUic) { - this->AutogenTarget.Headers.emplace(sf, std::move(muf)); + addMUHeader(std::move(muf), extLower); } } } else if (cm->IsSourceExtension(extLower)) { - if (!cmContains(this->AutogenTarget.Headers, sf)) { - auto muf = makeMUFile(sf, fullPath, false); + if (!cmContains(this->AutogenTarget.Sources, sf.get())) { + auto muf = makeMUFile(sf.get(), fullPath, false); if (muf->SkipMoc || muf->SkipUic) { - this->AutogenTarget.Sources.emplace(sf, std::move(muf)); + addMUSource(std::move(muf)); } } } else if (this->Uic.Enabled && (extLower == kw.ui)) { @@ -946,6 +964,35 @@ bool cmQtAutoGenInitializer::InitScanFiles() } } + // Generate CMP0100 warning + if (this->MocOrUicEnabled() && + !this->AutogenTarget.CMP0100HeadersWarn.empty()) { + cm::string_view property; + if (this->Moc.Enabled && this->Uic.Enabled) { + property = "SKIP_AUTOGEN"; + } else if (this->Moc.Enabled) { + property = "SKIP_AUTOMOC"; + } else if (this->Uic.Enabled) { + property = "SKIP_AUTOUIC"; + } + std::string files; + for (cmSourceFile* sf : this->AutogenTarget.CMP0100HeadersWarn) { + files += cmStrCat(" ", Quoted(sf->GetFullPath()), '\n'); + } + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + cmPolicies::GetPolicyWarning(cmPolicies::CMP0100), '\n', + "For compatibility, CMake is excluding the header file(s):\n", files, + "from processing by ", + cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false), + ". If any of the files should be processed, set CMP0100 to NEW. " + "If any of the files should not be processed, " + "explicitly exclude them by setting the source file property ", + property, ":\n set_property(SOURCE file.hh PROPERTY ", property, + " ON)\n")); + } + // Process qrc files if (!this->Rcc.Qrcs.empty()) { const bool modernQt = (this->QtVersion.Major >= 5); @@ -1172,7 +1219,10 @@ bool cmQtAutoGenInitializer::InitRccTargets() // Register info file as generated by CMake this->Makefile->AddCMakeOutputFile(qrc.InfoFile); // Register file at target - this->AddGeneratedSource(qrc.OutputFile, this->Rcc); + { + cmSourceFile* sf = this->AddGeneratedSource(qrc.OutputFile, this->Rcc); + sf->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "On"); + } std::vector<std::string> ccOutput; ccOutput.push_back(qrc.OutputFile); @@ -1467,27 +1517,30 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() return true; } -void cmQtAutoGenInitializer::RegisterGeneratedSource( +cmSourceFile* cmQtAutoGenInitializer::RegisterGeneratedSource( std::string const& filename) { cmSourceFile* gFile = this->Makefile->GetOrCreateSource(filename, true); gFile->SetProperty("GENERATED", "1"); gFile->SetProperty("SKIP_AUTOGEN", "1"); + return gFile; } -bool cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, - GenVarsT const& genVars, - bool prepend) +cmSourceFile* cmQtAutoGenInitializer::AddGeneratedSource( + std::string const& filename, GenVarsT const& genVars, bool prepend) { // Register source at makefile - this->RegisterGeneratedSource(filename); + cmSourceFile* gFile = this->RegisterGeneratedSource(filename); // Add source file to target this->GenTarget->AddSource(filename, prepend); + // Add source file to source group - return this->AddToSourceGroup(filename, genVars.GenNameUpper); + this->AddToSourceGroup(filename, genVars.GenNameUpper); + + return gFile; } -bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, +void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, cm::string_view genNameUpper) { cmSourceGroup* sourceGroup = nullptr; @@ -1518,14 +1571,12 @@ bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, cmStrCat(genNameUpper, " error in ", property, ": Could not find or create the source group ", cmQtAutoGen::Quoted(groupName))); - return false; } } } if (sourceGroup != nullptr) { sourceGroup->AddGroupFile(fileName); } - return true; } void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName) @@ -1634,21 +1685,39 @@ std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf) if (!muf.MocIt) { return res; } - { - std::string const basePath = - cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_", - FileNameWithoutLastExtension(muf.FullPath)); - std::string suffix; - constexpr std::size_t num_tries_max = 256; - for (std::size_t ii = 0; ii != num_tries_max; ++ii) { - res = cmStrCat(basePath, suffix, ".cpp"); - if (this->Moc.EmittedBuildPaths.emplace(res).second) { - break; - } - // Compute new suffix - suffix = cmStrCat('_', ii + 1); + + std::string basePath = + cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_", + FileNameWithoutLastExtension(muf.FullPath)); + + res = cmStrCat(basePath, ".cpp"); + if (this->Moc.EmittedBuildPaths.emplace(res).second) { + return res; + } + + // File name already emitted. + // Try appending the header suffix to the base path. + basePath = cmStrCat(basePath, '_', muf.SF->GetExtension()); + res = cmStrCat(basePath, ".cpp"); + if (this->Moc.EmittedBuildPaths.emplace(res).second) { + return res; + } + + // File name with header extension already emitted. + // Try adding a number to the base path. + constexpr std::size_t number_begin = 2; + constexpr std::size_t number_end = 256; + for (std::size_t ii = number_begin; ii != number_end; ++ii) { + res = cmStrCat(basePath, '_', ii, ".cpp"); + if (this->Moc.EmittedBuildPaths.emplace(res).second) { + return res; } } + + // Output file name conflict (unlikely, but still...) + cmSystemTools::Error( + cmStrCat("moc output file name conflict for ", muf.FullPath)); + return res; } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 486dab7..8cedf14 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -129,10 +129,11 @@ private: bool SetupWriteAutogenInfo(); bool SetupWriteRccInfo(); - void RegisterGeneratedSource(std::string const& filename); - bool AddGeneratedSource(std::string const& filename, GenVarsT const& genVars, - bool prepend = false); - bool AddToSourceGroup(std::string const& fileName, + cmSourceFile* RegisterGeneratedSource(std::string const& filename); + cmSourceFile* AddGeneratedSource(std::string const& filename, + GenVarsT const& genVars, + bool prepend = false); + void AddToSourceGroup(std::string const& fileName, cm::string_view genNameUpper); void AddCleanFile(std::string const& fileName); @@ -159,6 +160,8 @@ private: bool MultiConfig = false; bool CMP0071Accept = false; bool CMP0071Warn = false; + bool CMP0100Accept = false; + bool CMP0100Warn = false; std::string ConfigDefault; std::vector<std::string> ConfigsList; std::string TargetsFolder; @@ -192,6 +195,7 @@ private: std::unordered_map<cmSourceFile*, MUFileHandle> Headers; std::unordered_map<cmSourceFile*, MUFileHandle> Sources; std::vector<MUFile*> FilesGenerated; + std::vector<cmSourceFile*> CMP0100HeadersWarn; } AutogenTarget; /** moc variables. */ diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 56003df..1d4ea01 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -744,7 +744,7 @@ void cmServerProtocol1::GeneratorInformation::SetupGenerator( cm->SetHomeDirectory(SourceDirectory); cm->SetHomeOutputDirectory(BuildDirectory); - cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName); + auto gg = cm->CreateGlobalGenerator(fullGeneratorName); if (!gg) { setErrorMessage( errorMessage, @@ -753,7 +753,7 @@ void cmServerProtocol1::GeneratorInformation::SetupGenerator( return; } - cm->SetGlobalGenerator(gg); + cm->SetGlobalGenerator(std::move(gg)); cm->SetGeneratorToolset(Toolset); cm->SetGeneratorPlatform(Platform); diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 8c3a4cb..5e2a146 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -121,7 +121,7 @@ bool cmSetCommand(std::vector<std::string> const& args, if (cache) { std::string::size_type cacheStart = args.size() - 3 - (force ? 1 : 0); - if (!cmState::StringToCacheEntryType(args[cacheStart + 1].c_str(), type)) { + if (!cmState::StringToCacheEntryType(args[cacheStart + 1], type)) { std::string m = "implicitly converting '" + args[cacheStart + 1] + "' to 'STRING' type."; status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, m); diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 2a345eb..60adf7f 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -128,7 +128,7 @@ bool cmSourceFile::FindFullPath(std::string* error) // The file is not generated. It must exist on disk. cmMakefile const* makefile = this->Location.GetMakefile(); // Location path - std::string const lPath = this->Location.GetFullPath(); + std::string const& lPath = this->Location.GetFullPath(); // List of extension lists std::array<std::vector<std::string> const*, 2> const extsLists = { { &makefile->GetCMakeInstance()->GetSourceExtensions(), @@ -145,7 +145,7 @@ bool cmSourceFile::FindFullPath(std::string* error) return true; } // Try full path with extension - for (auto exts : extsLists) { + for (auto& exts : extsLists) { for (std::string const& ext : *exts) { if (!ext.empty()) { std::string extPath = cmStrCat(fullPath, '.', ext); diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index df702b0..5f807b8 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -31,7 +31,8 @@ cmSourceFileLocation::cmSourceFileLocation(cmMakefile const* mf, this->AmbiguousExtension = true; this->Directory = cmSystemTools::GetFilenamePath(name); if (cmSystemTools::FileIsFullPath(this->Directory)) { - this->Directory = cmSystemTools::CollapseFullPath(this->Directory); + this->Directory = cmSystemTools::CollapseFullPath( + this->Directory, mf->GetHomeOutputDirectory()); } this->Name = cmSystemTools::GetFilenameName(name); if (kind == cmSourceFileLocationKind::Known) { diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 72f663d..35f07a1 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -3,9 +3,9 @@ #include "cmState.h" #include <algorithm> +#include <array> #include <cassert> #include <cstdlib> -#include <cstring> #include <utility> #include <cm/memory> @@ -60,43 +60,44 @@ const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType) return nullptr; } -const char* cmCacheEntryTypes[] = { "BOOL", "PATH", "FILEPATH", - "STRING", "INTERNAL", "STATIC", - "UNINITIALIZED", nullptr }; +static const std::array<std::string, 7> cmCacheEntryTypes = { + { "BOOL", "PATH", "FILEPATH", "STRING", "INTERNAL", "STATIC", + "UNINITIALIZED" } +}; -const char* cmState::CacheEntryTypeToString(cmStateEnums::CacheEntryType type) +const std::string& cmState::CacheEntryTypeToString( + cmStateEnums::CacheEntryType type) { - if (type > 6) { - return cmCacheEntryTypes[6]; + if (type < cmStateEnums::BOOL || type > cmStateEnums::UNINITIALIZED) { + type = cmStateEnums::UNINITIALIZED; } return cmCacheEntryTypes[type]; } -cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(const char* s) +cmStateEnums::CacheEntryType cmState::StringToCacheEntryType( + const std::string& s) { cmStateEnums::CacheEntryType type = cmStateEnums::STRING; StringToCacheEntryType(s, type); return type; } -bool cmState::StringToCacheEntryType(const char* s, +bool cmState::StringToCacheEntryType(const std::string& s, cmStateEnums::CacheEntryType& type) { - int i = 0; - while (cmCacheEntryTypes[i]) { - if (strcmp(s, cmCacheEntryTypes[i]) == 0) { + for (size_t i = 0; i < cmCacheEntryTypes.size(); ++i) { + if (s == cmCacheEntryTypes[i]) { type = static_cast<cmStateEnums::CacheEntryType>(i); return true; } - ++i; } return false; } bool cmState::IsCacheEntryType(std::string const& key) { - for (int i = 0; cmCacheEntryTypes[i]; ++i) { - if (key == cmCacheEntryTypes[i]) { + for (const std::string& i : cmCacheEntryTypes) { + if (key == i) { return true; } } @@ -149,8 +150,7 @@ const std::string* cmState::GetInitializedCacheValue( cmStateEnums::CacheEntryType cmState::GetCacheEntryType( std::string const& key) const { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); return it.GetType(); } @@ -164,8 +164,7 @@ void cmState::SetCacheEntryProperty(std::string const& key, std::string const& propertyName, std::string const& value) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); it.SetProperty(propertyName, value.c_str()); } @@ -173,24 +172,21 @@ void cmState::SetCacheEntryBoolProperty(std::string const& key, std::string const& propertyName, bool value) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); it.SetProperty(propertyName, value); } std::vector<std::string> cmState::GetCacheEntryPropertyList( const std::string& key) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); return it.GetPropertyList(); } const char* cmState::GetCacheEntryProperty(std::string const& key, std::string const& propertyName) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); if (!it.PropertyExists(propertyName)) { return nullptr; } @@ -200,8 +196,8 @@ const char* cmState::GetCacheEntryProperty(std::string const& key, bool cmState::GetCacheEntryPropertyAsBool(std::string const& key, std::string const& propertyName) { - return this->CacheManager->GetCacheIterator(key.c_str()) - .GetPropertyAsBool(propertyName); + return this->CacheManager->GetCacheIterator(key).GetPropertyAsBool( + propertyName); } void cmState::AddCacheEntry(const std::string& key, const char* value, @@ -253,15 +249,14 @@ void cmState::AppendCacheEntryProperty(const std::string& key, const std::string& property, const std::string& value, bool asString) { - this->CacheManager->GetCacheIterator(key.c_str()) - .AppendProperty(property, value.c_str(), asString); + this->CacheManager->GetCacheIterator(key).AppendProperty(property, value, + asString); } void cmState::RemoveCacheEntryProperty(std::string const& key, std::string const& propertyName) { - this->CacheManager->GetCacheIterator(key.c_str()) - .SetProperty(propertyName, nullptr); + this->CacheManager->GetCacheIterator(key).SetProperty(propertyName, nullptr); } cmStateSnapshot cmState::Reset() @@ -1006,12 +1001,12 @@ bool cmState::ParseCacheEntry(const std::string& entry, std::string& var, bool flag = false; if (regQuoted.find(entry)) { var = regQuoted.match(1); - type = cmState::StringToCacheEntryType(regQuoted.match(2).c_str()); + type = cmState::StringToCacheEntryType(regQuoted.match(2)); value = regQuoted.match(3); flag = true; } else if (reg.find(entry)) { var = reg.match(1); - type = cmState::StringToCacheEntryType(reg.match(2).c_str()); + type = cmState::StringToCacheEntryType(reg.match(2)); value = reg.match(3); flag = true; } diff --git a/Source/cmState.h b/Source/cmState.h index cd871b9..a744266 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -70,10 +70,12 @@ public: cmStateSnapshot const& originSnapshot); cmStateSnapshot Pop(cmStateSnapshot const& originSnapshot); - static cmStateEnums::CacheEntryType StringToCacheEntryType(const char*); - static bool StringToCacheEntryType(const char*, + static cmStateEnums::CacheEntryType StringToCacheEntryType( + const std::string&); + static bool StringToCacheEntryType(const std::string&, cmStateEnums::CacheEntryType& type); - static const char* CacheEntryTypeToString(cmStateEnums::CacheEntryType); + static const std::string& CacheEntryTypeToString( + cmStateEnums::CacheEntryType); static bool IsCacheEntryType(std::string const& key); bool LoadCache(const std::string& path, bool internal, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index d2693b8..a0b3138 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -336,6 +336,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("C_STANDARD"); initProp("C_STANDARD_REQUIRED"); initProp("C_EXTENSIONS"); + initProp("OBJC_COMPILER_LAUNCHER"); initProp("OBJC_STANDARD"); initProp("OBJC_STANDARD_REQUIRED"); initProp("OBJC_EXTENSIONS"); @@ -347,6 +348,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("CXX_STANDARD"); initProp("CXX_STANDARD_REQUIRED"); initProp("CXX_EXTENSIONS"); + initProp("OBJCXX_COMPILER_LAUNCHER"); initProp("OBJCXX_STANDARD"); initProp("OBJCXX_STANDARD_REQUIRED"); initProp("OBJCXX_EXTENSIONS"); @@ -358,7 +360,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("CUDA_RESOLVE_DEVICE_SYMBOLS"); initProp("LINK_SEARCH_START_STATIC"); initProp("LINK_SEARCH_END_STATIC"); - initProp("FOLDER"); initProp("Swift_LANGUAGE_VERSION"); initProp("Swift_MODULE_DIRECTORY"); initProp("VS_JUST_MY_CODE_DEBUGGING"); @@ -390,6 +391,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { + initProp("FOLDER"); + if (this->GetGlobalGenerator()->IsXcode()) { initProp("XCODE_GENERATE_SCHEME"); } @@ -510,6 +513,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->GetType() != cmStateEnums::UTILITY) { initProp("JOB_POOL_COMPILE"); initProp("JOB_POOL_LINK"); + initProp("JOB_POOL_PRECOMPILE_HEADER"); } if (impl->TargetType <= cmStateEnums::UTILITY) { @@ -934,14 +938,7 @@ cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries() return impl->OriginalLinkLibraries; } -void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib, - cmTargetLinkLibraryType llt) -{ - this->AddLinkLibrary(mf, lib, lib, llt); -} - void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, - std::string const& libRef, cmTargetLinkLibraryType llt) { cmTarget* tgt = mf.FindTargetToUse(lib); @@ -950,13 +947,13 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, const std::string libName = (isNonImportedTarget && llt != GENERAL_LibraryType) - ? targetNameGenex(libRef) - : libRef; + ? targetNameGenex(lib) + : lib; this->AppendProperty("LINK_LIBRARIES", this->GetDebugGeneratorExpressions(libName, llt)); } - if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef || + if (cmGeneratorExpression::Find(lib) != std::string::npos || (tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY || tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) || @@ -1559,8 +1556,12 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, cmMakefile* context) { - std::vector<cmTarget*> targets = context->GetOwnedImportedTargets(); - auto it = std::find(targets.begin(), targets.end(), target); + const auto& targets = context->GetOwnedImportedTargets(); + auto it = + std::find_if(targets.begin(), targets.end(), + [&](const std::unique_ptr<cmTarget>& importTarget) -> bool { + return target == importTarget.get(); + }); if (it == targets.end()) { std::ostringstream e; e << "Attempt to promote imported target \"" << target->GetName() diff --git a/Source/cmTarget.h b/Source/cmTarget.h index bdf8c0f..ca37f0d 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -110,10 +110,8 @@ public: //! Clear the dependency information recorded for this target, if any. void ClearDependencyInformation(cmMakefile& mf); - void AddLinkLibrary(cmMakefile& mf, const std::string& lib, - cmTargetLinkLibraryType llt); void AddLinkLibrary(cmMakefile& mf, std::string const& lib, - std::string const& libRef, cmTargetLinkLibraryType llt); + cmTargetLinkLibraryType llt); enum TLLSignature { diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index e39b726..dee2c10 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -5,6 +5,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmTargetPropCommandBase.h" @@ -27,10 +28,16 @@ private: bool HandleDirectContent(cmTarget* tgt, const std::vector<std::string>& content, - bool /*prepend*/, bool /*system*/) override + bool prepend, bool /*system*/) override { + cmPolicies::PolicyStatus policyStatus = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0101); + if (policyStatus == cmPolicies::OLD || policyStatus == cmPolicies::WARN) { + prepend = false; + } + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertCompileOption(this->Join(content), lfbt); + tgt->InsertCompileOption(this->Join(content), lfbt, prepend); return true; // Successfully handled. } diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index e1ac6a8..df751da 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -3,7 +3,10 @@ #include "cmTargetLinkLibrariesCommand.h" #include <cstring> +#include <memory> #include <sstream> +#include <unordered_set> +#include <utility> #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" @@ -34,15 +37,30 @@ enum ProcessingState const char* LinkLibraryTypeNames[3] = { "general", "debug", "optimized" }; +struct TLL +{ + cmMakefile& Makefile; + cmTarget* Target; + bool WarnRemoteInterface = false; + bool RejectRemoteLinking = false; + bool EncodeRemoteReference = false; + std::string DirectoryId; + std::unordered_set<std::string> Props; + + TLL(cmMakefile& mf, cmTarget* target); + ~TLL(); + + bool HandleLibrary(ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt); + void AppendProperty(std::string const& prop, std::string const& value); + void AffectsProperty(std::string const& prop); +}; + } // namespace static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, int right); -static bool HandleLibrary(cmMakefile& mf, cmTarget* target, - ProcessingState currentProcessingState, - const std::string& lib, cmTargetLinkLibraryType llt); - bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -64,11 +82,9 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, cmTarget* target = mf.GetCMakeInstance()->GetGlobalGenerator()->FindTarget(args[0]); if (!target) { - const std::vector<cmTarget*>& importedTargets = - mf.GetOwnedImportedTargets(); - for (cmTarget* importedTarget : importedTargets) { + for (const auto& importedTarget : mf.GetOwnedImportedTargets()) { if (importedTarget->GetName() == args[0]) { - target = importedTarget; + target = importedTarget.get(); break; } } @@ -149,6 +165,8 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, return true; } + TLL tll(mf, target); + // Keep track of link configuration specifiers. cmTargetLinkLibraryType llt = GENERAL_LibraryType; bool haveLLT = false; @@ -247,7 +265,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, } else if (haveLLT) { // The link type was specified by the previous argument. haveLLT = false; - if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { + if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) { return false; } } else { @@ -268,7 +286,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, llt = OPTIMIZED_LibraryType; } } - if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { + if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) { return false; } } @@ -311,21 +329,48 @@ static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, "\" instead of a library name. The first specifier will be ignored.")); } -static bool HandleLibrary(cmMakefile& mf, cmTarget* target, - ProcessingState currentProcessingState, - const std::string& lib, cmTargetLinkLibraryType llt) +namespace { + +TLL::TLL(cmMakefile& mf, cmTarget* target) + : Makefile(mf) + , Target(target) +{ + if (&this->Makefile != this->Target->GetMakefile()) { + // The LHS target was created in another directory. + switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0079)) { + case cmPolicies::WARN: + this->WarnRemoteInterface = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + this->RejectRemoteLinking = true; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + this->EncodeRemoteReference = true; + break; + } + } + if (this->EncodeRemoteReference) { + cmDirectoryId const dirId = this->Makefile.GetDirectoryId(); + this->DirectoryId = cmStrCat(CMAKE_DIRECTORY_ID_SEP, dirId.String); + } +} + +bool TLL::HandleLibrary(ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY && + if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && currentProcessingState != ProcessingKeywordLinkInterface) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, "INTERFACE library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; } - if (target->IsImported() && + if (this->Target->IsImported() && currentProcessingState != ProcessingKeywordLinkInterface) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, "IMPORTED library can only be used with the INTERFACE keyword of " "target_link_libraries"); @@ -340,11 +385,12 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, currentProcessingState == ProcessingKeywordLinkInterface) ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature; - if (!target->PushTLLCommandTrace(sig, mf.GetExecutionContext())) { + if (!this->Target->PushTLLCommandTrace( + sig, this->Makefile.GetExecutionContext())) { std::ostringstream e; const char* modal = nullptr; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (mf.GetPolicyStatus(cmPolicies::CMP0023)) { + switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0023)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; modal = "should"; @@ -365,73 +411,38 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, e << "The " << existingSig << " signature for target_link_libraries has " "already been used with the target \"" - << target->GetName() + << this->Target->GetName() << "\". All uses of target_link_libraries with a target " << modal << " be either all-keyword or all-plain.\n"; - target->GetTllSignatureTraces(e, - sig == cmTarget::KeywordTLLSignature - ? cmTarget::PlainTLLSignature - : cmTarget::KeywordTLLSignature); - mf.IssueMessage(messageType, e.str()); + this->Target->GetTllSignatureTraces(e, + sig == cmTarget::KeywordTLLSignature + ? cmTarget::PlainTLLSignature + : cmTarget::KeywordTLLSignature); + this->Makefile.IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } } } - bool warnRemoteInterface = false; - bool rejectRemoteLinking = false; - bool encodeRemoteReference = false; - if (&mf != target->GetMakefile()) { - // The LHS target was created in another directory. - switch (mf.GetPolicyStatus(cmPolicies::CMP0079)) { - case cmPolicies::WARN: - warnRemoteInterface = true; - CM_FALLTHROUGH; - case cmPolicies::OLD: - rejectRemoteLinking = true; - break; - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::NEW: - encodeRemoteReference = true; - break; - } - } - - std::string libRef; - if (encodeRemoteReference && !cmSystemTools::FileIsFullPath(lib)) { - // This is a library name added by a caller that is not in the - // same directory as the target was created. Add a suffix to - // the name to tell ResolveLinkItem to look up the name in the - // caller's directory. - cmDirectoryId const dirId = mf.GetDirectoryId(); - libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String; - } else { - // This is an absolute path or a library name added by a caller - // in the same directory as the target was created. We can use - // the original name directly. - libRef = lib; - } - // Handle normal case where the command was called with another keyword than // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES" // property of the target on the LHS shall be populated.) if (currentProcessingState != ProcessingKeywordLinkInterface && currentProcessingState != ProcessingPlainLinkInterface) { - if (rejectRemoteLinking) { - mf.IssueMessage( + if (this->RejectRemoteLinking) { + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Attempt to add link library \"", lib, "\" to target \"", - target->GetName(), + this->Target->GetName(), "\" which is not built in this " "directory.\nThis is allowed only when policy CMP0079 " "is set to NEW.")); return false; } - cmTarget* tgt = mf.GetGlobalGenerator()->FindTarget(lib); + cmTarget* tgt = this->Makefile.GetGlobalGenerator()->FindTarget(lib); if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) && (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) && @@ -439,7 +450,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) && (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) && !tgt->IsExecutableWithExports()) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, cmStrCat( "Target \"", lib, "\" of type ", @@ -449,15 +460,16 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, "executables with the ENABLE_EXPORTS property set.")); } - target->AddLinkLibrary(mf, lib, libRef, llt); + this->AffectsProperty("LINK_LIBRARIES"); + this->Target->AddLinkLibrary(this->Makefile, lib, llt); } - if (warnRemoteInterface) { - mf.IssueMessage( + if (this->WarnRemoteInterface) { + this->Makefile.IssueMessage( MessageType::AUTHOR_WARNING, cmStrCat( cmPolicies::GetPolicyWarning(cmPolicies::CMP0079), "\nTarget\n ", - target->GetName(), + this->Target->GetName(), "\nis not created in this " "directory. For compatibility with older versions of CMake, link " "library\n ", @@ -472,15 +484,15 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // STATIC library.) if (currentProcessingState == ProcessingKeywordPrivateInterface || currentProcessingState == ProcessingPlainPrivateInterface) { - if (target->GetType() == cmStateEnums::STATIC_LIBRARY || - target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY || + this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { std::string configLib = - target->GetDebugGeneratorExpressions(libRef, llt); + this->Target->GetDebugGeneratorExpressions(lib, llt); if (cmGeneratorExpression::IsValidTargetName(lib) || cmGeneratorExpression::Find(lib) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } - target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib); + this->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib); } return true; } @@ -488,8 +500,8 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Handle general case where the command was called with another keyword than // PRIVATE / LINK_PRIVATE or none at all. (The "INTERFACE_LINK_LIBRARIES" // property of the target on the LHS shall be populated.) - target->AppendProperty("INTERFACE_LINK_LIBRARIES", - target->GetDebugGeneratorExpressions(libRef, llt)); + this->AppendProperty("INTERFACE_LINK_LIBRARIES", + this->Target->GetDebugGeneratorExpressions(lib, llt)); // Stop processing if called without any keyword. if (currentProcessingState == ProcessingLinkLibraries) { @@ -497,13 +509,13 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, } // Stop processing if policy CMP0022 is set to NEW. const cmPolicies::PolicyStatus policy22Status = - target->GetPolicyStatusCMP0022(); + this->Target->GetPolicyStatusCMP0022(); if (policy22Status != cmPolicies::OLD && policy22Status != cmPolicies::WARN) { return true; } // Stop processing if called with an INTERFACE library on the LHS. - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { return true; } @@ -513,7 +525,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, { // Get the list of configurations considered to be DEBUG. std::vector<std::string> debugConfigs = - mf.GetCMakeInstance()->GetDebugConfigs(); + this->Makefile.GetCMakeInstance()->GetDebugConfigs(); std::string prop; // Include this library in the link interface for the target. @@ -521,22 +533,49 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Put in the DEBUG configuration interfaces. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - target->AppendProperty(prop, libRef); + this->AppendProperty(prop, lib); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef); + this->AppendProperty("LINK_INTERFACE_LIBRARIES", lib); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - if (!target->GetProperty(prop)) { - target->SetProperty(prop, ""); + if (!this->Target->GetProperty(prop)) { + this->Target->SetProperty(prop, ""); } } } } return true; } + +void TLL::AppendProperty(std::string const& prop, std::string const& value) +{ + this->AffectsProperty(prop); + this->Target->AppendProperty(prop, value); +} + +void TLL::AffectsProperty(std::string const& prop) +{ + if (!this->EncodeRemoteReference) { + return; + } + // Add a wrapper to the expression to tell LookupLinkItems to look up + // names in the caller's directory. + if (this->Props.insert(prop).second) { + this->Target->AppendProperty(prop, this->DirectoryId); + } +} + +TLL::~TLL() +{ + for (std::string const& prop : this->Props) { + this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP); + } +} + +} // namespace diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index baab8da..f37995c 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -62,6 +62,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( "COMPATIBLE_INTERFACE_NUMBER_MAX", "COMPATIBLE_INTERFACE_NUMBER_MIN", "COMPATIBLE_INTERFACE_STRING", + "DEPRECATION", "EXPORT_NAME", "EXPORT_PROPERTIES", "IMPORTED", diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 8e4f629..ab76df9 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2,6 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmake.h" +#include <algorithm> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iostream> +#include <sstream> +#include <utility> + #include <cm/memory> #include <cm/string_view> #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) @@ -10,6 +19,10 @@ #include <cmext/algorithm> +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" + #include "cm_sys_stat.h" #include "cmAlgorithms.h" @@ -58,6 +71,8 @@ // include the generator #if defined(_WIN32) && !defined(__CYGWIN__) # if !defined(CMAKE_BOOT_MINGW) +# include <cmext/memory> + # include "cmGlobalBorlandMakefileGenerator.h" # include "cmGlobalJOMMakefileGenerator.h" # include "cmGlobalNMakeMakefileGenerator.h" @@ -108,19 +123,6 @@ # include <sys/time.h> #endif -#include <algorithm> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <initializer_list> -#include <iostream> -#include <sstream> -#include <utility> - -#include "cmsys/FStream.hxx" -#include "cmsys/Glob.hxx" -#include "cmsys/RegularExpression.hxx" - namespace { #if !defined(CMAKE_BOOTSTRAP) @@ -203,14 +205,7 @@ cmake::cmake(Role role, cmState::Mode mode) } } -cmake::~cmake() -{ - if (this->GlobalGenerator) { - delete this->GlobalGenerator; - this->GlobalGenerator = nullptr; - } - cmDeleteAll(this->Generators); -} +cmake::~cmake() = default; #if !defined(CMAKE_BOOTSTRAP) Json::Value cmake::ReportVersionJson() const @@ -463,12 +458,12 @@ void cmake::ReadListFile(const std::vector<std::string>& args, { // if a generator was not yet created, temporarily create one cmGlobalGenerator* gg = this->GetGlobalGenerator(); - bool created = false; // if a generator was not specified use a generic one + std::unique_ptr<cmGlobalGenerator> gen; if (!gg) { - gg = new cmGlobalGenerator(this); - created = true; + gen = cm::make_unique<cmGlobalGenerator>(this); + gg = gen.get(); } // read in the list file to fill the cache @@ -490,11 +485,6 @@ void cmake::ReadListFile(const std::vector<std::string>& args, cmSystemTools::Error("Error processing file: " + path); } } - - // free generic one if generated - if (created) { - delete gg; - } } bool cmake::FindPackage(const std::vector<std::string>& args) @@ -502,9 +492,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); - // if a generator was not yet created, temporarily create one - cmGlobalGenerator* gg = new cmGlobalGenerator(this); - this->SetGlobalGenerator(gg); + this->SetGlobalGenerator(cm::make_unique<cmGlobalGenerator>(this)); cmStateSnapshot snapshot = this->GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentBinary( @@ -513,8 +501,9 @@ bool cmake::FindPackage(const std::vector<std::string>& args) cmSystemTools::GetCurrentWorkingDirectory()); // read in the list file to fill the cache snapshot.SetDefaultDefinitions(); - cmMakefile* mf = new cmMakefile(gg, snapshot); - gg->AddMakefile(mf); + auto mfu = cm::make_unique<cmMakefile>(this->GetGlobalGenerator(), snapshot); + cmMakefile* mf = mfu.get(); + this->GlobalGenerator->AddMakefile(std::move(mfu)); mf->SetArgcArgv(args); @@ -539,8 +528,8 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS"); std::vector<std::string> includeDirs = cmExpandedList(includes); - gg->CreateGenerationObjects(); - const auto& lg = gg->LocalGenerators[0]; + this->GlobalGenerator->CreateGenerationObjects(); + const auto& lg = this->GlobalGenerator->LocalGenerators[0]; std::string includeFlags = lg->GetIncludeFlags(includeDirs, nullptr, language); @@ -566,8 +555,9 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::string linkPath; std::string flags; std::string linkFlags; - gg->CreateGenerationObjects(); - cmGeneratorTarget* gtgt = gg->FindGeneratorTarget(tgt->GetName()); + this->GlobalGenerator->CreateGenerationObjects(); + cmGeneratorTarget* gtgt = + this->GlobalGenerator->FindGeneratorTarget(tgt->GetName()); cmLocalGenerator* lg = gtgt->GetLocalGenerator(); cmLinkLineComputer linkLineComputer(lg, lg->GetStateSnapshot().GetDirectory()); @@ -587,10 +577,6 @@ bool cmake::FindPackage(const std::vector<std::string>& args) }*/ } - // free generic one if generated - // this->SetGlobalGenerator(0); // setting 0-pointer is not possible - // delete gg; // this crashes inside the cmake instance - return packageFound; } @@ -838,7 +824,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) } value = args[i]; } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(value); + auto gen = this->CreateGlobalGenerator(value); if (!gen) { std::string kdevError; if (value.find("KDevelop3", 0) != std::string::npos) { @@ -850,7 +836,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) this->PrintGeneratorList(); return; } - this->SetGlobalGenerator(gen); + this->SetGlobalGenerator(std::move(gen)); } // no option assume it is the path to the source or an existing build else { @@ -1118,7 +1104,7 @@ void cmake::AddDefaultExtraGenerators() void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, bool includeNamesWithPlatform) const { - for (cmGlobalGeneratorFactory* gen : this->Generators) { + for (const auto& gen : this->Generators) { std::vector<std::string> names = gen->GetGeneratorNames(); if (includeNamesWithPlatform) { @@ -1167,7 +1153,8 @@ void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, } } -static std::pair<cmExternalMakefileProjectGenerator*, std::string> +static std::pair<std::unique_ptr<cmExternalMakefileProjectGenerator>, + std::string> createExtraGenerator( const std::vector<cmExternalMakefileProjectGeneratorFactory*>& in, const std::string& name) @@ -1190,15 +1177,17 @@ createExtraGenerator( return { nullptr, name }; } -cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname) +std::unique_ptr<cmGlobalGenerator> cmake::CreateGlobalGenerator( + const std::string& gname) { - std::pair<cmExternalMakefileProjectGenerator*, std::string> extra = - createExtraGenerator(this->ExtraGenerators, gname); - cmExternalMakefileProjectGenerator* extraGenerator = extra.first; - const std::string name = extra.second; + std::pair<std::unique_ptr<cmExternalMakefileProjectGenerator>, std::string> + extra = createExtraGenerator(this->ExtraGenerators, gname); + std::unique_ptr<cmExternalMakefileProjectGenerator>& extraGenerator = + extra.first; + const std::string& name = extra.second; - cmGlobalGenerator* generator = nullptr; - for (cmGlobalGeneratorFactory* g : this->Generators) { + std::unique_ptr<cmGlobalGenerator> generator; + for (const auto& g : this->Generators) { generator = g->CreateGlobalGenerator(name, this); if (generator) { break; @@ -1206,9 +1195,7 @@ cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname) } if (generator) { - generator->SetExternalMakefileProjectGenerator(extraGenerator); - } else { - delete extraGenerator; + generator->SetExternalMakefileProjectGenerator(std::move(extraGenerator)); } return generator; @@ -1260,15 +1247,13 @@ std::string cmake::FindCacheFile(const std::string& binaryDir) return cachePath; } -void cmake::SetGlobalGenerator(cmGlobalGenerator* gg) +void cmake::SetGlobalGenerator(std::unique_ptr<cmGlobalGenerator> gg) { if (!gg) { cmSystemTools::Error("Error SetGlobalGenerator called with null"); return; } - // delete the old generator if (this->GlobalGenerator) { - delete this->GlobalGenerator; // restore the original environment variables CXX and CC // Restore CC std::string env = "CC="; @@ -1284,7 +1269,7 @@ void cmake::SetGlobalGenerator(cmGlobalGenerator* gg) } // set the new - this->GlobalGenerator = gg; + this->GlobalGenerator = std::move(gg); // set the global flag for unix style paths on cmSystemTools as soon as // the generator is set. This allows gmake to be used on windows. @@ -1647,7 +1632,7 @@ int cmake::ActualConfigure() } } - cmMakefile* mf = this->GlobalGenerator->GetMakefiles()[0]; + auto& mf = this->GlobalGenerator->GetMakefiles()[0]; if (mf->IsOn("CTEST_USE_LAUNCHERS") && !this->State->GetGlobalProperty("RULE_LAUNCH_COMPILE")) { cmSystemTools::Error( @@ -1668,13 +1653,12 @@ int cmake::ActualConfigure() std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() { if (!this->EnvironmentGenerator.empty()) { - cmGlobalGenerator* gen = - this->CreateGlobalGenerator(this->EnvironmentGenerator); + auto gen = this->CreateGlobalGenerator(this->EnvironmentGenerator); if (!gen) { cmSystemTools::Error("CMAKE_GENERATOR was set but the specified " "generator doesn't exist. Using CMake default."); } else { - return std::unique_ptr<cmGlobalGenerator>(gen); + return gen; } } #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) @@ -1724,13 +1708,14 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() } } } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(found); + auto gen = this->CreateGlobalGenerator(found); if (!gen) { - gen = new cmGlobalNMakeMakefileGenerator(this); + gen = cm::make_unique<cmGlobalNMakeMakefileGenerator>(this); } - return std::unique_ptr<cmGlobalGenerator>(gen); + return std::unique_ptr<cmGlobalGenerator>(std::move(gen)); #else - return cm::make_unique<cmGlobalUnixMakefileGenerator3>(this); + return std::unique_ptr<cmGlobalGenerator>( + cm::make_unique<cmGlobalUnixMakefileGenerator3>(this)); #endif } @@ -1741,7 +1726,7 @@ void cmake::CreateDefaultGlobalGenerator() // This print could be unified for all platforms std::cout << "-- Building for: " << gen->GetName() << "\n"; #endif - this->SetGlobalGenerator(gen.release()); + this->SetGlobalGenerator(std::move(gen)); } void cmake::PreLoadCMakeFiles() @@ -1844,10 +1829,11 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) cmSystemTools::Message("CMake Configure step failed. " "Build files cannot be regenerated correctly. " "Attempting to stop IDE build."); - cmGlobalVisualStudioGenerator* gg = - static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); - gg->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop, - this->VSSolutionFile); + cmGlobalVisualStudioGenerator& gg = + cm::static_reference_cast<cmGlobalVisualStudioGenerator>( + this->GlobalGenerator); + gg.CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop, + this->VSSolutionFile); } #endif return ret; @@ -2103,7 +2089,7 @@ void cmake::AppendGlobalGeneratorsDocumentation( const std::string defaultName = defaultGenerator->GetName(); bool foundDefaultOne = false; - for (cmGlobalGeneratorFactory* g : this->Generators) { + for (const auto& g : this->Generators) { cmDocumentationEntry e; g->GetDocumentation(e); if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) { @@ -2243,8 +2229,8 @@ int cmake::CheckBuildSystem() } // Create the generator and use it to clear the dependencies. - std::unique_ptr<cmGlobalGenerator> ggd( - this->CreateGlobalGenerator(genName)); + std::unique_ptr<cmGlobalGenerator> ggd = + this->CreateGlobalGenerator(genName); if (ggd) { cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmMakefile mfd(ggd.get(), cm.GetCurrentSnapshot()); @@ -2457,12 +2443,12 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) } value = args[i]; } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(value); + auto gen = this->CreateGlobalGenerator(value); if (!gen) { cmSystemTools::Error("Could not create named generator " + value); this->PrintGeneratorList(); } else { - this->SetGlobalGenerator(gen); + this->SetGlobalGenerator(std::move(gen)); } } // no option assume it is the output file @@ -2674,34 +2660,37 @@ int cmake::Build(int jobs, const std::string& dir, std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; return 1; } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(cachedGenerator); + auto gen = this->CreateGlobalGenerator(cachedGenerator); if (!gen) { std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator << "\"\n"; return 1; } - this->SetGlobalGenerator(gen); + this->SetGlobalGenerator(std::move(gen)); const char* cachedGeneratorInstance = this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE"); if (cachedGeneratorInstance) { - cmMakefile mf(gen, this->GetCurrentSnapshot()); - if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) { + cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); + if (!this->GlobalGenerator->SetGeneratorInstance(cachedGeneratorInstance, + &mf)) { return 1; } } const char* cachedGeneratorPlatform = this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); if (cachedGeneratorPlatform) { - cmMakefile mf(gen, this->GetCurrentSnapshot()); - if (!gen->SetGeneratorPlatform(cachedGeneratorPlatform, &mf)) { + cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); + if (!this->GlobalGenerator->SetGeneratorPlatform(cachedGeneratorPlatform, + &mf)) { return 1; } } const char* cachedGeneratorToolset = this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); if (cachedGeneratorToolset) { - cmMakefile mf(gen, this->GetCurrentSnapshot()); - if (!gen->SetGeneratorToolset(cachedGeneratorToolset, true, &mf)) { + cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); + if (!this->GlobalGenerator->SetGeneratorToolset(cachedGeneratorToolset, + true, &mf)) { return 1; } } @@ -2776,10 +2765,11 @@ int cmake::Build(int jobs, const std::string& dir, } #endif - gen->PrintBuildCommandAdvice(std::cerr, jobs); - return gen->Build(jobs, "", dir, projName, targets, output, "", config, - clean, false, verbose, cmDuration::zero(), - cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions); + this->GlobalGenerator->PrintBuildCommandAdvice(std::cerr, jobs); + return this->GlobalGenerator->Build( + jobs, "", dir, projName, targets, output, "", config, clean, false, + verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH, + nativeOptions); } bool cmake::Open(const std::string& dir, bool dryRun) @@ -2807,8 +2797,8 @@ bool cmake::Open(const std::string& dir, bool dryRun) cmExternalMakefileProjectGenerator::CreateFullGeneratorName( genName, extraGenName ? *extraGenName : ""); - std::unique_ptr<cmGlobalGenerator> gen( - this->CreateGlobalGenerator(fullName)); + std::unique_ptr<cmGlobalGenerator> gen = + this->CreateGlobalGenerator(fullName); if (!gen) { std::cerr << "Error: could create CMAKE_GENERATOR \"" << fullName << "\"\n"; diff --git a/Source/cmake.h b/Source/cmake.h index 266d66c..22d3c39 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -213,21 +213,25 @@ public: void PreLoadCMakeFiles(); //! Create a GlobalGenerator - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name); + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name); //! Return the global generator assigned to this instance of cmake - cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; } + cmGlobalGenerator* GetGlobalGenerator() + { + return this->GlobalGenerator.get(); + } //! Return the global generator assigned to this instance of cmake, const const cmGlobalGenerator* GetGlobalGenerator() const { - return this->GlobalGenerator; + return this->GlobalGenerator.get(); } //! Return the full path to where the CMakeCache.txt file should be. static std::string FindCacheFile(const std::string& binaryDir); //! Return the global generator assigned to this instance of cmake - void SetGlobalGenerator(cmGlobalGenerator*); + void SetGlobalGenerator(std::unique_ptr<cmGlobalGenerator>); //! Get the names of the current registered generators void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, @@ -547,7 +551,8 @@ protected: void RunCheckForUnusedVariables(); int HandleDeleteCacheVariables(const std::string& var); - using RegisteredGeneratorsVector = std::vector<cmGlobalGeneratorFactory*>; + using RegisteredGeneratorsVector = + std::vector<std::unique_ptr<cmGlobalGeneratorFactory>>; RegisteredGeneratorsVector Generators; using RegisteredExtraGeneratorsVector = std::vector<cmExternalMakefileProjectGeneratorFactory*>; @@ -557,7 +562,6 @@ protected: void AddDefaultGenerators(); void AddDefaultExtraGenerators(); - cmGlobalGenerator* GlobalGenerator = nullptr; std::map<std::string, DiagLevel> DiagLevels; std::string GeneratorInstance; std::string GeneratorPlatform; @@ -638,6 +642,8 @@ private: std::stack<std::string> CheckInProgressMessages; + std::unique_ptr<cmGlobalGenerator> GlobalGenerator; + void UpdateConversionPathTable(); //! Print a list of valid generators to stderr. diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 9a07aef..67c776e 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1080,13 +1080,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) cm.SetHomeDirectory(homeDir); cm.SetHomeOutputDirectory(homeOutDir); cm.GetCurrentSnapshot().SetDefaultDefinitions(); - if (cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen)) { - cm.SetGlobalGenerator(ggd); + if (auto ggd = cm.CreateGlobalGenerator(gen)) { + cm.SetGlobalGenerator(std::move(ggd)); cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentBinary(startOutDir); snapshot.GetDirectory().SetCurrentSource(startDir); - cmMakefile mf(ggd, snapshot); - auto lgd = ggd->CreateLocalGenerator(&mf); + cmMakefile mf(cm.GetGlobalGenerator(), snapshot); + auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf); // Actually scan dependencies. return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2; diff --git a/Templates/MSBuild/FlagTables/v10_Cuda.json b/Templates/MSBuild/FlagTables/v10_Cuda.json index 1831b8a..b3230ac 100644 --- a/Templates/MSBuild/FlagTables/v10_Cuda.json +++ b/Templates/MSBuild/FlagTables/v10_Cuda.json @@ -20,6 +20,26 @@ ] }, { + "name": "AdditionalCompilerOptions", + "switch": "-compiler-options=", + "comment": "Host compiler options", + "value": "", + "flags": [ + "UserValue", + "SpaceAppendable" + ] + }, + { + "name": "AdditionalCompilerOptions", + "switch": "-compiler-options", + "comment": "Host compiler options", + "value": "", + "flags": [ + "UserFollowing", + "SpaceAppendable" + ] + }, + { "name": "CudaRuntime", "switch": "cudart=none", "comment": "No CUDA runtime library", diff --git a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt index 7c918e6..06d1111 100644 --- a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt @@ -2,7 +2,11 @@ add_executable(SubDirB SubDirB.c) # Link to a target imported in this directory that would not normally # be visible to the directory in which TopDir is defined. -target_link_libraries(TopDir PUBLIC SameNameImported) +target_link_libraries(TopDir PUBLIC debug SameNameImported optimized SameNameImported) + +# Link to a list of targets imported in this directory that would not +# normally be visible to the directory in which TopDir is defined. +target_link_libraries(TopDir PUBLIC "$<1:SameNameImported;SameNameImported>") # Link SubDirA to a target imported in this directory that has the same # name as a target imported in SubDirA's directory. We verify when diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 90eed4f..6fad175 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -989,6 +989,27 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH endif() endif() + # On Windows run the CPackNSISGenerator test + # if the nsis is available + if(WIN32 AND NSIS_MAKENSIS_EXECUTABLE) + add_test(CPackNSISGenerator ${CMAKE_CTEST_COMMAND} + -C \${CTEST_CONFIGURATION_TYPE} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/CPackNSISGenerator" + "${CMake_BINARY_DIR}/Tests/CPackNSISGenerator" + ${build_generator_args} + --build-project CPackNSISGenerator + --build-options + --test-command ${CMAKE_CMAKE_COMMAND} + "-DCPackNSISGenerator_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/CPackNSISGenerator" + "-Dconfig=\${CTEST_CONFIGURATION_TYPE}" + -P "${CMake_SOURCE_DIR}/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake") + + set_property(TEST CPackNSISGenerator PROPERTY + ATTACHED_FILES_ON_FAIL + "${CMake_BINARY_DIR}/Tests/CPackNSISGenerator/_CPack_Packages/win32/NSIS/NSISOutput.log") + endif() + if(CTEST_TEST_CPACK) add_test(CPackUseDefaultVersion ${CMAKE_CTEST_COMMAND} --build-and-test @@ -1595,6 +1616,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH set(tutorial_build_options -DUSE_MYMATH:BOOL=OFF) endif() add_test(${tutorial_test_name} ${CMAKE_CTEST_COMMAND} + -C "Release" --build-and-test "${CMake_SOURCE_DIR}/Help/guide/tutorial/${step_name}" ${tutorial_build_dir}_Build @@ -1606,11 +1628,11 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH endfunction() if(NOT CMake_TEST_EXTERNAL_CMAKE) - foreach(STP RANGE 2 11) + foreach(STP RANGE 2 12) add_tutorial_test(Step${STP} TRUE) endforeach() add_tutorial_test(Complete TRUE) - foreach(STP RANGE 3 11) + foreach(STP RANGE 3 12) add_tutorial_test(Step${STP} FALSE) endforeach() add_tutorial_test(Complete FALSE) diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 1619081..e32d693 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -33,8 +33,9 @@ AddCMakeTest(While "") AddCMakeTest(CMakeHostSystemInformation "") AddCMakeTest(FileDownload "") -set_property(TEST CMake.FileDownload PROPERTY +set_tests_properties(CMake.FileDownload PROPERTIES PASS_REGULAR_EXPRESSION "file already exists with expected MD5 sum" + FAIL_REGULAR_EXPRESSION "Unexpected status" ) AddCMakeTest(FileDownloadBadHash "") set_property(TEST CMake.FileDownloadBadHash PROPERTY diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in index 3935449..5bd3803 100644 --- a/Tests/CMakeTests/FileDownloadTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadTest.cmake.in @@ -1,23 +1,50 @@ +# We do not contact any real URLs, but do try a bogus one. +# Remove any proxy configuration that may change behavior. +unset(ENV{http_proxy}) +unset(ENV{https_proxy}) + +set(timeout 4) + if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") set(slash /) endif() set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") +# Beware Windows asynchronous file/directory removal, rename and then +# remove the renamed dir so we can be certain the dir isn't there when +# we get to the file() commands below +if(EXISTS "${dir}") + file(RENAME ${dir} "${dir}_beingRemoved") + file(REMOVE_RECURSE "${dir}_beingRemoved") +endif() + +function(__reportIfWrongStatus statusPair expectedStatusCode) + list(GET statusPair 0 statusCode) + if(NOT statusCode EQUAL expectedStatusCode) + message(SEND_ERROR + "Unexpected status: ${statusCode}, expected: ${expectedStatusCode}") + endif() +endfunction() + message(STATUS "FileDownload:1") file(DOWNLOAD ${url} ${dir}/file1.png - TIMEOUT 2 + TIMEOUT ${timeout} + STATUS status ) +__reportIfWrongStatus("${status}" 0) message(STATUS "FileDownload:2") file(DOWNLOAD ${url} ${dir}/file2.png - TIMEOUT 2 + TIMEOUT ${timeout} + STATUS status SHOW_PROGRESS ) +__reportIfWrongStatus("${status}" 0) # Two calls in a row, exactly the same arguments. # Since downloaded file should exist already for 2nd call, @@ -31,82 +58,108 @@ message(STATUS "FileDownload:3") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} + STATUS status EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92 ) +__reportIfWrongStatus("${status}" 0) message(STATUS "FileDownload:4") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status EXPECTED_HASH SHA1=67eee17f79d9ac557284fc0b8ad19f25723fb578 ) +__reportIfWrongStatus("${status}" 0) message(STATUS "FileDownload:5") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status EXPECTED_HASH SHA224=ba283726bbb602776818b463943189afd91836cb7ee5dd6e2c7b5ae4 ) +__reportIfWrongStatus("${status}" 0) message(STATUS "FileDownload:6") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status EXPECTED_HASH SHA256=cf3334b1275071e1da6e8c396ccb72cf1b2388d8c937526f3af26230affb9423 ) +__reportIfWrongStatus("${status}" 0) message(STATUS "FileDownload:7") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status EXPECTED_HASH SHA384=43a5d13978d97c660db44481aee0604cb4ff6ca0775cd5c2cd68cd8000e107e507c4caf6c228941231041e282ffb8950 ) +__reportIfWrongStatus("${status}" 0) message(STATUS "FileDownload:8") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status EXPECTED_HASH SHA512=6984e0909a1018030ccaa418e3be1654223cdccff0fe6adc745f9aea7e377f178be53b9fc7d54a6f81c2b62ef9ddcd38ba1978fedf4c5e7139baaf355eefad5b ) +__reportIfWrongStatus("${status}" 0) + message(STATUS "FileDownload:9") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status EXPECTED_HASH MD5=dbd330d52f4dbd60115d4191904ded92 ) +__reportIfWrongStatus("${status}" 0) message(STATUS "FileDownload:10") file(DOWNLOAD ${url} ${dir}/file3.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92 ) +__reportIfWrongStatus("${status}" 0) +# Print status because we check its message too message(STATUS "${status}") message(STATUS "FileDownload:11") file(DOWNLOAD badhostname.png ${dir}/file11.png - TIMEOUT 2 + TIMEOUT ${timeout} STATUS status ) message(STATUS "${status}") -list(GET status 0 status_code) -if(NOT ${status_code} EQUAL 6) - message(SEND_ERROR "error: expected status code 6 for bad host name, got: ${status_code}") +__reportIfWrongStatus("${status}" 6) # 6 corresponds to an unresolvable host name + +message(STATUS "FileDownload:12") +set(absFile "@CMAKE_CURRENT_BINARY_DIR@/file12.png") +if(EXISTS "${absFile}") + file(RENAME ${absFile} "${absFile}_beingRemoved") + file(REMOVE "${absFile}_beingRemoved") +endif() +file(DOWNLOAD + ${url} + file12.png + TIMEOUT ${timeout} + EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92 + STATUS status + ) +__reportIfWrongStatus("${status}" 0) +if(NOT EXISTS file12.png) + message(SEND_ERROR "file12.png not downloaded: ${status}") endif() diff --git a/Tests/CMakeTests/FileTestScript.cmake b/Tests/CMakeTests/FileTestScript.cmake index 9a43569..145f28a 100644 --- a/Tests/CMakeTests/FileTestScript.cmake +++ b/Tests/CMakeTests/FileTestScript.cmake @@ -183,7 +183,7 @@ elseif(testname STREQUAL to_native_path) # pass elseif(testname STREQUAL download_wrong_number_of_args) # fail file(DOWNLOAD zzzz://bogus/ffff) -elseif(testname STREQUAL download_file_with_no_path) # fail +elseif(testname STREQUAL download_file_with_no_path) # pass file(DOWNLOAD zzzz://bogus/ffff ffff) elseif(testname STREQUAL download_missing_time) # fail diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake index 86a74b2..f46a575 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake @@ -65,9 +65,10 @@ if(DPKGDEB_EXECUTABLE) "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` != `${expected_description}`") endif() elseif(dpkg_package_name STREQUAL "mylib-libraries") - if(NOT dpkg_description MATCHES "main description\n.*") + set(expected_description "main description") + if(NOT dpkg_description STREQUAL expected_description) set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} - "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` =~ `main description.*`") + "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` != `${expected_description}`") endif() else() set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake index d53c73d..c00921a 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake @@ -53,9 +53,10 @@ if(DPKGDEB_EXECUTABLE) message(STATUS "package='${dpkg_package_name}', description='${dpkg_description}'") if(dpkg_package_name STREQUAL "mylib-applications" OR dpkg_package_name STREQUAL "mylib-headers") - if(NOT dpkg_description MATCHES "main description 2\n.*") + set(expected_description "main description 2") + if(NOT dpkg_description STREQUAL expected_description) set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} - "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` =~ `main description 2`") + "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` != `${expected_description}`") endif() elseif(dpkg_package_name STREQUAL "mylib-libraries") set(expected_description "main description 2\n library description") diff --git a/Tests/CPackNSISGenerator/CMakeLists.txt b/Tests/CPackNSISGenerator/CMakeLists.txt new file mode 100644 index 0000000..b8b2ed6 --- /dev/null +++ b/Tests/CPackNSISGenerator/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.16) + +project(CPackNSISGenerator) + +add_executable(hello main.cpp) + +install(TARGETS hello + ARCHIVE DESTINATION . + RUNTIME DESTINATION . + LIBRARY DESTINATION . + BUNDLE DESTINATION .) + +set(CPACK_NSIS_MUI_HEADERIMAGE "${PROJECT_SOURCE_DIR}\\\\header-image.bmp") +set(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}\\\\header-icon.bmp") +set(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}\\\\install.ico") +set(CPACK_NSIS_MUI_UNIICON "${PROJECT_SOURCE_DIR}\\\\uninstall.ico") +set(CPACK_GENERATOR "NSIS") +set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) + +include(CPack) diff --git a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake new file mode 100644 index 0000000..01b37c5 --- /dev/null +++ b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake @@ -0,0 +1,46 @@ +message(STATUS "=============================================================") +message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") +message(STATUS "") + +if(NOT CPackNSISGenerator_BINARY_DIR) + message(FATAL_ERROR "CPackNSISGenerator_BINARY_DIR not set") +endif() + +message(STATUS "CMAKE_COMMAND: ${CMAKE_COMMAND}") +message(STATUS "CMAKE_CPACK_COMMAND: ${CMAKE_CPACK_COMMAND}") +message(STATUS "CPackNSISGenerator_BINARY_DIR: ${CPackNSISGenerator_BINARY_DIR}") + +if(config) + set(_C_config -C ${config}) +endif() + +execute_process(COMMAND "${CMAKE_CPACK_COMMAND}" + ${_C_config} + RESULT_VARIABLE CPack_result + OUTPUT_VARIABLE CPack_output + ERROR_VARIABLE CPack_error + WORKING_DIRECTORY "${CPackNSISGenerator_BINARY_DIR}") + +if(CPack_result) + message(FATAL_ERROR "CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}") +else () + message(STATUS "CPack_output=${CPack_output}") +endif() + +set(expected_file_mask "${CPackNSISGenerator_BINARY_DIR}/_CPack_Packages/*/NSIS/*.nsi") +file(GLOB project_file "${expected_file_mask}") + +message(STATUS "project_file='${project_file}'") +message(STATUS "expected_file_mask='${expected_file_mask}'") + +if(NOT project_file) + message(FATAL_ERROR "project_file does not exist.") +endif() + +# should match !define MUI_HEADERIMAGE_BITMAP "${PROJECT_SOURCE_DIR}\header-image.bmp" +file(STRINGS "${project_file}" line REGEX "^!define MUI_HEADERIMAGE_BITMAP") +string(FIND "${line}" "header-image.bmp" output_index) +message(STATUS "Found the bitmap at index ${output_index}") +if("${output_index}" EQUAL "-1") + message(FATAL_ERROR "MUI_HEADERIMAGE_BITMAP not found in the project") +endif() diff --git a/Tests/CPackNSISGenerator/header-icon.bmp b/Tests/CPackNSISGenerator/header-icon.bmp Binary files differnew file mode 100644 index 0000000..ef6a656 --- /dev/null +++ b/Tests/CPackNSISGenerator/header-icon.bmp diff --git a/Tests/CPackNSISGenerator/header-image.bmp b/Tests/CPackNSISGenerator/header-image.bmp Binary files differnew file mode 100644 index 0000000..15b1730 --- /dev/null +++ b/Tests/CPackNSISGenerator/header-image.bmp diff --git a/Tests/CPackNSISGenerator/install.ico b/Tests/CPackNSISGenerator/install.ico Binary files differnew file mode 100644 index 0000000..3b1e480 --- /dev/null +++ b/Tests/CPackNSISGenerator/install.ico diff --git a/Tests/CPackNSISGenerator/main.cpp b/Tests/CPackNSISGenerator/main.cpp new file mode 100644 index 0000000..956f345 --- /dev/null +++ b/Tests/CPackNSISGenerator/main.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 42; +} diff --git a/Tests/CPackNSISGenerator/uninstall.ico b/Tests/CPackNSISGenerator/uninstall.ico Binary files differnew file mode 100644 index 0000000..c4f6316 --- /dev/null +++ b/Tests/CPackNSISGenerator/uninstall.ico diff --git a/Tests/Cuda/CMakeLists.txt b/Tests/Cuda/CMakeLists.txt index 35b9022..58b9b03 100644 --- a/Tests/Cuda/CMakeLists.txt +++ b/Tests/Cuda/CMakeLists.txt @@ -9,8 +9,17 @@ ADD_TEST_MACRO(Cuda.MixedStandardLevels3 MixedStandardLevels3) ADD_TEST_MACRO(Cuda.MixedStandardLevels4 MixedStandardLevels4) ADD_TEST_MACRO(Cuda.MixedStandardLevels5 MixedStandardLevels5) ADD_TEST_MACRO(Cuda.NotEnabled CudaNotEnabled) +ADD_TEST_MACRO(Cuda.SeparableCompCXXOnly SeparableCompCXXOnly) ADD_TEST_MACRO(Cuda.Toolkit Toolkit) ADD_TEST_MACRO(Cuda.IncludePathNoToolkit IncludePathNoToolkit) ADD_TEST_MACRO(Cuda.ProperDeviceLibraries ProperDeviceLibraries) ADD_TEST_MACRO(Cuda.ProperLinkFlags ProperLinkFlags) +ADD_TEST_MACRO(Cuda.SharedRuntimePlusToolkit SharedRuntimePlusToolkit) + +# The CUDA only ships the shared version of the toolkit libraries +# on windows +if(NOT WIN32) + ADD_TEST_MACRO(Cuda.StaticRuntimePlusToolkit StaticRuntimePlusToolkit) +endif() + ADD_TEST_MACRO(Cuda.WithC CudaWithC) diff --git a/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt b/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt new file mode 100644 index 0000000..97670e3 --- /dev/null +++ b/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt @@ -0,0 +1,3 @@ +project(SeparableCompCXXOnly LANGUAGES CXX CUDA) +set(CMAKE_CUDA_SEPARABLE_COMPILATION ON) +add_executable(SeparableCompCXXOnly main.cpp) diff --git a/Tests/Cuda/SeparableCompCXXOnly/main.cpp b/Tests/Cuda/SeparableCompCXXOnly/main.cpp new file mode 100644 index 0000000..8135246 --- /dev/null +++ b/Tests/Cuda/SeparableCompCXXOnly/main.cpp @@ -0,0 +1,5 @@ + +int main(int, char const* []) +{ + return 0; +} diff --git a/Tests/Cuda/SharedRuntimePlusToolkit/CMakeLists.txt b/Tests/Cuda/SharedRuntimePlusToolkit/CMakeLists.txt new file mode 100644 index 0000000..48df558 --- /dev/null +++ b/Tests/Cuda/SharedRuntimePlusToolkit/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.15) +project(SharedRuntimePlusToolkit CXX) + +#Goal for this example: +# Validate that with c++ we can use some components of the CUDA toolkit, and +# specify the cuda runtime +find_package(CUDAToolkit REQUIRED) + +add_library(Common OBJECT curand.cpp nppif.cpp) +target_link_libraries(Common PRIVATE CUDA::toolkit) +set_target_properties(Common PROPERTIES POSITION_INDEPENDENT_CODE ON) + +#shared runtime with shared toolkit libraries +add_library(SharedToolkit SHARED shared.cpp) +target_link_libraries(SharedToolkit PRIVATE Common PUBLIC CUDA::curand CUDA::nppif) +target_link_libraries(SharedToolkit PUBLIC CUDA::cudart) + +# The CUDA only ships the shared version of the toolkit libraries +# on windows +if(NOT WIN32) + #shared runtime with static toolkit libraries + add_library(StaticToolkit SHARED static.cpp) + target_link_libraries(StaticToolkit PRIVATE Common CUDA::curand_static CUDA::nppif_static) + target_link_libraries(StaticToolkit PUBLIC CUDA::cudart) + + #static runtime with mixed toolkit libraries + add_library(MixedToolkit SHARED mixed.cpp) + target_link_libraries(MixedToolkit PRIVATE Common CUDA::curand_static CUDA::nppif) + target_link_libraries(MixedToolkit PUBLIC CUDA::cudart) +endif() + +add_executable(SharedRuntimePlusToolkit main.cpp) +target_link_libraries(SharedRuntimePlusToolkit PRIVATE SharedToolkit + $<TARGET_NAME_IF_EXISTS:StaticToolkit> + $<TARGET_NAME_IF_EXISTS:MixedToolkit>) diff --git a/Tests/Cuda/SharedRuntimePlusToolkit/curand.cpp b/Tests/Cuda/SharedRuntimePlusToolkit/curand.cpp new file mode 100644 index 0000000..fdd7b53 --- /dev/null +++ b/Tests/Cuda/SharedRuntimePlusToolkit/curand.cpp @@ -0,0 +1,65 @@ +// Comes from: +// https://docs.nvidia.com/cuda/curand/host-api-overview.html#host-api-example + +#ifdef _WIN32 +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + +/* + * This program uses the host CURAND API to generate 100 + * pseudorandom floats. + */ +#include <cuda.h> +#include <curand.h> +#include <stdio.h> +#include <stdlib.h> + +#define CUDA_CALL(x) \ + do { \ + if ((x) != cudaSuccess) { \ + printf("Error at %s:%d\n", __FILE__, __LINE__); \ + return EXIT_FAILURE; \ + } \ + } while (0) +#define CURAND_CALL(x) \ + do { \ + if ((x) != CURAND_STATUS_SUCCESS) { \ + printf("Error at %s:%d\n", __FILE__, __LINE__); \ + return EXIT_FAILURE; \ + } \ + } while (0) + +EXPORT int curand_main() +{ + size_t n = 100; + size_t i; + curandGenerator_t gen; + float *devData, *hostData; + + /* Allocate n floats on host */ + hostData = (float*)calloc(n, sizeof(float)); + + /* Allocate n floats on device */ + CUDA_CALL(cudaMalloc((void**)&devData, n * sizeof(float))); + + /* Create pseudo-random number generator */ + CURAND_CALL(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT)); + + /* Set seed */ + CURAND_CALL(curandSetPseudoRandomGeneratorSeed(gen, 1234ULL)); + + /* Generate n floats on device */ + CURAND_CALL(curandGenerateUniform(gen, devData, n)); + + /* Copy device memory to host */ + CUDA_CALL( + cudaMemcpy(hostData, devData, n * sizeof(float), cudaMemcpyDeviceToHost)); + + /* Cleanup */ + CURAND_CALL(curandDestroyGenerator(gen)); + CUDA_CALL(cudaFree(devData)); + free(hostData); + return EXIT_SUCCESS; +} diff --git a/Tests/Cuda/SharedRuntimePlusToolkit/main.cpp b/Tests/Cuda/SharedRuntimePlusToolkit/main.cpp new file mode 100644 index 0000000..2a4da22 --- /dev/null +++ b/Tests/Cuda/SharedRuntimePlusToolkit/main.cpp @@ -0,0 +1,23 @@ + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +IMPORT int shared_version(); +int static_version() +{ + return 0; +} +int mixed_version() +{ + return 0; +} +#else +int shared_version(); +int static_version(); +int mixed_version(); +#endif + +int main() +{ + return mixed_version() == 0 && shared_version() == 0 && + static_version() == 0; +} diff --git a/Tests/Cuda/SharedRuntimePlusToolkit/mixed.cpp b/Tests/Cuda/SharedRuntimePlusToolkit/mixed.cpp new file mode 100644 index 0000000..6de6886 --- /dev/null +++ b/Tests/Cuda/SharedRuntimePlusToolkit/mixed.cpp @@ -0,0 +1,16 @@ + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +# define EXPORT __declspec(dllexport) +#else +# define IMPORT +# define EXPORT +#endif + +IMPORT int curand_main(); +IMPORT int nppif_main(); + +EXPORT int mixed_version() +{ + return curand_main() == 0 && nppif_main() == 0; +} diff --git a/Tests/Cuda/SharedRuntimePlusToolkit/nppif.cpp b/Tests/Cuda/SharedRuntimePlusToolkit/nppif.cpp new file mode 100644 index 0000000..ac5341c --- /dev/null +++ b/Tests/Cuda/SharedRuntimePlusToolkit/nppif.cpp @@ -0,0 +1,92 @@ +// Comes from +// https://devtalk.nvidia.com/default/topic/1037482/gpu-accelerated-libraries/help-me-help-you-with-modern-cmake-and-cuda-mwe-for-npp/post/5271066/#5271066 + +#ifdef _WIN32 +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + +#include <cstdio> +#include <iostream> + +#include <assert.h> +#include <cuda_runtime_api.h> +#include <nppi_filtering_functions.h> + +EXPORT int nppif_main() +{ + /** + * 8-bit unsigned single-channel 1D row convolution. + */ + const int simgrows = 32; + const int simgcols = 32; + Npp8u *d_pSrc, *d_pDst; + const int nMaskSize = 3; + NppiSize oROI; + oROI.width = simgcols - nMaskSize; + oROI.height = simgrows; + const int simgsize = simgrows * simgcols * sizeof(d_pSrc[0]); + const int dimgsize = oROI.width * oROI.height * sizeof(d_pSrc[0]); + const int simgpix = simgrows * simgcols; + const int dimgpix = oROI.width * oROI.height; + const int nSrcStep = simgcols * sizeof(d_pSrc[0]); + const int nDstStep = oROI.width * sizeof(d_pDst[0]); + const int pixval = 1; + const int nDivisor = 1; + const Npp32s h_pKernel[nMaskSize] = { pixval, pixval, pixval }; + Npp32s* d_pKernel; + const Npp32s nAnchor = 2; + cudaError_t err = cudaMalloc((void**)&d_pSrc, simgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMalloc((void**)&d_pDst, dimgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMalloc((void**)&d_pKernel, nMaskSize * sizeof(d_pKernel[0])); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + // set image to pixval initially + err = cudaMemset(d_pSrc, pixval, simgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMemset(d_pDst, 0, dimgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMemcpy(d_pKernel, h_pKernel, nMaskSize * sizeof(d_pKernel[0]), + cudaMemcpyHostToDevice); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + // copy src to dst + NppStatus ret = + nppiFilterRow_8u_C1R(d_pSrc, nSrcStep, d_pDst, nDstStep, oROI, d_pKernel, + nMaskSize, nAnchor, nDivisor); + assert(ret == NPP_NO_ERROR); + Npp8u* h_imgres = new Npp8u[dimgpix]; + err = cudaMemcpy(h_imgres, d_pDst, dimgsize, cudaMemcpyDeviceToHost); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + // test for filtering + for (int i = 0; i < dimgpix; i++) { + if (h_imgres[i] != (pixval * pixval * nMaskSize)) { + fprintf(stderr, "h_imgres at index %d failed to match\n", i); + return 1; + } + } + + return 0; +} diff --git a/Tests/Cuda/SharedRuntimePlusToolkit/shared.cpp b/Tests/Cuda/SharedRuntimePlusToolkit/shared.cpp new file mode 100644 index 0000000..f3c3dbc --- /dev/null +++ b/Tests/Cuda/SharedRuntimePlusToolkit/shared.cpp @@ -0,0 +1,16 @@ + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +# define EXPORT __declspec(dllexport) +#else +# define IMPORT +# define EXPORT +#endif + +int curand_main(); +int nppif_main(); + +EXPORT int shared_version() +{ + return curand_main() == 0 && nppif_main() == 0; +} diff --git a/Tests/Cuda/SharedRuntimePlusToolkit/static.cpp b/Tests/Cuda/SharedRuntimePlusToolkit/static.cpp new file mode 100644 index 0000000..6932fa3 --- /dev/null +++ b/Tests/Cuda/SharedRuntimePlusToolkit/static.cpp @@ -0,0 +1,16 @@ + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +# define EXPORT __declspec(dllexport) +#else +# define IMPORT +# define EXPORT +#endif + +IMPORT int curand_main(); +IMPORT int nppif_main(); + +EXPORT int static_version() +{ + return curand_main() == 0 && nppif_main() == 0; +} diff --git a/Tests/Cuda/StaticRuntimePlusToolkit/CMakeLists.txt b/Tests/Cuda/StaticRuntimePlusToolkit/CMakeLists.txt new file mode 100644 index 0000000..df6c392 --- /dev/null +++ b/Tests/Cuda/StaticRuntimePlusToolkit/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.15) +project(StaticRuntimePlusToolkit CXX) + +#Goal for this example: +# Validate that with c++ we can use some components of the CUDA toolkit, and +# specify the cuda runtime +find_package(CUDAToolkit REQUIRED) + +add_library(Common OBJECT curand.cpp nppif.cpp) +target_link_libraries(Common PRIVATE CUDA::toolkit) +set_target_properties(Common PROPERTIES POSITION_INDEPENDENT_CODE ON) + +#static runtime with shared toolkit libraries +add_library(SharedToolkit SHARED shared.cpp) +target_link_libraries(SharedToolkit PRIVATE Common PUBLIC CUDA::curand CUDA::nppif) +target_link_libraries(SharedToolkit PUBLIC CUDA::cudart_static) + +#static runtime with static toolkit libraries +add_library(StaticToolkit SHARED static.cpp) +target_link_libraries(StaticToolkit PRIVATE Common CUDA::curand_static CUDA::nppif_static) +target_link_libraries(StaticToolkit PUBLIC CUDA::cudart_static) + +#static runtime with mixed toolkit libraries +add_library(MixedToolkit SHARED mixed.cpp) +target_link_libraries(MixedToolkit PRIVATE Common CUDA::curand CUDA::nppif_static) +target_link_libraries(MixedToolkit PUBLIC CUDA::cudart_static) + +add_executable(StaticRuntimePlusToolkit main.cpp) +target_link_libraries(StaticRuntimePlusToolkit PRIVATE SharedToolkit StaticToolkit MixedToolkit) diff --git a/Tests/Cuda/StaticRuntimePlusToolkit/curand.cpp b/Tests/Cuda/StaticRuntimePlusToolkit/curand.cpp new file mode 100644 index 0000000..95872f0 --- /dev/null +++ b/Tests/Cuda/StaticRuntimePlusToolkit/curand.cpp @@ -0,0 +1,59 @@ +// Comes from: +// https://docs.nvidia.com/cuda/curand/host-api-overview.html#host-api-example + +/* + * This program uses the host CURAND API to generate 100 + * pseudorandom floats. + */ +#include <cuda.h> +#include <curand.h> +#include <stdio.h> +#include <stdlib.h> + +#define CUDA_CALL(x) \ + do { \ + if ((x) != cudaSuccess) { \ + printf("Error at %s:%d\n", __FILE__, __LINE__); \ + return EXIT_FAILURE; \ + } \ + } while (0) +#define CURAND_CALL(x) \ + do { \ + if ((x) != CURAND_STATUS_SUCCESS) { \ + printf("Error at %s:%d\n", __FILE__, __LINE__); \ + return EXIT_FAILURE; \ + } \ + } while (0) + +int curand_main() +{ + size_t n = 100; + size_t i; + curandGenerator_t gen; + float *devData, *hostData; + + /* Allocate n floats on host */ + hostData = (float*)calloc(n, sizeof(float)); + + /* Allocate n floats on device */ + CUDA_CALL(cudaMalloc((void**)&devData, n * sizeof(float))); + + /* Create pseudo-random number generator */ + CURAND_CALL(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT)); + + /* Set seed */ + CURAND_CALL(curandSetPseudoRandomGeneratorSeed(gen, 1234ULL)); + + /* Generate n floats on device */ + CURAND_CALL(curandGenerateUniform(gen, devData, n)); + + /* Copy device memory to host */ + CUDA_CALL( + cudaMemcpy(hostData, devData, n * sizeof(float), cudaMemcpyDeviceToHost)); + + /* Cleanup */ + CURAND_CALL(curandDestroyGenerator(gen)); + CUDA_CALL(cudaFree(devData)); + free(hostData); + return EXIT_SUCCESS; +} diff --git a/Tests/Cuda/StaticRuntimePlusToolkit/main.cpp b/Tests/Cuda/StaticRuntimePlusToolkit/main.cpp new file mode 100644 index 0000000..5a09f8e --- /dev/null +++ b/Tests/Cuda/StaticRuntimePlusToolkit/main.cpp @@ -0,0 +1,11 @@ + + +int shared_version(); +int static_version(); +int mixed_version(); + +int main() +{ + return mixed_version() == 0 && shared_version() == 0 && + static_version() == 0; +} diff --git a/Tests/Cuda/StaticRuntimePlusToolkit/mixed.cpp b/Tests/Cuda/StaticRuntimePlusToolkit/mixed.cpp new file mode 100644 index 0000000..a05140d --- /dev/null +++ b/Tests/Cuda/StaticRuntimePlusToolkit/mixed.cpp @@ -0,0 +1,8 @@ + +int curand_main(); +int nppif_main(); + +int mixed_version() +{ + return curand_main() == 0 && nppif_main() == 0; +} diff --git a/Tests/Cuda/StaticRuntimePlusToolkit/nppif.cpp b/Tests/Cuda/StaticRuntimePlusToolkit/nppif.cpp new file mode 100644 index 0000000..2871090 --- /dev/null +++ b/Tests/Cuda/StaticRuntimePlusToolkit/nppif.cpp @@ -0,0 +1,86 @@ +// Comes from +// https://devtalk.nvidia.com/default/topic/1037482/gpu-accelerated-libraries/help-me-help-you-with-modern-cmake-and-cuda-mwe-for-npp/post/5271066/#5271066 + +#include <cstdio> +#include <iostream> + +#include <assert.h> +#include <cuda_runtime_api.h> +#include <nppi_filtering_functions.h> + +int nppif_main() +{ + /** + * 8-bit unsigned single-channel 1D row convolution. + */ + const int simgrows = 32; + const int simgcols = 32; + Npp8u *d_pSrc, *d_pDst; + const int nMaskSize = 3; + NppiSize oROI; + oROI.width = simgcols - nMaskSize; + oROI.height = simgrows; + const int simgsize = simgrows * simgcols * sizeof(d_pSrc[0]); + const int dimgsize = oROI.width * oROI.height * sizeof(d_pSrc[0]); + const int simgpix = simgrows * simgcols; + const int dimgpix = oROI.width * oROI.height; + const int nSrcStep = simgcols * sizeof(d_pSrc[0]); + const int nDstStep = oROI.width * sizeof(d_pDst[0]); + const int pixval = 1; + const int nDivisor = 1; + const Npp32s h_pKernel[nMaskSize] = { pixval, pixval, pixval }; + Npp32s* d_pKernel; + const Npp32s nAnchor = 2; + cudaError_t err = cudaMalloc((void**)&d_pSrc, simgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMalloc((void**)&d_pDst, dimgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMalloc((void**)&d_pKernel, nMaskSize * sizeof(d_pKernel[0])); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + // set image to pixval initially + err = cudaMemset(d_pSrc, pixval, simgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMemset(d_pDst, 0, dimgsize); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + err = cudaMemcpy(d_pKernel, h_pKernel, nMaskSize * sizeof(d_pKernel[0]), + cudaMemcpyHostToDevice); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + // copy src to dst + NppStatus ret = + nppiFilterRow_8u_C1R(d_pSrc, nSrcStep, d_pDst, nDstStep, oROI, d_pKernel, + nMaskSize, nAnchor, nDivisor); + assert(ret == NPP_NO_ERROR); + Npp8u* h_imgres = new Npp8u[dimgpix]; + err = cudaMemcpy(h_imgres, d_pDst, dimgsize, cudaMemcpyDeviceToHost); + if (err != cudaSuccess) { + fprintf(stderr, "Cuda error %d\n", __LINE__); + return 1; + } + // test for filtering + for (int i = 0; i < dimgpix; i++) { + if (h_imgres[i] != (pixval * pixval * nMaskSize)) { + fprintf(stderr, "h_imgres at index %d failed to match\n", i); + return 1; + } + } + + return 0; +} diff --git a/Tests/Cuda/StaticRuntimePlusToolkit/shared.cpp b/Tests/Cuda/StaticRuntimePlusToolkit/shared.cpp new file mode 100644 index 0000000..9967b66 --- /dev/null +++ b/Tests/Cuda/StaticRuntimePlusToolkit/shared.cpp @@ -0,0 +1,8 @@ + +int curand_main(); +int nppif_main(); + +int shared_version() +{ + return curand_main() == 0 && nppif_main() == 0; +} diff --git a/Tests/Cuda/StaticRuntimePlusToolkit/static.cpp b/Tests/Cuda/StaticRuntimePlusToolkit/static.cpp new file mode 100644 index 0000000..ca7eb4c --- /dev/null +++ b/Tests/Cuda/StaticRuntimePlusToolkit/static.cpp @@ -0,0 +1,8 @@ + +int curand_main(); +int nppif_main(); + +int static_version() +{ + return curand_main() == 0 && nppif_main() == 0; +} diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt index 00fd7d2..ba9bf04 100644 --- a/Tests/CudaOnly/WithDefs/CMakeLists.txt +++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt @@ -28,7 +28,7 @@ target_compile_options(CudaOnlyWithDefs PRIVATE -DFLAG_COMPILE_LANG_$<COMPILE_LANGUAGE> -DFLAG_LANG_IS_CUDA=$<COMPILE_LANGUAGE:CUDA> - -Xcompiler=-DHOST_DEFINE + --compiler-options=-DHOST_DEFINE $<$<CONFIG:DEBUG>:$<BUILD_INTERFACE:${debug_compile_flags}>> ) diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index 70e8476..196fea3 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -535,6 +535,7 @@ set_property(SOURCE "${gen_file}" PROPERTY SYMBOLIC ON) add_custom_target(command_expand_lists ALL DEPENDS "${gen_file}") set_property(TARGET command_expand_lists PROPERTY CMPARGS "${cmp_args}") +# This also tests that `./` is squeezed out of the resulting path. set(depends_path "./depended_upon_path.txt") add_custom_command( @@ -549,3 +550,19 @@ add_custom_command( ) add_custom_target(depends_on_path ALL DEPENDS "depends_on_path.txt") + +add_custom_command( + OUTPUT "depends_on_in_source_path.txt" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/main.cxx" depends_on_in_source_path.txt + DEPENDS main.cxx +) + +add_custom_target(depends_on_in_source_path ALL DEPENDS "depends_on_in_source_path.txt") + +add_custom_command( + OUTPUT "depends_on_in_rel_source_path.txt" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/main.cxx" depends_on_in_rel_source_path.txt + DEPENDS ./main.cxx +) + +add_custom_target(depends_on_in_rel_source_path ALL DEPENDS "depends_on_in_rel_source_path.txt") diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 4d411a9..387fe6b 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -156,6 +156,7 @@ target_link_libraries(testLibDepends PRIVATE testStaticLibRequiredPrivate) cmake_policy(POP) cmake_policy(PUSH) +cmake_policy(SET CMP0022 NEW) cmake_policy(SET CMP0079 NEW) add_library(TopDirLib STATIC testTopDirLib.c) add_subdirectory(SubDirLinkA) @@ -240,6 +241,10 @@ set_property(TARGET testLibRequired APPEND PROPERTY ) include(GenerateExportHeader) +# Test deprecation of imported library +add_library(testLibDeprecation STATIC testLib1.c) +set_property(TARGET testLibDeprecation PROPERTY DEPRECATION "Deprecated version. Please use latest version") + add_subdirectory(renamed) add_library(testSharedLibRequired SHARED testSharedLibRequired.cpp) @@ -515,6 +520,7 @@ install( testExe2lib testLib4lib testLib4libdbg testLib4libopt testLib6 testLib7 testLib8 testLib9 + testLibDeprecation testLibCycleA testLibCycleB testLibNoSONAME cmp0022NEW cmp0022OLD @@ -585,6 +591,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3 export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib testLib8 testLib9 testLib9ObjPub testLib9ObjPriv testLib9ObjIface + testLibDeprecation testLib4lib testLib4libdbg testLib4libopt testLibCycleA testLibCycleB testLibNoSONAME diff --git a/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt b/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt index 1c3c9dc..1aa41d2 100644 --- a/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt +++ b/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(SubDirLinkAImported IMPORTED INTERFACE) target_compile_definitions(SubDirLinkAImported INTERFACE DEF_SubDirLinkAImportedForExport) -target_link_libraries(TopDirLib PUBLIC SubDirLinkAImported) +target_link_libraries(TopDirLib PUBLIC debug "$<1:SubDirLinkAImported;SubDirLinkAImported>" optimized "$<1:SubDirLinkAImported;SubDirLinkAImported>") add_library(SubDirLinkA STATIC SubDirLinkA.c) diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index c5304da..3cb3833 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -51,6 +51,12 @@ checkForProperty(bld_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1") checkForProperty(exp_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1") checkForProperty(bld_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2") checkForProperty(exp_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2") +checkForProperty(bld_testLibDeprecation "DEPRECATION" "Deprecated version. Please use latest version") +checkForProperty(exp_testLibDeprecation "DEPRECATION" "Deprecated version. Please use latest version") + +# Try linking to a deprecated library +target_link_libraries(imp_testExe1 exp_testLibDeprecation) + # Try linking to a library imported from the install tree. target_link_libraries(imp_testExe1 diff --git a/Tests/FindLibXml2/Test/CMakeLists.txt b/Tests/FindLibXml2/Test/CMakeLists.txt index df5d8c3..041cc13 100644 --- a/Tests/FindLibXml2/Test/CMakeLists.txt +++ b/Tests/FindLibXml2/Test/CMakeLists.txt @@ -14,3 +14,7 @@ add_executable(test_var main.c) target_include_directories(test_var PRIVATE ${LIBXML2_INCLUDE_DIRS}) target_link_libraries(test_var PRIVATE ${LIBXML2_LIBRARIES}) add_test(NAME test_var COMMAND test_var) + +add_test(NAME xmllint_tgt COMMAND LibXml2::xmllint --version) + +add_test(NAME xmllint_var COMMAND ${LIBXML2_XMLLINT_EXECUTABLE} --version) diff --git a/Tests/FindPython/CMakeLists.txt b/Tests/FindPython/CMakeLists.txt index 5e20dd3..bfec986 100644 --- a/Tests/FindPython/CMakeLists.txt +++ b/Tests/FindPython/CMakeLists.txt @@ -148,6 +148,34 @@ if(CMake_TEST_FindPython) --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) + if (CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") + add_test(NAME FindPython.Interpreter.SOABI COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/SOABI" + "${CMake_BINARY_DIR}/Tests/FindPython/SOABI.Interpreter" + ${build_generator_args} + --build-project TestSOABI + --build-options ${build_options} "-Dbuild_generator_args=${build_generator_args}" + "-DCMake_SOURCE_DIR=${CMake_SOURCE_DIR}" + "-DCMake_BINARY_DIR=${CMake_BINARY_DIR}" + "-DCMake_TEST_FindPython_COMPONENT=Interpreter" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + add_test(NAME FindPython.Development.SOABI COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/SOABI" + "${CMake_BINARY_DIR}/Tests/FindPython/SOABI.Development" + ${build_generator_args} + --build-project TestSOABI + --build-options ${build_options} "-Dbuild_generator_args=${build_generator_args}" + "-DCMake_SOURCE_DIR=${CMake_SOURCE_DIR}" + "-DCMake_BINARY_DIR=${CMake_BINARY_DIR}" + "-DCMake_TEST_FindPython_COMPONENT=Development" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + endif() endif() if(CMake_TEST_FindPython_NumPy) diff --git a/Tests/FindPython/SOABI/CMakeLists.txt b/Tests/FindPython/SOABI/CMakeLists.txt new file mode 100644 index 0000000..aea2baf --- /dev/null +++ b/Tests/FindPython/SOABI/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.1) + +project(TestSOABI C) + +find_package(Python3 COMPONENTS ${CMake_TEST_FindPython_COMPONENT}) +if (NOT Python3_FOUND) + message (FATAL_ERROR "Fail to found Python 3") +endif() + +if(NOT DEFINED Python3_SOABI) + message(FATAL_ERROR "Python3_SOABI for ${CMake_TEST_FindPython_COMPONENT} not found") +endif() diff --git a/Tests/QtAutogen/MocCMP0100/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/CMakeLists.txt new file mode 100644 index 0000000..559cffe --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.10) +project(MocCMP0100) +include("../AutogenCoreTest.cmake") + +set(CMAKE_AUTOMOC ON) +set(CSD ${CMAKE_CURRENT_SOURCE_DIR}) + +add_subdirectory(OLD) +add_subdirectory(NEW) diff --git a/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt new file mode 100644 index 0000000..654b31e --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16) +cmake_policy(SET CMP0100 NEW) + +add_executable(mocCMP0100New + ${CSD}/main.cpp + ${CSD}/Obj.hh # Manually include Obj.hh + ${CSD}/Obj.cpp + ${CSD}/Obj2.cpp # Let AUTOMOC detect Obj2.hh +) +target_link_libraries(mocCMP0100New ${QT_LIBRARIES}) diff --git a/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt new file mode 100644 index 0000000..2be0535 --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.16) +cmake_policy(SET CMP0100 OLD) + +# Generate moc files externally. +# If AUTOMOC generates the header moc files as well +# (it should not in OLD behavior), the test will fail with a +# multiple definition error when linking the executable. +qtx_wrap_cpp(mocCMP0100OldMoc ${CSD}/Obj.hh ${CSD}/Obj2.hh) +qtx_generate_moc(${CBD}/Obj.cpp ${CMAKE_CURRENT_BINARY_DIR}/Obj.moc) +qtx_generate_moc(${CBD}/Obj2.cpp ${CMAKE_CURRENT_BINARY_DIR}/Obj2.moc) + +# Make sure AUTOGEN file skipping is disabled +set_source_files_properties( + ${CSD}/Obj.hh + ${CBD}/Obj.cpp + ${CSD}/Obj2.hh + ${CBD}/Obj2.cpp + PROPERTIES + SKIP_AUTOGEN OFF + SKIP_AUTOMOC OFF +) + +add_executable(mocCMP0100Old + ${CSD}/main.cpp + ${CSD}/Obj.hh # Manually include Obj.hh + ${CSD}/Obj.cpp + ${CSD}/Obj2.cpp # Let AUTOMOC detect Obj2.hh + ${mocCMP0100OldMoc} +) +target_link_libraries(mocCMP0100Old ${QT_LIBRARIES}) +target_include_directories(mocCMP0100Old PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/Tests/QtAutogen/MocCMP0100/Obj.cpp b/Tests/QtAutogen/MocCMP0100/Obj.cpp new file mode 100644 index 0000000..bb6d0a0 --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/Obj.cpp @@ -0,0 +1,31 @@ +#include "Obj.hh" + +#include <QObject> + +class ObjPrivate : public QObject +{ + Q_OBJECT +public: + ObjPrivate(); + ~ObjPrivate(); +}; + +ObjPrivate::ObjPrivate() +{ +} + +ObjPrivate::~ObjPrivate() +{ +} + +Obj::Obj() + : d(new ObjPrivate) +{ +} + +Obj::~Obj() +{ + delete d; +} + +#include "Obj.moc" diff --git a/Tests/QtAutogen/MocCMP0100/Obj.hh b/Tests/QtAutogen/MocCMP0100/Obj.hh new file mode 100644 index 0000000..940bfc2 --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/Obj.hh @@ -0,0 +1,20 @@ +#ifndef OBJ_HH +#define OBJ_HH + +#include <QObject> + +// Qt enabled private class +class ObjPrivate; +// Qt enabled class +class Obj : public QObject +{ + Q_OBJECT +public: + Obj(); + ~Obj(); + +private: + ObjPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/MocCMP0100/Obj2.cpp b/Tests/QtAutogen/MocCMP0100/Obj2.cpp new file mode 100644 index 0000000..8a359ad --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/Obj2.cpp @@ -0,0 +1,31 @@ +#include "Obj2.hh" + +#include <QObject> + +class Obj2Private : public QObject +{ + Q_OBJECT +public: + Obj2Private(); + ~Obj2Private(); +}; + +Obj2Private::Obj2Private() +{ +} + +Obj2Private::~Obj2Private() +{ +} + +Obj2::Obj2() + : d(new Obj2Private) +{ +} + +Obj2::~Obj2() +{ + delete d; +} + +#include "Obj2.moc" diff --git a/Tests/QtAutogen/MocCMP0100/Obj2.hh b/Tests/QtAutogen/MocCMP0100/Obj2.hh new file mode 100644 index 0000000..1c74cdd --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/Obj2.hh @@ -0,0 +1,20 @@ +#ifndef OBJ2_HH +#define OBJ2_HH + +#include <QObject> + +// Qt enabled private class +class Obj2Private; +// Qt enabled class +class Obj2 : public QObject +{ + Q_OBJECT +public: + Obj2(); + ~Obj2(); + +private: + Obj2Private* const d; +}; + +#endif diff --git a/Tests/QtAutogen/MocCMP0100/main.cpp b/Tests/QtAutogen/MocCMP0100/main.cpp new file mode 100644 index 0000000..17061da --- /dev/null +++ b/Tests/QtAutogen/MocCMP0100/main.cpp @@ -0,0 +1,9 @@ +#include "Obj.hh" +#include "Obj2.hh" + +int main(int argv, char** args) +{ + Obj obj; + Obj2 obj2; + return 0; +} diff --git a/Tests/QtAutogen/SameName/CMakeLists.txt b/Tests/QtAutogen/SameName/CMakeLists.txt index cd29a2a..4ce8dbd 100644 --- a/Tests/QtAutogen/SameName/CMakeLists.txt +++ b/Tests/QtAutogen/SameName/CMakeLists.txt @@ -1,7 +1,10 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16.0) project(SameName) include("../AutogenGuiTest.cmake") +# Process .hh headers in AUTOMOC +cmake_policy(SET CMP0100 NEW) + # Test AUTOMOC and AUTORCC on source files with the same name # but in different subdirectories @@ -18,6 +21,7 @@ add_executable(sameName ccc/data.qrc item.cpp object.h + object.hh object.h++ object.hpp object.hxx diff --git a/Tests/QtAutogen/SameName/main.cpp b/Tests/QtAutogen/SameName/main.cpp index 19a6f6d..725f4cd 100644 --- a/Tests/QtAutogen/SameName/main.cpp +++ b/Tests/QtAutogen/SameName/main.cpp @@ -6,6 +6,7 @@ #include "item.hpp" #include "object.h" #include "object.h++" +#include "object.hh" #include "object.hpp" #include "object.hxx" #include "object_upper_ext.H" @@ -21,6 +22,7 @@ int main(int argv, char** args) ::ccc::Item ccc_item; // Object instances ::Object_h obj_h; + ::Object_hh obj_hh; ::Object_hplpl obj_hplpl; ::Object_hpp obj_hpp; ::Object_hxx obj_hxx; diff --git a/Tests/QtAutogen/SameName/object.hh b/Tests/QtAutogen/SameName/object.hh new file mode 100644 index 0000000..3e16f83 --- /dev/null +++ b/Tests/QtAutogen/SameName/object.hh @@ -0,0 +1,13 @@ +#ifndef OBJECT_HH +#define OBJECT_HH + +#include <QObject> + +class Object_hh : public QObject +{ + Q_OBJECT + Q_SLOT + void go(){}; +}; + +#endif diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake index 2b001d4..a19a9ae 100644 --- a/Tests/QtAutogen/Tests.cmake +++ b/Tests/QtAutogen/Tests.cmake @@ -32,6 +32,7 @@ ADD_AUTOGEN_TEST(UicSkipSource) if(QT_TEST_ALLOW_QT_MACROS) ADD_AUTOGEN_TEST(MocCMP0071) + ADD_AUTOGEN_TEST(MocCMP0100) ADD_AUTOGEN_TEST(MocInclude) ADD_AUTOGEN_TEST(MocIncludeSymlink) ADD_AUTOGEN_TEST(MocSkipSource) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 1939612..d302fe3 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -140,6 +140,9 @@ if(CMAKE_GENERATOR MATCHES "Ninja") if(CMake_TEST_Qt5 AND Qt5Core_FOUND) list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1) endif() + if(DEFINED CMake_TEST_CUDA) + list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) + endif() add_RunCMake_test(NinjaMultiConfig) endif() add_RunCMake_test(CTest) @@ -217,6 +220,7 @@ add_RunCMake_test(ScriptMode) add_RunCMake_test(Swift -DCMAKE_Swift_COMPILER=${CMAKE_Swift_COMPILER}) add_RunCMake_test(TargetObjects) add_RunCMake_test(TargetSources) +add_RunCMake_test(TargetProperties) add_RunCMake_test(ToolchainFile) add_RunCMake_test(find_dependency) add_RunCMake_test(CompileDefinitions) @@ -348,6 +352,7 @@ add_RunCMake_test(alias_targets) add_RunCMake_test(interface_library) add_RunCMake_test(no_install_prefix) add_RunCMake_test(configure_file) +add_RunCMake_test(CTestTimeout -DTIMEOUT=${CTestTestTimeout_TIME}) add_RunCMake_test(CTestTimeoutAfterMatch) # ctresalloc links against CMakeLib and CTestLib, which means it can't be built @@ -449,7 +454,7 @@ add_RunCMake_test(target_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_I add_RunCMake_test(target_compile_definitions) add_RunCMake_test(target_compile_features) -add_RunCMake_test(target_compile_options) +add_RunCMake_test(target_compile_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) add_RunCMake_test(target_include_directories) add_RunCMake_test(target_sources) add_RunCMake_test(CheckModules) @@ -543,6 +548,9 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") if(CMAKE_Fortran_COMPILER) list(APPEND CompilerLauncher_ARGS -DCMake_TEST_Fortran=1) endif() + if (APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU") + list(APPEND CompilerLauncher_ARGS -DCMake_TEST_OBJC=1) + endif() add_RunCMake_test(CompilerLauncher) add_RunCMake_test(ctest_labels_for_subprojects) endif() @@ -596,6 +604,9 @@ set(cpack_tests STGZ External ) +if(APPLE) + list(APPEND cpack_tests DragNDrop) +endif() add_RunCMake_test_group(CPack "${cpack_tests}") # add a test to make sure symbols are exported from a shared library # for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used diff --git a/Tests/RunCMake/CPack/DragNDrop/Helpers.cmake b/Tests/RunCMake/CPack/DragNDrop/Helpers.cmake new file mode 100644 index 0000000..023e597 --- /dev/null +++ b/Tests/RunCMake/CPack/DragNDrop/Helpers.cmake @@ -0,0 +1,54 @@ +set(ALL_FILES_GLOB "*.dmg") + +function(getPackageContent FILE RESULT_VAR) + get_filename_component(path_ "${FILE}" DIRECTORY) + file(REMOVE_RECURSE "${path_}/content") + file(MAKE_DIRECTORY "${path_}/content") + execute_process(COMMAND ${HDIUTIL_EXECUTABLE} attach -mountroot ${path_}/content -nobrowse ${FILE} + RESULT_VARIABLE attach_result_ + ERROR_VARIABLE attach_error_ + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(attach_result_) + message(FATAL_ERROR "Failed to attach DMG: '${attach_result_}';" + " '${attach_error_}'.") + endif() + + file(GLOB_RECURSE package_content_ LIST_DIRECTORIES true RELATIVE + "${path_}/content" "${path_}/content/*") + # Some versions of macOS have .Trashes, others do not. + list(FILTER package_content_ EXCLUDE REGEX "/.Trashes$") + set(${RESULT_VAR} "${package_content_}" PARENT_SCOPE) + + execute_process(COMMAND ${HDIUTIL_EXECUTABLE} detach ${path_}/content/volume-name + RESULT_VARIABLE detach_result_ + ERROR_VARIABLE detach_error_ + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(detach_result_) + message(FATAL_ERROR "Failed to detach DMG: '${detach_result_}';" + " '${detach_error_}'.") + endif() +endfunction() + +function(getPackageNameGlobexpr NAME COMPONENT VERSION REVISION FILE_NO RESULT_VAR) + if(COMPONENT) + set(COMPONENT "-${COMPONENT}") + endif() + + set(${RESULT_VAR} "${NAME}-${VERSION}-Darwin${COMPONENT}.dmg" PARENT_SCOPE) +endfunction() + +function(getPackageContentList FILE RESULT_VAR) + getPackageContent("${FILE}" package_content_) + + set(${RESULT_VAR} "${package_content_}" PARENT_SCOPE) +endfunction() + +function(toExpectedContentList FILE_NO CONTENT_VAR) + set(prefix_ "volume-name") + list(TRANSFORM ${CONTENT_VAR} PREPEND "${prefix_}" OUTPUT_VARIABLE prepared_) + list(APPEND prepared_ "${prefix_}") + + set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/DragNDrop/Prerequirements.cmake b/Tests/RunCMake/CPack/DragNDrop/Prerequirements.cmake new file mode 100644 index 0000000..f0aaf2c --- /dev/null +++ b/Tests/RunCMake/CPack/DragNDrop/Prerequirements.cmake @@ -0,0 +1,8 @@ +function(get_test_prerequirements found_var config_file) + find_program(HDIUTIL_EXECUTABLE hdiutil) + + if(HDIUTIL_EXECUTABLE) + file(WRITE "${config_file}" "set(HDIUTIL_EXECUTABLE \"${HDIUTIL_EXECUTABLE}\")") + set(${found_var} true PARENT_SCOPE) + endif() +endfunction() diff --git a/Tests/RunCMake/CPack/DragNDrop/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/DragNDrop/packaging_COMPONENT_default.cmake new file mode 100644 index 0000000..aa6c8ff --- /dev/null +++ b/Tests/RunCMake/CPack/DragNDrop/packaging_COMPONENT_default.cmake @@ -0,0 +1,3 @@ +set(CPACK_COMPONENTS_GROUPING "IGNORE") +set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK ON) +set(CPACK_DMG_VOLUME_NAME "volume-name") diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 76d16e1..0fb0cc4 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -5,7 +5,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake") # run_cpack_test args: TEST_NAME "GENERATORS" RUN_CMAKE_BUILD_STEP "PACKAGING_TYPES" run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM.CUSTOM_BINARY_SPEC_FILE" false "MONOLITHIC;COMPONENT") -run_cpack_test(CUSTOM_NAMES "RPM.CUSTOM_NAMES;DEB.CUSTOM_NAMES;TGZ" true "COMPONENT") +run_cpack_test(CUSTOM_NAMES "RPM.CUSTOM_NAMES;DEB.CUSTOM_NAMES;TGZ;DragNDrop" true "COMPONENT") run_cpack_test(DEBUGINFO "RPM.DEBUGINFO;DEB.DEBUGINFO" true "COMPONENT") run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM.DEFAULT_PERMISSIONS;DEB.DEFAULT_PERMISSIONS" false "MONOLITHIC;COMPONENT") run_cpack_test(DEPENDENCIES "RPM.DEPENDENCIES;DEB.DEPENDENCIES" true "COMPONENT") @@ -38,7 +38,7 @@ run_cpack_test(DEB_PACKAGE_VERSION_BACK_COMPATIBILITY "DEB.DEB_PACKAGE_VERSION_B run_cpack_test_subtests(EXTERNAL "none;good;good_multi;bad_major;bad_minor;invalid_good;invalid_bad;stage_and_package" "External" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests( DEB_DESCRIPTION - "CPACK_DEBIAN_PACKAGE_DESCRIPTION;CPACK_PACKAGE_DESCRIPTION;CPACK_PACKAGE_DESCRIPTION_FILE" + "CPACK_DEBIAN_PACKAGE_DESCRIPTION;CPACK_PACKAGE_DESCRIPTION;CPACK_PACKAGE_DESCRIPTION_FILE;CPACK_NO_PACKAGE_DESCRIPTION" "DEB.DEB_DESCRIPTION" false "MONOLITHIC;COMPONENT" diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake index 07226df..9ac19e2 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake @@ -12,4 +12,7 @@ if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM") elseif(GENERATOR_TYPE STREQUAL "TGZ") set(EXPECTED_FILE_2 "second.tar.gz") set(EXPECTED_FILE_3 "pkg_3_abc.tar.gz") +elseif(GENERATOR_TYPE STREQUAL "DragNDrop") + set(EXPECTED_FILE_2 "second.dmg") + set(EXPECTED_FILE_3 "pkg_3_abc.dmg") endif() diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake index 4c20e41..899258e 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake @@ -10,6 +10,9 @@ if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM") elseif(GENERATOR_TYPE STREQUAL "TGZ") set(CPACK_ARCHIVE_PKG_2_FILE_NAME "second") set(CPACK_ARCHIVE_PKG_3_FILE_NAME "pkg_3_abc") +elseif(GENERATOR_TYPE STREQUAL "DragNDrop") + set(CPACK_DMG_PKG_2_FILE_NAME "second") + set(CPACK_DMG_PKG_3_FILE_NAME "pkg_3_abc") endif() install(FILES CMakeLists.txt DESTINATION foo COMPONENT pkg_1) diff --git a/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake index e9ac13a..a8e2e7a 100644 --- a/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake @@ -56,6 +56,8 @@ set(_expected_description [[ Description: This is the summary line # workaround required! if(RunCMake_SUBTEST_SUFFIX STREQUAL "CPACK_PACKAGE_DESCRIPTION_FILE" AND PACKAGING_TYPE STREQUAL "MONOLITHIC") string(APPEND _expected_description "\n ." ) +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "CPACK_NO_PACKAGE_DESCRIPTION") + set(_expected_description [[ Description: This is the summary line]]) endif() foreach(_file_no RANGE 1 ${EXPECTED_FILES_COUNT}) diff --git a/Tests/RunCMake/CTest/CMakeCTestArguments-test-check.cmake b/Tests/RunCMake/CTest/CMakeCTestArguments-test-check.cmake new file mode 100644 index 0000000..3e05953 --- /dev/null +++ b/Tests/RunCMake/CTest/CMakeCTestArguments-test-check.cmake @@ -0,0 +1,4 @@ +set(log "${RunCMake_TEST_BINARY_DIR}/output-log.txt") +if(NOT EXISTS "${log}") + set(RunCMake_TEST_FAILED "The expected output log file is missing:\n ${log}") +endif() diff --git a/Tests/RunCMake/CTest/CMakeCTestArguments.cmake b/Tests/RunCMake/CTest/CMakeCTestArguments.cmake new file mode 100644 index 0000000..37f2933 --- /dev/null +++ b/Tests/RunCMake/CTest/CMakeCTestArguments.cmake @@ -0,0 +1,2 @@ +include(CTest) +add_test(NAME CMakeCTestArguments COMMAND ${CMAKE_COMMAND} -E echo CMakeCTestArguments) diff --git a/Tests/RunCMake/CTest/RunCMakeTest.cmake b/Tests/RunCMake/CTest/RunCMakeTest.cmake index 1392240..761224a 100644 --- a/Tests/RunCMake/CTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTest/RunCMakeTest.cmake @@ -5,3 +5,16 @@ run_cmake(BeforeProject) unset(RunCMake_TEST_OPTIONS) run_cmake(NotOn) + +function(run_CMakeCTestArguments) + run_cmake_with_options(CMakeCTestArguments "-DCMAKE_CTEST_ARGUMENTS=--quiet\\;--output-log\\;output-log.txt") + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMakeCTestArguments-build) + if(RunCMake_GENERATOR MATCHES "Make|Ninja") + set(test "test") + else() + set(test "RUN_TESTS") + endif() + run_cmake_command(CMakeCTestArguments-test ${CMAKE_COMMAND} --build . --config Debug --target "${test}") +endfunction() +run_CMakeCTestArguments() diff --git a/Tests/RunCMake/CTestTimeout/Basic-stdout.txt b/Tests/RunCMake/CTestTimeout/Basic-stdout.txt new file mode 100644 index 0000000..30ed178 --- /dev/null +++ b/Tests/RunCMake/CTestTimeout/Basic-stdout.txt @@ -0,0 +1,6 @@ +Test project [^ +]*/Tests/RunCMake/CTestTimeout/Basic-build + Start 1: TestTimeout +1/1 Test #1: TestTimeout ......................\*\*\*Timeout +[0-9.]+ sec ++ +0% tests passed, 1 tests failed out of 1 diff --git a/Tests/RunCMake/CTestTimeout/CMakeLists.txt.in b/Tests/RunCMake/CTestTimeout/CMakeLists.txt.in new file mode 100644 index 0000000..20faa94 --- /dev/null +++ b/Tests/RunCMake/CTestTimeout/CMakeLists.txt.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.16) +project(CTestTest@CASE_NAME@ C) +include(CTest) + +add_executable(TestTimeout TestTimeout.c) + +if(NOT TIMEOUT) + set(TIMEOUT 4) +endif() +target_compile_definitions(TestTimeout PRIVATE TIMEOUT=${TIMEOUT}) + +add_test(NAME TestTimeout COMMAND TestTimeout) +set_property(TEST TestTimeout PROPERTY TIMEOUT ${TIMEOUT}) + +@CASE_CMAKELISTS_SUFFIX_CODE@ diff --git a/Tests/RunCMake/CTestTimeout/Fork-stdout.txt b/Tests/RunCMake/CTestTimeout/Fork-stdout.txt new file mode 100644 index 0000000..284e4b1 --- /dev/null +++ b/Tests/RunCMake/CTestTimeout/Fork-stdout.txt @@ -0,0 +1,6 @@ +Test project [^ +]*/Tests/RunCMake/CTestTimeout/Fork-build + Start 1: TestTimeout +1/1 Test #1: TestTimeout ......................\*\*\*Timeout +[0-9.]+ sec ++ +0% tests passed, 1 tests failed out of 1 diff --git a/Tests/RunCMake/CTestTimeout/RunCMakeTest.cmake b/Tests/RunCMake/CTestTimeout/RunCMakeTest.cmake new file mode 100644 index 0000000..7e96b6d --- /dev/null +++ b/Tests/RunCMake/CTestTimeout/RunCMakeTest.cmake @@ -0,0 +1,22 @@ +include(RunCTest) + +if(NOT TIMEOUT) + # Give the process time to load and start running. + set(TIMEOUT 4) +endif() + +function(run_ctest_timeout CASE_NAME) + configure_file(${RunCMake_SOURCE_DIR}/TestTimeout.c + ${RunCMake_BINARY_DIR}/${CASE_NAME}/TestTimeout.c COPYONLY) + run_ctest(${CASE_NAME}) +endfunction() + +run_ctest_timeout(Basic) + +if(UNIX) + string(CONCAT CASE_CMAKELISTS_SUFFIX_CODE [[ + target_compile_definitions(TestTimeout PRIVATE FORK) +]]) + run_ctest_timeout(Fork) + unset(CASE_CMAKELISTS_SUFFIX_CODE) +endif() diff --git a/Tests/RunCMake/CTestTimeout/TestTimeout.c b/Tests/RunCMake/CTestTimeout/TestTimeout.c new file mode 100644 index 0000000..5a008a7 --- /dev/null +++ b/Tests/RunCMake/CTestTimeout/TestTimeout.c @@ -0,0 +1,24 @@ +#if defined(_WIN32) +# include <windows.h> +#else +# include <unistd.h> +#endif + +#include <stdio.h> + +int main(void) +{ +#ifdef FORK + pid_t pid = fork(); + if (pid != 0) { + return 0; + } +#endif + +#if defined(_WIN32) + Sleep((TIMEOUT + 4) * 1000); +#else + sleep((TIMEOUT + 4)); +#endif + return 0; +} diff --git a/Tests/RunCMake/CTestTimeout/test.cmake.in b/Tests/RunCMake/CTestTimeout/test.cmake.in new file mode 100644 index 0000000..be2625b --- /dev/null +++ b/Tests/RunCMake/CTestTimeout/test.cmake.in @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.16) +@CASE_TEST_PREFIX_CODE@ + +set(CTEST_SITE "test-site") +set(CTEST_BUILD_NAME "test-build-name") +set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@") +set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build") +set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") + +ctest_start(Experimental) +ctest_configure(OPTIONS "-DTIMEOUT=@TIMEOUT@") +ctest_build() +ctest_test() diff --git a/Tests/RunCMake/CommandLine/trace-json-v1-check.py b/Tests/RunCMake/CommandLine/trace-json-v1-check.py index d69ac8f..14febaf 100755 --- a/Tests/RunCMake/CommandLine/trace-json-v1-check.py +++ b/Tests/RunCMake/CommandLine/trace-json-v1-check.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import argparse import json import os import sys @@ -8,15 +7,21 @@ import sys if sys.version_info[0] >= 3: unicode = str -parser = argparse.ArgumentParser(description='Checks the trace output') -parser.add_argument('-e', '--expand', action='store_true') -parser.add_argument('trace', type=str, help='the trace file to check') +trace_file = None +expand = False -args = parser.parse_args() +for i in sys.argv[1:]: + if trace_file is None and not i.startswith('-'): + trace_file = i + continue -assert os.path.exists(args.trace) + if i in ['-e', '--expand']: + expand = True -if args.expand: +assert trace_file is not None +assert os.path.exists(trace_file) + +if expand: msg_args = ['STATUS', 'fff', 'fff;sss; SPACES !!! ', ' 42 space in string!', ' SPACES !!! '] else: msg_args = ['STATUS', 'fff', '${ASDF}', ' ${FOO} ${BAR}', ' SPACES !!! '] @@ -44,7 +49,7 @@ required_traces = [ }, ] -with open(args.trace, 'r') as fp: +with open(trace_file, 'r') as fp: # Check for version (must be the first document) vers = json.loads(fp.readline()) assert sorted(vers.keys()) == ['version'] @@ -60,8 +65,8 @@ with open(args.trace, 'r') as fp: assert isinstance(line['file'], unicode) assert isinstance(line['line'], int) - for i in required_traces: - if i['cmd'] == line['cmd'] and i['args'] == line['args']: - i['found'] = True + for j in required_traces: + if j['cmd'] == line['cmd'] and j['args'] == line['args']: + j['found'] = True assert all([x.get('found', False) == True for x in required_traces]) diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJC-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-common.cmake b/Tests/RunCMake/CompilerLauncher/OBJC-common.cmake new file mode 100644 index 0000000..7b565f4 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-common.cmake @@ -0,0 +1,3 @@ +enable_language(OBJC) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.m) diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJC-env-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJC-env-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-env-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-env.cmake b/Tests/RunCMake/CompilerLauncher/OBJC-env.cmake new file mode 100644 index 0000000..949e88d --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-env.cmake @@ -0,0 +1 @@ +include(OBJC-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJC-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/OBJC-launch-env.cmake new file mode 100644 index 0000000..1cf13d3 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJC-env.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/OBJC-launch.cmake b/Tests/RunCMake/CompilerLauncher/OBJC-launch.cmake new file mode 100644 index 0000000..43e8521 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJC.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/OBJC.cmake b/Tests/RunCMake/CompilerLauncher/OBJC.cmake new file mode 100644 index 0000000..3374e82 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJC.cmake @@ -0,0 +1,2 @@ +set(CMAKE_OBJC_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +include(OBJC-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJCXX-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-common.cmake b/Tests/RunCMake/CompilerLauncher/OBJCXX-common.cmake new file mode 100644 index 0000000..e2ee4eb --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-common.cmake @@ -0,0 +1,3 @@ +enable_language(OBJCXX) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.mm) diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJCXX-env-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJCXX-env-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-env-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-env.cmake b/Tests/RunCMake/CompilerLauncher/OBJCXX-env.cmake new file mode 100644 index 0000000..3ed966d --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-env.cmake @@ -0,0 +1 @@ +include(OBJCXX-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/OBJCXX-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/OBJCXX-launch-env.cmake new file mode 100644 index 0000000..04c916a --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJCXX-env.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX-launch.cmake b/Tests/RunCMake/CompilerLauncher/OBJCXX-launch.cmake new file mode 100644 index 0000000..5a54bff --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJCXX.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/OBJCXX.cmake b/Tests/RunCMake/CompilerLauncher/OBJCXX.cmake new file mode 100644 index 0000000..993ec90 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/OBJCXX.cmake @@ -0,0 +1,2 @@ +set(CMAKE_OBJCXX_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +include(OBJCXX-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake index e9543f1..69fff20 100644 --- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake @@ -29,6 +29,9 @@ endif() if(CMake_TEST_Fortran) list(APPEND langs Fortran) endif() +if(CMake_TEST_OBJC) + list(APPEND langs OBJC OBJCXX) +endif() foreach(lang ${langs}) run_compiler_launcher(${lang}) diff --git a/Tests/RunCMake/CompilerLauncher/main.m b/Tests/RunCMake/CompilerLauncher/main.m new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/main.m @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/CompilerLauncher/main.mm b/Tests/RunCMake/CompilerLauncher/main.mm new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/main.mm @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/FPHSA/FindNameMismatch.cmake b/Tests/RunCMake/FPHSA/FindNameMismatch.cmake new file mode 100644 index 0000000..540aa67 --- /dev/null +++ b/Tests/RunCMake/FPHSA/FindNameMismatch.cmake @@ -0,0 +1,4 @@ +set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}") +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(NAMEMISMATCH REQUIRED_VARS "${CMAKE_FIND_PACKAGE_NAME}_MODULE") +set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1) diff --git a/Tests/RunCMake/FPHSA/FindNameMismatchOld.cmake b/Tests/RunCMake/FPHSA/FindNameMismatchOld.cmake new file mode 100644 index 0000000..d155ea7 --- /dev/null +++ b/Tests/RunCMake/FPHSA/FindNameMismatchOld.cmake @@ -0,0 +1,4 @@ +set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}") +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(NAMEMISMATCH "old signature" "${CMAKE_FIND_PACKAGE_NAME}_MODULE") +set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1) diff --git a/Tests/RunCMake/FPHSA/FindNameMismatchSuppressed.cmake b/Tests/RunCMake/FPHSA/FindNameMismatchSuppressed.cmake new file mode 100644 index 0000000..042a59a --- /dev/null +++ b/Tests/RunCMake/FPHSA/FindNameMismatchSuppressed.cmake @@ -0,0 +1,6 @@ +set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}") +include(FindPackageHandleStandardArgs) +set(FPHSA_NAME_MISMATCHED 1) +find_package_handle_standard_args(NAMEMISMATCH "old signature" "${CMAKE_FIND_PACKAGE_NAME}_MODULE") +unset(FPHSA_NAME_MISMATCHED) +set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1) diff --git a/Tests/RunCMake/FPHSA/FindNameMismatchSuppressedArg.cmake b/Tests/RunCMake/FPHSA/FindNameMismatchSuppressedArg.cmake new file mode 100644 index 0000000..6a0e964 --- /dev/null +++ b/Tests/RunCMake/FPHSA/FindNameMismatchSuppressedArg.cmake @@ -0,0 +1,4 @@ +set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}") +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(NAMEMISMATCH NAME_MISMATCHED REQUIRED_VARS "${CMAKE_FIND_PACKAGE_NAME}_MODULE") +set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1) diff --git a/Tests/RunCMake/FPHSA/FindNameMismatchSuppressedCompat.cmake b/Tests/RunCMake/FPHSA/FindNameMismatchSuppressedCompat.cmake new file mode 100644 index 0000000..791cfee --- /dev/null +++ b/Tests/RunCMake/FPHSA/FindNameMismatchSuppressedCompat.cmake @@ -0,0 +1,6 @@ +set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}") +include(FindPackageHandleStandardArgs) +set(FPHSA_NAME_MISMATCHED 1) +find_package_handle_standard_args(NAMEMISMATCH REQUIRED_VARS "${CMAKE_FIND_PACKAGE_NAME}_MODULE") +unset(FPHSA_NAME_MISMATCHED) +set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1) diff --git a/Tests/RunCMake/FPHSA/NameMismatch-stderr.txt b/Tests/RunCMake/FPHSA/NameMismatch-stderr.txt new file mode 100644 index 0000000..722b50b --- /dev/null +++ b/Tests/RunCMake/FPHSA/NameMismatch-stderr.txt @@ -0,0 +1,23 @@ +CMake Warning \(dev\) at .*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\): + The package name passed to `find_package_handle_standard_args` + \(NAMEMISMATCH\) does not match the name of the calling package + \(NameMismatch\). This can lead to problems in calling code that expects + `find_package` result variables \(e.g., `_FOUND`\) to follow a certain + pattern. +Call Stack \(most recent call first\): + FindNameMismatch.cmake:3 \(find_package_handle_standard_args\) + NameMismatch.cmake:3 \(find_package\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\) at .*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\): + The package name passed to `find_package_handle_standard_args` + \(NAMEMISMATCH\) does not match the name of the calling package + \(NameMismatchOld\). This can lead to problems in calling code that expects + `find_package` result variables \(e.g., `_FOUND`\) to follow a certain + pattern. +Call Stack \(most recent call first\): + FindNameMismatchOld.cmake:3 \(find_package_handle_standard_args\) + NameMismatch.cmake:4 \(find_package\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/FPHSA/NameMismatch.cmake b/Tests/RunCMake/FPHSA/NameMismatch.cmake new file mode 100644 index 0000000..9ca3cc6 --- /dev/null +++ b/Tests/RunCMake/FPHSA/NameMismatch.cmake @@ -0,0 +1,7 @@ +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + +find_package(NameMismatch REQUIRED) +find_package(NameMismatchOld REQUIRED) +find_package(NameMismatchSuppressed REQUIRED) +find_package(NameMismatchSuppressedCompat REQUIRED) +find_package(NameMismatchSuppressedArg REQUIRED) diff --git a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake index f3e6c3e..286915d 100644 --- a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake +++ b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake @@ -1,6 +1,7 @@ include(RunCMake) run_cmake(BadFoundVar) +run_cmake(NameMismatch) # The pseudo module will "find" a package with the given version. Check if the # version selection code in FPHSA works correctly. diff --git a/Tests/RunCMake/NinjaMultiConfig/CudaSimple-all-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CudaSimple-all-clean-build-check.cmake new file mode 100644 index 0000000..45f684b --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CudaSimple-all-clean-build-check.cmake @@ -0,0 +1,21 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplecudaexe_Debug} + ${TARGET_OBJECT_FILES_simplecudashared_Debug} + ${TARGET_OBJECT_FILES_simplecudaobj_Debug} + + ${TARGET_OBJECT_FILES_simplecudaexe_Release} + ${TARGET_OBJECT_FILES_simplecudashared_Release} + ${TARGET_OBJECT_FILES_simplecudaobj_Release} + + ${TARGET_OBJECT_FILES_simplecudaexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simplecudashared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplecudaobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simplecudaexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplecudashared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplecudaobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CudaSimple-debug-target-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CudaSimple-debug-target-build-check.cmake new file mode 100644 index 0000000..b0fca18 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CudaSimple-debug-target-build-check.cmake @@ -0,0 +1,27 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simplecudaexe_Debug} + ${TARGET_OBJECT_FILES_simplecudaexe_Debug} + + ${TARGET_FILE_simplecudashared_Debug} + ${TARGET_LINKER_FILE_simplecudashared_Debug} + ${TARGET_OBJECT_FILES_simplecudashared_Debug} + + ${TARGET_OBJECT_FILES_simplecudaobj_Debug} + + EXCLUDE + + ${TARGET_OBJECT_FILES_simplecudaexe_Release} + ${TARGET_OBJECT_FILES_simplecudashared_Release} + ${TARGET_OBJECT_FILES_simplecudaobj_Release} + + ${TARGET_OBJECT_FILES_simplecudaexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simplecudashared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplecudaobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simplecudaexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplecudashared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplecudaobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CudaSimple.cmake b/Tests/RunCMake/NinjaMultiConfig/CudaSimple.cmake new file mode 100644 index 0000000..2e9b1cb --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CudaSimple.cmake @@ -0,0 +1,21 @@ +enable_language(CUDA) +file(TOUCH ${CMAKE_BINARY_DIR}/empty.cmake) + +add_library(simplecudaobj OBJECT simplelib.cu) +set_target_properties(simplecudaobj + PROPERTIES + POSITION_INDEPENDENT_CODE ON) + +add_library(simplecudashared SHARED ) +target_link_libraries(simplecudashared PRIVATE simplecudaobj) +set_target_properties(simplecudaobj simplecudashared + PROPERTIES + CUDA_SEPARABLE_COMPILATION ON) + +add_executable(simplecudaexe main.cu ) +target_link_libraries(simplecudaexe PRIVATE simplecudashared) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(simplecudaexe simplecudashared simplecudaobj) + +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(GENERATED_FILES [==[${CMAKE_BINARY_DIR}/empty.cmake]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 4b51ddb..f3208ed 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -76,8 +76,9 @@ endfunction() set(RunCMake_TEST_NO_CLEAN 1) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Simple-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo") +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo;-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(Simple) +unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) run_cmake_build(Simple debug-target Debug simpleexe) run_ninja(Simple debug-target build-Debug.ninja simplestatic) @@ -103,8 +104,22 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1) file(TOUCH "${RunCMake_TEST_BINARY_DIR}/empty.cmake") run_ninja(Simple reconfigure-noconfig build.ninja simpleexe) +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SimpleNoCross-build) +run_cmake_configure(SimpleNoCross) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(SimpleNoCross debug-target Debug simpleexe) +run_ninja(SimpleNoCross debug-target build-Debug.ninja simplestatic:Debug) +run_ninja(SimpleNoCross relwithdebinfo-in-release-graph-target build-Release.ninja simplestatic:RelWithDebInfo) +run_cmake_build(SimpleNoCross relwithdebinfo-in-release-graph-all Release all:RelWithDebInfo) +run_cmake_build(SimpleNoCross relwithdebinfo-in-release-graph-clean Release clean:RelWithDebInfo) +run_ninja(SimpleNoCross all-target build-Debug.ninja simplestatic:all) +run_ninja(SimpleNoCross all-all build-Debug.ninja all:all) +run_cmake_build(SimpleNoCross all-clean Debug clean:all) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandGenerator-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(CustomCommandGenerator) +unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) run_cmake_build(CustomCommandGenerator debug Debug generated) run_cmake_command(CustomCommandGenerator-debug-generated "${TARGET_FILE_generated_Debug}") @@ -119,7 +134,9 @@ run_ninja(CustomCommandGenerator release-in-debug-graph build-Debug.ninja genera run_cmake_command(CustomCommandGenerator-release-in-debug-graph-generated "${TARGET_FILE_generated_Release}") set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandsAndTargets-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(CustomCommandsAndTargets) +unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) run_cmake_build(CustomCommandsAndTargets release-command Release SubdirCommand) #FIXME Get this working @@ -133,9 +150,9 @@ run_cmake_build(CustomCommandsAndTargets debug-targetpostbuild Debug TopTargetPo run_ninja(CustomCommandsAndTargets release-targetpostbuild build-Release.ninja SubdirTargetPostBuild) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostfixAndLocation-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release") +set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(PostfixAndLocation) -set(RunCMake_TEST_OPTIONS) +unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) run_cmake_build(PostfixAndLocation release-in-release-graph Release mylib:Release) run_cmake_build(PostfixAndLocation debug-in-release-graph Release mylib:Debug) @@ -148,14 +165,16 @@ run_ninja(Clean release-notall build-Release.ninja exenotall) run_cmake_build(Clean release-clean Release clean) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AdditionalCleanFiles-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(AdditionalCleanFiles) +unset(RunCMake_TEST_OPTIONS) run_cmake_build(AdditionalCleanFiles release-clean Release clean) run_ninja(AdditionalCleanFiles all-clean build-Debug.ninja clean:all) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Install-build) -set(RunCMake_TEST_OPTIONS -DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install) +set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install;-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(Install) -set(RunCMake_TEST_OPTIONS) +unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) run_cmake_build(Install release-install Release install) run_ninja(Install debug-in-release-graph-install build-Release.ninja install:Debug) @@ -165,9 +184,19 @@ run_ninja(Install debug-in-release-graph-install build-Release.ninja install:Deb #run_cmake_configure(AutoMocExecutable) #run_cmake_build(AutoMocExecutable debug-in-release-graph Release exe) +if(CMake_TEST_CUDA) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CudaSimple-build) + run_cmake_configure(CudaSimple) + include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) + run_cmake_build(CudaSimple debug-target Debug simplecudaexe) + run_ninja(CudaSimple all-clean build-Debug.ninja clean:Debug) +endif() + if(CMake_TEST_Qt5) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5-build) + set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(Qt5) + unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) run_cmake_build(Qt5 debug-in-release-graph Release exe:Debug) endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-result.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-stderr.txt new file mode 100644 index 0000000..905a355 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-stderr.txt @@ -0,0 +1 @@ +^ninja: error: unknown target 'all:all'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-result.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-stderr.txt new file mode 100644 index 0000000..43528de --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-stderr.txt @@ -0,0 +1 @@ +^ninja: error: unknown target 'clean:all'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-result.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-stderr.txt new file mode 100644 index 0000000..6db4bcc --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-stderr.txt @@ -0,0 +1 @@ +^ninja: error: unknown target 'simplestatic:all'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-build-check.cmake new file mode 100644 index 0000000..6bb7773 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-build-check.cmake @@ -0,0 +1,31 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-ninja-check.cmake new file mode 100644 index 0000000..c8a735a --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-ninja-check.cmake @@ -0,0 +1,32 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-result.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-stderr.txt new file mode 100644 index 0000000..fa8b462 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-stderr.txt @@ -0,0 +1 @@ +^ninja: error: unknown target 'all:RelWithDebInfo'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-result.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-stderr.txt new file mode 100644 index 0000000..70eef2f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-stderr.txt @@ -0,0 +1 @@ +^ninja: error: unknown target 'clean:RelWithDebInfo'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-result.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-stderr.txt new file mode 100644 index 0000000..1a1fe9e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-stderr.txt @@ -0,0 +1 @@ +^ninja: error: unknown target 'simplestatic:RelWithDebInfo'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross.cmake new file mode 100644 index 0000000..2a5b708 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleNoCross.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/Simple.cmake") diff --git a/Tests/RunCMake/NinjaMultiConfig/main.cu b/Tests/RunCMake/NinjaMultiConfig/main.cu new file mode 100644 index 0000000..563b9b2 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/main.cu @@ -0,0 +1,15 @@ + +#include <cuda.h> + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +#else +# define IMPORT +#endif + +IMPORT int simplelib(); + +int main(void) +{ + return simplelib(); +} diff --git a/Tests/RunCMake/NinjaMultiConfig/simplelib.cu b/Tests/RunCMake/NinjaMultiConfig/simplelib.cu new file mode 100644 index 0000000..7fc0812 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/simplelib.cu @@ -0,0 +1,9 @@ +#include <cuda.h> + +#ifdef _WIN32 +__declspec(dllexport) +#endif + int simplelib() +{ + return 0; +} diff --git a/Tests/RunCMake/TargetProperties/CMakeLists.txt b/Tests/RunCMake/TargetProperties/CMakeLists.txt new file mode 100644 index 0000000..be9d403 --- /dev/null +++ b/Tests/RunCMake/TargetProperties/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST}) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/TargetProperties/Deprecation-stderr.txt b/Tests/RunCMake/TargetProperties/Deprecation-stderr.txt new file mode 100644 index 0000000..11a4cd8 --- /dev/null +++ b/Tests/RunCMake/TargetProperties/Deprecation-stderr.txt @@ -0,0 +1,9 @@ +^CMake Warning \(dev\) at Deprecation\.cmake:[0-9]+ \(target_link_libraries\): + The library that is being linked to, testLibDeprecation, is marked as being + deprecated by the owner\. The message provided by the developer is: + + Deprecated version\. Please use latest version + +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/TargetProperties/Deprecation.cmake b/Tests/RunCMake/TargetProperties/Deprecation.cmake new file mode 100644 index 0000000..9361273 --- /dev/null +++ b/Tests/RunCMake/TargetProperties/Deprecation.cmake @@ -0,0 +1,5 @@ +add_library(testLibDeprecation STATIC empty.cpp) +set_property(TARGET testLibDeprecation PROPERTY DEPRECATION "Deprecated version. Please use latest version") + +add_executable(testExe1 empty.cpp) +target_link_libraries(testExe1 testLibDeprecation) diff --git a/Tests/RunCMake/TargetProperties/RunCMakeTest.cmake b/Tests/RunCMake/TargetProperties/RunCMakeTest.cmake new file mode 100644 index 0000000..5af31da --- /dev/null +++ b/Tests/RunCMake/TargetProperties/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(Deprecation) diff --git a/Tests/RunCMake/TargetProperties/empty.cpp b/Tests/RunCMake/TargetProperties/empty.cpp new file mode 100644 index 0000000..4086dcc --- /dev/null +++ b/Tests/RunCMake/TargetProperties/empty.cpp @@ -0,0 +1,4 @@ +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/UnityBuild/unitybuild_batchsize-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_batchsize-check.cmake index 32bb8e7..72cc2b9 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_batchsize-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_batchsize-check.cmake @@ -1,5 +1,5 @@ -set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") -set(unitybuild_c1 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_1.c") +set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") +set(unitybuild_c1 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_1_c.c") if(NOT EXISTS "${unitybuild_c0}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c0} does not exist.") return() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_c-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_c-check.cmake index c980df0..024286d 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_c-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_c-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") if(NOT EXISTS "${unitybuild_c}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c} does not exist.") return() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_c_and_cxx-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_c_and_cxx-check.cmake index 32c2992..269d545 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_c_and_cxx-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_c_and_cxx-check.cmake @@ -1,10 +1,10 @@ -set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") if(NOT EXISTS "${unitybuild_c}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c} does not exist.") return() endif() -set(unitybuild_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.cxx") +set(unitybuild_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_cxx.cxx") if(NOT EXISTS "${unitybuild_cxx}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_cxx} does not exist.") return() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_c_no_unity_build-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_c_no_unity_build-check.cmake index cb71ea3..22d2fc6 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_c_no_unity_build-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_c_no_unity_build-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") if(EXISTS "${unitybuild_c}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c} should not exist.") return() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_code_before_and_after_include-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_code_before_and_after_include-check.cmake index 8fcb18f..e0935c7 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_code_before_and_after_include-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_code_before_and_after_include-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") file(STRINGS ${unitybuild_c} unitybuild_c_strings) string(REGEX MATCH "#define NOMINMAX.*#include.*s1.c.*#undef NOMINMAX" matched_code ${unitybuild_c_strings}) if(NOT matched_code) diff --git a/Tests/RunCMake/UnityBuild/unitybuild_cxx-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_cxx-check.cmake index 89a037a..9ef4c21 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_cxx-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_cxx-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.cxx") +set(unitybuild_cxx "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_cxx.cxx") if(NOT EXISTS "${unitybuild_cxx}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_cxx} does not exist.") return() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_default_batchsize-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_default_batchsize-check.cmake index 7dfc007..9d39a70 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_default_batchsize-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_default_batchsize-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") file(STRINGS ${unitybuild_c0} unitybuild_c_strings REGEX "/s[0-9]+.c\"$" ) list(LENGTH unitybuild_c_strings number_of_includes) if(NOT number_of_includes EQUAL 8) diff --git a/Tests/RunCMake/UnityBuild/unitybuild_order-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_order-check.cmake index 533a89c..f26ec2e 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_order-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_order-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") file(STRINGS ${unitybuild_c} unitybuild_c_strings) string(REGEX MATCH ".*#include.*s3.c.*#include.*s1.c.*#include.*s2.c.*" matched_code ${unitybuild_c_strings}) if(NOT matched_code) diff --git a/Tests/RunCMake/UnityBuild/unitybuild_skip-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_skip-check.cmake index fdd45bc..e94ad72 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_skip-check.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_skip-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") file(STRINGS ${unitybuild_c} unitybuild_c_strings) string(REGEX MATCH "\\/s[1-6].c" matched_files_1_6 ${unitybuild_c_strings}) diff --git a/Tests/RunCMake/VS10Project/UnityBuildNative-check.cmake b/Tests/RunCMake/VS10Project/UnityBuildNative-check.cmake index 87f247d..693dcd9 100644 --- a/Tests/RunCMake/VS10Project/UnityBuildNative-check.cmake +++ b/Tests/RunCMake/VS10Project/UnityBuildNative-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") if(NOT EXISTS "${unitybuild_c0}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c0} does not exist.") return() @@ -32,7 +32,7 @@ if (NOT have_unity_support) endif() string(REPLACE "\\" "/" unity_source_line "${unity_source_line}") -string(FIND "${unity_source_line}" "CMakeFiles/tgt.dir/Unity/unity_0.c" unity_source_file_position) +string(FIND "${unity_source_line}" "CMakeFiles/tgt.dir/Unity/unity_0_c.c" unity_source_file_position) if (unity_source_file_position EQUAL "-1") set(RunCMake_TEST_FAILED "Generated project should include the generated unity source file.") return() diff --git a/Tests/RunCMake/VS10Project/UnityBuildPre2017-check.cmake b/Tests/RunCMake/VS10Project/UnityBuildPre2017-check.cmake index 1c6bab8..17e7b46 100644 --- a/Tests/RunCMake/VS10Project/UnityBuildPre2017-check.cmake +++ b/Tests/RunCMake/VS10Project/UnityBuildPre2017-check.cmake @@ -1,4 +1,4 @@ -set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0.c") +set(unitybuild_c0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_c.c") if(NOT EXISTS "${unitybuild_c0}") set(RunCMake_TEST_FAILED "Generated unity source files ${unitybuild_c0} does not exist.") return() @@ -28,7 +28,7 @@ foreach(line IN LISTS tgt_projects_strings) endforeach() string(REPLACE "\\" "/" unity_source_line ${unity_source_line}) -string(FIND "${unity_source_line}" "CMakeFiles/tgt.dir/Unity/unity_0.c" unity_source_file_position) +string(FIND "${unity_source_line}" "CMakeFiles/tgt.dir/Unity/unity_0_c.c" unity_source_file_position) if (unity_source_file_position EQUAL "-1") set(RunCMake_TEST_FAILED "Generated project should include the generated unity source file.") return() diff --git a/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt b/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt index 5856d56..b35f05e 100644 --- a/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt +++ b/Tests/RunCMake/find_package/FromPATHEnv-stderr.txt @@ -1,6 +1,7 @@ CMake Debug Log at FromPATHEnv.cmake:5 \(find_package\): - find_package considered the following paths for Resolved.cmake -.* + find_package considered the following paths for Resolved.cmake.* +.*/Modules/FindResolved.cmake.* + The file was not found.* <PackageName>_ROOT CMake variable.* CMAKE_PREFIX_PATH variable.* CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables.* @@ -13,4 +14,7 @@ CMake Debug Log at FromPATHEnv.cmake:5 \(find_package\): CMake variables defined in the Platform file.* CMake System Package Registry.* Paths specified by the find_package PATHS option.* - Checking file.*\[.*Tests/RunCMake/find_package/PackageRoot/ResolvedConfig\.cmake\] + find_package considered the following locations for the Config module:.* +.*Tests/RunCMake/find_package/PackageRoot/ResolvedConfig\.cmake.* + The file was found at.* +.*Tests/RunCMake/find_package/PackageRoot/ResolvedConfig\.cmake diff --git a/Tests/RunCMake/find_package/MissingConfigDebug-stderr.txt b/Tests/RunCMake/find_package/MissingConfigDebug-stderr.txt index 8ff04a9..379bf7a 100644 --- a/Tests/RunCMake/find_package/MissingConfigDebug-stderr.txt +++ b/Tests/RunCMake/find_package/MissingConfigDebug-stderr.txt @@ -9,8 +9,9 @@ CMake System Package Registry.* Paths specified by the find_package PATHS option.* .* - Checking file \[.*NotHereConfig.cmake\].* - Checking file \[.*nothere-config.cmake\].* + .*NotHereConfig.cmake + .*nothere-config.cmake +.* CMake Warning at MissingConfigDebug.cmake:3 \(message\): This warning must be reachable. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/target_compile_options/BEFORE_keyword.cmake b/Tests/RunCMake/target_compile_options/BEFORE_keyword.cmake new file mode 100644 index 0000000..8016230 --- /dev/null +++ b/Tests/RunCMake/target_compile_options/BEFORE_keyword.cmake @@ -0,0 +1,8 @@ + +add_executable (CMP0101_OLD CMP0101.c) +target_compile_options (main PRIVATE -UBEFORE_KEYWORD) +target_compile_options (main BEFORE PRIVATE -DBEFORE_KEYWORD) + +add_executable (CMP0101_NEW CMP0101.c) +target_compile_options (main PRIVATE -UBEFORE_KEYWORD) +target_compile_options (main BEFORE PRIVATE -DBEFORE_KEYWORD) diff --git a/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-NEW-result.txt b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-NEW-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-NEW-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-OLD-result.txt b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-OLD-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-OLD-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-OLD-stdout.txt b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-OLD-stdout.txt new file mode 100644 index 0000000..850aa65 --- /dev/null +++ b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-OLD-stdout.txt @@ -0,0 +1 @@ +BEFORE not honored diff --git a/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword.cmake b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword.cmake new file mode 100644 index 0000000..577427f --- /dev/null +++ b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword.cmake @@ -0,0 +1,15 @@ + +enable_language(C) + +cmake_policy (SET CMP0101 OLD) + +add_executable (CMP0101_OLD CMP0101.c) +target_compile_options (CMP0101_OLD PRIVATE -UBEFORE_KEYWORD) +target_compile_options (CMP0101_OLD BEFORE PRIVATE -DBEFORE_KEYWORD) + + +cmake_policy (SET CMP0101 NEW) + +add_executable (CMP0101_NEW CMP0101.c) +target_compile_options (CMP0101_NEW PRIVATE -UBEFORE_KEYWORD) +target_compile_options (CMP0101_NEW BEFORE PRIVATE -DBEFORE_KEYWORD) diff --git a/Tests/RunCMake/target_compile_options/CMP0101.c b/Tests/RunCMake/target_compile_options/CMP0101.c new file mode 100644 index 0000000..250869a --- /dev/null +++ b/Tests/RunCMake/target_compile_options/CMP0101.c @@ -0,0 +1,9 @@ + +#if defined(BEFORE_KEYWORD) +# error "BEFORE not honored" +#endif + +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake index b67c598..9f51a9a 100644 --- a/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake @@ -1,3 +1,21 @@ include(RunCMake) run_cmake(empty_keyword_args) + +if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + macro(run_cmake_target test subtest target) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) + set(RunCMake_TEST_OUTPUT_MERGE 1) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN}) + + unset(RunCMake_TEST_BINARY_DIR) + unset(RunCMake_TEST_OUTPUT_MERGE) + unset(RunCMake_TEST_NO_CLEAN) + endmacro() + + run_cmake(CMP0101-BEFORE_keyword) + + run_cmake_target(CMP0101-BEFORE_keyword OLD CMP0101_OLD) + run_cmake_target(CMP0101-BEFORE_keyword NEW CMP0101_NEW) +endif() diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt index 89cd806..1c5cf45 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt @@ -1 +1 @@ --- INTERFACE_LINK_LIBRARIES='foo::@<[Xx0-9A-Fa-f]+>' +-- INTERFACE_LINK_LIBRARIES='::@\([Xx0-9A-Fa-f]+\);\$<\$<CONFIG:DEBUG>:\$<1:foo;foo>>;\$<\$<NOT:\$<CONFIG:DEBUG>>:\$<1:foo;foo>>;::@' diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt index e575e16..4eb06d9 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt @@ -1 +1 @@ --- INTERFACE_LINK_LIBRARIES='foo' +-- INTERFACE_LINK_LIBRARIES='\$<\$<CONFIG:DEBUG>:\$<1:foo;foo>>;\$<\$<NOT:\$<CONFIG:DEBUG>>:\$<1:foo;foo>>' diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt index 6dd7d30..4c09a1f 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt @@ -10,7 +10,25 @@ is not created in this directory. For compatibility with older versions of CMake, link library - foo + \$<1:foo;foo> + + will be looked up in the directory in which the target was created rather + than in this calling directory. +This warning is for project developers. Use -Wno-dev to suppress it. ++ +CMake Warning \(dev\) at CMP0079-iface/CMakeLists.txt:[0-9]+ \(target_link_libraries\): + Policy CMP0079 is not set: target_link_libraries allows use with targets in + other directories. Run "cmake --help-policy CMP0079" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + + Target + + top + + is not created in this directory. For compatibility with older versions of + CMake, link library + + \$<1:foo;foo> will be looked up in the directory in which the target was created rather than in this calling directory. diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt index e575e16..4eb06d9 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt @@ -1 +1 @@ --- INTERFACE_LINK_LIBRARIES='foo' +-- INTERFACE_LINK_LIBRARIES='\$<\$<CONFIG:DEBUG>:\$<1:foo;foo>>;\$<\$<NOT:\$<CONFIG:DEBUG>>:\$<1:foo;foo>>' diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt index 4b15b32..e410607 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt @@ -1 +1 @@ -target_link_libraries(top INTERFACE foo) +target_link_libraries(top INTERFACE debug "$<1:foo;foo>" optimized "$<1:foo;foo>") diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt index 8ef35c1..9e38bec 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt @@ -1,5 +1,5 @@ ^CMake Error at CMP0079-link-NEW-bogus.cmake:[0-9]+ \(add_executable\): - Target "top" links to target "foo::@<0xdeadbeef>" but the target was not + Target "top" links to target "::@\(0xdeadbeef\)" but the target was not found. Perhaps a find_package\(\) call is missing for an IMPORTED target, or an ALIAS target is missing\? Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake index 8622f14..8932521 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake +++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake @@ -3,4 +3,4 @@ cmake_policy(SET CMP0079 NEW) enable_language(C) add_executable(top empty.c) -set_property(TARGET top APPEND PROPERTY LINK_LIBRARIES "foo::@<0xdeadbeef>") +set_property(TARGET top APPEND PROPERTY LINK_LIBRARIES "::@(0xdeadbeef);foo;::@") diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt index 84b30bd..fa5d4a3 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt @@ -1 +1 @@ --- LINK_LIBRARIES='foo::@<[Xx0-9A-Fa-f]+>' +-- LINK_LIBRARIES='::@\([Xx0-9A-Fa-f]+\);foo;::@' diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index d903dbe..f164fd0 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -191,6 +191,7 @@ _cmake_index_objs = { 'cpack_gen': _cmake_index_entry('cpack generator'), 'envvar': _cmake_index_entry('envvar'), 'generator': _cmake_index_entry('generator'), + 'guide': _cmake_index_entry('guide'), 'manual': _cmake_index_entry('manual'), 'module': _cmake_index_entry('module'), 'policy': _cmake_index_entry('policy'), @@ -251,7 +252,7 @@ class CMakeTransform(Transform): env = self.document.settings.env # Treat some documents as cmake domain objects. - objtype, sep, tail = env.docname.rpartition('/') + objtype, sep, tail = env.docname.partition('/') make_index_entry = _cmake_index_objs.get(objtype) if make_index_entry: title = self.parse_title(env.docname) @@ -373,6 +374,7 @@ class CMakeDomain(Domain): 'cpack_gen': ObjType('cpack_gen', 'cpack_gen'), 'envvar': ObjType('envvar', 'envvar'), 'generator': ObjType('generator', 'generator'), + 'guide': ObjType('guide', 'guide'), 'variable': ObjType('variable', 'variable'), 'module': ObjType('module', 'module'), 'policy': ObjType('policy', 'policy'), @@ -407,6 +409,7 @@ class CMakeDomain(Domain): 'cpack_gen': CMakeXRefRole(), 'envvar': CMakeXRefRole(), 'generator': CMakeXRefRole(), + 'guide': CMakeXRefRole(), 'variable': CMakeXRefRole(), 'module': CMakeXRefRole(), 'policy': CMakeXRefRole(), diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py index 6716b48..b5cd914 100755 --- a/Utilities/Sphinx/create_identifiers.py +++ b/Utilities/Sphinx/create_identifiers.py @@ -25,6 +25,7 @@ for line in lines: ("envvar", "envvar"), ("variable", "variable"), ("generator", "generator"), + ("guide", "guide"), ("target property", "prop_tgt"), ("test property", "prop_test"), ("source file property", "prop_sf"), diff --git a/Utilities/std/.gitattributes b/Utilities/std/.gitattributes index 789a754..ad5459d 100644 --- a/Utilities/std/.gitattributes +++ b/Utilities/std/.gitattributes @@ -1,2 +1,2 @@ -cm/* our-c-style -cmext/* our-c-style +cm/** our-c-style +cmext/** our-c-style diff --git a/Utilities/std/cm/bits/erase_if.hxx b/Utilities/std/cm/bits/erase_if.hxx new file mode 100644 index 0000000..8952fb5 --- /dev/null +++ b/Utilities/std/cm/bits/erase_if.hxx @@ -0,0 +1,29 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cm_bits_erase_if_hxx +#define cm_bits_erase_if_hxx + +namespace cm { +namespace internals { + +template <typename Container, typename Predicate> +void erase_if(Container& cont, Predicate pred) +{ + for (typename Container::iterator iter = cont.begin(), last = cont.end(); + iter != last;) { + if (pred(*iter)) { + iter = cont.erase(iter); + } else { + ++iter; + } + } +} + +} // namespace internals +} // namespace cm + +#endif diff --git a/Utilities/std/cm/deque b/Utilities/std/cm/deque new file mode 100644 index 0000000..4bb6725 --- /dev/null +++ b/Utilities/std/cm/deque @@ -0,0 +1,40 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_deque +#define cm_deque + +#include <algorithm> +#include <deque> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Allocator, typename V> +inline void erase(std::deque<T, Allocator>& cont, const V& value) +{ + cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end()); +} + +template <typename T, typename Allocator, typename Predicate> +inline void erase_if(std::deque<T, Allocator>& cont, Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/list b/Utilities/std/cm/list new file mode 100644 index 0000000..ba5d94a --- /dev/null +++ b/Utilities/std/cm/list @@ -0,0 +1,39 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_list +#define cm_list + +#include <list> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Allocator, typename V> +inline void erase(std::list<T, Allocator>& cont, const V& value) +{ + cont.remove_if([&](auto& elem) { return elem == value; }); +} + +template <typename T, typename Allocator, typename Predicate> +inline void erase_if(std::list<T, Allocator>& cont, Predicate pred) +{ + cont.remove_if(pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/map b/Utilities/std/cm/map new file mode 100644 index 0000000..e348dec --- /dev/null +++ b/Utilities/std/cm/map @@ -0,0 +1,44 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_map +#define cm_map + +#include <map> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename T, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::map<Key, T, Compare, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename T, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::multimap<Key, T, Compare, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/set b/Utilities/std/cm/set new file mode 100644 index 0000000..56dd474 --- /dev/null +++ b/Utilities/std/cm/set @@ -0,0 +1,43 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_set +#define cm_set + +#include <set> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::set<Key, Compare, Allocator>& cont, Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::multiset<Key, Compare, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/string b/Utilities/std/cm/string new file mode 100644 index 0000000..cc4c796 --- /dev/null +++ b/Utilities/std/cm/string @@ -0,0 +1,42 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_string +#define cm_string + +#include <algorithm> +#include <string> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Traits, typename Allocator, typename V> +inline void erase(std::basic_string<T, Traits, Allocator>& cont, + const V& value) +{ + cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end()); +} + +template <typename T, typename Traits, typename Allocator, typename Predicate> +inline void erase_if(std::basic_string<T, Traits, Allocator>& cont, + Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/type_traits b/Utilities/std/cm/type_traits index 4dfe17b..e32c2c6 100644 --- a/Utilities/std/cm/type_traits +++ b/Utilities/std/cm/type_traits @@ -33,6 +33,8 @@ using std::bool_constant; using std::invoke_result; using std::invoke_result_t; +using std::void_t; + #else // Helper classes @@ -46,6 +48,14 @@ using invoke_result = std::result_of<F(ArgTypes...)>; template <class F, typename... ArgTypes> using invoke_result_t = typename invoke_result<F, ArgTypes...>::type; +template <typename... ArgTypes> +struct make_void +{ + typedef void type; +}; +template <typename... ArgTypes> +using void_t = typename make_void<ArgTypes...>::type; + #endif } // namespace cm diff --git a/Utilities/std/cm/unordered_map b/Utilities/std/cm/unordered_map new file mode 100644 index 0000000..5b8a456 --- /dev/null +++ b/Utilities/std/cm/unordered_map @@ -0,0 +1,45 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_unordered_map +#define cm_unordered_map + +#include <unordered_map> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename T, typename Hash, typename KeyEqual, + typename Allocator, typename Predicate> +inline void erase_if( + std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& cont, Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename T, typename Hash, typename KeyEqual, + typename Allocator, typename Predicate> +inline void erase_if( + std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/unordered_set b/Utilities/std/cm/unordered_set new file mode 100644 index 0000000..9debac4 --- /dev/null +++ b/Utilities/std/cm/unordered_set @@ -0,0 +1,45 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_unordered_set +#define cm_unordered_set + +#include <unordered_set> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename Hash, typename KeyEqual, typename Allocator, + typename Predicate> +inline void erase_if(std::unordered_set<Key, Hash, KeyEqual, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename Hash, typename KeyEqual, typename Allocator, + typename Predicate> +inline void erase_if( + std::unordered_multiset<Key, Hash, KeyEqual, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/vector b/Utilities/std/cm/vector new file mode 100644 index 0000000..2dbe704 --- /dev/null +++ b/Utilities/std/cm/vector @@ -0,0 +1,40 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_vector +#define cm_vector + +#include <algorithm> +#include <vector> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Allocator, typename V> +inline void erase(std::vector<T, Allocator>& cont, const V& value) +{ + cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end()); +} + +template <typename T, typename Allocator, typename Predicate> +inline void erase_if(std::vector<T, Allocator>& cont, Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/memory b/Utilities/std/cmext/memory index 540a3de..50e79df 100644 --- a/Utilities/std/cmext/memory +++ b/Utilities/std/cmext/memory @@ -6,6 +6,8 @@ #ifndef cmext_memory #define cmext_memory +#include <typeinfo> + #include <cm/type_traits> namespace cm { @@ -24,7 +26,13 @@ template <typename T, typename O, int> = 0> T& dynamic_reference_cast(O& item) { - return *(dynamic_cast<T*>(item.get())); + auto p = dynamic_cast<T*>(item.get()); + + if (p == nullptr) { + throw std::bad_cast(); + } + + return *p; } } // namespace cm diff --git a/Utilities/std/cmext/type_traits b/Utilities/std/cmext/type_traits new file mode 100644 index 0000000..da6550d --- /dev/null +++ b/Utilities/std/cmext/type_traits @@ -0,0 +1,68 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_type_traits +#define cmext_type_traits + +#include <cm/type_traits> + +namespace cm { + +// type traits for managed pointer types +template <typename> +struct is_unique_ptr : std::false_type +{ +}; +template <typename T> +struct is_unique_ptr<std::unique_ptr<T>> : std::true_type +{ +}; + +// type traits for containers +template <typename, typename = void_t<>> +struct is_container : std::false_type +{ +}; +template <typename T> +struct is_container< + T, + cm::void_t<typename T::value_type, typename T::size_type, + typename T::difference_type, typename T::iterator>> + : std::true_type +{ +}; + +template <typename, typename = void_t<>> +struct is_associative_container : std::false_type +{ +}; +template <typename T> +struct is_associative_container< + T, cm::void_t<typename T::key_type, typename T::key_compare>> + : cm::is_container<T> +{ +}; + +template <typename, typename = void_t<>> +struct is_unordered_associative_container : std::false_type +{ +}; +template <typename T> +struct is_unordered_associative_container< + T, + cm::void_t<typename T::key_type, typename T::hasher, typename T::key_equal, + typename T::local_iterator>> : cm::is_container<T> +{ +}; + +template <typename T> +using is_sequence_container = + cm::bool_constant<cm::is_container<T>::value && + !cm::is_associative_container<T>::value && + !cm::is_unordered_associative_container<T>::value>; + +} // namespace cm + +#endif @@ -1595,6 +1595,7 @@ rebuild_cache: echo ' # Generated by '"${cmake_source_dir}"'/bootstrap # Default cmake settings. These may be overridden any settings below. +set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build.") # not FORCE to preserve defaults specified elsewhere set (CMAKE_INSTALL_PREFIX "'"${cmake_prefix_dir}"'" CACHE PATH "Install path prefix, prepended onto install directories." FORCE) set (CMAKE_DOC_DIR "'"${cmake_doc_dir}"'" CACHE PATH "Install location for documentation (relative to prefix)." FORCE) set (CMAKE_MAN_DIR "'"${cmake_man_dir}"'" CACHE PATH "Install location for man pages (relative to prefix)." FORCE) |