diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 9f3de09654..7c41dedb6e 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -98,6 +98,7 @@ Policies Introduced by CMake 4.1 .. toctree:: :maxdepth: 1 + CMP0187: Include source file without an extension after the same name with an extension. CMP0186: Regular expressions match ^ at most once in repeated searches. Policies Introduced by CMake 4.0 diff --git a/Help/policy/CMP0187.rst b/Help/policy/CMP0187.rst new file mode 100644 index 0000000000..d833d84399 --- /dev/null +++ b/Help/policy/CMP0187.rst @@ -0,0 +1,33 @@ +CMP0187 +------- + +.. versionadded:: 4.1 + +Include source file without an extension after the same name with an extension. + +In CMake 4.0 and below, if two source files have the same filename and only one +file has a file extension and the file with the extension is listed first, the +file without the extension is omitted from the target. + +For example, the following library target only include ``hello.c`` in the +target, but omits the file ``hello``. + +.. code-block:: cmake + + add_library(library hello.c hello) + +If the file without the extension is listed before the file with the extension, +both files are included in the target. + +Starting in CMake 4.1, CMake includes both files in the library target. + +This policy has no effect if :policy:`CMP0115` uses the ``OLD`` behavior. + +The ``OLD`` behavior for this policy is to omit the file without the extension. +The ``NEW`` behavior for this policy is to include it. + +.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.1 +.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn +.. include:: STANDARD_ADVICE.txt + +.. include:: DEPRECATED.txt diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 5f5f383a7d..785acc02a0 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -558,7 +558,11 @@ class cmMakefile; WARN) \ SELECT(POLICY, CMP0186, \ "Regular expressions match ^ at most once in repeated searches.", 4, \ - 1, 0, WARN) + 1, 0, WARN) \ + SELECT(POLICY, CMP0187, \ + "Include source file without an extension after the same name with " \ + "an extension.", \ + 4, 1, 0, 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/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index b7b9770902..c9ba19edd8 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -9,11 +9,19 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" -cmSourceFileLocation::cmSourceFileLocation() = default; +// if CMP0187 and CMP0115 are NEW, then we assume that source files that do not +// include a file extension are not ambiguous but intentionally do not have an +// extension. +bool NoAmbiguousExtensions(cmMakefile const& makefile) +{ + return makefile.GetPolicyStatus(cmPolicies::CMP0115) == cmPolicies::NEW && + makefile.GetPolicyStatus(cmPolicies::CMP0187) == cmPolicies::NEW; +} cmSourceFileLocation::cmSourceFileLocation(cmSourceFileLocation const& loc) : Makefile(loc.Makefile) @@ -30,7 +38,12 @@ cmSourceFileLocation::cmSourceFileLocation(cmMakefile const* mf, : Makefile(mf) { this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name); - this->AmbiguousExtension = true; + // If ambiguous extensions are allowed then the extension is assumed to be + // ambiguous unless the name has an extension, in which case + // `UpdateExtension` will update this. If ambiguous extensions are not + // allowed, then set this to false as the file extension must be provided or + // the file doesn't have an extension. + this->AmbiguousExtension = !NoAmbiguousExtensions(*mf); this->Directory = cmSystemTools::GetFilenamePath(name); if (cmSystemTools::FileIsFullPath(this->Directory)) { this->Directory = cmSystemTools::CollapseFullPath(this->Directory); diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-build-result.txt b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-build-result.txt new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-build-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-stderr.txt b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-stderr.txt new file mode 100644 index 0000000000..ac1885ac8a --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD-stderr.txt @@ -0,0 +1,3 @@ +^CMake Deprecation Warning at CMP0187-NEW-CMP0115-OLD\.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0115 will be removed from a future version + of CMake\. diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD.cmake b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD.cmake new file mode 100644 index 0000000000..ee45dfbd5e --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-CMP0115-OLD.cmake @@ -0,0 +1,4 @@ +cmake_policy(SET CMP0115 OLD) +cmake_policy(SET CMP0187 NEW) + +include(CMP0187.cmake) diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW-build-result.txt b/Tests/RunCMake/CMP0187/CMP0187-NEW-build-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187-NEW-build-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0187/CMP0187-NEW.cmake b/Tests/RunCMake/CMP0187/CMP0187-NEW.cmake new file mode 100644 index 0000000000..a140325ee3 --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187-NEW.cmake @@ -0,0 +1,3 @@ +cmake_policy(SET CMP0187 NEW) + +include(CMP0187.cmake) diff --git a/Tests/RunCMake/CMP0187/CMP0187-OLD-build-result.txt b/Tests/RunCMake/CMP0187/CMP0187-OLD-build-result.txt new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187-OLD-build-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0187/CMP0187-OLD.cmake b/Tests/RunCMake/CMP0187/CMP0187-OLD.cmake new file mode 100644 index 0000000000..d48b4bb140 --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187-OLD.cmake @@ -0,0 +1,3 @@ +cmake_policy(SET CMP0187 OLD) + +include(CMP0187.cmake) diff --git a/Tests/RunCMake/CMP0187/CMP0187.cmake b/Tests/RunCMake/CMP0187/CMP0187.cmake new file mode 100644 index 0000000000..029d0c9546 --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMP0187.cmake @@ -0,0 +1,4 @@ +add_custom_command(OUTPUT z.h COMMAND ${CMAKE_COMMAND} -E true) +add_custom_command(OUTPUT z COMMAND ${CMAKE_COMMAND} -E false) + +add_library(lib INTERFACE z z.h) diff --git a/Tests/RunCMake/CMP0187/CMakeLists.txt b/Tests/RunCMake/CMP0187/CMakeLists.txt new file mode 100644 index 0000000000..7e8fde0b90 --- /dev/null +++ b/Tests/RunCMake/CMP0187/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 4.0) + +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0187/RunCMakeTest.cmake b/Tests/RunCMake/CMP0187/RunCMakeTest.cmake new file mode 100644 index 0000000000..f28cc704ac --- /dev/null +++ b/Tests/RunCMake/CMP0187/RunCMakeTest.cmake @@ -0,0 +1,34 @@ +include(RunCMake) + +block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0187-NEW-build) + run_cmake_with_options(CMP0187-NEW "-DCMAKE_POLICY_DEFAULT_CMP0187=NEW") + + if(RunCMake_GENERATOR MATCHES "Ninja.*") + set(RunCMake_TEST_NO_CLEAN 1) + # -n: dry-run to avoid actually compiling, -v: verbose to capture executed command + run_cmake_command(CMP0187-NEW-build ${CMAKE_COMMAND} --build .) + endif() +endblock() + +block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0187-OLD-build) + run_cmake_with_options(CMP0187-OLD "-DCMAKE_POLICY_DEFAULT_CMP0187=OLD") + + if(RunCMake_GENERATOR MATCHES "Ninja.*") + set(RunCMake_TEST_NO_CLEAN 1) + # -n: dry-run to avoid actually compiling, -v: verbose to capture executed command + run_cmake_command(CMP0187-OLD-build ${CMAKE_COMMAND} --build .) + endif() +endblock() + +block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0187-NEW-CMP0115-OLD-build) + run_cmake(CMP0187-NEW-CMP0115-OLD) + + if(RunCMake_GENERATOR MATCHES "Ninja.*") + set(RunCMake_TEST_NO_CLEAN 1) + # -n: dry-run to avoid actually compiling, -v: verbose to capture executed command + run_cmake_command(CMP0187-NEW-CMP0115-OLD-build ${CMAKE_COMMAND} --build .) + endif() +endblock() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 54fc875db5..fdf26cec6f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -179,6 +179,7 @@ add_RunCMake_test(CMP0169) add_RunCMake_test(CMP0170) add_RunCMake_test(CMP0171) add_RunCMake_test(CMP0173) +add_RunCMake_test(CMP0187) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode