build_command: Return a "cmake --build" command-line

Re-implement the build_command() command to use "cmake --build" instead
of generating a native build tool invocation directly.  This command
will internally invoke the proper native build tool.

This avoids requiring cmGlobalGenerator::GenerateBuildCommand to produce
a string so that it can be later refactored to produce a vector with no
quoting or escaping.  It will also allow us to later teach CMake to
delay the decision about which build tool to invoke until after the
project build system is generated to disk.  For example, on Visual
Studio 10 and above the preferred command-line tool is MSBuild, but we
need to fall back to devenv if the .sln has Intel Fortran .vfproj files.
This commit is contained in:
Brad King 2013-11-13 16:01:20 -05:00
parent 05923172f9
commit bca67c710f
6 changed files with 46 additions and 54 deletions

View File

@ -1,37 +1,44 @@
build_command build_command
------------- -------------
Get the command line to build this project. Get a command line to build the current project.
This is mainly intended for internal use by the :module:`CTest` module.
:: .. code-block:: cmake
build_command(<variable> build_command(<variable>
[CONFIGURATION <config>] [CONFIGURATION <config>]
[PROJECT_NAME <projname>] [TARGET <target>]
[TARGET <target>]) [PROJECT_NAME <projname>] # legacy, causes warning
)
Sets the given <variable> to a string containing the command line for Sets the given ``<variable>`` to a command-line string of the form::
building one configuration of a target in a project using the build
tool appropriate for the current CMAKE_GENERATOR.
If CONFIGURATION is omitted, CMake chooses a reasonable default value <cmake> --build . [--config <config>] [--target <target>] [-- -i]
for multi-configuration generators. CONFIGURATION is ignored for
single-configuration generators.
If PROJECT_NAME is omitted, the resulting command line will build the where ``<cmake>`` is the location of the :manual:`cmake(1)` command-line
top level PROJECT in the current build tree. tool, and ``<config>`` and ``<target>`` are the values provided to the
``CONFIGURATION`` and ``TARGET`` options, if any. The trailing ``-- -i``
option is added for Makefile generators.
If TARGET is omitted, the resulting command line will build When invoked, this ``cmake --build`` command line will launch the
everything, effectively using build target 'all' or 'ALL_BUILD'. underlying build system tool.
:: .. code-block:: cmake
build_command(<cachevariable> <makecommand>) build_command(<cachevariable> <makecommand>)
This second signature is deprecated, but still available for backwards This second signature is deprecated, but still available for backwards
compatibility. Use the first signature instead. compatibility. Use the first signature instead.
Sets the given <cachevariable> to a string containing the command to It sets the given ``<cachevariable>`` to a command-line string as
build this project from the root of the build tree using the build above but without the ``--config`` or ``--target`` options.
tool given by <makecommand>. <makecommand> should be the full path to The ``<makecommand>`` is ignored but should be the full path to
msdev, devenv, nmake, make or one of the end user build tools. msdev, devenv, nmake, make or one of the end user build tools
for legacy invocations.
.. note::
In CMake versions prior to 3.0 this command returned a command
line that directly invokes the native build tool for the current
generator. Their implementation of the ``PROJECT_NAME`` option
had no useful effects, so CMake now warns on use of the option.

View File

@ -85,18 +85,7 @@ bool cmBuildCommand
} }
} }
const char* makeprogram // If null/empty CONFIGURATION argument, cmake --build uses 'Debug'
= this->Makefile->GetDefinition("CMAKE_MAKE_PROGRAM");
if(!makeprogram)
{
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
"build_command() requires CMAKE_MAKE_PROGRAM to be defined. "
"Call project() or enable_language() first.");
return true;
}
// If null/empty CONFIGURATION argument, GenerateBuildCommand uses 'Debug'
// in the currently implemented multi-configuration global generators... // in the currently implemented multi-configuration global generators...
// so we put this code here to end up with the same default configuration // so we put this code here to end up with the same default configuration
// as the original 2-arg build_command signature: // as the original 2-arg build_command signature:
@ -110,19 +99,15 @@ bool cmBuildCommand
configuration = "Release"; configuration = "Release";
} }
// If null/empty PROJECT_NAME argument, use the Makefile's project name: if(project_name && *project_name)
//
if(!project_name || !*project_name)
{ {
project_name = this->Makefile->GetProjectName(); this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
"Ignoring PROJECT_NAME option because it has no effect.");
} }
// If null/empty TARGET argument, GenerateBuildCommand omits any mention
// of a target name on the build command line...
//
std::string makecommand = this->Makefile->GetLocalGenerator() std::string makecommand = this->Makefile->GetLocalGenerator()
->GetGlobalGenerator()->GenerateBuildCommand ->GetGlobalGenerator()->GenerateCMakeBuildCommand(target, configuration,
(makeprogram, project_name, 0, 0, target, configuration, true, false); 0, true);
this->Makefile->AddDefinition(variable, makecommand.c_str()); this->Makefile->AddDefinition(variable, makecommand.c_str());
@ -142,7 +127,6 @@ bool cmBuildCommand
const char* define = args[0].c_str(); const char* define = args[0].c_str();
const char* cacheValue const char* cacheValue
= this->Makefile->GetDefinition(define); = this->Makefile->GetDefinition(define);
std::string makeprogram = args[1];
std::string configType = "Release"; std::string configType = "Release";
const char* cfg = getenv("CMAKE_CONFIG_TYPE"); const char* cfg = getenv("CMAKE_CONFIG_TYPE");
@ -152,9 +136,8 @@ bool cmBuildCommand
} }
std::string makecommand = this->Makefile->GetLocalGenerator() std::string makecommand = this->Makefile->GetLocalGenerator()
->GetGlobalGenerator()->GenerateBuildCommand ->GetGlobalGenerator()->GenerateCMakeBuildCommand(0, configType.c_str(),
(makeprogram.c_str(), this->Makefile->GetProjectName(), 0, 0, 0, true);
0, configType.c_str(), true, false);
if(cacheValue) if(cacheValue)
{ {

View File

@ -1,6 +1,6 @@
CMake Error at .*/Modules/CTest.cmake:[0-9]+ \(build_command\): CMake Error at .*/Modules/CTestTargets.cmake:20 \(message\):
build_command\(\) requires CMAKE_MAKE_PROGRAM to be defined. Call project\(\) Do not include\(CTest\) before calling project\(\).
or enable_language\(\) first.
Call Stack \(most recent call first\): Call Stack \(most recent call first\):
BeforeProject.cmake:[0-9]+ \(include\) .*/Modules/CTest.cmake:297 \(include\)
CMakeLists.txt:[0-9]+ \(include\) BeforeProject.cmake:1 \(include\)
CMakeLists.txt:5 \(include\)

View File

@ -1,5 +1,7 @@
CMake Error at BeforeProject.cmake:[0-9]+ \(build_command\): CMake Warning \(dev\) at BeforeProject.cmake:2 \(message\):
build_command\(\) requires CMAKE_MAKE_PROGRAM to be defined. Call project\(\) build_command\(\) returned:
or enable_language\(\) first.
.*cmake.* --build \..*
Call Stack \(most recent call first\): Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\) CMakeLists.txt:5 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.

View File

@ -1,2 +1,3 @@
build_command(MAKECOMMAND_DEFAULT_VALUE) build_command(MAKECOMMAND_DEFAULT_VALUE)
message(AUTHOR_WARNING "build_command() returned:\n ${MAKECOMMAND_DEFAULT_VALUE}")
project(${RunCMake_TEST} NONE) project(${RunCMake_TEST} NONE)