custom rule: enhance output file set management

* Add control over output file set BASE_DIRS
* Add patterns for output file set directories
This commit is contained in:
Marc Chevrier committed 2026-10-16 16:53:19 +02:00
1 parent 1cdd7458c0
commit 8c0a8b0b4c
5 files changed
+69 -5

No files matched your search

+10 -2
View File
@@ -53,8 +53,10 @@ Generating Files
custom command will be declared as part of a file set attached to
the same target. The type of this file set, as well as its name, are
controlled by the :prop_rule:`OUTPUT_FILE_SET` rule property. This output
file set will have the same scope (``PRIVATE``, ``PUBLIC``, or ``INTERFACE``)
as the input file set.
file set will be created in the same directory and will have the same scope
(``PRIVATE``, ``PUBLIC``, or ``INTERFACE``) as the input file set. The base
directories can be specified by the :prop_rule:`OUTPUT_FILE_SET_BASE_DIRS`
rule property.
To parameterize the template, some patterns are defined which can be used as
part of the ``add_custom_rule`` arguments as well as the :ref:`rule's
@@ -90,6 +92,12 @@ Generating Files
``<CURRENT_BINARY_DIR>``
The path to the binary directory of the file set creation.
``<OUTPUT_CURRENT_SOURCE_DIR>``
The path to the source directory of the output file set creation.
``<OUTPUT_CURRENT_BINARY_DIR>``
The path to the binary directory of the output file set creation.
``<SOURCE>``
The full path of the current source file being processed.
+1
View File
@@ -131,6 +131,7 @@ Properties on Rules
/prop_rule/NAME
/prop_rule/OUTPUT
/prop_rule/OUTPUT_FILE_SET
/prop_rule/OUTPUT_FILE_SET_BASE_DIRS
/prop_rule/PARENT_RULE
/prop_rule/SOURCE_CONFIGURATORS
/prop_rule/USES_TERMINAL
@@ -0,0 +1,29 @@
OUTPUT_FILE_SET_BASE_DIRS
-------------------------
.. versionadded:: 4.5
Specify the base directories for the output file set.
The ``OUTPUT_FILE_SET_BASE_DIRS`` may be set to a
:ref:`semicolon-separated list <CMake Language Lists>` of directories.
The directories can use the following patterns:
* ``<RULE>``: name of the rule
* ``<TARGET>``: name of the target
* ``<FILE_SET>``: name of the file set
* ``<CURRENT_SOURCE_DIR>``: path to the source directory of the file set
creation
* ``<CURRENT_BINARY_DIR>``: path to the binary directory of the file set
creation
* ``<OUTPUT_CURRENT_SOURCE_DIR>``: path to the source directory of the output
file set creation
* ``<OUTPUT_CURRENT_BINARY_DIR>``: path to the binary directory of the output
file set creation
This property gets the following default value: ``<CURRENT_BINARY_DIR>``.
Contents of ``OUTPUT_FILE_SET_BASE_DIRS`` may use generator expressions with
the syntax ``$<...>``. See the cmake-buildsystem(7) manual for more on defining
buildsystem properties.
+4 -3
View File
@@ -36,6 +36,8 @@ std::vector<cm::string_view> ReservedPatterns{ "RULE"_s,
"BINARY_DIR"_s,
"CURRENT_SOURCE_DIR"_s,
"CURRENT_BINARY_DIR"_s,
"OUTPUT_CURRENT_SOURCE_DIR"_s,
"OUTPUT_CURRENT_BINARY_DIR"_s,
"SOURCE"_s,
"INPUT_DIR"_s,
"FILE_NAME"_s,
@@ -107,6 +109,8 @@ cmGeneratorRule::cmGeneratorRule(cmRule const* rule, cmTarget const* target,
values.insert({ "BINARY_DIR", this->GetMakefile().GetHomeOutputDirectory() });
values.insert({ "CURRENT_SOURCE_DIR", this->GetMakefile().GetCurrentSourceDirectory() });
values.insert({ "CURRENT_BINARY_DIR", this->GetMakefile().GetCurrentBinaryDirectory() });
values.insert({ "OUTPUT_CURRENT_SOURCE_DIR", outputFileSet->GetMakefile()->GetCurrentSourceDirectory() });
values.insert({ "OUTPUT_CURRENT_BINARY_DIR", outputFileSet->GetMakefile()->GetCurrentBinaryDirectory() });
values.insert({ "SOURCE", file.GenericString() });
values.insert({ "INPUT_DIR", file.GetParentPath().GenericString() });
values.insert({ "FILE_NAME", file.GetFileName().GenericString() });
@@ -306,9 +310,6 @@ std::unique_ptr<cmCustomCommand> cmGeneratorRule::Generate(
// populate file set with outputs from custom command
for (auto const& output : cc->GetOutputs()) {
outFileSet->AddFileEntry(BT<std::string>{ output });
// get the directory of the generated file
outFileSet->AddDirectoryEntry(
BT<std::string>{ cmStrCat("$<PATH:GET_PARENT_PATH,", output, '>') });
}
return cc;
+25
View File
@@ -47,6 +47,8 @@ cm::string_view const INCLUDE_DIRECTORIES = "INCLUDE_DIRECTORIES"_s;
cm::string_view const JOB_POOL_COMPILE = "JOB_POOL_COMPILE"_s;
cm::string_view const JOB_SERVER_AWARE = "JOB_SERVER_AWARE"_s;
cm::string_view const OUTPUT_FILE_SET = "OUTPUT_FILE_SET"_s;
cm::string_view const OUTPUT_FILE_SET_BASE_DIRS =
"OUTPUT_FILE_SET_BASE_DIRS"_s;
cm::string_view const PARENT_RULE = "PARENT_RULE"_s;
cm::string_view const FILE_SET_CONFIGURATORS = "FILE_SET_CONFIGURATORS"_s;
cm::string_view const SOURCE_CONFIGURATORS = "SOURCE_CONFIGURATORS"_s;
@@ -126,6 +128,7 @@ bool IsSettableProperty(cm::string_view prop, cmRule const* rule)
{ JOB_POOL_COMPILE, { ROC::Generation } },
{ JOB_SERVER_AWARE, { ROC::Generation } },
{ OUTPUT_FILE_SET, { ROC::Generation } },
{ OUTPUT_FILE_SET_BASE_DIRS, { ROC::Generation } },
{ PARENT_RULE, { ROC::All } },
{ FILE_SET_CONFIGURATORS, { ROC::All } },
{ SOURCE_CONFIGURATORS, { ROC::All } },
@@ -182,6 +185,7 @@ cmRule::cmRule(cmMakefile& makefile, std::string name, cm::RuleScope scope)
this->SetProperty("COMMAND_EXPAND_LISTS", cmValue::True);
this->SetProperty("OUTPUT_FILE_SET",
"__cmake_rule_<RULE>_<TARGET>_<FILE_SET>_outputs;SOURCES");
this->SetProperty("OUTPUT_FILE_SET_BASE_DIRS", "<CURRENT_BINARY_DIR>");
}
cmRule::cmRule(cmRule const& parent, cmMakefile& makefile, std::string name,
@@ -265,6 +269,27 @@ cmFileSet* cmRule::GetOutputFileSet(cmTarget* target,
return nullptr;
}
if (result.first->GetDirectoryEntries().empty()) {
if (cmValue baseDirs =
this->GetProperty(std::string{ OUTPUT_FILE_SET_BASE_DIRS })) {
expander.Values["CURRENT_SOURCE_DIR"] =
fileSet->GetMakefile()->GetCurrentSourceDirectory();
expander.Values["CURRENT_BINARY_DIR"] =
fileSet->GetMakefile()->GetCurrentBinaryDirectory();
expander.Values["OUTPUT_CURRENT_SOURCE_DIR"] =
result.first->GetMakefile()->GetCurrentSourceDirectory();
expander.Values["OUTPUT_CURRENT_BINARY_DIR"] =
result.first->GetMakefile()->GetCurrentBinaryDirectory();
std::string dirs{ baseDirs };
expander.ExpandVariables(dirs);
result.first->AddDirectoryEntry(BT<std::string>{ dirs });
} else {
// Add default base directory if none are specified
result.first->AddDirectoryEntry(BT<std::string>{
fileSet->GetMakefile()->GetCurrentBinaryDirectory() });
}
}
return result.first;
}