Commit 8ed6efbb authored by Brad King's avatar Brad King Committed by Kitware Robot

Merge topic 'default-generator-env'

d0f0ba0f Tests: Add environment generator tests
a48ce8f4 Help: Add documentation for default generator environment variables
083cf7e8 cmake: Allow default generator to be set by environment variables
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !3218
parents fc4cbbc2 d0f0ba0f
Pipeline #137560 passed with stage
in 0 seconds
CMAKE_GENERATOR
---------------
.. include:: ENV_VAR.txt
Specifies the CMake default generator to use when no generator is supplied
with ``-G``. If the provided value doesn't name a generator known by CMake,
the internal default is used. Either way the resulting generator selection
is stored in the :variable:`CMAKE_GENERATOR` variable.
Some generators may be additionally configured using the environment
variables:
* :envvar:`CMAKE_GENERATOR_PLATFORM`
* :envvar:`CMAKE_GENERATOR_TOOLSET`
* :envvar:`CMAKE_GENERATOR_INSTANCE`
CMAKE_GENERATOR_INSTANCE
------------------------
.. include:: ENV_VAR.txt
Default value for :variable:`CMAKE_GENERATOR_INSTANCE` if no Cache entry is
present. This value is only applied if :envvar:`CMAKE_GENERATOR` is set.
CMAKE_GENERATOR_PLATFORM
------------------------
.. include:: ENV_VAR.txt
Default value for :variable:`CMAKE_GENERATOR_PLATFORM` if no Cache entry
is present and no value is specified by :manual:`cmake(1)` ``-A`` option.
This value is only applied if :envvar:`CMAKE_GENERATOR` is set.
CMAKE_GENERATOR_TOOLSET
-----------------------
.. include:: ENV_VAR.txt
Default value for :variable:`CMAKE_GENERATOR_TOOLSET` if no Cache entry
is present and no value is specified by :manual:`cmake(1)` ``-T`` option.
This value is only applied if :envvar:`CMAKE_GENERATOR` is set.
......@@ -56,6 +56,9 @@
build system. Possible generator names are specified in the
:manual:`cmake-generators(7)` manual.
If not specified, CMake checks the :envvar:`CMAKE_GENERATOR` environment
variable and otherwise falls back to a builtin default selection.
``-T <toolset-spec>``
Toolset specification for the generator, if supported.
......
......@@ -23,6 +23,10 @@ Environment Variables that Control the Build
/envvar/CMAKE_BUILD_PARALLEL_LEVEL
/envvar/CMAKE_CONFIG_TYPE
/envvar/CMAKE_GENERATOR
/envvar/CMAKE_GENERATOR_INSTANCE
/envvar/CMAKE_GENERATOR_PLATFORM
/envvar/CMAKE_GENERATOR_TOOLSET
/envvar/CMAKE_MSVCIDE_RUN_PATH
/envvar/CMAKE_NO_VERBOSE
/envvar/CMAKE_OSX_ARCHITECTURES
......
default-generator-env
---------------------
* The :envvar:`CMAKE_GENERATOR` environment variable was added
to specify a default generator to use when :manual:`cmake(1)` is
run without a ``-G`` option. Additionally, environment variables
:envvar:`CMAKE_GENERATOR_PLATFORM`, :envvar:`CMAKE_GENERATOR_TOOLSET`,
and :envvar:`CMAKE_GENERATOR_INSTANCE` were created to configure
the generator.
......@@ -5,3 +5,8 @@ The generator used to build the project. See :manual:`cmake-generators(7)`.
The name of the generator that is being used to generate the build
files. (e.g. ``Unix Makefiles``, ``Ninja``, etc.)
The value of this variable should never be modified by project code.
A generator may be selected via the :manual:`cmake(1)` ``-G`` option,
interactively in :manual:`cmake-gui(1)`, or via the :envvar:`CMAKE_GENERATOR`
environment variable.
......@@ -5,9 +5,10 @@ Generator-specific instance specification provided by user.
Some CMake generators support selection of an instance of the native build
system when multiple instances are available. If the user specifies an
instance (e.g. by setting this cache entry), or after a default instance is
chosen when a build tree is first configured, the value will be available in
this variable.
instance (e.g. by setting this cache entry or via the
:envvar:`CMAKE_GENERATOR_INSTANCE` environment variable), or after a default
instance is chosen when a build tree is first configured, the value will be
available in this variable.
The value of this variable should never be modified by project code.
A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE`
......
......@@ -6,7 +6,8 @@ Generator-specific target platform specification provided by user.
Some CMake generators support a target platform name to be given
to the native build system to choose a compiler toolchain.
If the user specifies a platform name (e.g. via the :manual:`cmake(1)` ``-A``
option) the value will be available in this variable.
option or via the :envvar:`CMAKE_GENERATOR_PLATFORM` environment variable)
the value will be available in this variable.
The value of this variable should never be modified by project code.
A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE`
......
......@@ -5,7 +5,8 @@ Native build system toolset specification provided by user.
Some CMake generators support a toolset specification to tell the
native build system how to choose a compiler. If the user specifies
a toolset (e.g. via the :manual:`cmake(1)` ``-T`` option) the value
a toolset (e.g. via the :manual:`cmake(1)` ``-T`` option or via
the :envvar:`CMAKE_GENERATOR_TOOLSET` environment variable) the value
will be available in this variable.
The value of this variable should never be modified by project code.
......
......@@ -159,6 +159,9 @@ cmake::cmake(Role role, cmState::Mode mode)
#endif
this->GlobalGenerator = nullptr;
this->GeneratorInstanceSet = false;
this->GeneratorPlatformSet = false;
this->GeneratorToolsetSet = false;
this->CurrentWorkingMode = NORMAL_MODE;
#ifdef CMAKE_BUILD_WITH_CMAKE
......@@ -174,6 +177,10 @@ cmake::cmake(Role role, cmState::Mode mode)
this->AddProjectCommands();
}
if (mode == cmState::Project) {
this->LoadEnvironmentPresets();
}
// Make sure we can capture the build tool output.
cmSystemTools::EnableVSConsoleOutput();
......@@ -612,6 +619,35 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
return packageFound;
}
void cmake::LoadEnvironmentPresets()
{
std::string envGenVar;
bool hasEnvironmentGenerator = false;
if (cmSystemTools::GetEnv("CMAKE_GENERATOR", envGenVar)) {
hasEnvironmentGenerator = true;
this->EnvironmentGenerator = envGenVar;
}
auto readGeneratorVar = [&](std::string name, std::string& key) {
std::string varValue;
if (cmSystemTools::GetEnv(name, varValue)) {
if (hasEnvironmentGenerator) {
key = varValue;
} else if (!this->GetIsInTryCompile()) {
std::string message = "Warning: Environment variable ";
message += name;
message += " will be ignored, because CMAKE_GENERATOR ";
message += "is not set.";
cmSystemTools::Message(message, "Warning");
}
}
};
readGeneratorVar("CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance);
readGeneratorVar("CMAKE_GENERATOR_PLATFORM", this->GeneratorPlatform);
readGeneratorVar("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset);
}
// Parse the args
void cmake::SetArgs(const std::vector<std::string>& args)
{
......@@ -767,7 +803,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
cmSystemTools::Error("Multiple -A options not allowed");
return;
}
this->GeneratorPlatform = value;
this->SetGeneratorPlatform(value);
havePlatform = true;
} else if (arg.find("-T", 0) == 0) {
std::string value = arg.substr(2);
......@@ -783,7 +819,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
cmSystemTools::Error("Multiple -T options not allowed");
return;
}
this->GeneratorToolset = value;
this->SetGeneratorToolset(value);
haveToolset = true;
} else if (arg.find("-G", 0) == 0) {
std::string value = arg.substr(2);
......@@ -814,6 +850,16 @@ void cmake::SetArgs(const std::vector<std::string>& args)
else {
this->SetDirectoriesFromFile(arg);
}
// Empty instance, platform and toolset if only a generator is specified
if (this->GlobalGenerator) {
this->GeneratorInstance = "";
if (!this->GeneratorPlatformSet) {
this->GeneratorPlatform = "";
}
if (!this->GeneratorToolsetSet) {
this->GeneratorToolset = "";
}
}
}
const bool haveSourceDir = !this->GetHomeDirectory().empty();
......@@ -1446,8 +1492,7 @@ int cmake::ActualConfigure()
if (const std::string* instance =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
if (!this->GeneratorInstance.empty() &&
this->GeneratorInstance != *instance) {
if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) {
std::string message = "Error: generator instance: ";
message += this->GeneratorInstance;
message += "\nDoes not match the instance used previously: ";
......@@ -1465,7 +1510,7 @@ int cmake::ActualConfigure()
if (const std::string* platformName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
if (!this->GeneratorPlatform.empty() &&
if (this->GeneratorPlatformSet &&
this->GeneratorPlatform != *platformName) {
std::string message = "Error: generator platform: ";
message += this->GeneratorPlatform;
......@@ -1484,7 +1529,7 @@ int cmake::ActualConfigure()
if (const std::string* tsName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
if (!this->GeneratorToolset.empty() && this->GeneratorToolset != *tsName) {
if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) {
std::string message = "Error: generator toolset: ";
message += this->GeneratorToolset;
message += "\nDoes not match the toolset used previously: ";
......@@ -1562,6 +1607,16 @@ int cmake::ActualConfigure()
std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator()
{
if (!this->EnvironmentGenerator.empty()) {
cmGlobalGenerator* gen =
this->CreateGlobalGenerator(this->EnvironmentGenerator);
if (!gen) {
cmSystemTools::Error("CMAKE_GENERATOR was set but the specified "
"generator doesn't exist. Using CMake default.");
} else {
return std::unique_ptr<cmGlobalGenerator>(gen);
}
}
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
std::string found;
// Try to find the newest VS installed on the computer and
......
......@@ -214,18 +214,21 @@ public:
void SetGeneratorInstance(std::string const& instance)
{
this->GeneratorInstance = instance;
this->GeneratorInstanceSet = true;
}
//! Set the name of the selected generator-specific platform.
void SetGeneratorPlatform(std::string const& ts)
{
this->GeneratorPlatform = ts;
this->GeneratorPlatformSet = true;
}
//! Set the name of the selected generator-specific toolset.
void SetGeneratorToolset(std::string const& ts)
{
this->GeneratorToolset = ts;
this->GeneratorToolsetSet = true;
}
const std::vector<std::string>& GetSourceExtensions() const
......@@ -276,6 +279,9 @@ public:
*/
int GetSystemInformation(std::vector<std::string>&);
//! Parse environment variables
void LoadEnvironmentPresets();
//! Parse command line arguments
void SetArgs(const std::vector<std::string>& args);
......@@ -479,6 +485,9 @@ protected:
std::string GeneratorInstance;
std::string GeneratorPlatform;
std::string GeneratorToolset;
bool GeneratorInstanceSet;
bool GeneratorPlatformSet;
bool GeneratorToolsetSet;
//! read in a cmake list file to initialize the cache
void ReadListFile(const std::vector<std::string>& args,
......@@ -521,6 +530,7 @@ private:
std::string CheckStampFile;
std::string CheckStampList;
std::string VSSolutionFile;
std::string EnvironmentGenerator;
std::vector<std::string> SourceFileExtensions;
std::unordered_set<std::string> SourceFileExtensionsSet;
std::vector<std::string> HeaderFileExtensions;
......
......@@ -23,4 +23,10 @@ if(NOT CTEST_CONFIGURATION_TYPE)
message("Guessing configuration ${CTEST_CONFIGURATION_TYPE}")
endif()
# Isolate tests from user configuration in the environment.
unset(ENV{CMAKE_GENERATOR})
unset(ENV{CMAKE_GENERATOR_INSTANCE})
unset(ENV{CMAKE_GENERATOR_PLATFORM})
unset(ENV{CMAKE_GENERATOR_TOOLSET})
@TEST_HOME_ENV_CODE@
cmake_minimum_required(VERSION 3.14)
project(EnvGenerator C)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
message(STATUS "CMAKE_VS_PLATFORM_NAME='${CMAKE_VS_PLATFORM_NAME}'")
endif()
add_custom_command(
OUTPUT output.txt
COMMAND ${CMAKE_COMMAND} -E echo CustomCommand > output.txt
)
add_custom_target(CustomTarget ALL DEPENDS output.txt)
^CMake Error at CMakeLists.+
No CMAKE_C_COMPILER could be found.
^CMake Error at CMakeLists.+
.+Platform='fromcli'.+
^CMake Error at CMakeLists.+
.+(Platform Toolset = 'fromcli'|Specified platform toolset \(fromcli\) is not installed or invalid).+
^CMake Error: No generator specified for -G
CMake Error: CMAKE_GENERATOR was set but the specified generator doesn't exist. Using CMake default.
Generators.*
\* (Unix Makefiles|Visual Studio).*
^CMake Error at CMakeLists.+
could not find specified instance of Visual Studio.+
^CMake Error: No generator specified for -G
Generators.*
\* Ninja.*
^CMake Error at CMakeLists.+
No CMAKE_C_COMPILER could be found.
^CMake Error at CMakeLists.+
.+Platform='invalid'.+
^CMake Error at CMakeLists.+
.+(Platform Toolset = 'invalid'|Specified platform toolset \(invalid\) is not installed or invalid).+
^CMake Error: No generator specified for -G
Generators.*
\* (Unix Makefiles|Visual Studio).*
^Warning: Environment variable CMAKE_GENERATOR_INSTANCE will be ignored, because CMAKE_GENERATOR is not set.
Warning: Environment variable CMAKE_GENERATOR_PLATFORM will be ignored, because CMAKE_GENERATOR is not set.
Warning: Environment variable CMAKE_GENERATOR_TOOLSET will be ignored, because CMAKE_GENERATOR is not set.
CMake Error: No generator specified for -G
Generators.*
\* (Unix Makefiles|Visual Studio).*
......@@ -172,6 +172,74 @@ function(run_BuildDir)
endfunction()
run_BuildDir()
function(run_EnvironmentGenerator)
set(source_dir ${RunCMake_SOURCE_DIR}/EnvGenerator)
set(ENV{CMAKE_GENERATOR_INSTANCE} "instance")
set(ENV{CMAKE_GENERATOR_PLATFORM} "platform")
set(ENV{CMAKE_GENERATOR_TOOLSET} "toolset")
run_cmake_command(Envgen-warnings ${CMAKE_COMMAND} -G)
unset(ENV{CMAKE_GENERATOR_INSTANCE})
unset(ENV{CMAKE_GENERATOR_PLATFORM})
unset(ENV{CMAKE_GENERATOR_TOOLSET})
# Test CMAKE_GENERATOR without actual configuring
run_cmake_command(Envgen-unset ${CMAKE_COMMAND} -G)
set(ENV{CMAKE_GENERATOR} "Ninja")
run_cmake_command(Envgen-ninja ${CMAKE_COMMAND} -G)
set(ENV{CMAKE_GENERATOR} "NoSuchGenerator")
run_cmake_command(Envgen-bad ${CMAKE_COMMAND} -G)
unset(ENV{CMAKE_GENERATOR})
if(RunCMake_GENERATOR MATCHES "Visual Studio.*")
set(ENV{CMAKE_GENERATOR} "${RunCMake_GENERATOR}")
run_cmake_command(Envgen ${CMAKE_COMMAND} ${source_dir})
# Toolset is available since VS 2010.
if(RunCMake_GENERATOR MATCHES "Visual Studio [1-9][0-9]")
set(ENV{CMAKE_GENERATOR_TOOLSET} "invalid")
# Envvar shouldn't affect existing build tree
run_cmake_command(Envgen-toolset-existing ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build Envgen-build)
run_cmake_command(Envgen-toolset-invalid ${CMAKE_COMMAND} ${source_dir})
# Command line -G implies -T""
run_cmake_command(Envgen-G-implicit-toolset ${CMAKE_COMMAND} -G "${RunCMake_GENERATOR}" ${source_dir})
run_cmake_command(Envgen-T-toolset ${CMAKE_COMMAND} -T "fromcli" ${source_dir})
unset(ENV{CMAKE_GENERATOR_TOOLSET})
endif()
# Platform can be set only if not in generator name.
if(RunCMake_GENERATOR MATCHES "^Visual Studio [0-9]+ [0-9]+$")
set(ENV{CMAKE_GENERATOR_PLATFORM} "invalid")
# Envvar shouldn't affect existing build tree
run_cmake_command(Envgen-platform-existing ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build Envgen-build)
if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 ")
set(RunCMake-stderr-file "Envgen-platform-invalid-stderr-vs9.txt")
endif()
run_cmake_command(Envgen-platform-invalid ${CMAKE_COMMAND} ${source_dir})
unset(RunCMake-stderr-file)
# Command line -G implies -A""
run_cmake_command(Envgen-G-implicit-platform ${CMAKE_COMMAND} -G "${RunCMake_GENERATOR}" ${source_dir})
if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 ")
set(RunCMake-stderr-file "Envgen-A-platform-stderr-vs9.txt")
endif()
run_cmake_command(Envgen-A-platform ${CMAKE_COMMAND} -A "fromcli" ${source_dir})
unset(RunCMake-stderr-file)
unset(ENV{CMAKE_GENERATOR_PLATFORM})
endif()
# Instance is available since VS 2017.
if(RunCMake_GENERATOR MATCHES "Visual Studio (15|16).*")
set(ENV{CMAKE_GENERATOR_INSTANCE} "invalid")
# Envvar shouldn't affect existing build tree
run_cmake_command(Envgen-instance-existing ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build Envgen-build)
run_cmake_command(Envgen-instance-invalid ${CMAKE_COMMAND} ${source_dir})
unset(ENV{CMAKE_GENERATOR_INSTANCE})
endif()
unset(ENV{CMAKE_GENERATOR})
endif()
endfunction()
run_EnvironmentGenerator()
if(RunCMake_GENERATOR STREQUAL "Ninja")
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Build-build)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment