summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.gitlab/ci/docker/fedora34/install_deps.sh1
-rw-r--r--.gitlab/ci/env_fedora34_makefiles.cmake2
-rw-r--r--.gitlab/os-linux.yml2
-rw-r--r--Help/command/install.rst8
-rw-r--r--Help/manual/cmake-file-api.7.rst5
-rw-r--r--Help/release/dev/install-script-all-components.rst7
-rw-r--r--Help/release/dev/message-color.rst4
-rw-r--r--Modules/ExternalProject.cmake8
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx4
-rw-r--r--Source/CursesDialog/ccmake.cxx5
-rw-r--r--Source/QtDialog/QCMake.cxx5
-rw-r--r--Source/cmCommandLineArgument.h111
-rw-r--r--Source/cmFileAPICodemodel.cxx5
-rw-r--r--Source/cmGeneratorTarget.cxx29
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx77
-rw-r--r--Source/cmGlobalNinjaGenerator.h30
-rw-r--r--Source/cmInstallCommand.cxx12
-rw-r--r--Source/cmInstallDirectoryGenerator.cxx2
-rw-r--r--Source/cmInstallExportGenerator.cxx2
-rw-r--r--Source/cmInstallFilesGenerator.cxx2
-rw-r--r--Source/cmInstallGenerator.cxx18
-rw-r--r--Source/cmInstallGenerator.h5
-rw-r--r--Source/cmInstallScriptGenerator.cxx5
-rw-r--r--Source/cmInstallScriptGenerator.h2
-rw-r--r--Source/cmInstallSubdirectoryGenerator.cxx6
-rw-r--r--Source/cmInstallSubdirectoryGenerator.h1
-rw-r--r--Source/cmInstallTargetGenerator.cxx2
-rw-r--r--Source/cmLocalGenerator.cxx4
-rw-r--r--Source/cmLocalNinjaGenerator.cxx43
-rw-r--r--Source/cmLocalNinjaGenerator.h1
-rw-r--r--Source/cmMakefile.cxx2
-rw-r--r--Source/cmMessageMetadata.h11
-rw-r--r--Source/cmMessenger.cxx26
-rw-r--r--Source/cmNinjaTypes.h1
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx17
-rw-r--r--Source/cmSystemTools.cxx10
-rw-r--r--Source/cmSystemTools.h6
-rw-r--r--Source/cmake.cxx66
-rw-r--r--Source/cmakemain.cxx33
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake19
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-check.py4
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json54
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2.cmake1
-rw-r--r--Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt1
-rw-r--r--Tests/RunCMake/Framework/ImportedFrameworkTest.cmake10
-rw-r--r--Tests/RunCMake/Framework/RunCMakeTest.cmake12
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake2
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake2
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake2
-rw-r--r--Tests/RunCMake/install/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake1
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake1
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake1
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake5
64 files changed, 570 insertions, 170 deletions
diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh
index ece0666..dfd7db8 100755
--- a/.gitlab/ci/docker/fedora34/install_deps.sh
+++ b/.gitlab/ci/docker/fedora34/install_deps.sh
@@ -68,6 +68,7 @@ dnf install --setopt=install_weak_deps=False -y \
libuv-devel \
libxml2-devel \
libxslt-devel \
+ mpich-devel \
openmpi-devel \
patch \
perl \
diff --git a/.gitlab/ci/env_fedora34_makefiles.cmake b/.gitlab/ci/env_fedora34_makefiles.cmake
index 1d0efa7..aa84e23 100644
--- a/.gitlab/ci/env_fedora34_makefiles.cmake
+++ b/.gitlab/ci/env_fedora34_makefiles.cmake
@@ -1,2 +1,2 @@
set(ENV{MY_RUBY_HOME} "/usr/local/rvm/rubies/ruby-2.7.0")
-set(ENV{PATH} "/usr/lib64/openmpi/bin:$ENV{PATH}")
+set(ENV{PATH} "/usr/lib64/mpich/bin:$ENV{PATH}")
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 1bf4098..dcaa643 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -69,7 +69,7 @@
### Fedora
.fedora34:
- image: "kitware/cmake:ci-fedora34-x86_64-2021-05-10"
+ image: "kitware/cmake:ci-fedora34-x86_64-2021-05-21"
variables:
GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes"
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 993cf7f..2259176 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -619,7 +619,7 @@ Custom Installation Logic
.. code-block:: cmake
install([[SCRIPT <file>] [CODE <code>]]
- [COMPONENT <component>] [EXCLUDE_FROM_ALL] [...])
+ [COMPONENT <component>] [EXCLUDE_FROM_ALL] [ALL_COMPONENTS] [...])
The ``SCRIPT`` form will invoke the given CMake script files during
installation. If the script file name is a relative path it will be
@@ -634,6 +634,12 @@ example, the code
will print a message during installation.
+The option ``ALL_COMPONENTS``
+ .. versionadded:: 3.21
+
+ Run the custom installation script code for every component of a
+ component-specific installation.
+
.. versionadded:: 3.14
``<file>`` or ``<code>`` may use "generator expressions" with the syntax
``$<...>`` (in the case of ``<file>``, this refers to their use in the file
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst
index 445ebeb..0e530bc 100644
--- a/Help/manual/cmake-file-api.7.rst
+++ b/Help/manual/cmake-file-api.7.rst
@@ -751,6 +751,11 @@ with members:
Optional member that is present with boolean value ``true`` when
:command:`install` is called with the ``EXCLUDE_FROM_ALL`` option.
+ ``isForAllComponents``
+ Optional member that is present with boolean value ``true`` when
+ :command:`install(SCRIPT|CODE)` is called with the
+ ``ALL_COMPONENTS`` option.
+
``isOptional``
Optional member that is present with boolean value ``true`` when
:command:`install` is called with the ``OPTIONAL`` option.
diff --git a/Help/release/dev/install-script-all-components.rst b/Help/release/dev/install-script-all-components.rst
new file mode 100644
index 0000000..e421d3d
--- /dev/null
+++ b/Help/release/dev/install-script-all-components.rst
@@ -0,0 +1,7 @@
+install-script-all-components
+-----------------------------
+
+* The :command:`install(SCRIPT|CODE)` command
+ supports a new option ``ALL_COMPONENTS`` which allows
+ the corresponding code to run for every component of
+ a per component installation.
diff --git a/Help/release/dev/message-color.rst b/Help/release/dev/message-color.rst
new file mode 100644
index 0000000..4acf15e
--- /dev/null
+++ b/Help/release/dev/message-color.rst
@@ -0,0 +1,4 @@
+message-color
+-------------
+
+* Messages printed to a terminal now may be colored by message type.
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 026d1fc..9e25bee 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -2680,9 +2680,11 @@ function(_ep_add_download_command name)
get_property(git_progress TARGET ${name} PROPERTY _EP_GIT_PROGRESS)
get_property(git_config TARGET ${name} PROPERTY _EP_GIT_CONFIG)
- # Make checkouts quiet when checking out a git hash (this avoids the
- # very noisy detached head message)
- list(PREPEND git_config advice.detachedHead=false)
+ # If git supports it, make checkouts quiet when checking out a git hash.
+ # This avoids the very noisy detached head message.
+ if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7)
+ list(PREPEND git_config advice.detachedHead=false)
+ endif()
# For the download step, and the git clone operation, only the repository
# should be recorded in a configured RepositoryInfo file. If the repo
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index c19c154..bd9e4c2 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -638,6 +638,7 @@ set(SRCS
cmMathCommand.h
cmMessageCommand.cxx
cmMessageCommand.h
+ cmMessageMetadata.h
cmOptionCommand.cxx
cmOptionCommand.h
cmOutputRequiredFilesCommand.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index f559e04..e92c2a0 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 20)
-set(CMake_VERSION_PATCH 20210520)
+set(CMake_VERSION_PATCH 20210525)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index a18cbb4..adfc8ef 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -19,6 +19,8 @@
#include "cmWorkingDirectory.h"
#include "cmake.h"
+struct cmMessageMetadata;
+
cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
{
this->BuildTwoConfig = false;
@@ -125,7 +127,7 @@ public:
: CM(cm)
{
cmSystemTools::SetMessageCallback(
- [&s](const std::string& msg, const char* /*unused*/) {
+ [&s](const std::string& msg, const cmMessageMetadata& /* unused */) {
s += msg;
s += "\n";
});
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 85e256b..1ba45e5 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -19,6 +19,7 @@
#include "cmCursesStandardIncludes.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h" // IWYU pragma: keep
+#include "cmMessageMetadata.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -181,8 +182,8 @@ int main(int argc, char const* const* argv)
return msg;
};
cmSystemTools::SetMessageCallback(
- [&](const std::string& message, const char* title) {
- myform->AddError(cleanMessage(message), title);
+ [&](const std::string& message, const cmMessageMetadata& md) {
+ myform->AddError(cleanMessage(message), md.title);
});
cmSystemTools::SetStderrCallback([&](const std::string& message) {
myform->AddError(cleanMessage(message), "");
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index a83622a..e6faef4 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -13,6 +13,7 @@
#include "cmExternalMakefileProjectGenerator.h"
#include "cmGlobalGenerator.h"
+#include "cmMessageMetadata.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -37,8 +38,8 @@ QCMake::QCMake(QObject* p)
cmSystemTools::SetRunCommandHideConsole(true);
cmSystemTools::SetMessageCallback(
- [this](std::string const& msg, const char* title) {
- this->messageCallback(msg, title);
+ [this](std::string const& msg, const cmMessageMetadata& md) {
+ this->messageCallback(msg, md.title);
});
cmSystemTools::SetStdoutCallback(
[this](std::string const& msg) { this->stdoutCallback(msg); });
diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h
index 5031c65..72ab045 100644
--- a/Source/cmCommandLineArgument.h
+++ b/Source/cmCommandLineArgument.h
@@ -17,10 +17,25 @@ struct cmCommandLineArgument
OneOrMore
};
+ enum class RequiresSeparator
+ {
+ Yes,
+ No
+ };
+
+ enum class ParseMode
+ {
+ Valid,
+ Invalid,
+ SyntaxError,
+ ValueError
+ };
+
std::string InvalidSyntaxMessage;
std::string InvalidValueMessage;
std::string Name;
Values Type;
+ RequiresSeparator SeparatorNeeded;
std::function<FunctionSignature> StoreCall;
template <typename FunctionType>
@@ -29,6 +44,19 @@ struct cmCommandLineArgument
, InvalidValueMessage(cmStrCat("Invalid value used with ", n))
, Name(std::move(n))
, Type(t)
+ , SeparatorNeeded(RequiresSeparator::Yes)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, Values t, RequiresSeparator s,
+ FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
+ , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
+ , Name(std::move(n))
+ , Type(t)
+ , SeparatorNeeded(s)
, StoreCall(std::forward<FunctionType>(func))
{
}
@@ -40,14 +68,39 @@ struct cmCommandLineArgument
, InvalidValueMessage(std::move(failedMsg))
, Name(std::move(n))
, Type(t)
+ , SeparatorNeeded(RequiresSeparator::Yes)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
+ RequiresSeparator s, FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
+ , InvalidValueMessage(std::move(failedMsg))
+ , Name(std::move(n))
+ , Type(t)
+ , SeparatorNeeded(s)
, StoreCall(std::forward<FunctionType>(func))
{
}
bool matches(std::string const& input) const
{
- return (this->Type == Values::Zero) ? (input == this->Name)
- : cmHasPrefix(input, this->Name);
+ bool matched = false;
+ if (this->Type == Values::Zero) {
+ matched = (input == this->Name);
+ } else if (this->SeparatorNeeded == RequiresSeparator::No) {
+ matched = cmHasPrefix(input, this->Name);
+ } else if (cmHasPrefix(input, this->Name)) {
+ if (input.size() == this->Name.size()) {
+ matched = true;
+ } else {
+ matched =
+ (input[this->Name.size()] == '=' || input[this->Name.size()] == ' ');
+ }
+ }
+ return matched;
}
template <typename T, typename... CallState>
@@ -55,13 +108,6 @@ struct cmCommandLineArgument
std::vector<std::string> const& allArgs,
CallState&&... state) const
{
- enum class ParseMode
- {
- Valid,
- Invalid,
- SyntaxError,
- ValueError
- };
ParseMode parseState = ParseMode::Valid;
if (this->Type == Values::Zero) {
@@ -95,23 +141,10 @@ struct cmCommandLineArgument
index = nextValueIndex;
}
} else {
- // parse the string to get the value
- auto possible_value = cm::string_view(input).substr(this->Name.size());
- if (possible_value.empty()) {
- parseState = ParseMode::ValueError;
- } else if (possible_value[0] == '=') {
- possible_value.remove_prefix(1);
- if (possible_value.empty()) {
- parseState = ParseMode::ValueError;
- }
- }
+ auto value = this->extract_single_value(input, parseState);
if (parseState == ParseMode::Valid) {
- if (possible_value[0] == ' ') {
- possible_value.remove_prefix(1);
- }
-
- parseState = this->StoreCall(std::string(possible_value),
- std::forward<CallState>(state)...)
+ parseState =
+ this->StoreCall(value, std::forward<CallState>(state)...)
? ParseMode::Valid
: ParseMode::Invalid;
}
@@ -149,7 +182,13 @@ struct cmCommandLineArgument
index = (nextValueIndex - 1);
}
} else {
- parseState = ParseMode::SyntaxError;
+ auto value = this->extract_single_value(input, parseState);
+ if (parseState == ParseMode::Valid) {
+ parseState =
+ this->StoreCall(value, std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
}
}
@@ -161,4 +200,24 @@ struct cmCommandLineArgument
}
return (parseState == ParseMode::Valid);
}
+
+private:
+ std::string extract_single_value(std::string const& input,
+ ParseMode& parseState) const
+ {
+ // parse the string to get the value
+ auto possible_value = cm::string_view(input).substr(this->Name.size());
+ if (possible_value.empty()) {
+ parseState = ParseMode::ValueError;
+ } else if (possible_value[0] == '=') {
+ possible_value.remove_prefix(1);
+ if (possible_value.empty()) {
+ parseState = ParseMode::ValueError;
+ }
+ }
+ if (parseState == ParseMode::Valid && possible_value[0] == ' ') {
+ possible_value.remove_prefix(1);
+ }
+ return std::string(possible_value);
+ }
};
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 6b35842..945b547 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -1016,6 +1016,11 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
if (gen->GetExcludeFromAll()) {
installer["isExcludeFromAll"] = true;
}
+
+ if (gen->GetAllComponentsFlag()) {
+ installer["isForAllComponents"] = true;
+ }
+
this->AddBacktrace(installer, gen->GetBacktrace());
return installer;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index bbc0050..e2ec82a 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -52,6 +52,11 @@
class cmMessenger;
+namespace {
+const cmsys::RegularExpression FrameworkRegularExpression(
+ "^(.*/)?([^/]*)\\.framework/(.*)$");
+}
+
template <>
cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
@@ -2257,8 +2262,16 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const
return cmSystemTools::GetFilenameName(info->Location);
}
// Use the soname given if any.
+ if (this->IsFrameworkOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (FrameworkRegularExpression.find(info->SOName.c_str(), match)) {
+ auto frameworkName = match.match(2);
+ auto fileName = match.match(3);
+ return cmStrCat(frameworkName, ".framework/", fileName);
+ }
+ }
if (cmHasLiteralPrefix(info->SOName, "@rpath/")) {
- return info->SOName.substr(6);
+ return info->SOName.substr(cmStrLen("@rpath/"));
}
return info->SOName;
}
@@ -6459,9 +6472,19 @@ std::string cmGeneratorTarget::GetDirectory(
const std::string& config, cmStateEnums::ArtifactType artifact) const
{
if (this->IsImported()) {
+ auto fullPath = this->Target->ImportedGetFullPath(config, artifact);
+ if (this->IsFrameworkOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (FrameworkRegularExpression.find(fullPath.c_str(), match)) {
+ auto path = match.match(1);
+ if (!path.empty()) {
+ path.erase(path.length() - 1);
+ }
+ return path;
+ }
+ }
// Return the directory from which the target is imported.
- return cmSystemTools::GetFilenamePath(
- this->Target->ImportedGetFullPath(config, artifact));
+ return cmSystemTools::GetFilenamePath(fullPath);
}
if (OutputInfo const* info = this->GetOutputInfo(config)) {
// Return the directory in which the target will be built.
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 565b951..6034434 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -216,22 +216,32 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
{
// Write explicit outputs
for (std::string const& output : build.Outputs) {
- buildStr += cmStrCat(' ', this->EncodePath(output));
+ buildStr = cmStrCat(buildStr, ' ', this->EncodePath(output));
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(output);
}
}
// Write implicit outputs
- if (!build.ImplicitOuts.empty()) {
- buildStr += " |";
+ if (!build.ImplicitOuts.empty() || !build.WorkDirOuts.empty()) {
+ buildStr = cmStrCat(buildStr, " |");
for (std::string const& implicitOut : build.ImplicitOuts) {
- buildStr += cmStrCat(' ', this->EncodePath(implicitOut));
+ buildStr = cmStrCat(buildStr, ' ', this->EncodePath(implicitOut));
+ if (this->ComputingUnknownDependencies) {
+ this->CombinedBuildOutputs.insert(implicitOut);
+ }
+ }
+ for (std::string const& workdirOut : build.WorkDirOuts) {
+ // Repeat some outputs, but expressed as absolute paths.
+ // This helps Ninja handle absolute paths found in a depfile.
+ // FIXME: Unfortunately this causes Ninja to stat the file twice.
+ // We could avoid this if Ninja Issue 1251 were fixed.
+ buildStr = cmStrCat(buildStr, " ${cmake_ninja_workdir}",
+ this->EncodePath(workdirOut));
}
}
- buildStr += ':';
// Write the rule.
- buildStr += cmStrCat(' ', build.Rule);
+ buildStr = cmStrCat(buildStr, ": ", build.Rule);
}
std::string arguments;
@@ -307,21 +317,46 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule()
this->AddRule(rule);
}
+void cmGlobalNinjaGenerator::CCOutputs::Add(
+ std::vector<std::string> const& paths)
+{
+ for (std::string const& path : paths) {
+ std::string out = this->GG->ConvertToNinjaPath(path);
+ if (this->GG->SupportsImplicitOuts() &&
+ !cmSystemTools::FileIsFullPath(out)) {
+ // This output is expressed as a relative path. Repeat it,
+ // but expressed as an absolute path for Ninja Issue 1251.
+ this->WorkDirOuts.emplace_back(out);
+ }
+ this->GG->SeenCustomCommandOutput(out);
+ this->ExplicitOuts.emplace_back(std::move(out));
+ }
+}
+
void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
- const std::string& command, const std::string& description,
- const std::string& comment, const std::string& depfile,
- const std::string& job_pool, bool uses_terminal, bool restat,
- const cmNinjaDeps& outputs, const std::string& config,
- const cmNinjaDeps& explicitDeps, const cmNinjaDeps& orderOnlyDeps)
+ std::string const& command, std::string const& description,
+ std::string const& comment, std::string const& depfile,
+ std::string const& job_pool, bool uses_terminal, bool restat,
+ std::string const& config, CCOutputs outputs, cmNinjaDeps explicitDeps,
+ cmNinjaDeps orderOnlyDeps)
{
this->AddCustomCommandRule();
+ if (this->ComputingUnknownDependencies) {
+ // we need to track every dependency that comes in, since we are trying
+ // to find dependencies that are side effects of build commands
+ for (std::string const& dep : explicitDeps) {
+ this->CombinedCustomCommandExplicitDependencies.insert(dep);
+ }
+ }
+
{
cmNinjaBuild build("CUSTOM_COMMAND");
build.Comment = comment;
- build.Outputs = outputs;
- build.ExplicitDeps = explicitDeps;
- build.OrderOnlyDeps = orderOnlyDeps;
+ build.Outputs = std::move(outputs.ExplicitOuts);
+ build.WorkDirOuts = std::move(outputs.WorkDirOuts);
+ build.ExplicitDeps = std::move(explicitDeps);
+ build.OrderOnlyDeps = std::move(orderOnlyDeps);
cmNinjaVars& vars = build.Variables;
{
@@ -351,14 +386,6 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
this->WriteBuild(*this->GetImplFileStream(config), build);
}
}
-
- if (this->ComputingUnknownDependencies) {
- // we need to track every dependency that comes in, since we are trying
- // to find dependencies that are side effects of build commands
- for (std::string const& dep : explicitDeps) {
- this->CombinedCustomCommandExplicitDependencies.insert(dep);
- }
- }
}
void cmGlobalNinjaGenerator::AddMacOSXContentRule()
@@ -1198,6 +1225,8 @@ void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os) const
void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
for (auto const& asd : this->AssumedSourceDependencies) {
+ CCOutputs outputs(this);
+ outputs.ExplicitOuts.emplace_back(asd.first);
cmNinjaDeps orderOnlyDeps;
std::copy(asd.second.begin(), asd.second.end(),
std::back_inserter(orderOnlyDeps));
@@ -1206,8 +1235,8 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
"Assume dependencies for generated source file.",
/*depfile*/ "", /*job_pool*/ "",
/*uses_terminal*/ false,
- /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(),
- orderOnlyDeps);
+ /*restat*/ true, std::string(), outputs, cmNinjaDeps(),
+ std::move(orderOnlyDeps));
}
}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 9f31708..7a3674e 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -110,13 +110,29 @@ public:
void WriteBuild(std::ostream& os, cmNinjaBuild const& build,
int cmdLineLimit = 0, bool* usedResponseFile = nullptr);
- void WriteCustomCommandBuild(
- const std::string& command, const std::string& description,
- const std::string& comment, const std::string& depfile,
- const std::string& pool, bool uses_terminal, bool restat,
- const cmNinjaDeps& outputs, const std::string& config,
- const cmNinjaDeps& explicitDeps = cmNinjaDeps(),
- const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps());
+ class CCOutputs
+ {
+ cmGlobalNinjaGenerator* GG;
+
+ public:
+ CCOutputs(cmGlobalNinjaGenerator* gg)
+ : GG(gg)
+ {
+ }
+ void Add(std::vector<std::string> const& outputs);
+ cmNinjaDeps ExplicitOuts;
+ cmNinjaDeps WorkDirOuts;
+ };
+
+ void WriteCustomCommandBuild(std::string const& command,
+ std::string const& description,
+ std::string const& comment,
+ std::string const& depfile,
+ std::string const& pool, bool uses_terminal,
+ bool restat, std::string const& config,
+ CCOutputs outputs,
+ cmNinjaDeps explicitDeps = cmNinjaDeps(),
+ cmNinjaDeps orderOnlyDeps = cmNinjaDeps());
void WriteMacOSXContentBuild(std::string input, std::string output,
const std::string& config);
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index d5d6d93..e973764 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -161,6 +161,7 @@ bool HandleScriptMode(std::vector<std::string> const& args,
bool doing_script = false;
bool doing_code = false;
bool exclude_from_all = false;
+ bool all_components = false;
// Scan the args once for COMPONENT. Only allow one.
//
@@ -172,6 +173,8 @@ bool HandleScriptMode(std::vector<std::string> const& args,
}
if (args[i] == "EXCLUDE_FROM_ALL") {
exclude_from_all = true;
+ } else if (args[i] == "ALL_COMPONENTS") {
+ all_components = true;
}
}
@@ -182,6 +185,11 @@ bool HandleScriptMode(std::vector<std::string> const& args,
return false;
}
+ if (all_components && componentCount == 1) {
+ status.SetError("ALL_COMPONENTS and COMPONENT are mutually exclusive");
+ return false;
+ }
+
// Scan the args again, this time adding install generators each time we
// encounter a SCRIPT or CODE arg:
//
@@ -208,14 +216,14 @@ bool HandleScriptMode(std::vector<std::string> const& args,
}
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallScriptGenerator>(
- script, false, component, exclude_from_all,
+ script, false, component, exclude_from_all, all_components,
helper.Makefile->GetBacktrace()));
} else if (doing_code) {
doing_code = false;
std::string const& code = arg;
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallScriptGenerator>(
- code, true, component, exclude_from_all,
+ code, true, component, exclude_from_all, all_components,
helper.Makefile->GetBacktrace()));
}
}
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index 4eb5f69..86362e4 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -18,7 +18,7 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
MessageLevel message, bool exclude_from_all, std::string literal_args,
bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, LocalGenerator(nullptr)
, Directories(dirs)
, FilePermissions(std::move(file_permissions))
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index fdc3f8c..ccefd92 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -26,7 +26,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
std::string filename, std::string name_space, bool exportOld, bool android,
cmListFileBacktrace backtrace)
: cmInstallGenerator(destination, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, ExportSet(exportSet)
, FilePermissions(std::move(file_permissions))
, FileName(std::move(filename))
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index 556c938..04aaa29 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -17,7 +17,7 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
MessageLevel message, bool exclude_from_all, std::string rename,
bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, LocalGenerator(nullptr)
, Files(files)
, FilePermissions(std::move(file_permissions))
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 98e3766..cf5f45e 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -11,12 +11,13 @@
cmInstallGenerator::cmInstallGenerator(
std::string destination, std::vector<std::string> const& configurations,
std::string component, MessageLevel message, bool exclude_from_all,
- cmListFileBacktrace backtrace)
+ bool all_components, cmListFileBacktrace backtrace)
: cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
, Destination(std::move(destination))
, Component(std::move(component))
, Message(message)
, ExcludeFromAll(exclude_from_all)
+ , AllComponents(all_components)
, Backtrace(std::move(backtrace))
{
}
@@ -160,15 +161,20 @@ void cmInstallGenerator::GenerateScript(std::ostream& os)
Indent indent;
// Begin this block of installation.
- std::string component_test =
- this->CreateComponentTest(this->Component, this->ExcludeFromAll);
- os << indent << "if(" << component_test << ")\n";
+ if (!this->AllComponents) {
+ std::string component_test =
+ this->CreateComponentTest(this->Component, this->ExcludeFromAll);
+ os << indent << "if(" << component_test << ")\n";
+ }
// Generate the script possibly with per-configuration code.
- this->GenerateScriptConfigs(os, indent.Next());
+ this->GenerateScriptConfigs(os,
+ this->AllComponents ? indent : indent.Next());
// End this block of installation.
- os << indent << "endif()\n\n";
+ if (!this->AllComponents) {
+ os << indent << "endif()\n\n";
+ }
}
bool cmInstallGenerator::InstallsForConfig(const std::string& config)
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index 6cd9ff9..0117617 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -33,7 +33,8 @@ public:
cmInstallGenerator(std::string destination,
std::vector<std::string> const& configurations,
std::string component, MessageLevel message,
- bool exclude_from_all, cmListFileBacktrace backtrace);
+ bool exclude_from_all, bool all_components,
+ cmListFileBacktrace backtrace);
~cmInstallGenerator() override;
cmInstallGenerator(cmInstallGenerator const&) = delete;
@@ -65,6 +66,7 @@ public:
std::string const& GetComponent() const { return this->Component; }
bool GetExcludeFromAll() const { return this->ExcludeFromAll; }
+ bool GetAllComponentsFlag() const { return this->AllComponents; }
cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
@@ -79,5 +81,6 @@ protected:
std::string const Component;
MessageLevel const Message;
bool const ExcludeFromAll;
+ bool const AllComponents;
cmListFileBacktrace const Backtrace;
};
diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx
index bb38990..bec98b6 100644
--- a/Source/cmInstallScriptGenerator.cxx
+++ b/Source/cmInstallScriptGenerator.cxx
@@ -14,9 +14,10 @@
cmInstallScriptGenerator::cmInstallScriptGenerator(
std::string script, bool code, std::string const& component,
- bool exclude_from_all, cmListFileBacktrace backtrace)
+ bool exclude_from_all, bool all_components, cmListFileBacktrace backtrace)
: cmInstallGenerator("", std::vector<std::string>(), component,
- MessageDefault, exclude_from_all, std::move(backtrace))
+ MessageDefault, exclude_from_all, all_components,
+ std::move(backtrace))
, Script(std::move(script))
, Code(code)
, AllowGenex(false)
diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h
index 6274f1c..2cf6a4b 100644
--- a/Source/cmInstallScriptGenerator.h
+++ b/Source/cmInstallScriptGenerator.h
@@ -21,7 +21,7 @@ class cmInstallScriptGenerator : public cmInstallGenerator
public:
cmInstallScriptGenerator(
std::string script, bool code, std::string const& component,
- bool exclude_from_all,
+ bool exclude_from_all, bool all_components,
cmListFileBacktrace backtrace = cmListFileBacktrace());
~cmInstallScriptGenerator() override;
diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx
index 76806e5..794694e 100644
--- a/Source/cmInstallSubdirectoryGenerator.cxx
+++ b/Source/cmInstallSubdirectoryGenerator.cxx
@@ -14,10 +14,10 @@
#include "cmSystemTools.h"
cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
- cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll,
+ cmMakefile* makefile, std::string binaryDirectory,
cmListFileBacktrace backtrace)
: cmInstallGenerator("", std::vector<std::string>(), "", MessageDefault,
- excludeFromAll, std::move(backtrace))
+ false, false, std::move(backtrace))
, Makefile(makefile)
, BinaryDirectory(std::move(binaryDirectory))
{
@@ -52,7 +52,7 @@ bool cmInstallSubdirectoryGenerator::Compute(cmLocalGenerator* lg)
void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os)
{
- if (!this->ExcludeFromAll) {
+ if (!this->Makefile->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
cmPolicies::PolicyStatus status =
this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082);
switch (status) {
diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h
index 614cef9..f174d07 100644
--- a/Source/cmInstallSubdirectoryGenerator.h
+++ b/Source/cmInstallSubdirectoryGenerator.h
@@ -21,7 +21,6 @@ class cmInstallSubdirectoryGenerator : public cmInstallGenerator
public:
cmInstallSubdirectoryGenerator(cmMakefile* makefile,
std::string binaryDirectory,
- bool excludeFromAll,
cmListFileBacktrace backtrace);
~cmInstallSubdirectoryGenerator() override;
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index eb214fa..3e79ad8 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -46,7 +46,7 @@ cmInstallTargetGenerator::cmInstallTargetGenerator(
std::string const& component, MessageLevel message, bool exclude_from_all,
bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, TargetName(std::move(targetName))
, Target(nullptr)
, FilePermissions(std::move(file_permissions))
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4db9216..0c686aa 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -3317,7 +3317,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
// Include the user-specified pre-install script for this target.
if (cmProp preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) {
- cmInstallScriptGenerator g(*preinstall, false, "", false);
+ cmInstallScriptGenerator g(*preinstall, false, "", false, false);
g.Generate(os, config, configurationTypes);
}
@@ -3370,7 +3370,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
// Include the user-specified post-install script for this target.
if (cmProp postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) {
- cmInstallScriptGenerator g(*postinstall, false, "", false);
+ cmInstallScriptGenerator g(*postinstall, false, "", false, false);
g.Generate(os, config, configurationTypes);
}
}
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index a8570e2..fb6c730 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -263,6 +263,7 @@ void cmLocalNinjaGenerator::WriteBuildFileTop()
this->GetConfigNames().front());
}
this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream());
+ this->WriteNinjaWorkDir(this->GetCommonFileStream());
// For the rule file.
this->WriteProjectHeader(this->GetRulesFileStream());
@@ -364,6 +365,17 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os)
os << "\n";
}
+void cmLocalNinjaGenerator::WriteNinjaWorkDir(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ cmGlobalNinjaGenerator::WriteComment(
+ os, "Logical path to working directory; prefix for absolute paths.");
+ cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
+ std::string ninja_workdir = this->GetBinaryDirectory();
+ ng->StripNinjaOutputPathPrefixAsSuffix(ninja_workdir); // Also appends '/'.
+ os << "cmake_ninja_workdir = " << ng->EncodePath(ninja_workdir) << "\n";
+}
+
void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
@@ -638,16 +650,11 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
}
}
- cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size());
- std::transform(outputs.begin(), outputs.end(), ninjaOutputs.begin(),
- gg->MapToNinjaPath());
- std::transform(byproducts.begin(), byproducts.end(),
- ninjaOutputs.begin() + outputs.size(),
- gg->MapToNinjaPath());
+ cmGlobalNinjaGenerator::CCOutputs ccOutputs(gg);
+ ccOutputs.Add(outputs);
+ ccOutputs.Add(byproducts);
- for (std::string const& ninjaOutput : ninjaOutputs) {
- gg->SeenCustomCommandOutput(ninjaOutput);
- }
+ std::string mainOutput = ccOutputs.ExplicitOuts[0];
cmNinjaDeps ninjaDeps;
this->AppendCustomCommandDeps(ccg, ninjaDeps, fileConfig);
@@ -657,13 +664,14 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
if (cmdLines.empty()) {
cmNinjaBuild build("phony");
- build.Comment = "Phony custom command for " + ninjaOutputs[0];
- build.Outputs = std::move(ninjaOutputs);
+ build.Comment = cmStrCat("Phony custom command for ", mainOutput);
+ build.Outputs = std::move(ccOutputs.ExplicitOuts);
+ build.WorkDirOuts = std::move(ccOutputs.WorkDirOuts);
build.ExplicitDeps = std::move(ninjaDeps);
build.OrderOnlyDeps = orderOnlyDeps;
gg->WriteBuild(this->GetImplFileStream(fileConfig), build);
} else {
- std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+ std::string customStep = cmSystemTools::GetFilenameName(mainOutput);
if (this->GlobalGenerator->IsMultiConfig()) {
customStep += '-';
customStep += fileConfig;
@@ -673,7 +681,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
// Hash full path to make unique.
customStep += '-';
cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
- customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+ customStep += hash.HashString(mainOutput).substr(0, 7);
std::string depfile = ccg.GetDepfile();
if (!depfile.empty()) {
@@ -701,13 +709,14 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
}
}
+ std::string comment = cmStrCat("Custom command for ", mainOutput);
gg->WriteCustomCommandBuild(
this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig,
customStep),
- this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
- depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
- /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig,
- ninjaDeps, orderOnlyDeps);
+ this->ConstructComment(ccg), comment, depfile, cc->GetJobPool(),
+ cc->GetUsesTerminal(),
+ /*restat*/ !symbolic || !byproducts.empty(), fileConfig,
+ std::move(ccOutputs), std::move(ninjaDeps), std::move(orderOnlyDeps));
}
}
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index a73fa27..6404037 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -108,6 +108,7 @@ private:
const std::string& config);
void WriteNinjaFilesInclusionConfig(std::ostream& os);
void WriteNinjaFilesInclusionCommon(std::ostream& os);
+ void WriteNinjaWorkDir(std::ostream& os);
void WriteProcessedMakefile(std::ostream& os);
void WritePools(std::ostream& os);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index d7987c2..ffe94ba 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1844,7 +1844,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
}
this->AddInstallGenerator(cm::make_unique<cmInstallSubdirectoryGenerator>(
- subMf, binPath, excludeFromAll, this->GetBacktrace()));
+ subMf, binPath, this->GetBacktrace()));
}
const std::string& cmMakefile::GetCurrentSourceDirectory() const
diff --git a/Source/cmMessageMetadata.h b/Source/cmMessageMetadata.h
new file mode 100644
index 0000000..7b56fae
--- /dev/null
+++ b/Source/cmMessageMetadata.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmsys/Terminal.h"
+
+struct cmMessageMetadata
+{
+ const char* title = nullptr;
+ int desiredColor = cmsysTerminal_Color_Normal;
+};
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index af83478..1cb638a 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -3,6 +3,7 @@
#include "cmMessenger.h"
#include "cmDocumentationFormatter.h"
+#include "cmMessageMetadata.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -12,6 +13,8 @@
#include <sstream>
+#include "cmsys/Terminal.h"
+
MessageType cmMessenger::ConvertMessageType(MessageType t) const
{
bool warningsAsErrors;
@@ -84,6 +87,21 @@ static bool printMessagePreamble(MessageType t, std::ostream& msg)
return true;
}
+static int getMessageColor(MessageType t)
+{
+ switch (t) {
+ case MessageType::INTERNAL_ERROR:
+ case MessageType::FATAL_ERROR:
+ case MessageType::AUTHOR_ERROR:
+ return cmsysTerminal_Color_ForegroundRed;
+ case MessageType::AUTHOR_WARNING:
+ case MessageType::WARNING:
+ return cmsysTerminal_Color_ForegroundYellow;
+ default:
+ return cmsysTerminal_Color_Normal;
+ }
+}
+
void printMessageText(std::ostream& msg, std::string const& text)
{
msg << ":\n";
@@ -120,12 +138,16 @@ void displayMessage(MessageType t, std::ostringstream& msg)
#endif
// Output the message.
+ cmMessageMetadata md;
+ md.desiredColor = getMessageColor(t);
if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
cmSystemTools::SetErrorOccured();
- cmSystemTools::Message(msg.str(), "Error");
+ md.title = "Error";
+ cmSystemTools::Message(msg.str(), md);
} else {
- cmSystemTools::Message(msg.str(), "Warning");
+ md.title = "Warning";
+ cmSystemTools::Message(msg.str(), md);
}
}
diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h
index 320f41b..c8a411e 100644
--- a/Source/cmNinjaTypes.h
+++ b/Source/cmNinjaTypes.h
@@ -53,6 +53,7 @@ public:
std::string Rule;
cmNinjaDeps Outputs;
cmNinjaDeps ImplicitOuts;
+ cmNinjaDeps WorkDirOuts; // For cmake_ninja_workdir.
cmNinjaDeps ExplicitDeps;
cmNinjaDeps ImplicitDeps;
cmNinjaDeps OrderOnlyDeps;
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 7a04c47..1f5a7ff 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -73,7 +73,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
cmNinjaBuild phonyBuild("phony");
std::vector<std::string> commands;
cmNinjaDeps deps;
- cmNinjaDeps util_outputs(1, utilCommandName);
+ cmGlobalNinjaGenerator::CCOutputs util_outputs(gg);
+ util_outputs.ExplicitOuts.emplace_back(utilCommandName);
bool uses_terminal = false;
{
@@ -86,10 +87,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
cmCustomCommandGenerator ccg(ci, fileConfig, lg);
lg->AppendCustomCommandDeps(ccg, deps, fileConfig);
lg->AppendCustomCommandLines(ccg, commands);
- std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
- std::transform(ccByproducts.begin(), ccByproducts.end(),
- std::back_inserter(util_outputs),
- this->MapToNinjaPath());
+ util_outputs.Add(ccg.GetByproducts());
if (ci.GetUsesTerminal()) {
uses_terminal = true;
}
@@ -124,7 +122,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) {
lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(),
config);
- std::copy(util_outputs.begin(), util_outputs.end(),
+ std::copy(util_outputs.ExplicitOuts.begin(),
+ util_outputs.ExplicitOuts.end(),
std::back_inserter(gg->GetByproductsForCleanTarget()));
}
lg->AppendTargetDepends(genTarget, deps, config, fileConfig,
@@ -166,10 +165,6 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
return;
}
- for (std::string const& util_output : util_outputs) {
- gg->SeenCustomCommandOutput(util_output);
- }
-
std::string ccConfig;
if (genTarget->Target->IsPerConfig() &&
genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
@@ -180,7 +175,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
gg->WriteCustomCommandBuild(
command, desc, "Utility command for " + this->GetTargetName(),
/*depfile*/ "", /*job_pool*/ "", uses_terminal,
- /*restat*/ true, util_outputs, ccConfig, deps);
+ /*restat*/ true, ccConfig, std::move(util_outputs), std::move(deps));
}
phonyBuild.ExplicitDeps.push_back(utilCommandName);
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 2fba13f..9b81bf2 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -19,6 +19,7 @@
#include <cm3p/uv.h>
#include "cmDuration.h"
+#include "cmMessageMetadata.h"
#include "cmProcessOutput.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
@@ -263,8 +264,15 @@ void cmSystemTools::Stdout(const std::string& s)
void cmSystemTools::Message(const std::string& m, const char* title)
{
+ cmMessageMetadata md;
+ md.title = title;
+ Message(m, md);
+}
+
+void cmSystemTools::Message(const std::string& m, const cmMessageMetadata& md)
+{
if (s_MessageCallback) {
- s_MessageCallback(m, title);
+ s_MessageCallback(m, md);
} else {
std::cerr << m << std::endl;
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 474f591..5c3b5a9 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -19,6 +19,8 @@
#include "cmDuration.h"
#include "cmProcessOutput.h"
+struct cmMessageMetadata;
+
/** \class cmSystemTools
* \brief A collection of useful functions for CMake.
*
@@ -40,7 +42,8 @@ public:
/** Map help document name to file name. */
static std::string HelpFileName(cm::string_view);
- using MessageCallback = std::function<void(const std::string&, const char*)>;
+ using MessageCallback =
+ std::function<void(const std::string&, const cmMessageMetadata&)>;
/**
* Set the function used by GUIs to display error messages
* Function gets passed: message as a const char*,
@@ -57,6 +60,7 @@ public:
* Display a message.
*/
static void Message(const std::string& m, const char* title = nullptr);
+ static void Message(const std::string& m, const cmMessageMetadata& md);
using OutputCallback = std::function<void(std::string const&)>;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5440984..315bd20 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -529,25 +529,29 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
std::vector<CommandArgument> arguments = {
CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
- CommandArgument::Values::One, DefineLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, DefineLambda },
CommandArgument{ "-W", "-W must be followed with [no-]<name>.",
- CommandArgument::Values::One, WarningLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, WarningLambda },
CommandArgument{ "-U", "-U must be followed with VAR.",
- CommandArgument::Values::One, UnSetLambda },
- CommandArgument{ "-C", "-C must be followed by a file name.",
CommandArgument::Values::One,
- [&](std::string const& value, cmake* state) -> bool {
- cmSystemTools::Stdout("loading initial cache file " +
- value + "\n");
- // Resolve script path specified on command line
- // relative to $PWD.
- auto path = cmSystemTools::CollapseFullPath(value);
- state->ReadListFile(args, path);
- return true;
- } },
+ CommandArgument::RequiresSeparator::No, UnSetLambda },
+ CommandArgument{
+ "-C", "-C must be followed by a file name.",
+ CommandArgument::Values::One, CommandArgument::RequiresSeparator::No,
+ [&](std::string const& value, cmake* state) -> bool {
+ cmSystemTools::Stdout("loading initial cache file " + value + "\n");
+ // Resolve script path specified on command line
+ // relative to $PWD.
+ auto path = cmSystemTools::CollapseFullPath(value);
+ state->ReadListFile(args, path);
+ return true;
+ } },
CommandArgument{ "-P", "-P must be followed by a file name.",
- CommandArgument::Values::One, ScriptLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, ScriptLambda },
CommandArgument{ "--toolchain", "No file specified for --toolchain",
CommandArgument::Values::One, ToolchainLambda },
CommandArgument{ "--install-prefix",
@@ -830,31 +834,44 @@ void cmake::SetArgs(const std::vector<std::string>& args)
std::vector<CommandArgument> arguments = {
CommandArgument{ "-S", "No source directory specified for -S",
- CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, SourceArgLambda },
CommandArgument{ "-H", "No source directory specified for -H",
- CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, SourceArgLambda },
CommandArgument{ "-O", CommandArgument::Values::Zero,
IgnoreAndTrueLambda },
CommandArgument{ "-B", "No build directory specified for -B",
- CommandArgument::Values::One, BuildArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, BuildArgLambda },
CommandArgument{ "-P", "-P must be followed by a file name.",
CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const&, cmake*) -> bool {
scriptMode = true;
return true;
} },
CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
CommandArgument{ "-C", "-C must be followed by a file name.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
- CommandArgument{ "-U", "-U must be followed with VAR.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
+ CommandArgument{
+ "-U", "-U must be followed with VAR.", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, IgnoreAndTrueLambda },
CommandArgument{ "-W", "-W must be followed with [no-]<name>.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
CommandArgument{ "-A", "No platform specified for -A",
- CommandArgument::Values::One, PlatformLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, PlatformLambda },
CommandArgument{ "-T", "No toolset specified for -T",
- CommandArgument::Values::One, ToolsetLamda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, ToolsetLamda },
CommandArgument{ "--toolchain", "No file specified for --toolchain",
CommandArgument::Values::One, IgnoreAndTrueLambda },
CommandArgument{ "--install-prefix",
@@ -1079,6 +1096,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
bool badGeneratorName = false;
CommandArgument generatorCommand(
"-G", "No generator specified for -G", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const& value, cmake* state) -> bool {
bool valid = state->CreateAndSetGlobalGenerator(value, true);
badGeneratorName = !valid;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index ad64818..d83183f 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -6,6 +6,7 @@
#include <algorithm>
#include <cassert>
#include <climits>
+#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
@@ -23,6 +24,7 @@
#include "cmDocumentationEntry.h" // IWYU pragma: keep
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageMetadata.h"
#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
@@ -37,6 +39,7 @@
#endif
#include "cmsys/Encoding.hxx"
+#include "cmsys/Terminal.h"
namespace {
#ifndef CMAKE_BOOTSTRAP
@@ -147,10 +150,12 @@ std::string cmakemainGetStack(cmake* cm)
return msg;
}
-void cmakemainMessageCallback(const std::string& m, const char* /*unused*/,
- cmake* cm)
+void cmakemainMessageCallback(const std::string& m,
+ const cmMessageMetadata& md, cmake* cm)
{
- std::cerr << m << cmakemainGetStack(cm) << std::endl;
+ cmsysTerminal_cfprintf(md.desiredColor, stderr, "%s", m.c_str());
+ fflush(stderr); // stderr is buffered in some cases.
+ std::cerr << cmakemainGetStack(cm) << "\n";
}
void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm)
@@ -271,6 +276,7 @@ int do_cmake(int ac, char const* const* av)
} },
CommandArgument{ "-P", "No script specified for argument -P",
CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const& value) -> bool {
workingMode = cmake::SCRIPT_MODE;
parsedArgs.emplace_back("-P");
@@ -342,8 +348,8 @@ int do_cmake(int ac, char const* const* av)
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&cm](const std::string& msg, const cmMessageMetadata& md) {
+ cmakemainMessageCallback(msg, md, &cm);
});
cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
@@ -476,9 +482,10 @@ int do_build(int ac, char const* const* av)
listPresets = true;
return true;
} },
- CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, jLambda },
+ CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne,
+ CommandArgument::RequiresSeparator::No, jLambda },
CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne,
- parallelLambda },
+ CommandArgument::RequiresSeparator::No, parallelLambda },
CommandArgument{ "-t", CommandArgument::Values::OneOrMore, targetLambda },
CommandArgument{ "--target", CommandArgument::Values::OneOrMore,
targetLambda },
@@ -624,8 +631,8 @@ int do_build(int ac, char const* const* av)
cmake cm(cmake::RoleInternal, cmState::Project);
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&cm](const std::string& msg, const cmMessageMetadata& md) {
+ cmakemainMessageCallback(msg, md, &cm);
});
cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
@@ -857,8 +864,8 @@ int do_install(int ac, char const* const* av)
cmake cm(cmake::RoleScript, cmState::Script);
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&cm](const std::string& msg, const cmMessageMetadata& md) {
+ cmakemainMessageCallback(msg, md, &cm);
});
cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
@@ -938,8 +945,8 @@ int do_open(int ac, char const* const* av)
cmake cm(cmake::RoleInternal, cmState::Unknown);
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&cm](const std::string& msg, const cmMessageMetadata& md) {
+ cmakemainMessageCallback(msg, md, &cm);
});
cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake
new file mode 100644
index 0000000..22e7f27
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake
@@ -0,0 +1,19 @@
+enable_language(C)
+
+add_custom_command(
+ OUTPUT main.c
+ COMMAND ${CMAKE_COMMAND} -E copy main.c.in main.c
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/main.c.in
+ )
+add_executable(main main.c)
+set_property(TARGET main PROPERTY UNITY_BUILD ON)
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+set(check_pairs
+ \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c.in\"
+ \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c\"
+ )
+set(check_exes
+ \"$<TARGET_FILE:main>\"
+ )
+")
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake
new file mode 100644
index 0000000..87576eb
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
+int main(void) { return 1; }
+]])
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake
new file mode 100644
index 0000000..69b21b8
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
+int main(void) { return 2; }
+]])
diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
index 72faddb..0a80580 100644
--- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
+++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
@@ -1,5 +1,22 @@
include(RunCMake)
+if(RunCMake_GENERATOR MATCHES "Ninja")
+ # Detect ninja version so we know what tests can be supported.
+ execute_process(
+ COMMAND "${RunCMake_MAKE_PROGRAM}" --version
+ OUTPUT_VARIABLE ninja_out
+ ERROR_VARIABLE ninja_out
+ RESULT_VARIABLE ninja_res
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(ninja_res EQUAL 0 AND "x${ninja_out}" MATCHES "^x[0-9]+\\.[0-9]+")
+ set(ninja_version "${ninja_out}")
+ message(STATUS "ninja version: ${ninja_version}")
+ else()
+ message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}")
+ endif()
+endif()
+
if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR
RunCMake_GENERATOR STREQUAL "Watcom WMake")
set(fs_delay 3)
@@ -164,3 +181,11 @@ endif()
if(RunCMake_GENERATOR MATCHES "Make")
run_BuildDepends(MakeDependencies)
endif()
+
+if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 " OR
+ (RunCMake_GENERATOR MATCHES "Ninja" AND ninja_version VERSION_LESS 1.7))
+ # This build tool misses the dependency.
+ set(run_BuildDepends_skip_step_2 1)
+endif()
+run_BuildDepends(CustomCommandUnityBuild)
+unset(run_BuildDepends_skip_step_2)
diff --git a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
index 5fe2539..fa3adc8 100644
--- a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
@@ -1,2 +1 @@
-^CMake Error: '--target=invalid' is invalid syntax for --target
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+^Error: could not load cache
diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
index d69338a..e4ad6b2 100644
--- a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
@@ -1,2 +1,2 @@
-^CMake Error: '--targetinvalid' is invalid syntax for --target
+^Unknown argument --targetinvalid
Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index 0d718a4..b9a1fbf 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -136,6 +136,10 @@ def check_directory(c):
expected_keys.append("isExcludeFromAll")
assert is_bool(a["isExcludeFromAll"], e["isExcludeFromAll"])
+ if e["isForAllComponents"] is not None:
+ expected_keys.append("isForAllComponents")
+ assert is_bool(a["isForAllComponents"], e["isForAllComponents"])
+
if e["isOptional"] is not None:
expected_keys.append("isOptional")
assert is_bool(a["isOptional"], e["isOptional"])
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
index 55dd573..6d2952d 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
@@ -20,6 +20,7 @@
"^.*/Tests/RunCMake/FileAPIExternalSource/\\.$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": null,
"targetIndex": null,
@@ -51,6 +52,7 @@
"^.*/Tests/RunCMake/FileAPIExternalSource$"
],
"isExcludeFromAll": true,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": null,
"targetIndex": null,
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json
index ef2dd0b..44bc725 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json
@@ -23,6 +23,7 @@
"^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?c_object_exe(\\.exe)?$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^c_object_exe::@5ed5358f70faf8d8af7a$",
"targetIndex": "c_object_exe",
@@ -54,6 +55,7 @@
"^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_object_exe(\\.exe)?$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
"targetIndex": "cxx_object_exe",
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
index 4727607..99287fb 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
@@ -35,6 +35,7 @@
"^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_exe(\\.exe)?$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^cxx_exe::@a56b12a3f5c0529fb296$",
"targetIndex": "cxx_exe",
@@ -78,6 +79,7 @@
"^((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(lib|dll\\.a)$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
"targetIndex": "c_shared_lib",
@@ -126,6 +128,7 @@
"^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1|1\\.dylib)$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
"targetIndex": "c_shared_lib",
@@ -169,6 +172,7 @@
"^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?cxx_shared_lib\\.(lib|dll\\.a)$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
"targetIndex": "cxx_shared_lib",
@@ -213,6 +217,7 @@
"^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg|msys-)?cxx_shared_lib\\.(dll|so|dylib)$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
"targetIndex": "cxx_shared_lib",
@@ -256,6 +261,7 @@
"^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(dll|so|dylib)$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
"targetIndex": "c_shared_lib",
@@ -302,6 +308,7 @@
}
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": true,
"targetId": null,
"targetIndex": null,
@@ -346,6 +353,7 @@
"^empty\\.h$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": null,
"targetIndex": null,
@@ -394,6 +402,7 @@
}
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": true,
"targetId": null,
"targetIndex": null,
@@ -445,6 +454,7 @@
}
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": null,
"targetIndex": null,
@@ -488,6 +498,7 @@
"^CMakeFiles/Export/lib/cmake/foo/FooTargets\\.cmake$"
],
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": null,
"targetIndex": null,
@@ -534,6 +545,7 @@
"destination": null,
"paths": null,
"isExcludeFromAll": null,
+ "isForAllComponents": null,
"isOptional": null,
"targetId": null,
"targetIndex": null,
@@ -568,6 +580,48 @@
"hasParent": false
}
]
+ },
+ {
+ "component": "Unspecified",
+ "type": "code",
+ "destination": null,
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": true,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 54,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": null,
+ "command": null,
+ "hasParent": true
+ },
+ {
+ "file": "^CMakeLists\\.txt$",
+ "line": 3,
+ "command": "include",
+ "hasParent": true
+ },
+ {
+ "file": "^CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
}
]
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
index 528f075..da928eb 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake
+++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
@@ -51,3 +51,4 @@ install(DIRECTORY . dir cxx/ OPTIONAL DESTINATION dir1)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}/cxx/" DESTINATION dir2)
install(EXPORT FooTargets DESTINATION lib/cmake/foo)
install(SCRIPT InstallScript.cmake)
+install(CODE "message(foo)" ALL_COMPONENTS)
diff --git a/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt b/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt
new file mode 100644
index 0000000..bd75ccd
--- /dev/null
+++ b/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt
@@ -0,0 +1 @@
+xxx/no/exist/fw\.framework/Versions/A/fwxxx
diff --git a/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake b/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake
new file mode 100644
index 0000000..42edaea
--- /dev/null
+++ b/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake
@@ -0,0 +1,10 @@
+add_library(fw SHARED IMPORTED)
+set_target_properties(fw PROPERTIES
+ FRAMEWORK TRUE
+ IMPORTED_LOCATION "/no/exist/fw.framework/Versions/A/fw"
+ IMPORTED_SONAME "@rpath/fw.framework/Versions/A/fw"
+ )
+
+add_custom_target(print_fw ALL COMMAND
+ ${CMAKE_COMMAND} -E echo "xxx$<TARGET_SONAME_FILE:fw>xxx"
+ )
diff --git a/Tests/RunCMake/Framework/RunCMakeTest.cmake b/Tests/RunCMake/Framework/RunCMakeTest.cmake
index 6ee61a3..36eaf5c 100644
--- a/Tests/RunCMake/Framework/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Framework/RunCMakeTest.cmake
@@ -81,3 +81,15 @@ function(framework_multi_config_postfix_test)
endfunction()
framework_multi_config_postfix_test()
+
+function(imported_framework_test)
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ImportedFrameworkTest-build")
+ set(RunCMake_TEST_NO_CLEAN 1)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(ImportedFrameworkTest)
+ run_cmake_command(ImportedFrameworkTest-build ${CMAKE_COMMAND} --build .)
+endfunction()
+
+imported_framework_test()
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt
index 1bd7f49..32bb1a9 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt
@@ -1 +1,2 @@
install(CODE "message(STATUS \"exclude\")")
+set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL TRUE)
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake b/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake
index 56c1b81..8ebf21b 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake
@@ -1,3 +1,3 @@
add_subdirectory(CMP0082)
-add_subdirectory(CMP0082-ExcludeFromAll EXCLUDE_FROM_ALL)
+add_subdirectory(CMP0082-ExcludeFromAll)
install(CODE "message(STATUS \"top\")")
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake b/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake
index 56c1b81..8ebf21b 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake
@@ -1,3 +1,3 @@
add_subdirectory(CMP0082)
-add_subdirectory(CMP0082-ExcludeFromAll EXCLUDE_FROM_ALL)
+add_subdirectory(CMP0082-ExcludeFromAll)
install(CODE "message(STATUS \"top\")")
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake b/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake
index 56c1b81..8ebf21b 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake
@@ -1,3 +1,3 @@
add_subdirectory(CMP0082)
-add_subdirectory(CMP0082-ExcludeFromAll EXCLUDE_FROM_ALL)
+add_subdirectory(CMP0082-ExcludeFromAll)
install(CODE "message(STATUS \"top\")")
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index 3e56746..94887a0 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -179,3 +179,4 @@ run_install_test(FILES-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-NAMELINK_COMPONENT)
run_install_test(SCRIPT-COMPONENT)
+run_install_test(SCRIPT-ALL_COMPONENTS)
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake
new file mode 100644
index 0000000..48d8e1a
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake
@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake
new file mode 100644
index 0000000..48d8e1a
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake
@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake
new file mode 100644
index 0000000..48d8e1a
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake
@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake
new file mode 100644
index 0000000..aa3f9d1
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake
@@ -0,0 +1,5 @@
+install(
+ SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/install_script.cmake"
+ CODE "write_empty_file(empty2.txt)"
+ ALL_COMPONENTS
+ )