summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-03-06 13:32:15 (GMT)
committerKitware Robot <kwrobot@kitware.com>2019-03-06 13:32:39 (GMT)
commit809890e3f6bcb1a5def21e2e99a54bb6f38505fc (patch)
tree4b7e3f73bc6cea6567779b4eefa1b0a6f67f4334
parent43771d6e7384d7539144638d77ea96cad16a8203 (diff)
parent324d18bb3418aee8dcb63e28106ac0dac6abea71 (diff)
downloadCMake-809890e3f6bcb1a5def21e2e99a54bb6f38505fc.zip
CMake-809890e3f6bcb1a5def21e2e99a54bb6f38505fc.tar.gz
CMake-809890e3f6bcb1a5def21e2e99a54bb6f38505fc.tar.bz2
Merge topic 'issue-18883-support-for-multiple-targets'
324d18bb34 cmake: Teach --build mode to support multiple targets ebc94500c1 cmGlobalGenerator: Optimize Printable() method from GeneratedMakeCommand fdeb364a84 cmGlobalGenerator: Change case of methods from GeneratedMakeCommand struct b3955a08ab cmakemain: Remove ignored --use-stderr option from command line help f1367c8c51 cmGlobalGenerator: Remove unused code Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !2939
-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.cxx112
-rw-r--r--Source/cmGlobalGenerator.h37
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx42
-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.cxx34
-rw-r--r--Source/cmGlobalNinjaGenerator.h15
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx50
-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.cxx56
-rw-r--r--Source/cmGlobalXCodeGenerator.h15
-rw-r--r--Source/cmake.cxx8
-rw-r--r--Source/cmake.h4
-rw-r--r--Source/cmakemain.cxx45
-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, 432 insertions, 382 deletions
diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst
index b83edaf..6659005 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 f3b81ec..e9a08b5 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 0000000..1275ca3
--- /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 b2c88df..a7d4455 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 c2eb583..281d371 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 ca04b7b..02d0d5f 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 c7b3591..6964b62 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1763,20 +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;
-#if 0
-# if defined(_WIN32) || defined(__CYGWIN__)
- std::string tmp = target;
- // if the target does not already end in . something
- // then assume .exe
- if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
- {
- newTarget += ".exe";
- }
-# endif // WIN32
-#endif
+ newTarget = { target };
}
std::string config =
mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
@@ -1784,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*/,
- const std::string& /*unused*/, const std::string& /*unused*/,
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalGenerator::GenerateBuildCommand(
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*/)
{
- makeCommand.add("cmGlobalGenerator::GenerateBuildCommand not implemented");
+ GeneratedMakeCommand makeCommand;
+ makeCommand.Add("cmGlobalGenerator::GenerateBuildCommand not implemented");
+ return { std::move(makeCommand) };
}
void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
@@ -1801,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();
@@ -1830,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);
@@ -1869,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 ac01326..17eb340 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"
@@ -56,33 +57,20 @@ struct GeneratedMakeCommand
{
// Add each argument as a separate element to the vector
template <typename... T>
- void add(T&&... args)
+ void Add(T&&... args)
{
// iterate the args and append each one
AppendStrs(PrimaryCommand, std::forward<T>(args)...);
}
// Add each value in the iterators as a separate element to the vector
- void add(std::vector<std::string>::const_iterator start,
+ void Add(std::vector<std::string>::const_iterator start,
std::vector<std::string>::const_iterator end)
{
PrimaryCommand.insert(PrimaryCommand.end(), start, end);
}
- std::string printable() const
- {
- std::size_t size = PrimaryCommand.size();
- for (auto&& i : PrimaryCommand) {
- size += i.size();
- }
- std::string buffer;
- buffer.reserve(size);
- for (auto&& i : PrimaryCommand) {
- buffer.append(i);
- buffer.append(1, ' ');
- }
- return buffer;
- }
+ std::string Printable() const { return cmJoin(PrimaryCommand, " "); }
std::vector<std::string> PrimaryCommand;
bool RequiresOutputForward = false;
@@ -216,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>());
@@ -234,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 746ddad..4f1d06a 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -369,24 +369,26 @@ 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));
+ makeCommand.Add(this->SelectMakeProgram(makeProgram, (std::string)gbuild));
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
- makeCommand.add("-parallel");
+ makeCommand.Add("-parallel");
if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
- makeCommand.add(std::to_string(jobs));
+ makeCommand.Add(std::to_string(jobs));
}
}
- makeCommand.add(makeOptions.begin(), makeOptions.end());
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
/* determine which top-project file to use */
std::string proj = projectName + ".top" + FILE_EXTENSION;
@@ -399,18 +401,24 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
}
}
- makeCommand.add("-top", proj);
- if (!targetName.empty()) {
- if (targetName == "clean") {
- makeCommand.add("-clean");
+ makeCommand.Add("-top", proj);
+ 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 bc2b199..c39f40f 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 2b7f486..43c9666 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 aa8b5fb..341b2dd 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 ffe95f9..a4838bc 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 06c48e2..1fc2f9c 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 d21fd35..841587c 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -677,31 +677,37 @@ 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)
{
- makeCommand.add(this->SelectMakeProgram(makeProgram));
+ GeneratedMakeCommand makeCommand;
+ makeCommand.Add(this->SelectMakeProgram(makeProgram));
if (verbose) {
- makeCommand.add("-v");
+ makeCommand.Add("-v");
}
if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) &&
(jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) {
- makeCommand.add("-j", std::to_string(jobs));
+ makeCommand.Add("-j", std::to_string(jobs));
}
- makeCommand.add(makeOptions.begin(), makeOptions.end());
- if (!targetName.empty()) {
- if (targetName == "clean") {
- makeCommand.add("-t", "clean");
- } else {
- makeCommand.add(targetName);
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ 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 69210ec..efd1d8f 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 dac6ea6..3381c81 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,34 +517,38 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
mf = mfu.get();
}
+ GeneratedMakeCommand makeCommand;
+
// Make it possible to set verbosity also from command line
if (verbose) {
- makeCommand.add(cmSystemTools::GetCMakeCommand());
- makeCommand.add("-E");
- makeCommand.add("env");
- makeCommand.add("VERBOSE=1");
+ makeCommand.Add(cmSystemTools::GetCMakeCommand());
+ makeCommand.Add("-E");
+ makeCommand.Add("env");
+ makeCommand.Add("VERBOSE=1");
}
- makeCommand.add(this->SelectMakeProgram(makeProgram));
+ makeCommand.Add(this->SelectMakeProgram(makeProgram));
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
- makeCommand.add("-j");
+ makeCommand.Add("-j");
if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
- makeCommand.add(std::to_string(jobs));
+ makeCommand.Add(std::to_string(jobs));
}
}
- makeCommand.add(makeOptions.begin(), makeOptions.end());
- if (!targetName.empty()) {
- std::string tname = targetName;
- if (fast) {
- tname += "/fast";
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ 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 8a80acc..496104d 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 f872de5..26fd62b 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 3ef7abf..26db929 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 d457f60..c694902 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 3f1c173..954d1d3 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 c02c471..8a27384 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 6680b19..c96dc72 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 11cc98e..53baed5 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -334,46 +334,58 @@ 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(
+ makeCommand.Add(
this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
if (!projectName.empty()) {
- makeCommand.add("-project");
+ makeCommand.Add("-project");
std::string projectArg = projectName;
projectArg += ".xcode";
projectArg += "proj";
- makeCommand.add(projectArg);
+ 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));
+ makeCommand.Add("-configuration", (config.empty() ? "Debug" : config));
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
- makeCommand.add("-jobs");
+ makeCommand.Add("-jobs");
if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
- makeCommand.add(std::to_string(jobs));
+ makeCommand.Add(std::to_string(jobs));
}
}
if (this->XcodeVersion >= 70) {
- makeCommand.add("-hideShellScriptEnvironment");
+ makeCommand.Add("-hideShellScriptEnvironment");
}
- makeCommand.add(makeOptions.begin(), makeOptions.end());
+ 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 e1e412d..95db852 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 f6f0a95..63f5efb 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 6fa2d3a..1ffeabc 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 e6f4021..1c56bcd 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -63,11 +63,10 @@ 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" \
- " --use-stderr = Ignored. Behavior is default in CMake >= 3.0.\n" \
" -v --verbose = Enable verbose output - if supported - including\n" \
" the build commands to be executed. \n" \
" -- = Pass remaining options to the native tool.\n"
@@ -395,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
{
@@ -421,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)) {
@@ -456,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];
@@ -508,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 0000000..3c2c808
--- /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 f2cbaa6..0000000
--- 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 d00491f..d00491f 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 0000000..40d9bec
--- /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 0000000..d00491f
--- /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 0000000..40d9bec
--- /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 23fb9ef..ff2a8a5 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 ..