summaryrefslogtreecommitdiffstats
path: root/Source/cmGhsMultiTargetGenerator.cxx
diff options
context:
space:
mode:
authorGeoff Viola <geoffrey.viola@asirobots.com>2015-03-24 05:12:55 (GMT)
committerBrad King <brad.king@kitware.com>2015-04-20 17:55:40 (GMT)
commit48004d9dbeb2af20d3a8df66670323d924a3f4c6 (patch)
treee3135a857d1c51d34f424fe09f561a249bf9a35d /Source/cmGhsMultiTargetGenerator.cxx
parent051d8be17f1b36d52041bfe61856b926e36dfb8c (diff)
downloadCMake-48004d9dbeb2af20d3a8df66670323d924a3f4c6.zip
CMake-48004d9dbeb2af20d3a8df66670323d924a3f4c6.tar.gz
CMake-48004d9dbeb2af20d3a8df66670323d924a3f4c6.tar.bz2
Add a 'Green Hills MULTI' generator on Windows
Green Hills MULTI is an IDE for embedded real-time systems. The IDE's product page can be found here: http://www.ghs.com/products/MULTI_IDE.html It supports cross compiling on ARM, Intel x86, and other architectures with various operating systems. The IDE exists on Linux and Windows host systems, but CMake will currently only generate the project files on Windows host systems.
Diffstat (limited to 'Source/cmGhsMultiTargetGenerator.cxx')
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx600
1 files changed, 600 insertions, 0 deletions
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
new file mode 100644
index 0000000..01e2011
--- /dev/null
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -0,0 +1,600 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmGhsMultiTargetGenerator.h"
+#include "cmGlobalGhsMultiGenerator.h"
+#include "cmLocalGhsMultiGenerator.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSourceFile.h"
+#include <assert.h>
+#include <cmAlgorithms.h>
+
+std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic");
+
+cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmTarget *target)
+ : Target(target)
+ , LocalGenerator(static_cast<cmLocalGhsMultiGenerator *>(
+ target->GetMakefile()->GetLocalGenerator()))
+ , Makefile(target->GetMakefile())
+ , TargetGroup(DetermineIfTargetGroup(target))
+ , DynamicDownload(false)
+{
+ this->RelBuildFilePath = this->GetRelBuildFilePath(target);
+
+ this->RelOutputFileName =
+ this->RelBuildFilePath + this->Target->GetName() + ".a";
+
+ this->RelBuildFileName = this->RelBuildFilePath;
+ this->RelBuildFileName += this->GetBuildFileName(target);
+
+ std::string absPathToRoot = this->GetAbsPathToRoot(target);
+ absPathToRoot = this->AddSlashIfNeededToPath(absPathToRoot);
+ this->AbsBuildFilePath = absPathToRoot + this->RelBuildFilePath;
+ this->AbsBuildFileName = absPathToRoot + this->RelBuildFileName;
+ this->AbsOutputFileName = absPathToRoot + this->RelOutputFileName;
+}
+
+cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator()
+{
+ cmDeleteAll(this->FolderBuildStreams);
+}
+
+std::string
+cmGhsMultiTargetGenerator::GetRelBuildFilePath(const cmTarget *target)
+{
+ std::string output;
+ char const *folderProp = target->GetProperty("FOLDER");
+ output = NULL == folderProp ? "" : folderProp;
+ cmSystemTools::ConvertToUnixSlashes(output);
+ if (!output.empty())
+ {
+ output += "/";
+ }
+ output += target->GetName() + "/";
+ return output;
+}
+
+std::string
+cmGhsMultiTargetGenerator::GetAbsPathToRoot(const cmTarget *target)
+{
+ return target->GetMakefile()->GetHomeOutputDirectory();
+}
+
+std::string
+cmGhsMultiTargetGenerator::GetAbsBuildFilePath(const cmTarget *target)
+{
+ std::string output;
+ output = cmGhsMultiTargetGenerator::GetAbsPathToRoot(target);
+ output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
+ output += cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
+ return output;
+}
+
+std::string
+cmGhsMultiTargetGenerator::GetRelBuildFileName(const cmTarget *target)
+{
+ std::string output;
+ output = cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
+ output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
+ output += cmGhsMultiTargetGenerator::GetBuildFileName(target);
+ return output;
+}
+
+std::string cmGhsMultiTargetGenerator::GetBuildFileName(const cmTarget *target)
+{
+ std::string output;
+ output = target->GetName();
+ output += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
+ return output;
+}
+
+std::string
+cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(std::string const &input)
+{
+ std::string output(input);
+ if (!cmHasLiteralSuffix(output, "/"))
+ {
+ output += "/";
+ }
+ return output;
+}
+
+void cmGhsMultiTargetGenerator::Generate()
+{
+ const std::vector<cmSourceFile *> objectSources = this->GetSources();
+ if (!objectSources.empty() && this->IncludeThisTarget())
+ {
+ if (!cmSystemTools::FileExists(this->AbsBuildFilePath.c_str()))
+ {
+ cmSystemTools::MakeDirectory(this->AbsBuildFilePath.c_str());
+ }
+ cmGlobalGhsMultiGenerator::Open(std::string(""), this->AbsBuildFileName,
+ &this->FolderBuildStreams);
+ cmGlobalGhsMultiGenerator::OpenBuildFileStream(
+ this->GetFolderBuildStreams());
+ std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ if (0 == config.length())
+ {
+ config = "RELEASE";
+ }
+ const std::string language(this->Target->GetLinkerLanguage(config));
+ config = cmSystemTools::UpperCase(config);
+ this->DynamicDownload = this->DetermineIfDynamicDownload(config, language);
+ if (this->DynamicDownload)
+ {
+ *this->GetFolderBuildStreams() << "#component integrity_dynamic_download"
+ << std::endl;
+ }
+ GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), this->GetFolderBuildStreams());
+ cmGlobalGhsMultiGenerator::WriteDisclaimer(this->GetFolderBuildStreams());
+
+ bool const notKernel = this->IsNotKernel(config, language);
+ this->WriteTypeSpecifics(config, notKernel);
+ this->SetCompilerFlags(config, language, notKernel);
+ this->WriteCompilerFlags(config, language);
+ this->WriteCompilerDefinitions(config, language);
+ this->WriteIncludes(config, language);
+ if (this->Target->GetType() == cmTarget::EXECUTABLE)
+ {
+ this->WriteTargetLinkLibraries();
+ }
+ this->WriteCustomCommands();
+ if (this->DynamicDownload)
+ {
+ *this->GetFolderBuildStreams() << " " << this->DDOption << std::endl;
+ }
+
+ this->WriteSources(objectSources);
+ }
+}
+
+bool cmGhsMultiTargetGenerator::IncludeThisTarget()
+{
+ bool output = true;
+ char const *excludeFromAll = this->Target->GetProperty("EXCLUDE_FROM_ALL");
+ if (NULL != excludeFromAll && '1' == excludeFromAll[0] &&
+ '\0' == excludeFromAll[1])
+ {
+ output = false;
+ }
+ return output;
+}
+
+std::vector<cmSourceFile *> cmGhsMultiTargetGenerator::GetSources() const
+{
+ std::vector<cmSourceFile *> output;
+ std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ this->Target->GetSourceFiles(output, config);
+ return output;
+}
+
+GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const
+{
+ return cmGhsMultiTargetGenerator::GetGpjTag(this->Target);
+}
+
+GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag(const cmTarget *target)
+{
+ GhsMultiGpj::Types output;
+ if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup(target))
+ {
+ output = GhsMultiGpj::INTERGRITY_APPLICATION;
+ }
+ else if (target->GetType() == cmTarget::STATIC_LIBRARY)
+ {
+ output = GhsMultiGpj::LIBRARY;
+ }
+ else
+ {
+ output = GhsMultiGpj::PROGRAM;
+ }
+ return output;
+}
+
+cmGlobalGhsMultiGenerator*
+cmGhsMultiTargetGenerator::GetGlobalGenerator() const
+{
+ return static_cast<cmGlobalGhsMultiGenerator *>(
+ this->LocalGenerator->GetGlobalGenerator());
+}
+
+void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string &config,
+ bool const notKernel)
+{
+ std::string outputDir(this->GetOutputDirectory(config));
+ std::string outputFilename(this->GetOutputFilename(config));
+
+ if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
+ {
+ *this->GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o \""
+ << outputDir << outputFilename << ".a\""
+ << std::endl;
+ }
+ else if (this->Target->GetType() == cmTarget::EXECUTABLE)
+ {
+ if (notKernel && !this->IsTargetGroup())
+ {
+ *this->GetFolderBuildStreams() << " -relprog" << std::endl;
+ }
+ if (this->IsTargetGroup())
+ {
+ *this->GetFolderBuildStreams() << " -non_shared" << std::endl;
+ *this->GetFolderBuildStreams() << " -o \"" << outputDir
+ << outputFilename << ".elf\""
+ << std::endl;
+ }
+ else
+ {
+ *this->GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o \""
+ << outputDir << outputFilename << ".as\""
+ << std::endl;
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const &config,
+ const std::string &language,
+ bool const notKernel)
+{
+ std::map<std::string, std::string>::iterator i =
+ this->FlagsByLanguage.find(language);
+ if (i == this->FlagsByLanguage.end())
+ {
+ std::string flags;
+ const char *lang = language.c_str();
+
+ if (notKernel)
+ {
+ this->LocalGenerator->AddLanguageFlags(flags, lang, config);
+ }
+ else
+ {
+ this->LocalGenerator->AddLanguageFlags(
+ flags, lang + std::string("_GHS_KERNEL"), config);
+ }
+ this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang, config);
+ this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, lang);
+
+ // Append old-style preprocessor definition flags.
+ if (std::string(" ") != std::string(this->Makefile->GetDefineFlags()))
+ {
+ this->LocalGenerator->AppendFlags(flags,
+ this->Makefile->GetDefineFlags());
+ }
+
+ // Add target-specific flags.
+ this->LocalGenerator->AddCompileOptions(flags, this->Target, lang, config);
+
+ std::map<std::string, std::string>::value_type entry(language, flags);
+ i = this->FlagsByLanguage.insert(entry).first;
+ }
+}
+
+std::string cmGhsMultiTargetGenerator::GetDefines(const std::string &language,
+ std::string const &config)
+{
+ std::map<std::string, std::string>::iterator i =
+ this->DefinesByLanguage.find(language);
+ if (i == this->DefinesByLanguage.end())
+ {
+ std::set<std::string> defines;
+ const char *lang = language.c_str();
+ // Add the export symbol definition for shared library objects.
+ if (const char *exportMacro = this->Target->GetExportMacro())
+ {
+ this->LocalGenerator->AppendDefines(defines, exportMacro);
+ }
+
+ // Add preprocessor definitions for this target and configuration.
+ this->LocalGenerator->AddCompileDefinitions(defines, this->Target, config,
+ language);
+
+ std::string definesString;
+ this->LocalGenerator->JoinDefines(defines, definesString, lang);
+
+ std::map<std::string, std::string>::value_type entry(language,
+ definesString);
+ i = this->DefinesByLanguage.insert(entry).first;
+ }
+ return i->second;
+}
+
+void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::string const &,
+ const std::string &language)
+{
+ std::map<std::string, std::string>::iterator flagsByLangI =
+ this->FlagsByLanguage.find(language);
+ if (flagsByLangI != this->FlagsByLanguage.end())
+ {
+ if (!flagsByLangI->second.empty())
+ {
+ *this->GetFolderBuildStreams() << " " << flagsByLangI->second
+ << std::endl;
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
+ const std::string &config, const std::string &language)
+{
+ std::vector<std::string> compileDefinitions;
+ this->Target->GetCompileDefinitions(compileDefinitions, config, language);
+ for (std::vector<std::string>::const_iterator cdI =
+ compileDefinitions.begin();
+ cdI != compileDefinitions.end(); ++cdI)
+ {
+ *this->GetFolderBuildStreams() << " -D" << (*cdI) << std::endl;
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteIncludes(const std::string &config,
+ const std::string &language)
+{
+ std::vector<std::string> includes =
+ this->Target->GetIncludeDirectories(config, language);
+ for (std::vector<std::string>::const_iterator includes_i = includes.begin();
+ includes_i != includes.end(); ++includes_i)
+ {
+ *this->GetFolderBuildStreams() << " -I\"" << *includes_i << "\""
+ << std::endl;
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries()
+{
+ // library directories
+ cmTargetDependSet tds =
+ this->GetGlobalGenerator()->GetTargetDirectDepends(*this->Target);
+ for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end();
+ ++tdsI)
+ {
+ const cmTarget *tg(*tdsI);
+ *this->GetFolderBuildStreams() << " -L\"" << GetAbsBuildFilePath(tg)
+ << "\"" << std::endl;
+ }
+ // library targets
+ cmTarget::LinkLibraryVectorType llv =
+ this->Target->GetOriginalLinkLibraries();
+ for (cmTarget::LinkLibraryVectorType::const_iterator llvI = llv.begin();
+ llvI != llv.end(); ++llvI)
+ {
+ std::string libName = llvI->first;
+ // if it is a user defined target get the full path to the lib
+ cmTarget *tg(GetGlobalGenerator()->FindTarget(libName));
+ if (NULL != tg)
+ {
+ cmGhsMultiTargetGenerator gmtg(tg);
+ libName = tg->GetName() + ".a";
+ }
+ *this->GetFolderBuildStreams() << " -l\"" << libName << "\""
+ << std::endl;
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteCustomCommands()
+{
+ WriteCustomCommandsHelper(this->Target->GetPreBuildCommands(),
+ cmTarget::PRE_BUILD);
+ WriteCustomCommandsHelper(this->Target->GetPostBuildCommands(),
+ cmTarget::POST_BUILD);
+}
+
+void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
+ std::vector<cmCustomCommand> const &commandsSet,
+ cmTarget::CustomCommandType const commandType)
+{
+ for (std::vector<cmCustomCommand>::const_iterator commandsSetI =
+ commandsSet.begin();
+ commandsSetI != commandsSet.end(); ++commandsSetI)
+ {
+ cmCustomCommandLines const &commands = commandsSetI->GetCommandLines();
+ for (cmCustomCommandLines::const_iterator commandI = commands.begin();
+ commandI != commands.end(); ++commandI)
+ {
+ switch (commandType)
+ {
+ case cmTarget::PRE_BUILD:
+ *this->GetFolderBuildStreams() << " :preexecShellSafe=";
+ break;
+ case cmTarget::POST_BUILD:
+ *this->GetFolderBuildStreams() << " :postexecShellSafe=";
+ break;
+ default:
+ assert("Only pre and post are supported");
+ }
+ cmCustomCommandLine const &command = *commandI;
+ for (cmCustomCommandLine::const_iterator commandLineI = command.begin();
+ commandLineI != command.end(); ++commandLineI)
+ {
+ std::string subCommandE =
+ this->LocalGenerator->EscapeForShell(*commandLineI, true);
+ if (!command.empty())
+ {
+ *this->GetFolderBuildStreams()
+ << (command.begin() == commandLineI ? "'" : " ");
+ //Need to double escape backslashes
+ cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
+ }
+ *this->GetFolderBuildStreams() << subCommandE;
+ }
+ if (!command.empty())
+ {
+ *this->GetFolderBuildStreams() << "'" << std::endl;
+ }
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteSources(
+ std::vector<cmSourceFile *> const &objectSources)
+{
+ for (std::vector<cmSourceFile *>::const_iterator si = objectSources.begin();
+ si != objectSources.end(); ++si)
+ {
+ std::vector<cmSourceGroup> sourceGroups(this->Makefile->GetSourceGroups());
+ char const *sourceFullPath = (*si)->GetFullPath().c_str();
+ cmSourceGroup *sourceGroup =
+ this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups);
+ std::string sgPath(sourceGroup->GetFullName());
+ cmSystemTools::ConvertToUnixSlashes(sgPath);
+ cmGlobalGhsMultiGenerator::AddFilesUpToPath(
+ this->GetFolderBuildStreams(), &this->FolderBuildStreams,
+ this->Makefile->GetHomeOutputDirectory(), sgPath,
+ GhsMultiGpj::SUBPROJECT, this->RelBuildFilePath);
+
+ if ((*si)->GetExtension() == ".int")
+ {
+ *this->FolderBuildStreams[sgPath] << "\"" << (*si)->GetFullPath() << "\""
+ << std::endl;
+ }
+ else
+ {
+ *this->FolderBuildStreams[sgPath] << (*si)->GetFullPath() << std::endl;
+ }
+
+ if ("ld" != (*si)->GetExtension() && "int" != (*si)->GetExtension() &&
+ "bsp" != (*si)->GetExtension())
+ {
+ this->WriteObjectLangOverride(this->FolderBuildStreams[sgPath], (*si));
+
+ this->WriteObjectDir(this->FolderBuildStreams[sgPath],
+ this->AbsBuildFilePath + sgPath);
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
+ cmGeneratedFileStream *fileStream, cmSourceFile *sourceFile)
+{
+ const char *rawLangProp = sourceFile->GetProperty("LANGUAGE");
+ if (NULL != rawLangProp)
+ {
+ std::string sourceLangProp(rawLangProp);
+ std::string extension(sourceFile->GetExtension());
+ if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension))
+ {
+ *fileStream << " -dotciscxx" << std::endl;
+ }
+ }
+}
+
+void cmGhsMultiTargetGenerator::WriteObjectDir(
+ cmGeneratedFileStream *fileStream, std::string const &dir)
+{
+ std::string workingDir(dir);
+ cmSystemTools::ConvertToUnixSlashes(workingDir);
+ if (!workingDir.empty())
+ {
+ workingDir += "/";
+ }
+ workingDir += "Objs";
+ *fileStream << " -object_dir=\"" << workingDir << "\"" << std::endl;
+}
+
+std::string
+cmGhsMultiTargetGenerator::GetOutputDirectory(const std::string &config) const
+{
+ std::string outputDir(AbsBuildFilePath);
+
+ const char *runtimeOutputProp =
+ this->Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY");
+ if (NULL != runtimeOutputProp)
+ {
+ outputDir = runtimeOutputProp;
+ }
+
+ std::string configCapped(cmSystemTools::UpperCase(config));
+ const char *runtimeOutputSProp =
+ this->Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY_" + configCapped);
+ if (NULL != runtimeOutputSProp)
+ {
+ outputDir = runtimeOutputSProp;
+ }
+ cmSystemTools::ConvertToUnixSlashes(outputDir);
+
+ if (!outputDir.empty())
+ {
+ outputDir += "/";
+ }
+
+ return outputDir;
+}
+
+std::string
+cmGhsMultiTargetGenerator::GetOutputFilename(const std::string &config) const
+{
+ std::string outputFilename(this->Target->GetName());
+
+ const char *outputNameProp = this->Target->GetProperty("OUTPUT_NAME");
+ if (NULL != outputNameProp)
+ {
+ outputFilename = outputNameProp;
+ }
+
+ std::string configCapped(cmSystemTools::UpperCase(config));
+ const char *outputNameSProp =
+ this->Target->GetProperty(configCapped + "_OUTPUT_NAME");
+ if (NULL != outputNameSProp)
+ {
+ outputFilename = outputNameSProp;
+ }
+
+ return outputFilename;
+}
+
+bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const &config,
+ const std::string &language)
+{
+ bool output;
+ std::vector<std::string> options;
+ this->Target->GetCompileOptions(options, config, language);
+ output =
+ options.end() == std::find(options.begin(), options.end(), "-kernel");
+ return output;
+}
+
+bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup(const cmTarget *target)
+{
+ bool output = false;
+ std::vector<cmSourceFile *> sources;
+ std::string config =
+ target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ target->GetSourceFiles(sources, config);
+ for (std::vector<cmSourceFile *>::const_iterator sources_i = sources.begin();
+ sources.end() != sources_i; ++sources_i)
+ {
+ if ("int" == (*sources_i)->GetExtension())
+ {
+ output = true;
+ }
+ }
+ return output;
+}
+
+bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload(
+ std::string const &config, const std::string &language)
+{
+ std::vector<std::string> options;
+ bool output = false;
+ this->Target->GetCompileOptions(options, config, language);
+ for (std::vector<std::string>::const_iterator options_i = options.begin();
+ options_i != options.end(); ++options_i)
+ {
+ std::string option = *options_i;
+ if (this->DDOption == option)
+ {
+ output = true;
+ }
+ }
+ return output;
+}