From fd50a75fa01b4727a58350b494dbb23f6b0f103f Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 7 Oct 2020 14:05:34 -0400 Subject: CMP0115: Require source file extensions to be explicit --- Help/manual/cmake-policies.7.rst | 8 ++++ Help/policy/CMP0115.rst | 34 ++++++++++++++ Help/release/dev/explicit-source-extensions.rst | 5 ++ Source/cmGeneratorTarget.cxx | 8 +++- Source/cmPolicies.h | 4 +- Source/cmSourceFile.cxx | 61 ++++++++++++++++++------- Source/cmSourceFile.h | 5 +- Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt | 1 + Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt | 17 +++++++ Tests/RunCMake/CMP0115/CMP0115-NEW.cmake | 1 + Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt | 1 + Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt | 22 +++++++++ Tests/RunCMake/CMP0115/CMP0115-OLD.cmake | 1 + Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt | 1 + Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt | 36 +++++++++++++++ Tests/RunCMake/CMP0115/CMP0115-WARN.cmake | 1 + Tests/RunCMake/CMP0115/CMP0115.cmake | 3 ++ Tests/RunCMake/CMP0115/CMakeLists.txt | 3 ++ Tests/RunCMake/CMP0115/RunCMakeTest.cmake | 12 +++++ Tests/RunCMake/CMP0115/main.c | 4 ++ Tests/RunCMake/CMakeLists.txt | 1 + 21 files changed, 208 insertions(+), 21 deletions(-) create mode 100644 Help/policy/CMP0115.rst create mode 100644 Help/release/dev/explicit-source-extensions.rst create mode 100644 Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0115/CMP0115-NEW.cmake create mode 100644 Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt create mode 100644 Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0115/CMP0115-OLD.cmake create mode 100644 Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt create mode 100644 Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0115/CMP0115-WARN.cmake create mode 100644 Tests/RunCMake/CMP0115/CMP0115.cmake create mode 100644 Tests/RunCMake/CMP0115/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0115/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CMP0115/main.c diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 0392325..0836883 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.20 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0115: Source file extensions must be explicit. + Policies Introduced by CMake 3.19 ================================= diff --git a/Help/policy/CMP0115.rst b/Help/policy/CMP0115.rst new file mode 100644 index 0000000..7f82c43 --- /dev/null +++ b/Help/policy/CMP0115.rst @@ -0,0 +1,34 @@ +CMP0115 +------- + +.. versionadded:: 3.20 + +Source file extensions must be explicit. + +In CMake 3.19 and below, if a source file could not be found by the name +specified, it would append a list of known extensions to the name to see if +the file with the extension could be found. For example, this would allow the +user to run: + +.. code-block:: cmake + + add_executable(exe main) + +and put ``main.c`` in the executable without specifying the extension. + +Starting in CMake 3.20, CMake prefers all source files to have their extensions +explicitly listed: + +.. code-block:: cmake + + add_executable(exe main.c) + +The ``OLD`` behavior for this policy is to implicitly append known extensions +to source files if they can't be found. The ``NEW`` behavior of this policy is +to not append known extensions and require them to be explicit. + +This policy was introduced in CMake version 3.20. 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/release/dev/explicit-source-extensions.rst b/Help/release/dev/explicit-source-extensions.rst new file mode 100644 index 0000000..ccd9339 --- /dev/null +++ b/Help/release/dev/explicit-source-extensions.rst @@ -0,0 +1,5 @@ +explicit-source-extensions +-------------------------- + +* Source file extensions must now be explicit. See policy :policy:`CMP0115` for + details. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6ebc9e1..3b47550 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1539,10 +1539,14 @@ bool processSources(cmGeneratorTarget const* tgt, for (std::string& src : entry.Values) { cmSourceFile* sf = mf->GetOrCreateSource(src); std::string e; - std::string fullPath = sf->ResolveFullPath(&e); + std::string w; + std::string fullPath = sf->ResolveFullPath(&e, &w); + cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance(); + if (!w.empty()) { + cm->IssueMessage(MessageType::AUTHOR_WARNING, w, tgt->GetBacktrace()); + } if (fullPath.empty()) { if (!e.empty()) { - cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance(); cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace()); } return contextDependent; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 958d061..f9f7d0e 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -340,7 +340,9 @@ class cmMakefile; 3, 19, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0114, \ "ExternalProject step targets fully adopt their steps.", 3, 19, 0, \ - cmPolicies::WARN) + cmPolicies::WARN) \ + SELECT(POLICY, CMP0115, "Source file extensions must be explicit.", 3, 20, \ + 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/cmSourceFile.cxx b/Source/cmSourceFile.cxx index ef44a57..61f48e9 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -8,6 +8,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -93,10 +94,11 @@ cmSourceFileLocation const& cmSourceFile::GetLocation() const return this->Location; } -std::string const& cmSourceFile::ResolveFullPath(std::string* error) +std::string const& cmSourceFile::ResolveFullPath(std::string* error, + std::string* cmp0115Warning) { if (this->FullPath.empty()) { - if (this->FindFullPath(error)) { + if (this->FindFullPath(error, cmp0115Warning)) { this->CheckExtension(); } } @@ -108,7 +110,8 @@ std::string const& cmSourceFile::GetFullPath() const return this->FullPath; } -bool cmSourceFile::FindFullPath(std::string* error) +bool cmSourceFile::FindFullPath(std::string* error, + std::string* cmp0115Warning) { // If the file is generated compute the location without checking on disk. if (this->GetIsGenerated()) { @@ -131,9 +134,11 @@ bool cmSourceFile::FindFullPath(std::string* error) // List of extension lists std::vector exts = makefile->GetCMakeInstance()->GetAllExtensions(); + auto cmp0115 = makefile->GetPolicyStatus(cmPolicies::CMP0115); // Tries to find the file in a given directory - auto findInDir = [this, &exts, &lPath](std::string const& dir) -> bool { + auto findInDir = [this, &exts, &lPath, cmp0115, cmp0115Warning, + makefile](std::string const& dir) -> bool { // Compute full path std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir); // Try full path @@ -141,13 +146,29 @@ bool cmSourceFile::FindFullPath(std::string* error) this->FullPath = fullPath; return true; } - // Try full path with extension - for (std::string const& ext : exts) { - if (!ext.empty()) { - std::string extPath = cmStrCat(fullPath, '.', ext); - if (cmSystemTools::FileExists(extPath)) { - this->FullPath = extPath; - return true; + // This has to be an if statement due to a bug in Oracle Developer Studio. + // See https://community.oracle.com/tech/developers/discussion/4476246/ + // for details. + if (cmp0115 == cmPolicies::OLD || cmp0115 == cmPolicies::WARN) { + // Try full path with extension + for (std::string const& ext : exts) { + if (!ext.empty()) { + std::string extPath = cmStrCat(fullPath, '.', ext); + if (cmSystemTools::FileExists(extPath)) { + this->FullPath = extPath; + if (cmp0115 == cmPolicies::WARN) { + std::string warning = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0115), + "\nFile:\n ", extPath); + if (cmp0115Warning) { + *cmp0115Warning = std::move(warning); + } else { + makefile->GetCMakeInstance()->IssueMessage( + MessageType::AUTHOR_WARNING, warning); + } + } + return true; + } } } } @@ -168,11 +189,19 @@ bool cmSourceFile::FindFullPath(std::string* error) } // Compose error - std::string err = - cmStrCat("Cannot find source file:\n ", lPath, "\nTried extensions"); - for (std::string const& ext : exts) { - err += " ."; - err += ext; + std::string err = cmStrCat("Cannot find source file:\n ", lPath); + switch (cmp0115) { + case cmPolicies::OLD: + case cmPolicies::WARN: + err = cmStrCat(err, "\nTried extensions"); + for (auto const& ext : exts) { + err = cmStrCat(err, " .", ext); + } + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + break; } if (error != nullptr) { *error = std::move(err); diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 39ea8e3..3196b3f 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -77,7 +77,8 @@ public: * Resolves the full path to the file. Attempts to locate the file on disk * and finalizes its location. */ - std::string const& ResolveFullPath(std::string* error = nullptr); + std::string const& ResolveFullPath(std::string* error = nullptr, + std::string* cmp0115Warning = nullptr); /** * The resolved full path to the file. The returned file name might be empty @@ -138,7 +139,7 @@ private: bool FindFullPathFailed = false; bool IsGenerated = false; - bool FindFullPath(std::string* error); + bool FindFullPath(std::string* error, std::string* cmp0115Warning); void CheckExtension(); void CheckLanguage(std::string const& ext); diff --git a/Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt b/Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt new file mode 100644 index 0000000..b63c53d --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt @@ -0,0 +1,17 @@ +^CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\): + Cannot find source file: + + main +Call Stack \(most recent call first\): + CMP0115-NEW\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\): + No SOURCES given to target: exe +Call Stack \(most recent call first\): + CMP0115-NEW\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Generate step failed\. Build files cannot be regenerated correctly\.$ diff --git a/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake b/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake new file mode 100644 index 0000000..ddf5071 --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake @@ -0,0 +1 @@ +include(CMP0115.cmake) diff --git a/Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt b/Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt new file mode 100644 index 0000000..8b90311 --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt @@ -0,0 +1,22 @@ +^CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\): + Cannot find source file: + + noexist + + Tried extensions [^ +]* + [^ +]* +Call Stack \(most recent call first\): + CMP0115-OLD\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\): + No SOURCES given to target: exe +Call Stack \(most recent call first\): + CMP0115-OLD\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Generate step failed\. Build files cannot be regenerated correctly\.$ diff --git a/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake b/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake new file mode 100644 index 0000000..ddf5071 --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake @@ -0,0 +1 @@ +include(CMP0115.cmake) diff --git a/Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt b/Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt new file mode 100644 index 0000000..7b100b6 --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt @@ -0,0 +1,36 @@ +^CMake Warning \(dev\) at CMP0115\.cmake:[0-9]+ \(add_executable\): + Policy CMP0115 is not set: Source file extensions must be explicit\. Run + "cmake --help-policy CMP0115" for policy details\. Use the cmake_policy + command to set the policy and suppress this warning\. + + File: + + [^ +]*/Tests/RunCMake/CMP0115/main\.c +Call Stack \(most recent call first\): + CMP0115-WARN\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\): + Cannot find source file: + + noexist + + Tried extensions [^ +]* + [^ +]* +Call Stack \(most recent call first\): + CMP0115-WARN\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\): + No SOURCES given to target: exe +Call Stack \(most recent call first\): + CMP0115-WARN\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Generate step failed\. Build files cannot be regenerated correctly\.$ diff --git a/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake b/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake new file mode 100644 index 0000000..ddf5071 --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake @@ -0,0 +1 @@ +include(CMP0115.cmake) diff --git a/Tests/RunCMake/CMP0115/CMP0115.cmake b/Tests/RunCMake/CMP0115/CMP0115.cmake new file mode 100644 index 0000000..be910a4 --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMP0115.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_executable(exe main noexist) diff --git a/Tests/RunCMake/CMP0115/CMakeLists.txt b/Tests/RunCMake/CMP0115/CMakeLists.txt new file mode 100644 index 0000000..b646c4a --- /dev/null +++ b/Tests/RunCMake/CMP0115/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.18) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0115/RunCMakeTest.cmake b/Tests/RunCMake/CMP0115/RunCMakeTest.cmake new file mode 100644 index 0000000..58182ac --- /dev/null +++ b/Tests/RunCMake/CMP0115/RunCMakeTest.cmake @@ -0,0 +1,12 @@ +include(RunCMake) + +function(run_cmp0115 status) + if(NOT status STREQUAL "WARN") + set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0115=${status}) + endif() + run_cmake(CMP0115-${status}) +endfunction() + +run_cmp0115(OLD) +run_cmp0115(WARN) +run_cmp0115(NEW) diff --git a/Tests/RunCMake/CMP0115/main.c b/Tests/RunCMake/CMP0115/main.c new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/RunCMake/CMP0115/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 63738d7..a8261c6 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -125,6 +125,7 @@ if(CMake_TEST_CUDA) endif() add_RunCMake_test(CMP0106) add_RunCMake_test(CMP0111) +add_RunCMake_test(CMP0115) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode -- cgit v0.12