summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Kosiorek <bartosz.kosiorek@tomtom.com>2019-02-08 14:28:49 +0100
committerBrad King <brad.king@kitware.com>2019-03-05 08:55:28 -0500
commit324d18bb3418aee8dcb63e28106ac0dac6abea71 (patch)
tree390a0ccc8c8bb955c0330af9bd66621a71ea2041
parentebc94500c1726f393ac6119848d53deca47e1ccf (diff)
downloadcmake-324d18bb3418aee8dcb63e28106ac0dac6abea71.tar.gz
cmake: Teach --build mode to support multiple targets
Fixes: #16136
-rw-r--r--Help/command/build_command.rst2
-rw-r--r--Help/manual/cmake.1.rst4
-rw-r--r--Help/release/dev/cmake-build-multiply-targets.rst5
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx2
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx17
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h15
-rw-r--r--Source/cmGlobalGenerator.cxx99
-rw-r--r--Source/cmGlobalGenerator.h18
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx30
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h15
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx17
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h15
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx17
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h15
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx28
-rw-r--r--Source/cmGlobalNinjaGenerator.h15
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx34
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h15
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx121
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h15
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx58
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h15
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx18
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h15
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx40
-rw-r--r--Source/cmGlobalXCodeGenerator.h15
-rw-r--r--Source/cmake.cxx8
-rw-r--r--Source/cmake.h4
-rw-r--r--Source/cmakemain.cxx44
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-jobs-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-result.txt (renamed from Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake6
36 files changed, 403 insertions, 328 deletions
diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst
index b83edaf575..6659005bee 100644
--- a/Help/command/build_command.rst
+++ b/Help/command/build_command.rst
@@ -14,7 +14,7 @@ This is mainly intended for internal use by the :module:`CTest` module.
Sets the given ``<variable>`` to a command-line string of the form::
- <cmake> --build . [--config <config>] [--target <target>] [-- -i]
+ <cmake> --build . [--config <config>] [--target <target>...] [-- -i]
where ``<cmake>`` is the location of the :manual:`cmake(1)` command-line
tool, and ``<config>`` and ``<target>`` are the values provided to the
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index f3b81ecb68..e9a08b543e 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -276,8 +276,8 @@ following options:
The :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` environment variable, if set,
specifies a default parallel level when this option is not given.
-``--target <tgt>``
- Build ``<tgt>`` instead of default targets. May only be specified once.
+``--target <tgt>...``
+ Build ``<tgt>`` instead of default targets. May be specified multiple times.
``--config <cfg>``
For multi-configuration tools, choose configuration ``<cfg>``.
diff --git a/Help/release/dev/cmake-build-multiply-targets.rst b/Help/release/dev/cmake-build-multiply-targets.rst
new file mode 100644
index 0000000000..1275ca3160
--- /dev/null
+++ b/Help/release/dev/cmake-build-multiply-targets.rst
@@ -0,0 +1,5 @@
+cmake-build-multiply-targets
+----------------------------
+
+* The :manual:`cmake(1)` ``--build`` tool ``--target`` parameter gained support for
+ multiple targets, e.g. ``cmake --build . --target Library1 Library2``.
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index b2c88df6d1..a7d4455e20 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -256,7 +256,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
}
int retVal = cm.GetGlobalGenerator()->Build(
cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
- this->BuildProject, tar, output, this->BuildMakeProgram, config,
+ this->BuildProject, { tar }, output, this->BuildMakeProgram, config,
!this->BuildNoClean, false, false, remainingTime);
out << output;
// if the build failed then return
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index c2eb583a93..281d3718ee 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -53,15 +53,16 @@ void cmGlobalBorlandMakefileGenerator::GetDocumentation(
entry.Brief = "Generates Borland makefiles.";
}
-void cmGlobalBorlandMakefileGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalBorlandMakefileGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
- this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+ return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
}
void cmGlobalBorlandMakefileGenerator::PrintBuildCommandAdvice(
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index ca04b7b739..02d0d5ffd3 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -46,15 +46,12 @@ public:
bool AllowDeleteOnError() const override { return false; }
protected:
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index a9f37b7a7f..6964b62e46 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1763,9 +1763,9 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
this->FirstTimeProgress);
}
- std::string newTarget;
+ std::vector<std::string> newTarget = {};
if (!target.empty()) {
- newTarget += target;
+ newTarget = { target };
}
std::string config =
mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
@@ -1773,14 +1773,16 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
config, false, fast, false, this->TryCompileTimeout);
}
-void cmGlobalGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& /*unused*/,
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalGenerator::GenerateBuildCommand(
const std::string& /*unused*/, const std::string& /*unused*/,
- const std::string& /*unused*/, const std::string& /*unused*/,
- bool /*unused*/, int /*unused*/, bool /*unused*/,
- std::vector<std::string> const& /*unused*/)
+ const std::string& /*unused*/, std::vector<std::string> const& /*unused*/,
+ const std::string& /*unused*/, bool /*unused*/, int /*unused*/,
+ bool /*unused*/, std::vector<std::string> const& /*unused*/)
{
+ GeneratedMakeCommand makeCommand;
makeCommand.Add("cmGlobalGenerator::GenerateBuildCommand not implemented");
+ return { std::move(makeCommand) };
}
void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
@@ -1790,15 +1792,13 @@ void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
// they do not support certain build command line options
}
-int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/,
- const std::string& bindir,
- const std::string& projectName,
- const std::string& target, std::string& output,
- const std::string& makeCommandCSTR,
- const std::string& config, bool clean, bool fast,
- bool verbose, cmDuration timeout,
- cmSystemTools::OutputOption outputflag,
- std::vector<std::string> const& nativeOptions)
+int cmGlobalGenerator::Build(
+ int jobs, const std::string& /*unused*/, const std::string& bindir,
+ const std::string& projectName, const std::vector<std::string>& targets,
+ std::string& output, const std::string& makeCommandCSTR,
+ const std::string& config, bool clean, bool fast, bool verbose,
+ cmDuration timeout, cmSystemTools::OutputOption outputflag,
+ std::vector<std::string> const& nativeOptions)
{
bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
@@ -1819,32 +1819,37 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/,
return 1;
}
- int retVal;
+ int retVal = 0;
cmSystemTools::SetRunCommandHideConsole(true);
std::string outputBuffer;
std::string* outputPtr = &outputBuffer;
- GeneratedMakeCommand makeCommand;
- this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir,
- target, config, fast, jobs, verbose,
- nativeOptions);
+ std::vector<GeneratedMakeCommand> makeCommand =
+ this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir, targets,
+ config, fast, jobs, verbose, nativeOptions);
// Workaround to convince some commands to produce output.
if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
- makeCommand.RequiresOutputForward) {
+ makeCommand.back().RequiresOutputForward) {
outputflag = cmSystemTools::OUTPUT_FORWARD;
}
// should we do a clean first?
if (clean) {
- GeneratedMakeCommand cleanCommand;
- this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName,
- bindir, "clean", config, fast, jobs, verbose);
+ std::vector<GeneratedMakeCommand> cleanCommand =
+ this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
+ { "clean" }, config, fast, jobs, verbose);
output += "\nRun Clean Command:";
- output += cleanCommand.Printable();
+ output += cleanCommand.front().Printable();
output += "\n";
-
- if (!cmSystemTools::RunSingleCommand(cleanCommand.PrimaryCommand,
+ if (cleanCommand.size() != 1) {
+ this->GetCMakeInstance()->IssueMessage(MessageType::INTERNAL_ERROR,
+ "The generator did not produce "
+ "exactly one command for the "
+ "'clean' target");
+ return 1;
+ }
+ if (!cmSystemTools::RunSingleCommand(cleanCommand.front().PrimaryCommand,
outputPtr, outputPtr, &retVal,
nullptr, outputflag, timeout)) {
cmSystemTools::SetRunCommandHideConsole(hideconsole);
@@ -1858,25 +1863,33 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/,
}
// now build
- std::string makeCommandStr = makeCommand.Printable();
+ std::string makeCommandStr;
output += "\nRun Build Command(s):";
- output += makeCommandStr;
- output += "\n";
- if (!cmSystemTools::RunSingleCommand(makeCommand.PrimaryCommand, outputPtr,
- outputPtr, &retVal, nullptr, outputflag,
- timeout)) {
- cmSystemTools::SetRunCommandHideConsole(hideconsole);
- cmSystemTools::Error(
- "Generator: execution of make failed. Make command was: " +
- makeCommandStr);
- output += *outputPtr;
- output += "\nGenerator: execution of make failed. Make command was: " +
- makeCommandStr + "\n";
+ for (auto command = makeCommand.begin(); command != makeCommand.end();
+ ++command) {
+ makeCommandStr = command->Printable();
+ if (command != makeCommand.end()) {
+ makeCommandStr += " && ";
+ }
- return 1;
+ output += makeCommandStr;
+ if (!cmSystemTools::RunSingleCommand(command->PrimaryCommand, outputPtr,
+ outputPtr, &retVal, nullptr,
+ outputflag, timeout)) {
+ cmSystemTools::SetRunCommandHideConsole(hideconsole);
+ cmSystemTools::Error(
+ "Generator: execution of make failed. Make command was: " +
+ makeCommandStr);
+ output += *outputPtr;
+ output += "\nGenerator: execution of make failed. Make command was: " +
+ makeCommandStr + "\n";
+
+ return 1;
+ }
+ output += *outputPtr;
}
- output += *outputPtr;
+ output += "\n";
cmSystemTools::SetRunCommandHideConsole(hideconsole);
// The OpenWatcom tools do not return an error code when a link
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 1eda572f79..17eb340663 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -13,6 +13,7 @@
#include <utility>
#include <vector>
+#include "cmAlgorithms.h"
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmExportSetMap.h"
@@ -203,10 +204,10 @@ public:
*/
int Build(
int jobs, const std::string& srcdir, const std::string& bindir,
- const std::string& projectName, const std::string& targetName,
- std::string& output, const std::string& makeProgram,
- const std::string& config, bool clean, bool fast, bool verbose,
- cmDuration timeout,
+ const std::string& projectName,
+ std::vector<std::string> const& targetNames, std::string& output,
+ const std::string& makeProgram, const std::string& config, bool clean,
+ bool fast, bool verbose, cmDuration timeout,
cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_NONE,
std::vector<std::string> const& nativeOptions =
std::vector<std::string>());
@@ -221,11 +222,10 @@ public:
{
};
- virtual void GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- int jobs, bool verbose,
+ virtual std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
std::vector<std::string> const& makeOptions = std::vector<std::string>());
virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 3511a15092..4f1d06a232 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -369,12 +369,14 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
fout.Close();
}
-void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
- int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalGhsMultiGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& /*config*/, bool /*fast*/, int jobs, bool /*verbose*/,
+ std::vector<std::string> const& makeOptions)
{
+ GeneratedMakeCommand makeCommand = {};
const char* gbuild =
this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
makeCommand.Add(this->SelectMakeProgram(makeProgram, (std::string)gbuild));
@@ -400,17 +402,23 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
}
makeCommand.Add("-top", proj);
- if (!targetName.empty()) {
- if (targetName == "clean") {
+ if (!targetNames.empty()) {
+ if (std::find(targetNames.begin(), targetNames.end(), "clean") !=
+ targetNames.end()) {
makeCommand.Add("-clean");
} else {
- if (targetName.compare(targetName.size() - 4, 4, ".gpj") == 0) {
- makeCommand.Add(targetName);
- } else {
- makeCommand.Add(targetName + ".gpj");
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ if (tname.compare(tname.size() - 4, 4, ".gpj") == 0) {
+ makeCommand.Add(tname);
+ } else {
+ makeCommand.Add(tname + ".gpj");
+ }
+ }
}
}
}
+ return { makeCommand };
}
void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout)
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index bc2b199a00..c39f40fbec 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -88,15 +88,12 @@ public:
protected:
void Generate() override;
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
private:
void GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts);
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 2b7f486955..43c966649b 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -54,11 +54,12 @@ void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
-void cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- int jobs, bool verbose, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
std::vector<std::string> jomMakeOptions;
@@ -75,7 +76,7 @@ void cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
}
- cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, jobs, verbose, jomMakeOptions);
+ return cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast, jobs,
+ verbose, jomMakeOptions);
}
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index aa8b5fbb02..341b2dd091 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -40,15 +40,12 @@ public:
bool optional) override;
protected:
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index ffe95f905c..a4838bc27e 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -54,11 +54,12 @@ void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
-void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
std::vector<std::string> nmakeMakeOptions;
@@ -68,9 +69,9 @@ void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
nmakeMakeOptions.insert(nmakeMakeOptions.end(), makeOptions.begin(),
makeOptions.end());
- this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions);
+ return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions);
}
void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 06c48e22ba..1fc2f9c770 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -45,15 +45,12 @@ public:
bool optional) override;
protected:
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 61571f1b99..841587cce7 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -677,12 +677,15 @@ void cmGlobalNinjaGenerator::EnableLanguage(
// cmGlobalXCodeGenerator
// Called by:
// cmGlobalGenerator::Build()
-void cmGlobalNinjaGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& /*projectName*/, const std::string& /*projectDir*/,
- const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
- int jobs, bool verbose, std::vector<std::string> const& makeOptions)
-{
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalNinjaGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& /*projectName*/,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& /*config*/,
+ bool /*fast*/, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
+{
+ GeneratedMakeCommand makeCommand;
makeCommand.Add(this->SelectMakeProgram(makeProgram));
if (verbose) {
@@ -695,13 +698,16 @@ void cmGlobalNinjaGenerator::GenerateBuildCommand(
}
makeCommand.Add(makeOptions.begin(), makeOptions.end());
- if (!targetName.empty()) {
- if (targetName == "clean") {
- makeCommand.Add("-t", "clean");
- } else {
- makeCommand.Add(targetName);
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ if (tname == "clean") {
+ makeCommand.Add("-t", "clean");
+ } else {
+ makeCommand.Add(tname);
+ }
}
}
+ return { std::move(makeCommand) };
}
// Non-virtual public methods.
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 69210ecc55..efd1d8fc3a 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -200,15 +200,12 @@ public:
void EnableLanguage(std::vector<std::string> const& languages,
cmMakefile* mf, bool optional) override;
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
// Setup target names
const char* GetAllTargetName() const override { return "all"; }
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 8f8239ef71..3381c81143 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -494,11 +494,13 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
}
-void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& /*projectName*/, const std::string& /*projectDir*/,
- const std::string& targetName, const std::string& /*config*/, bool fast,
- int jobs, bool verbose, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& /*projectName*/,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& /*config*/,
+ bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
std::unique_ptr<cmMakefile> mfu;
cmMakefile* mf;
@@ -515,6 +517,8 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
mf = mfu.get();
}
+ GeneratedMakeCommand makeCommand;
+
// Make it possible to set verbosity also from command line
if (verbose) {
makeCommand.Add(cmSystemTools::GetCMakeCommand());
@@ -532,17 +536,19 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
}
makeCommand.Add(makeOptions.begin(), makeOptions.end());
- if (!targetName.empty()) {
- std::string tname = targetName;
- if (fast) {
- tname += "/fast";
+ for (auto tname : targetNames) {
+ if (!tname.empty()) {
+ if (fast) {
+ tname += "/fast";
+ }
+ tname =
+ mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained(
+ mf->GetState()->GetBinaryDirectory(), tname);
+ cmSystemTools::ConvertToOutputSlashes(tname);
+ makeCommand.Add(std::move(tname));
}
- tname =
- mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained(
- mf->GetState()->GetBinaryDirectory(), tname);
- cmSystemTools::ConvertToOutputSlashes(tname);
- makeCommand.Add(std::move(tname));
}
+ return { std::move(makeCommand) };
}
void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 8a80acc057..496104d741 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -127,15 +127,12 @@ public:
std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }
// change the build command for speed
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
/** Record per-target progress information. */
void RecordTargetProgress(cmMakefileTargetGenerator* tg);
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 9e83425d98..26fd62b896 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -878,12 +878,14 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
return true;
}
-void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- int jobs, bool verbose, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalVisualStudio10Generator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
+ std::vector<GeneratedMakeCommand> makeCommands;
// Select the caller- or user-preferred make program, else MSBuild.
std::string makeProgramSelected =
this->SelectMakeProgram(makeProgram, this->GetMSBuildCommand());
@@ -895,7 +897,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
makeProgramLower.find("vcexpress") != std::string::npos);
// Workaround to convince VCExpress.exe to produce output.
- makeCommand.RequiresOutputForward =
+ const bool requiresOutputForward =
(makeProgramLower.find("vcexpress") != std::string::npos);
// MSBuild is preferred (and required for VS Express), but if the .sln has
@@ -926,62 +928,71 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
}
if (useDevEnv) {
// Use devenv to build solutions containing Intel Fortran projects.
- cmGlobalVisualStudio7Generator::GenerateBuildCommand(
- makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, jobs, verbose, makeOptions);
- return;
- }
+ return cmGlobalVisualStudio7Generator::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast, jobs,
+ verbose, makeOptions);
+ }
+
+ std::vector<std::string> realTargetNames = targetNames;
+ if (targetNames.empty() ||
+ ((targetNames.size() == 1) && targetNames.front().empty())) {
+ realTargetNames = { "ALL_BUILD" };
+ }
+ for (const auto& tname : realTargetNames) {
+ // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug
+ // /target:ALL_BUILD
+ // /m
+ if (tname.empty()) {
+ continue;
+ }
- makeCommand.Add(makeProgramSelected);
+ GeneratedMakeCommand makeCommand;
+ makeCommand.RequiresOutputForward = requiresOutputForward;
+ makeCommand.Add(makeProgramSelected);
- std::string realTarget = targetName;
- // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD
- // /m
- if (realTarget.empty()) {
- realTarget = "ALL_BUILD";
- }
- if (realTarget == "clean") {
- makeCommand.Add(std::string(projectName) + ".sln");
- makeCommand.Add("/t:Clean");
- } else {
- std::string targetProject(realTarget);
- targetProject += ".vcxproj";
- if (targetProject.find('/') == std::string::npos) {
- // it might be in a subdir
- if (cmSlnProjectEntry const* proj =
- slnData.GetProjectByName(realTarget)) {
- targetProject = proj->GetRelativePath();
- cmSystemTools::ConvertToUnixSlashes(targetProject);
+ if (tname == "clean") {
+ makeCommand.Add(std::string(projectName) + ".sln");
+ makeCommand.Add("/t:Clean");
+ } else {
+ std::string targetProject(tname);
+ targetProject += ".vcxproj";
+ if (targetProject.find('/') == std::string::npos) {
+ // it might be in a subdir
+ if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) {
+ targetProject = proj->GetRelativePath();
+ cmSystemTools::ConvertToUnixSlashes(targetProject);
+ }
}
+ makeCommand.Add(std::move(targetProject));
}
- makeCommand.Add(std::move(targetProject));
- }
- std::string configArg = "/p:Configuration=";
- if (!config.empty()) {
- configArg += config;
- } else {
- configArg += "Debug";
- }
- makeCommand.Add(configArg);
- makeCommand.Add(std::string("/p:Platform=") + this->GetPlatformName());
- makeCommand.Add(std::string("/p:VisualStudioVersion=") +
- this->GetIDEVersion());
-
- if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
- if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
- makeCommand.Add("/m");
+ std::string configArg = "/p:Configuration=";
+ if (!config.empty()) {
+ configArg += config;
} else {
- makeCommand.Add(std::string("/m:") + std::to_string(jobs));
+ configArg += "Debug";
+ }
+ makeCommand.Add(configArg);
+ makeCommand.Add(std::string("/p:Platform=") + this->GetPlatformName());
+ makeCommand.Add(std::string("/p:VisualStudioVersion=") +
+ this->GetIDEVersion());
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add("/m");
+ } else {
+ makeCommand.Add(std::string("/m:") + std::to_string(jobs));
+ }
+ // Having msbuild.exe and cl.exe using multiple jobs is discouraged
+ makeCommand.Add("/p:CL_MPCount=1");
}
- // Having msbuild.exe and cl.exe using multiple jobs is discouraged
- makeCommand.Add("/p:CL_MPCount=1");
- }
-
- // Respect the verbosity: 'n' normal will show build commands
- // 'm' minimal only the build step's title
- makeCommand.Add(std::string("/v:") + ((verbose) ? "n" : "m"));
- makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ // Respect the verbosity: 'n' normal will show build commands
+ // 'm' minimal only the build step's title
+ makeCommand.Add(std::string("/v:") + ((verbose) ? "n" : "m"));
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ makeCommands.emplace_back(std::move(makeCommand));
+ }
+ return makeCommands;
}
bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 3ef7abfd05..26db92940e 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -22,15 +22,12 @@ public:
bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
///! create the correct local generator
cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index f091d90938..c694902428 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -190,11 +190,14 @@ const char* cmGlobalVisualStudio7Generator::ExternalProjectType(
}
return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
}
-void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& /*projectDir*/,
- const std::string& targetName, const std::string& config, bool /*fast*/,
- int /*jobs*/, bool /*verbose*/, std::vector<std::string> const& makeOptions)
+
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalVisualStudio7Generator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& config,
+ bool /*fast*/, int /*jobs*/, bool /*verbose*/,
+ std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else devenv.
std::string makeProgramSelected =
@@ -210,24 +213,39 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
}
// Workaround to convince VCExpress.exe to produce output.
- makeCommand.RequiresOutputForward =
+ const bool requiresOutputForward =
(makeProgramLower.find("vcexpress") != std::string::npos);
+ std::vector<GeneratedMakeCommand> makeCommands;
- makeCommand.Add(makeProgramSelected);
-
- makeCommand.Add(std::string(projectName) + ".sln");
- std::string realTarget = targetName;
- bool clean = false;
- if (realTarget == "clean") {
- clean = true;
- realTarget = "ALL_BUILD";
+ std::vector<std::string> realTargetNames = targetNames;
+ if (targetNames.empty() ||
+ ((targetNames.size() == 1) && targetNames.front().empty())) {
+ realTargetNames = { "ALL_BUILD" };
}
-
- makeCommand.Add((clean ? "/clean" : "/build"));
- makeCommand.Add((config.empty() ? "Debug" : config));
- makeCommand.Add("/project");
- makeCommand.Add((realTarget.empty() ? "ALL_BUILD" : realTarget));
- makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ for (const auto& tname : realTargetNames) {
+ std::string realTarget;
+ if (!tname.empty()) {
+ realTarget = tname;
+ } else {
+ continue;
+ }
+ bool clean = false;
+ if (realTarget == "clean") {
+ clean = true;
+ realTarget = "ALL_BUILD";
+ }
+ GeneratedMakeCommand makeCommand;
+ makeCommand.RequiresOutputForward = requiresOutputForward;
+ makeCommand.Add(makeProgramSelected);
+ makeCommand.Add(std::string(projectName) + ".sln");
+ makeCommand.Add((clean ? "/clean" : "/build"));
+ makeCommand.Add((config.empty() ? "Debug" : config));
+ makeCommand.Add("/project");
+ makeCommand.Add(realTarget);
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ makeCommands.emplace_back(std::move(makeCommand));
+ }
+ return makeCommands;
}
///! Create a local generator appropriate to this Global Generator
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 3f1c1732d1..954d1d325d 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -52,15 +52,12 @@ public:
* Try running cmake and building a file. This is used for dynamically
* loaded commands, not as part of the usual build process.
*/
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
/**
* Generate the DSW workspace file.
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index c02c4711aa..8a27384311 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -3,6 +3,7 @@
#include "cmGlobalWatcomWMakeGenerator.h"
#include "cmDocumentationEntry.h"
+#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmake.h"
@@ -50,15 +51,16 @@ void cmGlobalWatcomWMakeGenerator::GetDocumentation(
entry.Brief = "Generates Watcom WMake makefiles.";
}
-void cmGlobalWatcomWMakeGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalWatcomWMakeGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
- this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+ return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
}
void cmGlobalWatcomWMakeGenerator::PrintBuildCommandAdvice(std::ostream& os,
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index 6680b193f0..c96dc7245f 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -50,15 +50,12 @@ public:
bool AllowDeleteOnError() const override { return false; }
protected:
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 88720b6dc8..53baed58b3 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -334,12 +334,15 @@ bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
return ret;
}
-void cmGlobalXCodeGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& /*projectDir*/,
- const std::string& targetName, const std::string& config, bool /*fast*/,
- int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
-{
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalXCodeGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& config,
+ bool /*fast*/, int jobs, bool /*verbose*/,
+ std::vector<std::string> const& makeOptions)
+{
+ GeneratedMakeCommand makeCommand;
// now build the test
makeCommand.Add(
this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
@@ -351,16 +354,24 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
projectArg += "proj";
makeCommand.Add(projectArg);
}
-
- bool clean = false;
- std::string realTarget = targetName;
- if (realTarget == "clean") {
- clean = true;
- realTarget = "ALL_BUILD";
+ if (std::find(targetNames.begin(), targetNames.end(), "clean") !=
+ targetNames.end()) {
+ makeCommand.Add("clean");
+ makeCommand.Add("-target", "ALL_BUILD");
+ } else {
+ makeCommand.Add("build");
+ if (targetNames.empty() ||
+ ((targetNames.size() == 1) && targetNames.front().empty())) {
+ makeCommand.Add("-target", "ALL_BUILD");
+ } else {
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ makeCommand.Add("-target", tname);
+ }
+ }
+ }
}
- makeCommand.Add((clean ? "clean" : "build"));
- makeCommand.Add("-target", (realTarget.empty() ? "ALL_BUILD" : realTarget));
makeCommand.Add("-configuration", (config.empty() ? "Debug" : config));
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
@@ -374,6 +385,7 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
makeCommand.Add("-hideShellScriptEnvironment");
}
makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ return { std::move(makeCommand) };
}
///! Create a local generator appropriate to this Global Generator
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index e1e412dca5..95db852caf 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -66,15 +66,12 @@ public:
* Try running cmake and building a file. This is used for dynalically
* loaded commands, not as part of the usual build process.
*/
- void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, int jobs,
- bool verbose,
- std::vector<std::string> const& makeOptions =
- std::vector<std::string>()) override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
/** Append the subdirectory for the given configuration. */
void AppendDirectoryForConfig(const std::string& prefix,
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index f6f0a953dd..63f5efb81a 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2529,7 +2529,8 @@ cmMessenger* cmake::GetMessenger() const
return this->Messenger;
}
-int cmake::Build(int jobs, const std::string& dir, const std::string& target,
+int cmake::Build(int jobs, const std::string& dir,
+ const std::vector<std::string>& targets,
const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean,
bool verbose)
@@ -2648,9 +2649,8 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target,
#endif
gen->PrintBuildCommandAdvice(std::cerr, jobs);
-
- return gen->Build(jobs, "", dir, projName, target, output, "", config, clean,
- false, verbose, cmDuration::zero(),
+ return gen->Build(jobs, "", dir, projName, targets, output, "", config,
+ clean, false, verbose, cmDuration::zero(),
cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions);
}
diff --git a/Source/cmake.h b/Source/cmake.h
index 6fa2d3a947..1ffeabcb9c 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -424,8 +424,8 @@ public:
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
///! run the --build option
- int Build(int jobs, const std::string& dir, const std::string& target,
- const std::string& config,
+ int Build(int jobs, const std::string& dir,
+ const std::vector<std::string>& targets, const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean,
bool verbose);
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 3465721729..1c56bcd278 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -63,7 +63,7 @@ static const char* cmDocumentationUsageNote[][2] = {
"option\n" \
" is not given.\n" \
" --target <tgt> = Build <tgt> instead of default targets.\n" \
- " May only be specified once.\n" \
+ " May be specified multiple times.\n" \
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
" --clean-first = Build target 'clean' first, then build.\n" \
" (To clean only, use --target 'clean'.)\n" \
@@ -394,13 +394,14 @@ static int do_build(int ac, char const* const* av)
return -1;
#else
int jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
- std::string target;
+ std::vector<std::string> targets;
std::string config = "Debug";
std::string dir;
std::vector<std::string> nativeOptions;
- bool clean = false;
+ bool cleanFirst = false;
+ bool foundClean = false;
+ bool foundNonClean = false;
bool verbose = cmSystemTools::HasEnv("VERBOSE");
- bool hasTarget = false;
enum Doing
{
@@ -420,25 +421,20 @@ static int do_build(int ac, char const* const* av)
if (jobs < 0) {
dir.clear();
}
+ doing = DoingNone;
} else if (cmHasLiteralPrefix(av[i], "--parallel")) {
const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr);
jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1);
if (jobs < 0) {
dir.clear();
}
+ doing = DoingNone;
} else if (strcmp(av[i], "--target") == 0) {
- if (!hasTarget) {
- doing = DoingTarget;
- hasTarget = true;
- } else {
- std::cerr << "'--target' may not be specified more than once.\n\n";
- dir.clear();
- break;
- }
+ doing = DoingTarget;
} else if (strcmp(av[i], "--config") == 0) {
doing = DoingConfig;
} else if (strcmp(av[i], "--clean-first") == 0) {
- clean = true;
+ cleanFirst = true;
doing = DoingNone;
} else if ((strcmp(av[i], "--verbose") == 0) ||
(strcmp(av[i], "-v") == 0)) {
@@ -455,8 +451,23 @@ static int do_build(int ac, char const* const* av)
doing = DoingNone;
break;
case DoingTarget:
- target = av[i];
- doing = DoingNone;
+ if (strlen(av[i]) == 0) {
+ std::cerr << "Warning: Argument number " << i
+ << " after --target option is empty." << std::endl;
+ } else {
+ targets.emplace_back(av[i]);
+ if (strcmp(av[i], "clean") == 0) {
+ foundClean = true;
+ } else {
+ foundNonClean = true;
+ }
+ }
+ if (foundClean && foundNonClean) {
+ std::cerr << "Error: Building 'clean' and other targets together "
+ "is not supported."
+ << std::endl;
+ dir.clear();
+ }
break;
case DoingConfig:
config = av[i];
@@ -507,7 +518,8 @@ static int do_build(int ac, char const* const* av)
cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
});
- return cm.Build(jobs, dir, target, config, nativeOptions, clean, verbose);
+ return cm.Build(jobs, dir, targets, config, nativeOptions, cleanFirst,
+ verbose);
#endif
}
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-jobs-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-jobs-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-jobs-stderr.txt
@@ -0,0 +1 @@
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-stderr.txt
deleted file mode 100644
index f2cbaa6227..0000000000
--- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-stderr.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-^'--target' may not be specified more than once\.
-+
-Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-result.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-result.txt
index d00491fd7e..d00491fd7e 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-result.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-result.txt
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt
new file mode 100644
index 0000000000..40d9bec845
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt
@@ -0,0 +1,2 @@
+^Error: Building 'clean' and other targets together is not supported\.
+Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-result.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt
new file mode 100644
index 0000000000..40d9bec845
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt
@@ -0,0 +1,2 @@
+^Error: Building 'clean' and other targets together is not supported\.
+Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 23fb9ef46d..ff2a8a578e 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -107,6 +107,12 @@ function(run_BuildDir)
${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget)
run_cmake_command(BuildDir--build-multiple-targets ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget2 --target CustomTarget3)
+ run_cmake_command(BuildDir--build-multiple-targets-jobs ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget CustomTarget2 -j2 --target CustomTarget3)
+ run_cmake_command(BuildDir--build-multiple-targets-with-clean-first ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --target clean CustomTarget)
+ run_cmake_command(BuildDir--build-multiple-targets-with-clean-second ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget clean)
run_cmake_command(BuildDir--build-jobs-bad-number ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build BuildDir-build -j 12ab)
run_cmake_command(BuildDir--build-jobs-good-number ${CMAKE_COMMAND} -E chdir ..