diff options
33 files changed, 320 insertions, 15 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 1fcf06c..5fe4326 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -87,6 +87,11 @@ The options are: :ref:`Target-dependent expressions <Target-Dependent Queries>` are not permitted. + .. versionchanged:: 3.28 + In targets using :ref:`file sets`, custom command byproducts are now + considered private unless they are listed in a non-private file set. + See policy :policy:`CMP0154`. + ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, @@ -270,6 +275,11 @@ The options are: :ref:`Target-dependent expressions <Target-Dependent Queries>` are not permitted. + .. versionchanged:: 3.28 + In targets using :ref:`file sets`, custom command outputs are now + considered private unless they are listed in a non-private file set. + See policy :policy:`CMP0154`. + ``USES_TERMINAL`` .. versionadded:: 3.2 diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst index ef0c8d9..0385a93 100644 --- a/Help/command/add_custom_target.rst +++ b/Help/command/add_custom_target.rst @@ -63,6 +63,11 @@ The options are: :ref:`Target-dependent expressions <Target-Dependent Queries>` are not permitted. + .. versionchanged:: 3.28 + In custom targets using :ref:`file sets`, byproducts are now + considered private unless they are listed in a non-private file set. + See policy :policy:`CMP0154`. + ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst index 4a8eda2..86bf7fb 100644 --- a/Help/command/target_sources.rst +++ b/Help/command/target_sources.rst @@ -60,6 +60,8 @@ expressions to ensure the sources are correctly assigned to the target. See the :manual:`cmake-buildsystem(7)` manual for more on defining buildsystem properties. +.. _`File Sets`: + File Sets ^^^^^^^^^ diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index a018aff..dff4f34 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.28 .. toctree:: :maxdepth: 1 + CMP0154: Generated files are private by default in targets using file sets. </policy/CMP0154> CMP0153: The exec_program command should not be called. </policy/CMP0153> CMP0152: file(REAL_PATH) resolves symlinks before collapsing ../ components. </policy/CMP0152> diff --git a/Help/policy/CMP0154.rst b/Help/policy/CMP0154.rst new file mode 100644 index 0000000..cb93d41 --- /dev/null +++ b/Help/policy/CMP0154.rst @@ -0,0 +1,53 @@ +CMP0154 +------- + +.. versionadded:: 3.28 + +Generated files are private by default in targets using :ref:`file sets`. + +CMake 3.27 and below assume that any file generated as an output or byproduct +of :command:`add_custom_command` or :command:`add_custom_target` may be a +public header file meant for inclusion by dependents' source files. This +requires :ref:`Ninja Generators` to add conservative order-only dependencies +that prevent a target's source files from compiling before custom commands +from the target's dependencies are finished, even if those custom commands +only produce sources private to their own target. + +:ref:`File Sets`, introduced by CMake 3.23, provide a way to express the +visibility of generated header files. CMake 3.28 and above prefer to +assume that, in targets using file sets, generated files are private to +their own target by default. Generated public headers must be specified +as members of a ``PUBLIC`` (or ``INTERFACE``) ``FILE_SET``, typically of +type ``HEADERS``. With this information, :ref:`Ninja Generators` may omit +the above-mentioned conservative dependencies and produce more efficient +build graphs. + +This policy provides compatibility for projects using file sets in targets +with generated header files that have not been updated. Such projects +should be updated to express generated public headers in a file set. +For example: + +.. code-block:: cmake + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h + ... + ) + target_sources(foo + PUBLIC FILE_SET HEADERS + BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR} + FILES ${CMAKE_CURRENT_BINARY_DIR}/foo.h + ) + +The ``OLD`` behavior for this policy is to assume generated files are +public, even in targets using file sets, and for :ref:`Ninja Generators` +to produce conservative build graphs. The ``NEW`` behavior for this +policy is to assume generated files are private in targets using file sets, +and for :ref:`Ninja Generators` to produce more efficient build graphs. + +This policy was introduced in CMake version 3.28. 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/release/dev/fileset-private-dep.rst b/Help/release/dev/fileset-private-dep.rst new file mode 100644 index 0000000..5ffb036 --- /dev/null +++ b/Help/release/dev/fileset-private-dep.rst @@ -0,0 +1,7 @@ +fileset-private-dep +------------------- + +* Generated files, in targets using :ref:`file sets`, are now considered + private by default. Generated public headers must be specified using + file sets. This allows :ref:`Ninja Generators` to produce more + efficient build graphs. See policy :policy:`CMP0154`. diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 30305a1..7368a6a 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1278,6 +1278,13 @@ std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget( return cmStrCat("cmake_object_order_depends_target_", target->GetName()); } +std::string cmGlobalNinjaGenerator::OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const +{ + return cmStrCat(this->OrderDependsTargetForTarget(target, config), + "_private"); +} + void cmGlobalNinjaGenerator::AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, const std::string& config, cmNinjaTargetDepends depends) const @@ -3176,3 +3183,10 @@ std::string cmGlobalNinjaMultiGenerator::OrderDependsTargetForTarget( return cmStrCat("cmake_object_order_depends_target_", target->GetName(), '_', cmSystemTools::UpperCase(config)); } + +std::string cmGlobalNinjaMultiGenerator::OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const +{ + return cmStrCat(this->OrderDependsTargetForTarget(target, config), + "_private"); +} diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index c43e27c..56a922c 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -349,6 +349,9 @@ public: virtual std::string OrderDependsTargetForTarget( cmGeneratorTarget const* target, const std::string& config) const; + virtual std::string OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const; + void AppendTargetOutputs(cmGeneratorTarget const* target, cmNinjaDeps& outputs, const std::string& config, cmNinjaTargetDepends depends) const; @@ -738,6 +741,9 @@ public: std::string OrderDependsTargetForTarget( cmGeneratorTarget const* target, const std::string& config) const override; + std::string OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const override; + protected: bool OpenBuildFileStreams() override; void CloseBuildFileStreams() override; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 6187543..193cc0f 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -38,6 +38,7 @@ #include "cmNinjaNormalTargetGenerator.h" #include "cmNinjaUtilityTargetGenerator.h" #include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -169,6 +170,13 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget( this->GeneratorTarget, config); } +std::string cmNinjaTargetGenerator::OrderDependsTargetForTargetPrivate( + const std::string& config) +{ + return this->GetGlobalGenerator()->OrderDependsTargetForTargetPrivate( + this->GeneratorTarget, config); +} + // TODO: Most of the code is picked up from // void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink), // void cmMakefileTargetGenerator::WriteTargetLanguageFlags() @@ -1020,6 +1028,45 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( cmStrCat("Order-only phony target for ", this->GetTargetName()); build.Outputs.push_back(this->OrderDependsTargetForTarget(config)); + // Gather order-only dependencies on custom command outputs. + std::vector<std::string> ccouts; + std::vector<std::string> ccouts_private; + bool usePrivateGeneratedSources = false; + if (this->GeneratorTarget->Target->HasFileSets()) { + switch (this->GetGeneratorTarget()->GetPolicyStatusCMP0154()) { + case cmPolicies::WARN: + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + usePrivateGeneratedSources = true; + break; + } + } + for (cmCustomCommand const* cc : customCommands) { + cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); + const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); + const std::vector<std::string>& ccbyproducts = ccg.GetByproducts(); + ccouts.insert(ccouts.end(), ccoutputs.begin(), ccoutputs.end()); + ccouts.insert(ccouts.end(), ccbyproducts.begin(), ccbyproducts.end()); + if (usePrivateGeneratedSources) { + auto it = ccouts.begin(); + while (it != ccouts.end()) { + cmFileSet const* fileset = + this->GeneratorTarget->GetFileSetForSource( + config, this->Makefile->GetOrCreateGeneratedSource(*it)); + if (fileset && + fileset->GetVisibility() != cmFileSetVisibility::Private) { + ++it; + } else { + ccouts_private.push_back(*it); + it = ccouts.erase(it); + } + } + } + } + cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends( this->GeneratorTarget, orderOnlyDeps, config, fileConfig, @@ -1029,17 +1076,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( cm::append(orderOnlyDeps, this->Configs[config].ExtraFiles); // Add order-only dependencies on custom command outputs. - for (cmCustomCommand const* cc : customCommands) { - cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); - const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); - const std::vector<std::string>& ccbyproducts = ccg.GetByproducts(); - std::transform(ccoutputs.begin(), ccoutputs.end(), - std::back_inserter(orderOnlyDeps), - this->MapToNinjaPath()); - std::transform(ccbyproducts.begin(), ccbyproducts.end(), - std::back_inserter(orderOnlyDeps), - this->MapToNinjaPath()); - } + std::transform(ccouts.begin(), ccouts.end(), + std::back_inserter(orderOnlyDeps), this->MapToNinjaPath()); std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end()); orderOnlyDeps.erase( @@ -1060,8 +1098,32 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig), build); - } + // Add order-only dependencies on custom command outputs that are + // private to this target. + this->HasPrivateGeneratedSources = !ccouts_private.empty(); + if (this->HasPrivateGeneratedSources) { + cmNinjaBuild buildPrivate("phony"); + cmNinjaDeps& orderOnlyDepsPrivate = buildPrivate.OrderOnlyDeps; + orderOnlyDepsPrivate.push_back( + this->OrderDependsTargetForTarget(config)); + + buildPrivate.Outputs.push_back( + this->OrderDependsTargetForTargetPrivate(config)); + + std::transform(ccouts_private.begin(), ccouts_private.end(), + std::back_inserter(orderOnlyDepsPrivate), + this->MapToNinjaPath()); + + std::sort(orderOnlyDepsPrivate.begin(), orderOnlyDepsPrivate.end()); + orderOnlyDepsPrivate.erase( + std::unique(orderOnlyDepsPrivate.begin(), orderOnlyDepsPrivate.end()), + orderOnlyDepsPrivate.end()); + + this->GetGlobalGenerator()->WriteBuild( + this->GetImplFileStream(fileConfig), buildPrivate); + } + } { std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, config); @@ -1388,7 +1450,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->MapToNinjaPath()); } - objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config)); + if (this->HasPrivateGeneratedSources) { + objBuild.OrderOnlyDeps.push_back( + this->OrderDependsTargetForTargetPrivate(config)); + } else { + objBuild.OrderOnlyDeps.push_back( + this->OrderDependsTargetForTarget(config)); + } // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index d41d86e..3f56113 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -81,6 +81,7 @@ protected: bool CompileWithDefines(std::string const& lang) const; std::string OrderDependsTargetForTarget(const std::string& config); + std::string OrderDependsTargetForTargetPrivate(const std::string& config); std::string ComputeOrderDependsForTarget(); @@ -228,6 +229,7 @@ protected: private: cmLocalNinjaGenerator* LocalGenerator; + bool HasPrivateGeneratedSources = false; struct ScanningFiles { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 26c141d..e894073 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -465,7 +465,11 @@ class cmMakefile; "file(REAL_PATH) resolves symlinks before collapsing ../ components.", 3, \ 28, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0153, "The exec_program command should not be called.", \ - 3, 28, 0, cmPolicies::WARN) + 3, 28, 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0154, \ + "Generated files are private by default in targets using file sets.", 3, \ + 28, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -503,7 +507,8 @@ class cmMakefile; F(CMP0113) \ F(CMP0119) \ F(CMP0131) \ - F(CMP0142) + F(CMP0142) \ + F(CMP0154) #define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \ F(CMP0116) \ diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ace93e8..abbf29e 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -3201,6 +3201,11 @@ std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const return result; } +bool cmTarget::HasFileSets() const +{ + return !this->impl->FileSets.empty(); +} + bool cmTargetInternals::CheckImportedLibName(std::string const& prop, std::string const& value) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b77ea0c..584856a 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -321,6 +321,8 @@ public: static std::string GetFileSetsPropertyName(const std::string& type); static std::string GetInterfaceFileSetsPropertyName(const std::string& type); + bool HasFileSets() const; + private: template <typename ValueType> void StoreProperty(const std::string& prop, ValueType value); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 9b9a53e..62c9628 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -242,6 +242,9 @@ if(CMAKE_GENERATOR MATCHES "Ninja") add_RunCMake_test(NinjaMultiConfig) set_property(TEST RunCMake.NinjaMultiConfig APPEND PROPERTY LABELS "CUDA") + add_RunCMake_test(NinjaPrivateDeps + -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION} + -DRunCMake_GENERATOR_IS_MULTI_CONFIG=${_isMultiConfig}) endif() add_RunCMake_test(CTest) diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-EmptyFileSet-Source-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-EmptyFileSet-Source-check.cmake new file mode 100644 index 0000000..7658930 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-EmptyFileSet-Source-check.cmake @@ -0,0 +1,3 @@ +if (EXISTS ${RunCMake_TEST_BINARY_DIR}/empty.cpp) + set(RunCMake_TEST_FAILED "Compiled source generated before compilation of consumers.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-EmptyFileSet-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-EmptyFileSet-check.cmake new file mode 100644 index 0000000..3287a65 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-EmptyFileSet-check.cmake @@ -0,0 +1,3 @@ +if (NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/empty.cpp) + set(RunCMake_TEST_FAILED "Compiled source did not generate.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-NoFileSet-Source-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-NoFileSet-Source-check.cmake new file mode 100644 index 0000000..9e99ed8 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-NoFileSet-Source-check.cmake @@ -0,0 +1,3 @@ +if (NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/none.cpp) + set(RunCMake_TEST_FAILED "Private source dependency used for target without filesets.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PrivateFileSet-Source-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PrivateFileSet-Source-check.cmake new file mode 100644 index 0000000..dd814c9 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PrivateFileSet-Source-check.cmake @@ -0,0 +1,3 @@ +if (EXISTS ${RunCMake_TEST_BINARY_DIR}/private.h) + set(RunCMake_TEST_FAILED "Private header generated before compilation.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PrivateFileSet-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PrivateFileSet-check.cmake new file mode 100644 index 0000000..357b8c0 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PrivateFileSet-check.cmake @@ -0,0 +1,3 @@ +if (NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/private.h) + set(RunCMake_TEST_FAILED "Private header generated before compilation.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PublicFileSet-Source-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PublicFileSet-Source-check.cmake new file mode 100644 index 0000000..cfceb7a --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW-Build-PublicFileSet-Source-check.cmake @@ -0,0 +1,3 @@ +if (NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/public.h) + set(RunCMake_TEST_FAILED "Public header did not generate before compilation.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW.cmake new file mode 100644 index 0000000..3330269 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0154 NEW) +include(CMP0154-common.cmake) diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-Build-EmptyFileSet-Source-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-Build-EmptyFileSet-Source-check.cmake new file mode 100644 index 0000000..8ee1ad4 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-Build-EmptyFileSet-Source-check.cmake @@ -0,0 +1,3 @@ +if (NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/empty.cpp) + set(RunCMake_TEST_FAILED "Policy CMP0154 set to OLD but using new behavior compiled sources.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-Build-PrivateFileSet-Source-check.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-Build-PrivateFileSet-Source-check.cmake new file mode 100644 index 0000000..25c23d7 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD-Build-PrivateFileSet-Source-check.cmake @@ -0,0 +1,3 @@ +if (NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/private.h) + set(RunCMake_TEST_FAILED "Policy CMP0154 set to OLD but using new behavior private headers.") +endif() diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD.cmake new file mode 100644 index 0000000..691530c --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0154 OLD) +include(CMP0154-common.cmake) diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMP0154-common.cmake b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-common.cmake new file mode 100644 index 0000000..a9e6d20 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMP0154-common.cmake @@ -0,0 +1,45 @@ +enable_language(CXX) + +function(copy_file file dest) + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/${dest} + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/${file} ${CMAKE_BINARY_DIR}/${dest} + ) +endfunction() + +copy_file(header.h.in private.h) +copy_file(header.h.in public.h) +copy_file(source.cpp.in empty.cpp) +copy_file(source.cpp.in none.cpp) + +add_library(HelloLib_PrivateFileSet STATIC hello_lib.cpp) +target_sources(HelloLib_PrivateFileSet + PRIVATE FILE_SET HEADERS + BASE_DIRS ${CMAKE_BINARY_DIR} + FILES ${CMAKE_BINARY_DIR}/private.h +) + +add_library(HelloLib_PublicFileSet STATIC hello_lib.cpp) +target_sources(HelloLib_PublicFileSet + PUBLIC FILE_SET HEADERS + BASE_DIRS ${CMAKE_BINARY_DIR} + FILES ${CMAKE_BINARY_DIR}/public.h +) + +add_library(HelloLib_EmptyFileSet STATIC hello_lib.cpp empty.cpp) +target_sources(HelloLib_EmptyFileSet + PUBLIC FILE_SET HEADERS +) + +add_library(HelloLib_NoFileSet STATIC hello_lib.cpp none.cpp) + +function(hello_executable name) + add_executable(Hello_${name} hello.cpp) + target_link_libraries(Hello_${name} PRIVATE HelloLib_${name}) +endfunction() + +hello_executable(PrivateFileSet) +hello_executable(PublicFileSet) +hello_executable(EmptyFileSet) +hello_executable(NoFileSet) diff --git a/Tests/RunCMake/NinjaPrivateDeps/CMakeLists.txt b/Tests/RunCMake/NinjaPrivateDeps/CMakeLists.txt new file mode 100644 index 0000000..54a4d62 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.26) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/NinjaPrivateDeps/RunCMakeTest.cmake b/Tests/RunCMake/NinjaPrivateDeps/RunCMakeTest.cmake new file mode 100644 index 0000000..e821185 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/RunCMakeTest.cmake @@ -0,0 +1,30 @@ +include(RunCMake) + +function(compile_source test target) + if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(config "Debug/") + endif() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-Build-${target}-Source ${CMAKE_COMMAND} --build . + --target CMakeFiles/Hello_${target}.dir/${config}hello.cpp${CMAKE_C_OUTPUT_EXTENSION}) +endfunction() + +function(compile_target test target) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-Build-${target} ${CMAKE_COMMAND} --build . + --target Hello_${target}) +endfunction() + +run_cmake(CMP0154-OLD) +compile_source(CMP0154-OLD PrivateFileSet) +compile_source(CMP0154-OLD EmptyFileSet) + +run_cmake(CMP0154-NEW) +compile_source(CMP0154-NEW PrivateFileSet) +compile_target(CMP0154-NEW PrivateFileSet) +compile_source(CMP0154-NEW PublicFileSet) +compile_source(CMP0154-NEW NoFileSet) +compile_source(CMP0154-NEW EmptyFileSet) +compile_target(CMP0154-NEW EmptyFileSet) diff --git a/Tests/RunCMake/NinjaPrivateDeps/header.h.in b/Tests/RunCMake/NinjaPrivateDeps/header.h.in new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/header.h.in diff --git a/Tests/RunCMake/NinjaPrivateDeps/hello.cpp b/Tests/RunCMake/NinjaPrivateDeps/hello.cpp new file mode 100644 index 0000000..34fabe9 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/hello.cpp @@ -0,0 +1,6 @@ +#include "hello_lib.h" + +int main() +{ + say_hello(); +} diff --git a/Tests/RunCMake/NinjaPrivateDeps/hello_lib.cpp b/Tests/RunCMake/NinjaPrivateDeps/hello_lib.cpp new file mode 100644 index 0000000..d67113f --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/hello_lib.cpp @@ -0,0 +1,8 @@ +#include "hello_lib.h" + +#include <iostream> + +void say_hello() +{ + std::cout << "hello" << std::endl; +} diff --git a/Tests/RunCMake/NinjaPrivateDeps/hello_lib.h b/Tests/RunCMake/NinjaPrivateDeps/hello_lib.h new file mode 100644 index 0000000..3b4775f --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/hello_lib.h @@ -0,0 +1 @@ +void say_hello(); diff --git a/Tests/RunCMake/NinjaPrivateDeps/source.cpp.in b/Tests/RunCMake/NinjaPrivateDeps/source.cpp.in new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/NinjaPrivateDeps/source.cpp.in diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 0d8e4c9..7e91b76 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -37,6 +37,7 @@ \* CMP0119 \* CMP0131 \* CMP0142 + \* CMP0154 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) |