Commit a37a4a00 authored by Fred Baksik's avatar Fred Baksik
Browse files

GHS: Add toolset selection support

-- Use the specified toolset located within GHS_TOOLSET_ROOT
-- Update how the latest toolset is determined; scan the location GHS_TOOLSET_ROOT and sort it
   No longer use registry settings looking for installations
     The registry values are assigned in installation order for Green Hills tools not version order
-- Update to use gbuild.exe from the proper toolset
-- Clarify that CMAKE_MAKE_PROGRAM should not be set by user.
-- Detect some toolset changes when regenerating project files
   This could occur if GHS_TOOLSET_ROOT was changed by user after the initial project generation
   This could occur if CMAKE_MAKE_PROGRAM was changed at the command line
-- Use placeholder values for CMAKE_<LANG>_COMPILER
   The MULTI build system only uses gbuild to build a project
     gbuild uses the project file to determine which set of compilers to use based on target platform and architecture
     because compiler detection is skipped, placeholder values are used so that CMake does not complain
parent 5d40d2b4
......@@ -9,6 +9,15 @@ The ``-A <arch>`` can be supplied for setting the target architecture.
``<arch>`` usually is one of "arm", "ppc", "86", etcetera. If the target architecture
is not specified then the default architecture of "arm" will be used.
The ``-T <toolset>`` can be supplied for setting the toolset to be used.
All toolsets are expected to be located at ``GHS_TOOLSET_ROOT``.
If the toolset is not specified then the latest toolset will be used.
Default to ``C:/ghs``. Root path for ``toolset``.
Customizations are available through the following cache variables:
......@@ -18,6 +18,7 @@ Toolset specification is supported only on specific generators:
* :ref:`Visual Studio Generators` for VS 2010 and above
* The :generator:`Xcode` generator for Xcode 3.0 and above
* The :generator:`Green Hills MULTI` generator
See native build system documentation for allowed toolset names.
......@@ -55,9 +55,11 @@ to configure the project:
the CMake cache then CMake will use the specified value if
* The :generator:`Green Hills MULTI` generator sets this to ``gbuild``.
If a user or project explicitly adds ``CMAKE_MAKE_PROGRAM`` to
the CMake cache then CMake will use the specified value.
* The :generator:`Green Hills MULTI` generator sets this to the full
path to ``gbuild.exe`` based upon the toolset being used.
Once the generator has initialized a particular value for this
variable, changing the value has undefined behavior.
The ``CMAKE_MAKE_PROGRAM`` variable is set for use by project code.
The value is also used by the :manual:`cmake(1)` ``--build`` and
......@@ -14,13 +14,13 @@
#include "cmVersion.h"
const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
const char* cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild";
const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe";
const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "C:/ghs";
cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm)
: cmGlobalGenerator(cm)
, OSDirRelative(false)
this->GhsBuildCommandInitialized = false;
......@@ -41,6 +41,76 @@ void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
"Generates Green Hills MULTI files (experimental, work-in-progress).";
bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
cmMakefile* mf)
std::string tsp; /* toolset path */
std::string tsn = ts; /* toolset name */
GetToolset(mf, tsp, tsn);
/* no toolset was found */
if (tsn.empty()) {
return false;
} else if (ts.empty()) {
std::string message;
message =
"Green Hills MULTI: -T <toolset> not specified; defaulting to \"";
message += tsn;
message += "\"";
/* store the toolset for later use
* -- already done if -T<toolset> was specified
mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsn.c_str(),
"Name of generator toolset.",
/* set the build tool to use */
const char* prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM");
std::string gbuild(tsp + "/" + tsn + "/" + DEFAULT_BUILD_PROGRAM);
/* check if the toolset changed from last generate */
if (prevTool != NULL && (gbuild != prevTool)) {
std::string message = "generator toolset: ";
message += gbuild;
message += "\nDoes not match the toolset used previously: ";
message += prevTool;
message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.";
} else {
/* store the toolset that is being used for this build */
mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(),
"build program to use", cmStateEnums::INTERNAL,
mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsn.c_str());
// FIXME: compiler detection not implemented
// gbuild uses the primaryTarget setting in the top-level project
// file to determine which compiler to use. Because compiler
// detection is not implemented these variables must be
// set to skip past these tests. However cmake will verify that
// the executable pointed to by CMAKE_<LANG>_COMPILER exists.
// To pass this additional check gbuild is used as a place holder for the
// actual compiler.
mf->AddDefinition("CMAKE_C_COMPILER", gbuild.c_str());
mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER", gbuild.c_str());
mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS");
return true;
bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
cmMakefile* mf)
......@@ -65,127 +135,49 @@ void cmGlobalGhsMultiGenerator::EnableLanguage(
mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
const std::string ghsCompRoot(GetCompRoot());
mf->AddDefinition("GHS_COMP_ROOT", ghsCompRoot.c_str());
std::string ghsCompRootStart =
0 == ghsCompRootStart.size() ? "" : ghsCompRoot + "/";
std::string(ghsCompRootStart + "ccarm.exe").c_str());
mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE");
std::string(ghsCompRootStart + "cxarm.exe").c_str());
mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS");
if (!ghsCompRoot.empty()) {
static const char* compPreFix = "comp_";
std::string compFilename =
cmsys::SystemTools::FindLastString(ghsCompRoot.c_str(), compPreFix);
cmsys::SystemTools::ReplaceString(compFilename, compPreFix, "");
mf->AddDefinition("CMAKE_SYSTEM_VERSION", compFilename.c_str());
mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* mf)
bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/)
// The GHS generator knows how to lookup its build tool
// directly instead of needing a helper module to do it, so we
// do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
// The GHS generator only knows how to lookup its build tool
// during generation of the project files, but this
// can only be done after the toolset is specified.
return true;
std::string const& cmGlobalGhsMultiGenerator::GetGhsBuildCommand()
void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd,
std::string& ts)
if (!this->GhsBuildCommandInitialized) {
this->GhsBuildCommandInitialized = true;
this->GhsBuildCommand = this->FindGhsBuildCommand();
return this->GhsBuildCommand;
const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT");
std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand()
std::vector<std::string> userPaths;
std::string makeProgram =
cmSystemTools::FindProgram(DEFAULT_MAKE_PROGRAM, userPaths);
if (makeProgram.empty()) {
if (!ghsRoot) {
return makeProgram;
tsd = ghsRoot;
std::string cmGlobalGhsMultiGenerator::GetCompRoot()
std::string output;
const std::vector<std::string> potentialDirsHardPaths(
const std::vector<std::string> potentialDirsRegistry(GetCompRootRegistry());
std::vector<std::string> potentialDirsComplete;
// Use latest version
std::string outputDirName;
for (std::vector<std::string>::const_iterator potentialDirsCompleteIt =
potentialDirsCompleteIt != potentialDirsComplete.end();
++potentialDirsCompleteIt) {
const std::string dirName(
if ( > 0) {
output = *potentialDirsCompleteIt;
outputDirName = dirName;
if (ts.empty()) {
std::vector<std::string> output;
return output;
// Use latest? version
cmSystemTools::Glob(tsd, "comp_[^;]+", output);
std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootHardPaths()
std::vector<std::string> output;
cmSystemTools::Glob("C:/ghs", "comp_[^;]+", output);
for (std::vector<std::string>::iterator outputIt = output.begin();
outputIt != output.end(); ++outputIt) {
*outputIt = "C:/ghs/" + *outputIt;
if (output.empty()) {
cmSystemTools::Error("GHS toolset not found in ", tsd.c_str());
ts = "";
} else {
ts = output.back();
} else {
std::string tryPath = tsd + std::string("/") + ts;
if (!cmSystemTools::FileExists(tryPath)) {
cmSystemTools::Error("GHS toolset \"", ts.c_str(), "\" not found in ",
ts = "";
return output;
std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry()
std::vector<std::string> output(2);
return output;
void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
......@@ -293,8 +285,10 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
const char* gbuild =
this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand()));
this->SelectMakeProgram(makeProgram, (std::string)gbuild));
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
......@@ -49,6 +49,7 @@ public:
static bool SupportsPlatform() { return true; }
// Toolset / Platform Support
virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
......@@ -96,11 +97,7 @@ protected:
std::vector<std::string> const& makeOptions = std::vector<std::string>());
std::string const& GetGhsBuildCommand();
std::string FindGhsBuildCommand();
std::string GetCompRoot();
std::vector<std::string> GetCompRootHardPaths();
std::vector<std::string> GetCompRootRegistry();
void GetToolset(cmMakefile* mf, std::string& tsd, std::string& ts);
void OpenBuildFileStream();
void WriteMacros();
......@@ -127,9 +124,8 @@ private:
std::vector<std::string> LibDirs;
bool OSDirRelative;
bool GhsBuildCommandInitialized;
std::string GhsBuildCommand;
static const char* DEFAULT_MAKE_PROGRAM;
static const char* DEFAULT_BUILD_PROGRAM;
static const char* DEFAULT_TOOLSET_ROOT;
Supports Markdown
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