Forráskód Böngészése

CMP0115: Require source file extensions to be explicit

Kyle Edwards 5 éve
szülő
commit
fd50a75fa0

+ 8 - 0
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
 to determine whether to report an error on use of deprecated macros or
 functions.
 functions.
 
 
+Policies Introduced by CMake 3.20
+=================================
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0115: Source file extensions must be explicit. </policy/CMP0115>
+
 Policies Introduced by CMake 3.19
 Policies Introduced by CMake 3.19
 =================================
 =================================
 
 

+ 34 - 0
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

+ 5 - 0
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.

+ 6 - 2
Source/cmGeneratorTarget.cxx

@@ -1539,10 +1539,14 @@ bool processSources(cmGeneratorTarget const* tgt,
     for (std::string& src : entry.Values) {
     for (std::string& src : entry.Values) {
       cmSourceFile* sf = mf->GetOrCreateSource(src);
       cmSourceFile* sf = mf->GetOrCreateSource(src);
       std::string e;
       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 (fullPath.empty()) {
         if (!e.empty()) {
         if (!e.empty()) {
-          cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
           cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace());
           cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace());
         }
         }
         return contextDependent;
         return contextDependent;

+ 3 - 1
Source/cmPolicies.h

@@ -340,7 +340,9 @@ class cmMakefile;
          3, 19, 0, cmPolicies::WARN)                                          \
          3, 19, 0, cmPolicies::WARN)                                          \
   SELECT(POLICY, CMP0114,                                                     \
   SELECT(POLICY, CMP0114,                                                     \
          "ExternalProject step targets fully adopt their steps.", 3, 19, 0,   \
          "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_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \

+ 45 - 16
Source/cmSourceFile.cxx

@@ -8,6 +8,7 @@
 #include "cmListFileCache.h"
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmMessageType.h"
+#include "cmPolicies.h"
 #include "cmProperty.h"
 #include "cmProperty.h"
 #include "cmState.h"
 #include "cmState.h"
 #include "cmStringAlgorithms.h"
 #include "cmStringAlgorithms.h"
@@ -93,10 +94,11 @@ cmSourceFileLocation const& cmSourceFile::GetLocation() const
   return this->Location;
   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->FullPath.empty()) {
-    if (this->FindFullPath(error)) {
+    if (this->FindFullPath(error, cmp0115Warning)) {
       this->CheckExtension();
       this->CheckExtension();
     }
     }
   }
   }
@@ -108,7 +110,8 @@ std::string const& cmSourceFile::GetFullPath() const
   return this->FullPath;
   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 the file is generated compute the location without checking on disk.
   if (this->GetIsGenerated()) {
   if (this->GetIsGenerated()) {
@@ -131,9 +134,11 @@ bool cmSourceFile::FindFullPath(std::string* error)
   // List of extension lists
   // List of extension lists
   std::vector<std::string> exts =
   std::vector<std::string> exts =
     makefile->GetCMakeInstance()->GetAllExtensions();
     makefile->GetCMakeInstance()->GetAllExtensions();
+  auto cmp0115 = makefile->GetPolicyStatus(cmPolicies::CMP0115);
 
 
   // Tries to find the file in a given directory
   // 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
     // Compute full path
     std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir);
     std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir);
     // Try full path
     // Try full path
@@ -141,13 +146,29 @@ bool cmSourceFile::FindFullPath(std::string* error)
       this->FullPath = fullPath;
       this->FullPath = fullPath;
       return true;
       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
   // 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) {
   if (error != nullptr) {
     *error = std::move(err);
     *error = std::move(err);

+ 3 - 2
Source/cmSourceFile.h

@@ -77,7 +77,8 @@ public:
    * Resolves the full path to the file.  Attempts to locate the file on disk
    * Resolves the full path to the file.  Attempts to locate the file on disk
    * and finalizes its location.
    * 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
    * The resolved full path to the file.  The returned file name might be empty
@@ -138,7 +139,7 @@ private:
   bool FindFullPathFailed = false;
   bool FindFullPathFailed = false;
   bool IsGenerated = false;
   bool IsGenerated = false;
 
 
-  bool FindFullPath(std::string* error);
+  bool FindFullPath(std::string* error, std::string* cmp0115Warning);
   void CheckExtension();
   void CheckExtension();
   void CheckLanguage(std::string const& ext);
   void CheckLanguage(std::string const& ext);
 
 

+ 1 - 0
Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt

@@ -0,0 +1 @@
+1

+ 17 - 0
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\.$

+ 1 - 0
Tests/RunCMake/CMP0115/CMP0115-NEW.cmake

@@ -0,0 +1 @@
+include(CMP0115.cmake)

+ 1 - 0
Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt

@@ -0,0 +1 @@
+1

+ 22 - 0
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\.$

+ 1 - 0
Tests/RunCMake/CMP0115/CMP0115-OLD.cmake

@@ -0,0 +1 @@
+include(CMP0115.cmake)

+ 1 - 0
Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt

@@ -0,0 +1 @@
+1

+ 36 - 0
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\.$

+ 1 - 0
Tests/RunCMake/CMP0115/CMP0115-WARN.cmake

@@ -0,0 +1 @@
+include(CMP0115.cmake)

+ 3 - 0
Tests/RunCMake/CMP0115/CMP0115.cmake

@@ -0,0 +1,3 @@
+enable_language(C)
+
+add_executable(exe main noexist)

+ 3 - 0
Tests/RunCMake/CMP0115/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 12 - 0
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)

+ 4 - 0
Tests/RunCMake/CMP0115/main.c

@@ -0,0 +1,4 @@
+int main(void)
+{
+  return 0;
+}

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -125,6 +125,7 @@ if(CMake_TEST_CUDA)
 endif()
 endif()
 add_RunCMake_test(CMP0106)
 add_RunCMake_test(CMP0106)
 add_RunCMake_test(CMP0111)
 add_RunCMake_test(CMP0111)
+add_RunCMake_test(CMP0115)
 
 
 # The test for Policy 65 requires the use of the
 # The test for Policy 65 requires the use of the
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode