diff options
24 files changed, 215 insertions, 47 deletions
diff --git a/Help/command/cmake_parse_arguments.rst b/Help/command/cmake_parse_arguments.rst index ec4ffed..b334a89 100644 --- a/Help/command/cmake_parse_arguments.rst +++ b/Help/command/cmake_parse_arguments.rst @@ -43,15 +43,18 @@ macro which can be followed by more than one value, like e.g. the ``<multi_value_keywords>``. A warning will be emitted if uniqueness is violated. -When done, ``cmake_parse_arguments`` will have defined for each of the +When done, ``cmake_parse_arguments`` will consider for each of the keywords listed in ``<options>``, ``<one_value_keywords>`` and ``<multi_value_keywords>`` a variable composed of the given ``<prefix>`` followed by ``"_"`` and the name of the respective keyword. These -variables will then hold the respective value from the argument list. -For the ``<options>`` keywords this will be ``TRUE`` or ``FALSE``. +variables will then hold the respective value from the argument list +or be undefined if the associated option could not be found. +For the ``<options>`` keywords, these will always be defined, +to ``TRUE`` or ``FALSE``, whether the option is in the argument list or not. All remaining arguments are collected in a variable -``<prefix>_UNPARSED_ARGUMENTS``, this can be checked afterwards to see +``<prefix>_UNPARSED_ARGUMENTS`` that will be undefined if all argument +where recognized. This can be checked afterwards to see whether your macro was called with unrecognized parameters. As an example here a ``my_install()`` macro, which takes similar arguments @@ -74,16 +77,16 @@ Assume ``my_install()`` has been called like this: my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) -After the ``cmake_parse_arguments`` call the macro will have set the -following variables:: +After the ``cmake_parse_arguments`` call the macro will have set or undefined +the following variables:: MY_INSTALL_OPTIONAL = TRUE - MY_INSTALL_FAST = FALSE (was not used in call to my_install) + MY_INSTALL_FAST = FALSE # was not used in call to my_install MY_INSTALL_DESTINATION = "bin" - MY_INSTALL_RENAME = "" (was not used) + MY_INSTALL_RENAME <UNDEFINED> # was not used MY_INSTALL_TARGETS = "foo;bar" - MY_INSTALL_CONFIGURATIONS = "" (was not used) - MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (nothing expected after "OPTIONAL") + MY_INSTALL_CONFIGURATIONS <UNDEFINED> # was not used + MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # nothing expected after "OPTIONAL" You can then continue and process these variables. diff --git a/Help/policy/CMP0040.rst b/Help/policy/CMP0040.rst index d46baf6..0afe589 100644 --- a/Help/policy/CMP0040.rst +++ b/Help/policy/CMP0040.rst @@ -2,7 +2,7 @@ CMP0040 ------- The target in the ``TARGET`` signature of :command:`add_custom_command` -must exist and must be defined in current directory. +must exist and must be defined in the current directory. CMake 2.8.12 and lower silently ignored a custom command created with the ``TARGET`` signature of :command:`add_custom_command` diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst index 30a612d..0762033 100644 --- a/Help/prop_tgt/CXX_STANDARD.rst +++ b/Help/prop_tgt/CXX_STANDARD.rst @@ -6,7 +6,8 @@ The C++ standard whose features are requested to build this target. This property specifies the C++ standard whose features are requested to build this target. For some compilers, this results in adding a flag such as ``-std=gnu++11`` to the compile line. For compilers that -have no notion of a standard level, such as MSVC, this has no effect. +have no notion of a standard level, such as Microsoft Visual C++ before +2015 Update 3, this has no effect. Supported values are ``98``, ``11``, ``14``, and ``17``. diff --git a/Help/prop_tgt/C_STANDARD.rst b/Help/prop_tgt/C_STANDARD.rst index 815a686..e7f7904 100644 --- a/Help/prop_tgt/C_STANDARD.rst +++ b/Help/prop_tgt/C_STANDARD.rst @@ -6,7 +6,8 @@ The C standard whose features are requested to build this target. This property specifies the C standard whose features are requested to build this target. For some compilers, this results in adding a flag such as ``-std=gnu11`` to the compile line. For compilers that -have no notion of a standard level, such as MSVC, this has no effect. +have no notion of a standard level, such as Microsoft Visual C++ before +2015 Update 3, this has no effect. Supported values are ``90``, ``99`` and ``11``. diff --git a/Modules/Compiler/Flang-Fortran.cmake b/Modules/Compiler/Flang-Fortran.cmake index f17dec7..a1051f4 100644 --- a/Modules/Compiler/Flang-Fortran.cmake +++ b/Modules/Compiler/Flang-Fortran.cmake @@ -7,6 +7,4 @@ set(CMAKE_Fortran_PREPROCESS_SOURCE set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form") set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form") -string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -fbounds-check") - set(CMAKE_Fortran_MODDIR_FLAG "-J") diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 578fcd2..7f4c44c 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -1036,13 +1036,8 @@ set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "Flag used by MPI to specify the num set(MPIEXEC_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by mpiexec.") set(MPIEXEC_POSTFLAGS "" CACHE STRING "These flags will be placed after all flags passed to mpiexec.") -# Set the number of processes to the processor count and the previous default -# of 2 if that couldn't be determined. -include(${CMAKE_CURRENT_LIST_DIR}/ProcessorCount.cmake) -ProcessorCount(_MPIEXEC_NUMPROCS) -if("${_MPIEXEC_NUMPROCS}" EQUAL "0") - set(_MPIEXEC_NUMPROCS 2) -endif() +# Set the number of processes to the physical processor count +cmake_host_system_information(RESULT _MPIEXEC_NUMPROCS QUERY NUMBER_OF_PHYSICAL_CORES) set(MPIEXEC_MAX_NUMPROCS "${_MPIEXEC_NUMPROCS}" CACHE STRING "Maximum number of processors available to run MPI applications.") unset(_MPIEXEC_NUMPROCS) mark_as_advanced(MPIEXEC_EXECUTABLE MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS) diff --git a/Modules/FindOpenACC.cmake b/Modules/FindOpenACC.cmake index 775cc18..dc8321d 100644 --- a/Modules/FindOpenACC.cmake +++ b/Modules/FindOpenACC.cmake @@ -49,7 +49,9 @@ be returned with OpenACC_<lang>_FLAGS. set(OpenACC_C_CXX_TEST_SOURCE " int main(){ -#ifndef _OPENACC +#ifdef _OPENACC + return 0; +#else breaks_on_purpose #endif } @@ -58,7 +60,9 @@ int main(){ set(OpenACC_Fortran_TEST_SOURCE " program test -#ifndef _OPENACC +#ifdef _OPENACC + return 0; +#else breaks_on_purpose #endif endprogram test @@ -79,6 +83,7 @@ const char accver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'A', int main() { puts(accver_str); + return 0; } ") set(OpenACC_Fortran_CHECK_VERSION_SOURCE diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake index b8a7d82..0db2dd2 100644 --- a/Modules/FindOpenCL.cmake +++ b/Modules/FindOpenCL.cmake @@ -37,7 +37,7 @@ function(_FIND_OPENCL_VERSION) set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY}) CMAKE_PUSH_CHECK_STATE() - foreach(VERSION "2_0" "1_2" "1_1" "1_0") + foreach(VERSION "2_2" "2_1" "2_0" "1_2" "1_1" "1_0") set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}") if(APPLE) diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index a39a234..489476b 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -123,7 +123,9 @@ set(OpenMP_C_CXX_TEST_SOURCE " #include <omp.h> int main() { -#ifndef _OPENMP +#ifdef _OPENMP + return 0; +#else breaks_on_purpose #endif } @@ -273,6 +275,7 @@ const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', int main() { puts(ompver_str); + return 0; } ") diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index 64bd09e..91361d2 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -123,6 +123,9 @@ # allow users who create additional path variables to also compute # absolute paths where necessary, using the same logic. +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced + # Convert a cache variable to PATH type macro(_GNUInstallDirs_cache_convert_to_path var description) @@ -371,3 +374,5 @@ foreach(dir ) GNUInstallDirs_get_absolute_install_dir(CMAKE_INSTALL_FULL_${dir} CMAKE_INSTALL_${dir}) endforeach() + +cmake_policy(POP) diff --git a/Modules/Platform/Windows-Clang-CXX.cmake b/Modules/Platform/Windows-Clang-CXX.cmake index 2c3688a..f1d40f2 100644 --- a/Modules/Platform/Windows-Clang-CXX.cmake +++ b/Modules/Platform/Windows-Clang-CXX.cmake @@ -1,2 +1,3 @@ include(Platform/Windows-Clang) +set(_COMPILE_CXX_MSVC " -TP") __windows_compiler_clang(CXX) diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index bcfda93..007ae53 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -12,6 +12,7 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") include(Platform/Windows-MSVC) macro(__windows_compiler_clang lang) + set(_COMPILE_${lang} "${_COMPILE_${lang}_MSVC}") __windows_compiler_msvc(${lang}) endmacro() else() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 354011a..6c33e2b 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -126,7 +126,7 @@ class cmMakefile; 3, 0, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0040, \ "The target in the TARGET signature of add_custom_command() must " \ - "exist.", \ + "exist and must be defined in the current directory.", \ 3, 0, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0041, \ "Error on relative include with generator expression.", 3, 0, 0, \ diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index e7080cd..c7550e6 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -9,6 +9,7 @@ #include "cmFilePathChecksum.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" @@ -16,6 +17,7 @@ #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" +#include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cm_sys_stat.h" @@ -24,6 +26,7 @@ #include <algorithm> #include <array> +#include <deque> #include <map> #include <set> #include <sstream> @@ -156,7 +159,7 @@ static void GetConfigs(cmMakefile* makefile, std::string& configDefault, { configDefault = makefile->GetConfigurations(configsList); if (configsList.empty()) { - configsList.push_back(""); + configsList.push_back(configDefault); } } @@ -299,6 +302,50 @@ static std::vector<std::string> AddGeneratedSource( return genFiles; } +/* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its + * recursive STATIC_LIBRARY dependencies depends on targetOrigin + * (STATIC_LIBRARY cycle). + */ +static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, + cmGeneratorTarget const* targetDepend, + std::string const& config) +{ + bool cycle = false; + if ((targetOrigin->GetType() == cmStateEnums::STATIC_LIBRARY) && + (targetDepend->GetType() == cmStateEnums::STATIC_LIBRARY)) { + std::set<cmGeneratorTarget const*> knownLibs; + std::deque<cmGeneratorTarget const*> testLibs; + + // Insert initial static_library dependency + knownLibs.insert(targetDepend); + testLibs.push_back(targetDepend); + + while (!testLibs.empty()) { + cmGeneratorTarget const* testTarget = testLibs.front(); + testLibs.pop_front(); + // Check if the test target is the origin target (cycle) + if (testTarget == targetOrigin) { + cycle = true; + break; + } + // Collect all static_library dependencies from the test target + cmLinkImplementationLibraries const* libs = + testTarget->GetLinkImplementationLibraries(config); + if (libs != nullptr) { + for (cmLinkItem const& item : libs->Libraries) { + cmGeneratorTarget const* depTarget = item.Target; + if ((depTarget != nullptr) && + (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) && + knownLibs.insert(depTarget).second) { + testLibs.push_back(depTarget); + } + } + } + } + } + return cycle; +} + struct cmQtAutoGenSetup { std::set<std::string> MocSkip; @@ -631,7 +678,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( GetConfigs(makefile, configDefault, configsList); std::set<std::string> autogenDependFiles; - std::set<std::string> autogenDependTargets; + std::set<cmTarget*> autogenDependTargets; std::vector<std::string> autogenProvides; // Remove build directories on cleanup @@ -953,7 +1000,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // Allow target and file dependencies auto* depTarget = makefile->FindTargetToUse(depName); if (depTarget != nullptr) { - autogenDependTargets.insert(depTarget->GetName()); + autogenDependTargets.insert(depTarget); } else { autogenDependFiles.insert(depName); } @@ -980,8 +1027,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // Create the autogen target/command if (usePRE_BUILD) { // Add additional autogen target dependencies to origin target - for (std::string const& depTarget : autogenDependTargets) { - target->Target->AddUtility(depTarget, makefile); + for (cmTarget* depTarget : autogenDependTargets) { + target->Target->AddUtility(depTarget->GetName(), makefile); } // Add the pre-build command directly to bypass the OBJECT_LIBRARY @@ -999,20 +1046,35 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( target->Target->AddPreBuildCommand(cc); } else { - // Add utility target dependencies to the autogen target dependencies - for (std::string const& depTarget : target->Target->GetUtilities()) { - autogenDependTargets.insert(depTarget); - } + // Convert file dependencies std::set to std::vector + std::vector<std::string> autogenDepends(autogenDependFiles.begin(), + autogenDependFiles.end()); + // Add link library target dependencies to the autogen target dependencies - for (const auto& item : target->Target->GetOriginalLinkLibraries()) { - if (makefile->FindTargetToUse(item.first) != nullptr) { - autogenDependTargets.insert(item.first); + for (std::string const& config : configsList) { + cmLinkImplementationLibraries const* libs = + target->GetLinkImplementationLibraries(config); + if (libs != nullptr) { + for (cmLinkItem const& item : libs->Libraries) { + cmGeneratorTarget const* libTarget = item.Target; + if ((libTarget != nullptr) && + !StaticLibraryCycle(target, libTarget, config)) { + std::string util; + if (configsList.size() > 1) { + util += "$<$<CONFIG:"; + util += config; + util += ">:"; + } + util += libTarget->GetName(); + if (configsList.size() > 1) { + util += ">"; + } + autogenDepends.push_back(util); + } + } } } - // Convert file dependencies std::set to std::vector - const std::vector<std::string> autogenDepends(autogenDependFiles.begin(), - autogenDependFiles.end()); // Create autogen target cmTarget* autogenTarget = makefile->AddUtilityCommand( autogenTargetName, true, workingDirectory.c_str(), @@ -1022,9 +1084,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( localGen->AddGeneratorTarget( new cmGeneratorTarget(autogenTarget, localGen)); + // Forward origin utilities to autogen target + for (std::string const& depName : target->Target->GetUtilities()) { + autogenTarget->AddUtility(depName, makefile); + } // Add additional autogen target dependencies to autogen target - for (std::string const& depTarget : autogenDependTargets) { - autogenTarget->AddUtility(depTarget, makefile); + for (cmTarget* depTarget : autogenDependTargets) { + autogenTarget->AddUtility(depTarget->GetName(), makefile); } // Set FOLDER property in autogen target diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index ec35b89..b9d8e46 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -214,5 +214,9 @@ add_subdirectory(objectLibrary) add_subdirectory(sameName) # -- Test +# Tests static library cycles +add_subdirectory(staticLibraryCycle) + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/staticLibraryCycle/CMakeLists.txt b/Tests/QtAutogen/staticLibraryCycle/CMakeLists.txt new file mode 100644 index 0000000..144a435 --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/CMakeLists.txt @@ -0,0 +1,17 @@ +# Test AUTOMOC and AUTORCC on source files with the same name +# but in different subdirectories + +set(CMAKE_AUTOMOC ON) + +# Cyclic static libraries +add_library(slc_a STATIC a.cpp) +target_link_libraries(slc_a ${QT_LIBRARIES} slc_b) + +add_library(slc_b STATIC b.cpp) +target_link_libraries(slc_b ${QT_LIBRARIES} slc_c) + +add_library(slc_c STATIC c.cpp) +target_link_libraries(slc_c ${QT_LIBRARIES} slc_a) + +add_executable(slc main.cpp) +target_link_libraries(slc ${QT_LIBRARIES} slc_a) diff --git a/Tests/QtAutogen/staticLibraryCycle/a.cpp b/Tests/QtAutogen/staticLibraryCycle/a.cpp new file mode 100644 index 0000000..97cc66e --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/a.cpp @@ -0,0 +1,7 @@ +#include "a.h" +#include "b.h" + +A::A() +{ + B b; +} diff --git a/Tests/QtAutogen/staticLibraryCycle/a.h b/Tests/QtAutogen/staticLibraryCycle/a.h new file mode 100644 index 0000000..7176170 --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/a.h @@ -0,0 +1,13 @@ +#ifndef CLASSA_HPP +#define CLASSA_HPP + +#include <QObject> + +class A : public QObject +{ + Q_OBJECT +public: + A(); +}; + +#endif diff --git a/Tests/QtAutogen/staticLibraryCycle/b.cpp b/Tests/QtAutogen/staticLibraryCycle/b.cpp new file mode 100644 index 0000000..a807d89 --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/b.cpp @@ -0,0 +1,7 @@ +#include "b.h" +#include "c.h" + +B::B() +{ + C c; +} diff --git a/Tests/QtAutogen/staticLibraryCycle/b.h b/Tests/QtAutogen/staticLibraryCycle/b.h new file mode 100644 index 0000000..ededbd8 --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/b.h @@ -0,0 +1,13 @@ +#ifndef CLASSB_HPP +#define CLASSB_HPP + +#include <QObject> + +class B : public QObject +{ + Q_OBJECT +public: + B(); +}; + +#endif diff --git a/Tests/QtAutogen/staticLibraryCycle/c.cpp b/Tests/QtAutogen/staticLibraryCycle/c.cpp new file mode 100644 index 0000000..7d427c2 --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/c.cpp @@ -0,0 +1,7 @@ +#include "c.h" +#include "a.h" + +C::C() +{ + A a; +} diff --git a/Tests/QtAutogen/staticLibraryCycle/c.h b/Tests/QtAutogen/staticLibraryCycle/c.h new file mode 100644 index 0000000..20f3725 --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/c.h @@ -0,0 +1,13 @@ +#ifndef CLASSC_HPP +#define CLASSC_HPP + +#include <QObject> + +class C : public QObject +{ + Q_OBJECT +public: + C(); +}; + +#endif diff --git a/Tests/QtAutogen/staticLibraryCycle/main.cpp b/Tests/QtAutogen/staticLibraryCycle/main.cpp new file mode 100644 index 0000000..f5b7fd2 --- /dev/null +++ b/Tests/QtAutogen/staticLibraryCycle/main.cpp @@ -0,0 +1,8 @@ +#include "a.h" + +int main(int argv, char** args) +{ + // Object instances + A a; + return 0; +} diff --git a/Tests/RunCMake/CMP0040/CMP0040-WARN-missing-target-stderr.txt b/Tests/RunCMake/CMP0040/CMP0040-WARN-missing-target-stderr.txt index e3e3ff4..70ed05b 100644 --- a/Tests/RunCMake/CMP0040/CMP0040-WARN-missing-target-stderr.txt +++ b/Tests/RunCMake/CMP0040/CMP0040-WARN-missing-target-stderr.txt @@ -1,8 +1,8 @@ CMake Warning \(dev\) at CMP0040-WARN-missing-target.cmake:2 \(add_custom_command\): Policy CMP0040 is not set: The target in the TARGET signature of - add_custom_command\(\) must exist. Run "cmake --help-policy CMP0040" for - policy details. Use the cmake_policy command to set the policy and - suppress this warning. + add_custom_command\(\) must exist and must be defined in the current + directory. Run "cmake --help-policy CMP0040" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. + No TARGET 'foobar' has been created in this directory. Call Stack \(most recent call first\): |