summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Help/envvar/CMAKE_BUILD_PARALLEL_LEVEL.rst9
-rw-r--r--Help/manual/cmake-env-variables.7.rst1
-rw-r--r--Help/manual/cmake.1.rst7
-rw-r--r--Help/release/dev/parallel_build_option.rst6
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx6
-rw-r--r--Source/cmCoreTryCompile.cxx3
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx29
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h24
-rw-r--r--Source/cmGlobalGenerator.cxx21
-rw-r--r--Source/cmGlobalGenerator.h13
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx9
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h2
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx26
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h18
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx37
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h20
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx8
-rw-r--r--Source/cmGlobalNinjaGenerator.h12
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx45
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h12
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx16
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h12
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h12
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx30
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h11
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx10
-rw-r--r--Source/cmGlobalXCodeGenerator.h12
-rw-r--r--Source/cmMakefile.cxx4
-rw-r--r--Source/cmMakefile.h3
-rw-r--r--Source/cmake.cxx6
-rw-r--r--Source/cmake.h5
-rw-r--r--Source/cmakemain.cxx50
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-trailing--target-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-trailing-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-trailing--target-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-trailing-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-trailing--target-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-trailing-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--target-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake23
50 files changed, 424 insertions, 100 deletions
diff --git a/Help/envvar/CMAKE_BUILD_PARALLEL_LEVEL.rst b/Help/envvar/CMAKE_BUILD_PARALLEL_LEVEL.rst
new file mode 100644
index 0000000000..198dc513f1
--- /dev/null
+++ b/Help/envvar/CMAKE_BUILD_PARALLEL_LEVEL.rst
@@ -0,0 +1,9 @@
+CMAKE_BUILD_PARALLEL_LEVEL
+--------------------------
+
+Specifies the maximum number of concurrent processes to use when building
+using the ``cmake --build`` command line
+:ref:`Build Tool Mode <Build Tool Mode>`.
+
+If this variable is defined empty the native build tool's default number is
+used.
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index 2d8869f9e4..2d17bb5401 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -13,6 +13,7 @@ Environment Variables that Control the Build
.. toctree::
:maxdepth: 1
+ /envvar/CMAKE_BUILD_PARALLEL_LEVEL
/envvar/CMAKE_CONFIG_TYPE
/envvar/CMAKE_MSVCIDE_RUN_PATH
/envvar/CMAKE_OSX_ARCHITECTURES
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 577d321476..177acd4cc3 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -159,6 +159,13 @@ following options:
``--build <dir>``
Project binary directory to be built. This is required and must be first.
+``-j [<jobs>], --parallel [<jobs>]``
+ The maximum number of concurrent processes to use when building.
+ If ``<jobs>`` is omitted the native build tool's default number is used.
+
+ 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.
diff --git a/Help/release/dev/parallel_build_option.rst b/Help/release/dev/parallel_build_option.rst
new file mode 100644
index 0000000000..2451fd033d
--- /dev/null
+++ b/Help/release/dev/parallel_build_option.rst
@@ -0,0 +1,6 @@
+parallel_build_option
+---------------------
+
+* The :manual:`cmake(1)` :ref:`Build Tool Mode` (``cmake --build``) gained
+ ``--parallel [<jobs>]`` and ``-j [<jobs>]`` options to specify a parallel
+ build level. They map to corresponding options of the native build tool.
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index b2c68e76ed..fccbc95303 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -253,9 +253,9 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
config = "Debug";
}
int retVal = cm.GetGlobalGenerator()->Build(
- this->SourceDir, this->BinaryDir, this->BuildProject, tar, output,
- this->BuildMakeProgram, config, !this->BuildNoClean, false, false,
- remainingTime);
+ cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
+ this->BuildProject, tar, output, this->BuildMakeProgram, config,
+ !this->BuildNoClean, false, false, remainingTime);
out << output;
// if the build failed then return
if (retVal) {
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 26e0db9e28..a9b7adf9b3 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -818,7 +818,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// actually do the try compile now that everything is setup
int res = this->Makefile->TryCompile(
sourceDirectory, this->BinaryDirectory, projectName, targetName,
- this->SrcFileSignature, &cmakeFlags, output);
+ this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, &cmakeFlags,
+ output);
if (erroroc) {
cmSystemTools::SetErrorOccured();
}
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index d2372a766d..23891031bf 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -51,3 +51,32 @@ void cmGlobalBorlandMakefileGenerator::GetDocumentation(
entry.Name = cmGlobalBorlandMakefileGenerator::GetActualName();
entry.Brief = "Generates Borland makefiles.";
}
+
+void cmGlobalBorlandMakefileGenerator::GenerateBuildCommand(
+ std::vector<std::string>& 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)
+{
+ this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+}
+
+void cmGlobalBorlandMakefileGenerator::PrintBuildCommandAdvice(
+ std::ostream& os, int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // Borland's make does not support parallel builds
+ // see http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Make
+
+ /* clang-format off */
+ os <<
+ "Warning: Borland's make does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index 5578d76461..85fee7439d 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -5,6 +5,8 @@
#include "cmGlobalNMakeMakefileGenerator.h"
+#include <iosfwd>
+
/** \class cmGlobalBorlandMakefileGenerator
* \brief Write a Borland makefiles.
*
@@ -21,7 +23,7 @@ public:
}
///! Get the name for the generator.
- virtual std::string GetName() const
+ std::string GetName() const override
{
return cmGlobalBorlandMakefileGenerator::GetActualName();
}
@@ -31,17 +33,27 @@ public:
static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+ bool AllowNotParallel() const override { return false; }
+ bool AllowDeleteOnError() const override { return false; }
+
+protected:
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
- virtual bool AllowNotParallel() const { return false; }
- virtual bool AllowDeleteOnError() const { return false; }
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index cf277d5f41..8a89f362a7 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1741,7 +1741,7 @@ void cmGlobalGenerator::CheckTargetProperties()
}
}
-int cmGlobalGenerator::TryCompile(const std::string& srcdir,
+int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
const std::string& bindir,
const std::string& projectName,
const std::string& target, bool fast,
@@ -1782,7 +1782,7 @@ int cmGlobalGenerator::TryCompile(const std::string& srcdir,
}
std::string config =
mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
- return this->Build(srcdir, bindir, projectName, newTarget, output, "",
+ return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "",
config, false, fast, false, this->TryCompileTimeout);
}
@@ -1790,13 +1790,21 @@ void cmGlobalGenerator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& /*unused*/,
const std::string& /*unused*/, const std::string& /*unused*/,
const std::string& /*unused*/, const std::string& /*unused*/,
- bool /*unused*/, bool /*unused*/, std::vector<std::string> const& /*unused*/)
+ bool /*unused*/, int /*unused*/, bool /*unused*/,
+ std::vector<std::string> const& /*unused*/)
{
makeCommand.push_back(
"cmGlobalGenerator::GenerateBuildCommand not implemented");
}
-int cmGlobalGenerator::Build(const std::string& /*unused*/,
+void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
+ int /*jobs*/) const
+{
+ // Subclasses override this method if they e.g want to give a warning that
+ // 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,
@@ -1832,7 +1840,8 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
std::vector<std::string> makeCommand;
this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir,
- target, config, fast, verbose, nativeOptions);
+ target, config, fast, jobs, verbose,
+ nativeOptions);
// Workaround to convince VCExpress.exe to produce output.
if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
@@ -1846,7 +1855,7 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
if (clean) {
std::vector<std::string> cleanCommand;
this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName,
- bindir, "clean", config, fast, verbose);
+ bindir, "clean", config, fast, jobs, verbose);
output += "\nRun Clean Command:";
output += cmSystemTools::PrintSingleCommand(cleanCommand);
output += "\n";
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 34ed5b0e6d..62c544170f 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -147,9 +147,10 @@ public:
* Try running cmake and building a file. This is used for dynamically
* loaded commands, not as part of the usual build process.
*/
- int TryCompile(const std::string& srcdir, const std::string& bindir,
- const std::string& projectName, const std::string& targetName,
- bool fast, std::string& output, cmMakefile* mf);
+ int TryCompile(int jobs, const std::string& srcdir,
+ const std::string& bindir, const std::string& projectName,
+ const std::string& targetName, bool fast, std::string& output,
+ cmMakefile* mf);
/**
* Build a file given the following information. This is a more direct call
@@ -157,7 +158,7 @@ public:
* empty then all is assumed. clean indicates if a "make clean" should be
* done first.
*/
- int Build(const std::string& srcdir, const std::string& bindir,
+ 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,
@@ -176,9 +177,11 @@ public:
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& projectDir,
const std::string& targetName, const std::string& config, bool fast,
- bool verbose,
+ int jobs, bool verbose,
std::vector<std::string> const& makeOptions = std::vector<std::string>());
+ virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
+
/** Generate a "cmake --build" call for a given target and config. */
std::string GenerateCMakeBuildCommand(const std::string& target,
const std::string& config,
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 946ed80ca8..f4ecff2877 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -273,11 +273,18 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& /*projectName*/, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
makeCommand.push_back(
this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand()));
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("-parallel");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back(std::to_string(jobs));
+ }
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
if (!targetName.empty()) {
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index 7d4b2ba7fe..c5388ad397 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -89,7 +89,7 @@ protected:
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& projectDir,
const std::string& targetName, const std::string& config, bool fast,
- bool verbose,
+ int jobs, bool verbose,
std::vector<std::string> const& makeOptions = std::vector<std::string>());
private:
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 18c45e0d86..0f41ea1482 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -52,3 +52,29 @@ void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+
+void cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
+ std::vector<std::string>& 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> jomMakeOptions;
+
+ // Since we have full control over the invocation of JOM, let us
+ // make it quiet.
+ jomMakeOptions.push_back(this->MakeSilentFlag);
+ jomMakeOptions.insert(jomMakeOptions.end(), makeOptions.begin(),
+ makeOptions.end());
+
+ // JOM does parallel builds by default, the -j is only needed if a specific
+ // number is given
+ // see https://github.com/qt-labs/jom/blob/v1.1.2/src/jomlib/options.cpp
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
+ }
+
+ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, jobs, verbose, jomMakeOptions);
+}
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 2e8ee29392..65f340cdce 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -5,6 +5,8 @@
#include "cmGlobalUnixMakefileGenerator3.h"
+#include <iosfwd>
+
/** \class cmGlobalJOMMakefileGenerator
* \brief Write a JOM makefiles.
*
@@ -19,7 +21,7 @@ public:
return new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>();
}
///! Get the name for the generator.
- virtual std::string GetName() const
+ std::string GetName() const override
{
return cmGlobalJOMMakefileGenerator::GetActualName();
}
@@ -34,12 +36,20 @@ public:
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+protected:
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const;
+ const char* envVar) const override;
};
#endif
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index da683fb39f..eb66bd12b1 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -52,3 +52,40 @@ void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+
+void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
+ std::vector<std::string>& 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> nmakeMakeOptions;
+
+ // Since we have full control over the invocation of nmake, let us
+ // make it quiet.
+ nmakeMakeOptions.push_back(this->MakeSilentFlag);
+ 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);
+}
+
+void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
+ int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // nmake does not support parallel build level
+ // see https://msdn.microsoft.com/en-us/library/afyyse50.aspx
+
+ /* clang-format off */
+ os <<
+ "Warning: NMake does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 05ab90435f..4b6382e1c5 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -5,6 +5,8 @@
#include "cmGlobalUnixMakefileGenerator3.h"
+#include <iosfwd>
+
/** \class cmGlobalNMakeMakefileGenerator
* \brief Write a NMake makefiles.
*
@@ -20,7 +22,7 @@ public:
cmGlobalNMakeMakefileGenerator>();
}
///! Get the name for the generator.
- virtual std::string GetName() const
+ std::string GetName() const override
{
return cmGlobalNMakeMakefileGenerator::GetActualName();
}
@@ -39,12 +41,22 @@ public:
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+protected:
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
+
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const;
+ const char* envVar) const override;
};
#endif
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index c19a61c8f9..69bc3be46e 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -674,7 +674,7 @@ void cmGlobalNinjaGenerator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& /*projectName*/, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
- bool verbose, std::vector<std::string> const& makeOptions)
+ int jobs, bool verbose, std::vector<std::string> const& makeOptions)
{
makeCommand.push_back(this->SelectMakeProgram(makeProgram));
@@ -682,6 +682,12 @@ void cmGlobalNinjaGenerator::GenerateBuildCommand(
makeCommand.push_back("-v");
}
+ if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) &&
+ (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) {
+ makeCommand.push_back("-j");
+ makeCommand.push_back(std::to_string(jobs));
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
if (!targetName.empty()) {
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index bfff3d98ae..17b9a7d793 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -202,13 +202,11 @@ public:
void EnableLanguage(std::vector<std::string> const& languages,
cmMakefile* mf, bool optional) override;
- void GenerateBuildCommand(std::vector<std::string>& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
- std::vector<std::string> const& makeOptions =
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
// Setup target names
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index c07f10faa5..641b76002a 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -7,7 +7,6 @@
#include <sstream>
#include <utility>
-#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
@@ -494,31 +493,33 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& /*projectName*/, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& /*config*/, bool fast,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
+ cmMakefile* mf;
+ if (!this->Makefiles.empty()) {
+ mf = this->Makefiles[0];
+ } else {
+ cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
+ snapshot.GetDirectory().SetCurrentSource(
+ this->CMakeInstance->GetHomeDirectory());
+ snapshot.GetDirectory().SetCurrentBinary(
+ this->CMakeInstance->GetHomeOutputDirectory());
+ snapshot.SetDefaultDefinitions();
+ mf = new cmMakefile(this, snapshot);
+ }
+
makeCommand.push_back(this->SelectMakeProgram(makeProgram));
- // Since we have full control over the invocation of nmake, let us
- // make it quiet.
- if (cmHasLiteralPrefix(this->GetName(), "NMake Makefiles")) {
- makeCommand.push_back("/NOLOGO");
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("-j");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back(std::to_string(jobs));
+ }
}
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
if (!targetName.empty()) {
- cmMakefile* mf;
- if (!this->Makefiles.empty()) {
- mf = this->Makefiles[0];
- } else {
- cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
- snapshot.GetDirectory().SetCurrentSource(
- this->CMakeInstance->GetHomeDirectory());
- snapshot.GetDirectory().SetCurrentBinary(
- this->CMakeInstance->GetHomeOutputDirectory());
- snapshot.SetDefaultDefinitions();
- mf = new cmMakefile(this, snapshot);
- }
-
std::string tname = targetName;
if (fast) {
tname += "/fast";
@@ -528,9 +529,9 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
cmSystemTools::ConvertToOutputSlashes(tname);
makeCommand.push_back(std::move(tname));
- if (this->Makefiles.empty()) {
- delete mf;
- }
+ }
+ if (this->Makefiles.empty()) {
+ delete mf;
}
}
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index f9ce88cb4d..097678fb82 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -127,13 +127,11 @@ public:
std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }
// change the build command for speed
- void GenerateBuildCommand(std::vector<std::string>& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
- std::vector<std::string> const& makeOptions =
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
/** Record per-target progress information. */
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 205e0d06bf..51e9ab152d 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -764,7 +764,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& projectDir,
const std::string& targetName, const std::string& config, bool fast,
- bool verbose, std::vector<std::string> const& makeOptions)
+ int jobs, bool verbose, std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else MSBuild.
std::string makeProgramSelected =
@@ -805,7 +805,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
// Use devenv to build solutions containing Intel Fortran projects.
cmGlobalVisualStudio7Generator::GenerateBuildCommand(
makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, verbose, makeOptions);
+ fast, jobs, verbose, makeOptions);
return;
}
@@ -813,6 +813,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
std::string realTarget = targetName;
// msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD
+ // /m
if (realTarget.empty()) {
realTarget = "ALL_BUILD";
}
@@ -841,6 +842,17 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
makeCommand.push_back(configArg);
makeCommand.push_back(std::string("/p:VisualStudioVersion=") +
this->GetIDEVersion());
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("/m");
+ } else {
+ makeCommand.push_back(std::string("/m:") + std::to_string(jobs));
+ }
+ // Having msbuild.exe and cl.exe using multiple jobs is discouraged
+ makeCommand.push_back("/p:CL_MPCount=1");
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index f2501c2229..098c8d48ee 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -24,13 +24,11 @@ public:
bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
- void GenerateBuildCommand(std::vector<std::string>& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
- std::vector<std::string> const& makeOptions =
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
///! create the correct local generator
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 7ff007f5b8..158f484315 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -199,7 +199,7 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& config, bool /*fast*/,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int /*jobs*/, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else devenv.
std::string makeProgramSelected =
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 8d1bdc0cc6..77d4a9691c 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -55,13 +55,11 @@ 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(std::vector<std::string>& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
- std::vector<std::string> const& makeOptions =
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
/**
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index 94cdb38486..558ef15859 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -7,6 +7,8 @@
#include "cmState.h"
#include "cmake.h"
+#include <ostream>
+
cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator(cmake* cm)
: cmGlobalUnixMakefileGenerator3(cm)
{
@@ -47,3 +49,31 @@ void cmGlobalWatcomWMakeGenerator::GetDocumentation(
entry.Name = cmGlobalWatcomWMakeGenerator::GetActualName();
entry.Brief = "Generates Watcom WMake makefiles.";
}
+
+void cmGlobalWatcomWMakeGenerator::GenerateBuildCommand(
+ std::vector<std::string>& 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)
+{
+ this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+}
+
+void cmGlobalWatcomWMakeGenerator::PrintBuildCommandAdvice(std::ostream& os,
+ int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // wmake does not support parallel build level
+
+ /* clang-format off */
+ os <<
+ "Warning: Watcom's WMake does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index e8b3a73c95..1729bf14f8 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -8,6 +8,7 @@
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include <iosfwd>
#include <string>
#include <vector>
@@ -47,6 +48,16 @@ public:
bool AllowNotParallel() const override { return false; }
bool AllowDeleteOnError() const override { return false; }
+
+protected:
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
+
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
#endif
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 4481bdc244..f69f23e6e2 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -325,7 +325,7 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& config, bool /*fast*/,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
// now build the test
makeCommand.push_back(
@@ -356,6 +356,14 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
}
makeCommand.push_back("-configuration");
makeCommand.push_back(!config.empty() ? config : "Debug");
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("-jobs");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back(std::to_string(jobs));
+ }
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 7c51177592..f7f44289c2 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -66,13 +66,11 @@ 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(std::vector<std::string>& makeCommand,
- const std::string& makeProgram,
- const std::string& projectName,
- const std::string& projectDir,
- const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
- std::vector<std::string> const& makeOptions =
+ void GenerateBuildCommand(
+ std::vector<std::string>& 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;
/** Append the subdirectory for the given configuration. */
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 33e76b233b..f41c2f01e6 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -3269,7 +3269,7 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
int cmMakefile::TryCompile(const std::string& srcdir,
const std::string& bindir,
const std::string& projectName,
- const std::string& targetName, bool fast,
+ const std::string& targetName, bool fast, int jobs,
const std::vector<std::string>* cmakeArgs,
std::string& output)
{
@@ -3381,7 +3381,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// finally call the generator to actually build the resulting project
int ret = this->GetGlobalGenerator()->TryCompile(
- srcdir, bindir, projectName, targetName, fast, output, this);
+ jobs, srcdir, bindir, projectName, targetName, fast, output, this);
this->IsSourceFileTryCompile = false;
return ret;
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 9f32c4f5cf..ac7baae5c9 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -102,7 +102,8 @@ public:
*/
int TryCompile(const std::string& srcdir, const std::string& bindir,
const std::string& projectName, const std::string& targetName,
- bool fast, const std::vector<std::string>* cmakeArgs,
+ bool fast, int jobs,
+ const std::vector<std::string>* cmakeArgs,
std::string& output);
bool GetIsSourceFileTryCompile() const;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5bae4e74a1..801d52d934 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2398,7 +2398,7 @@ cmMessenger* cmake::GetMessenger() const
return this->Messenger;
}
-int cmake::Build(const std::string& dir, const std::string& target,
+int cmake::Build(int jobs, const std::string& dir, const std::string& target,
const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean)
{
@@ -2508,7 +2508,9 @@ int cmake::Build(const std::string& dir, const std::string& target,
}
#endif
- return gen->Build("", dir, projName, target, output, "", config, clean,
+ gen->PrintBuildCommandAdvice(std::cerr, jobs);
+
+ return gen->Build(jobs, "", dir, projName, target, output, "", config, clean,
false, verbose, cmDuration::zero(),
cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions);
}
diff --git a/Source/cmake.h b/Source/cmake.h
index 63dbe9f795..6c0d77ca10 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -119,6 +119,9 @@ public:
typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
+ static const int NO_BUILD_PARALLEL_LEVEL = -1;
+ static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0;
+
/// Default constructor
cmake(Role role);
/// Destructor
@@ -430,7 +433,7 @@ public:
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
///! run the --build option
- int Build(const std::string& dir, const std::string& target,
+ int Build(int jobs, const std::string& dir, const std::string& target,
const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean);
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index b185a1bc4a..9c9f65c4e5 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -22,6 +22,8 @@
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmsys/ConsoleBuf.hxx"
#endif
+
+#include <ctype.h>
#include <iostream>
#include <string.h>
#include <string>
@@ -49,6 +51,12 @@ static const char* cmDocumentationUsageNote[][2] = {
#define CMAKE_BUILD_OPTIONS \
" <dir> = Project binary directory to be built.\n" \
+ " -j [<jobs>] --parallel [<jobs>] = Build in parallel using\n" \
+ " the given number of jobs. If <jobs> is omitted\n" \
+ " the native build tool's default number is used.\n" \
+ " The CMAKE_BUILD_PARALLEL_LEVEL environment variable\n" \
+ " specifies a default parallel level when this option\n" \
+ " is not given.\n" \
" --target <tgt> = Build <tgt> instead of default targets.\n" \
" May only be specified once.\n" \
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
@@ -338,6 +346,7 @@ static int do_build(int ac, char const* const* av)
std::cerr << "This cmake does not support --build\n";
return -1;
#else
+ int jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
std::string target;
std::string config = "Debug";
std::string dir;
@@ -348,6 +357,7 @@ static int do_build(int ac, char const* const* av)
enum Doing
{
DoingNone,
+ DoingJobs,
DoingDir,
DoingTarget,
DoingConfig,
@@ -357,6 +367,13 @@ static int do_build(int ac, char const* const* av)
for (int i = 2; i < ac; ++i) {
if (doing == DoingNative) {
nativeOptions.push_back(av[i]);
+ } else if ((strcmp(av[i], "-j") == 0) ||
+ (strcmp(av[i], "--parallel") == 0)) {
+ jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL;
+ /* does the next argument start with a number? */
+ if ((i + 1 < ac) && (isdigit(*av[i + 1]))) {
+ doing = DoingJobs;
+ }
} else if (strcmp(av[i], "--target") == 0) {
if (!hasTarget) {
doing = DoingTarget;
@@ -377,6 +394,18 @@ static int do_build(int ac, char const* const* av)
doing = DoingNative;
} else {
switch (doing) {
+ case DoingJobs: {
+ unsigned long numJobs = 0;
+ if (cmSystemTools::StringToULong(av[i], &numJobs)) {
+ jobs = int(numJobs);
+ doing = DoingNone;
+ } else {
+ std::cerr << "'" << av[i - 1] << "' invalid number '" << av[i]
+ << "' given.\n\n";
+ dir.clear();
+ break;
+ }
+ } break;
case DoingDir:
dir = cmSystemTools::CollapseFullPath(av[i]);
doing = DoingNone;
@@ -396,6 +425,25 @@ static int do_build(int ac, char const* const* av)
}
}
}
+
+ if (jobs == cmake::NO_BUILD_PARALLEL_LEVEL) {
+ std::string parallel;
+ if (cmSystemTools::GetEnv("CMAKE_BUILD_PARALLEL_LEVEL", parallel)) {
+ if (parallel.empty()) {
+ jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL;
+ } else {
+ unsigned long numJobs = 0;
+ if (cmSystemTools::StringToULong(parallel.c_str(), &numJobs)) {
+ jobs = int(numJobs);
+ } else {
+ std::cerr << "'CMAKE_BUILD_PARALLEL_LEVEL' environment variable\n"
+ << "invalid number '" << parallel << "' given.\n\n";
+ dir.clear();
+ }
+ }
+ }
+ }
+
if (dir.empty()) {
/* clang-format off */
std::cerr <<
@@ -410,7 +458,7 @@ static int do_build(int ac, char const* const* av)
cmake cm(cmake::RoleInternal);
cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm);
cm.SetProgressCallback(cmakemainProgressCallback, &cm);
- return cm.Build(dir, target, config, nativeOptions, clean);
+ return cm.Build(jobs, dir, target, config, nativeOptions, clean);
#endif
}
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-result.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt
new file mode 100644
index 0000000000..e73d76020b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt
@@ -0,0 +1,3 @@
+^'--parallel' invalid number '12ab' given\.
++
+Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-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--parallel-good-number-trailing--target-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-trailing--target-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-trailing--target-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--parallel-good-number-trailing-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-trailing-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-good-number-trailing-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--parallel-no-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-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--parallel-no-number-trailing--target-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-trailing--target-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-trailing--target-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--parallel-no-number-trailing-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-trailing-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-number-trailing-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-jobs-bad-number-result.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt
new file mode 100644
index 0000000000..c810087861
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt
@@ -0,0 +1,3 @@
+^'-j' invalid number '12ab' given\.
++
+Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-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-jobs-good-number-trailing--target-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-trailing--target-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-trailing--target-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-jobs-good-number-trailing-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-trailing-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-good-number-trailing-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-jobs-no-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-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-jobs-no-number-trailing--target-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--target-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing--target-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-jobs-no-number-trailing-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing-stderr.txt
new file mode 100644
index 0000000000..3c2c808e97
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-number-trailing-stderr.txt
@@ -0,0 +1 @@
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index d8dbeec860..3bb2a89f5b 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -59,6 +59,29 @@ 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-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 ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j 2)
+ run_cmake_command(BuildDir--build-jobs-good-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j 2 --target CustomTarget)
+ run_cmake_command(BuildDir--build--parallel-bad-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel 12ab)
+ run_cmake_command(BuildDir--build--parallel-good-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel 2)
+ run_cmake_command(BuildDir--build--parallel-good-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel 2 --target CustomTarget)
+ # No default jobs for Xcode and FreeBSD build command
+ if(NOT RunCMake_GENERATOR MATCHES "Xcode" AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ run_cmake_command(BuildDir--build-jobs-no-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j)
+ run_cmake_command(BuildDir--build-jobs-no-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j --target CustomTarget)
+ run_cmake_command(BuildDir--build--parallel-no-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel)
+ run_cmake_command(BuildDir--build--parallel-no-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel --target CustomTarget)
+ endif()
endfunction()
run_BuildDir()