summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt9
-rw-r--r--Source/cmGhsMultiGpj.cxx44
-rw-r--r--Source/cmGhsMultiGpj.h34
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx600
-rw-r--r--Source/cmGhsMultiTargetGenerator.h119
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx548
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h127
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx1
-rw-r--r--Source/cmLocalGenerator.cxx14
-rw-r--r--Source/cmLocalGenerator.h9
-rw-r--r--Source/cmLocalGhsMultiGenerator.cxx55
-rw-r--r--Source/cmLocalGhsMultiGenerator.h56
-rw-r--r--Source/cmake.cxx3
13 files changed, 1609 insertions, 10 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 786e3eb..6f12785 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -480,6 +480,14 @@ if (WIN32)
cmVisualStudioSlnParser.cxx
cmVisualStudioWCEPlatformParser.h
cmVisualStudioWCEPlatformParser.cxx
+ cmGlobalGhsMultiGenerator.cxx
+ cmGlobalGhsMultiGenerator.h
+ cmLocalGhsMultiGenerator.cxx
+ cmLocalGhsMultiGenerator.h
+ cmGhsMultiTargetGenerator.cxx
+ cmGhsMultiTargetGenerator.h
+ cmGhsMultiGpj.cxx
+ cmGhsMultiGpj.h
)
endif()
endif ()
@@ -507,6 +515,7 @@ set(SRCS ${SRCS}
cmNinjaUtilityTargetGenerator.cxx
cmNinjaUtilityTargetGenerator.h
)
+
if(WIN32 AND NOT CYGWIN)
set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501)
add_executable(cmcldeps cmcldeps.cxx)
diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx
new file mode 100644
index 0000000..e1dce52
--- /dev/null
+++ b/Source/cmGhsMultiGpj.cxx
@@ -0,0 +1,44 @@
+/*============================================================================
+ 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 "cmGhsMultiGpj.h"
+
+#include "cmGeneratedFileStream.h"
+
+void GhsMultiGpj::WriteGpjTag(Types const gpjType,
+ cmGeneratedFileStream *const filestream)
+{
+ char const *tag;
+ switch (gpjType)
+ {
+ case INTERGRITY_APPLICATION:
+ tag = "INTEGRITY Application";
+ break;
+ case LIBRARY:
+ tag = "Library";
+ break;
+ case PROJECT:
+ tag = "Project";
+ break;
+ case PROGRAM:
+ tag = "Program";
+ break;
+ case REFERENCE:
+ tag = "Reference";
+ break;
+ case SUBPROJECT:
+ tag = "Subproject";
+ break;
+ default:
+ tag = "";
+ }
+ *filestream << "[" << tag << "]" << std::endl;
+}
diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h
new file mode 100644
index 0000000..91ff0f4
--- /dev/null
+++ b/Source/cmGhsMultiGpj.h
@@ -0,0 +1,34 @@
+/*============================================================================
+ 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.
+============================================================================*/
+#ifndef cmGhsMultiGpj_h
+#define cmGhsMultiGpj_h
+
+class cmGeneratedFileStream;
+
+class GhsMultiGpj
+{
+public:
+ enum Types
+ {
+ INTERGRITY_APPLICATION,
+ LIBRARY,
+ PROJECT,
+ PROGRAM,
+ REFERENCE,
+ SUBPROJECT
+ };
+
+ static void WriteGpjTag(Types const gpjType,
+ cmGeneratedFileStream *filestream);
+};
+
+#endif // ! cmGhsMultiGpjType_h
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;
+}
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
new file mode 100644
index 0000000..8e81db8
--- /dev/null
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -0,0 +1,119 @@
+/*============================================================================
+ 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.
+============================================================================*/
+#ifndef cmGhsMultiTargetGenerator_h
+#define cmGhsMultiTargetGenerator_h
+
+#include "cmStandardIncludes.h"
+#include "cmTarget.h"
+#include "cmGhsMultiGpj.h"
+
+class cmGeneratedFileStream;
+class cmGlobalGhsMultiGenerator;
+class cmLocalGhsMultiGenerator;
+class cmMakefile;
+class cmSourceFile;
+class cmGeneratedFileStream;
+class cmCustomCommand;
+
+class cmGhsMultiTargetGenerator
+{
+public:
+ cmGhsMultiTargetGenerator(cmTarget *target);
+
+ virtual ~cmGhsMultiTargetGenerator();
+
+ virtual void Generate();
+
+ bool IncludeThisTarget();
+ std::vector<cmSourceFile *> GetSources() const;
+ GhsMultiGpj::Types GetGpjTag() const;
+ static GhsMultiGpj::Types GetGpjTag(const cmTarget *target);
+ const char *GetAbsBuildFilePath() const
+ {
+ return this->AbsBuildFilePath.c_str();
+ }
+ const char *GetRelBuildFileName() const
+ {
+ return this->RelBuildFileName.c_str();
+ }
+ const char *GetAbsBuildFileName() const
+ {
+ return this->AbsBuildFileName.c_str();
+ }
+ const char *GetAbsOutputFileName() const
+ {
+ return this->AbsOutputFileName.c_str();
+ }
+
+ static std::string GetRelBuildFilePath(const cmTarget *target);
+ static std::string GetAbsPathToRoot(const cmTarget *target);
+ static std::string GetAbsBuildFilePath(const cmTarget *target);
+ static std::string GetRelBuildFileName(const cmTarget *target);
+ static std::string GetBuildFileName(const cmTarget *target);
+ static std::string AddSlashIfNeededToPath(std::string const &input);
+
+private:
+ cmGlobalGhsMultiGenerator *GetGlobalGenerator() const;
+ cmGeneratedFileStream *GetFolderBuildStreams()
+ {
+ return this->FolderBuildStreams[""];
+ };
+ bool IsTargetGroup() const { return this->TargetGroup; }
+
+ void WriteTypeSpecifics(const std::string &config, bool notKernel);
+ void WriteCompilerFlags(const std::string &config,
+ const std::string &language);
+ void WriteCompilerDefinitions(const std::string &config,
+ const std::string &language);
+
+ void SetCompilerFlags(std::string const &config, const std::string &language,
+ bool const notKernel);
+ std::string GetDefines(const std::string &langugae,
+ std::string const &config);
+
+ void WriteIncludes(const std::string &config, const std::string &language);
+ void WriteTargetLinkLibraries();
+ void WriteCustomCommands();
+ void
+ WriteCustomCommandsHelper(std::vector<cmCustomCommand> const &commandsSet,
+ cmTarget::CustomCommandType commandType);
+ void WriteSources(std::vector<cmSourceFile *> const &objectSources);
+ static void WriteObjectLangOverride(cmGeneratedFileStream *fileStream,
+ cmSourceFile *sourceFile);
+ static void WriteObjectDir(cmGeneratedFileStream *fileStream,
+ std::string const &dir);
+ std::string GetOutputDirectory(const std::string &config) const;
+ std::string GetOutputFilename(const std::string &config) const;
+
+ bool IsNotKernel(std::string const &config, const std::string &language);
+ static bool DetermineIfTargetGroup(const cmTarget *target);
+ bool DetermineIfDynamicDownload(std::string const &config,
+ const std::string &language);
+
+ cmTarget *Target;
+ cmLocalGhsMultiGenerator *LocalGenerator;
+ cmMakefile *Makefile;
+ std::string AbsBuildFilePath;
+ std::string RelBuildFilePath;
+ std::string AbsBuildFileName;
+ std::string RelBuildFileName;
+ std::string RelOutputFileName;
+ std::string AbsOutputFileName;
+ std::map<std::string, cmGeneratedFileStream *> FolderBuildStreams;
+ bool TargetGroup;
+ bool DynamicDownload;
+ static std::string const DDOption;
+ std::map<std::string, std::string> FlagsByLanguage;
+ std::map<std::string, std::string> DefinesByLanguage;
+};
+
+#endif // ! cmGhsMultiTargetGenerator_h
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
new file mode 100644
index 0000000..bba29b1
--- /dev/null
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -0,0 +1,548 @@
+/*============================================================================
+ 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 "cmGlobalGhsMultiGenerator.h"
+#include "cmLocalGhsMultiGenerator.h"
+#include "cmMakefile.h"
+#include "cmVersion.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGhsMultiTargetGenerator.h"
+#include <cmsys/SystemTools.hxx>
+#include <cmAlgorithms.h>
+
+const char *cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
+const char *cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild";
+
+cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator()
+ : OSDirRelative(false)
+{
+ this->GhsBuildCommandInitialized = false;
+}
+
+cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator()
+{
+ cmDeleteAll(TargetFolderBuildStreams);
+}
+
+cmLocalGenerator *cmGlobalGhsMultiGenerator::CreateLocalGenerator()
+{
+ cmLocalGenerator *lg = new cmLocalGhsMultiGenerator;
+ lg->SetGlobalGenerator(this);
+ this->SetCurrentLocalGenerator(lg);
+ return lg;
+}
+
+void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry &entry)
+{
+ entry.Name = GetActualName();
+ entry.Brief =
+ "Generates Green Hills MULTI files (experimental, work-in-progress).";
+}
+
+void cmGlobalGhsMultiGenerator::EnableLanguage(
+ std::vector<std::string> const &l, cmMakefile *mf, bool optional)
+{
+ mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
+ mf->AddDefinition("CMAKE_SYSTEM_PROCESSOR", "ARM");
+
+ const std::string ghsCompRoot(GetCompRoot());
+ mf->AddDefinition("GHS_COMP_ROOT", ghsCompRoot.c_str());
+ std::string ghsCompRootStart =
+ 0 == ghsCompRootStart.size() ? "" : ghsCompRoot + "/";
+ mf->AddDefinition("CMAKE_C_COMPILER",
+ 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");
+
+ mf->AddDefinition("CMAKE_CXX_COMPILER",
+ std::string(ghsCompRootStart + "cxarm.exe").c_str());
+ mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE");
+ mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS");
+ mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE");
+
+ 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);
+}
+
+void 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")))
+ {
+ mf->AddDefinition("CMAKE_MAKE_PROGRAM",
+ this->GetGhsBuildCommand().c_str());
+ }
+}
+
+std::string const &cmGlobalGhsMultiGenerator::GetGhsBuildCommand()
+{
+ if (!this->GhsBuildCommandInitialized)
+ {
+ this->GhsBuildCommandInitialized = true;
+ this->GhsBuildCommand = this->FindGhsBuildCommand();
+ }
+ return this->GhsBuildCommand;
+}
+
+std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand()
+{
+ std::vector<std::string> userPaths;
+ userPaths.push_back(this->GetCompRoot());
+ std::string makeProgram =
+ cmSystemTools::FindProgram(DEFAULT_MAKE_PROGRAM, userPaths);
+ if (makeProgram.empty())
+ {
+ makeProgram = DEFAULT_MAKE_PROGRAM;
+ }
+ return makeProgram;
+}
+
+std::string cmGlobalGhsMultiGenerator::GetCompRoot()
+{
+ std::string output;
+
+ const std::vector<std::string>
+ potentialDirsHardPaths(GetCompRootHardPaths());
+ const std::vector<std::string> potentialDirsRegistry(GetCompRootRegistry());
+
+ std::vector<std::string> potentialDirsComplete;
+ potentialDirsComplete.insert(potentialDirsComplete.end(),
+ potentialDirsHardPaths.begin(),
+ potentialDirsHardPaths.end());
+ potentialDirsComplete.insert(potentialDirsComplete.end(),
+ potentialDirsRegistry.begin(),
+ potentialDirsRegistry.end());
+
+ // Use latest version
+ std::string outputDirName;
+ for (std::vector<std::string>::const_iterator potentialDirsCompleteIt =
+ potentialDirsComplete.begin();
+ potentialDirsCompleteIt != potentialDirsComplete.end();
+ ++potentialDirsCompleteIt)
+ {
+ const std::string dirName(
+ cmsys::SystemTools::GetFilenameName(*potentialDirsCompleteIt));
+ if (dirName.compare(outputDirName) > 0)
+ {
+ output = *potentialDirsCompleteIt;
+ outputDirName = dirName;
+ }
+ }
+
+ return 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;
+ }
+ return output;
+}
+
+std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry()
+{
+ std::vector<std::string> output(2);
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_"
+ "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
+ "Windows\\CurrentVersion\\Uninstall\\"
+ "GreenHillsSoftwared771f1b4;InstallLocation",
+ output[0]);
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_"
+ "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
+ "Windows\\CurrentVersion\\Uninstall\\"
+ "GreenHillsSoftware9881cef6;InstallLocation",
+ output[1]);
+ return output;
+}
+
+void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
+ std::string const &filepath, cmGeneratedFileStream **filestream)
+{
+ // Get a stream where to generate things.
+ if (NULL == *filestream)
+ {
+ *filestream = new cmGeneratedFileStream(filepath.c_str());
+ if (NULL != *filestream)
+ {
+ OpenBuildFileStream(*filestream);
+ }
+ }
+}
+
+void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
+ cmGeneratedFileStream *filestream)
+{
+ *filestream << "#!gbuild" << std::endl;
+}
+
+void cmGlobalGhsMultiGenerator::OpenBuildFileStream()
+{
+ // Compute GHS MULTI's build file path.
+ std::string buildFilePath =
+ this->GetCMakeInstance()->GetHomeOutputDirectory();
+ buildFilePath += "/";
+ buildFilePath += "default";
+ buildFilePath += FILE_EXTENSION;
+
+ this->Open(std::string(""), buildFilePath, &this->TargetFolderBuildStreams);
+ OpenBuildFileStream(GetBuildFileStream());
+
+ char const *osDir =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR");
+ if (NULL == osDir)
+ {
+ osDir = "";
+ cmSystemTools::Error("GHS_OS_DIR cache variable must be set");
+ }
+ else
+ {
+ this->GetCMakeInstance()->MarkCliAsUsed("GHS_OS_DIR");
+ }
+ std::string fOSDir(this->trimQuotes(osDir));
+ cmSystemTools::ReplaceString(fOSDir, "\\", "/");
+ if (!fOSDir.empty() && ('c' == fOSDir[0] || 'C' == fOSDir[0]))
+ {
+ this->OSDirRelative = false;
+ }
+ else
+ {
+ this->OSDirRelative = true;
+ }
+
+ char const *bspName =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
+ if (NULL == bspName)
+ {
+ bspName = "";
+ cmSystemTools::Error("GHS_BSP_NAME cache variable must be set");
+ }
+ else
+ {
+ this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME");
+ }
+ std::string fBspName(this->trimQuotes(bspName));
+ cmSystemTools::ReplaceString(fBspName, "\\", "/");
+ this->WriteMacros();
+ this->WriteHighLevelDirectives();
+
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream());
+ this->WriteDisclaimer(this->GetBuildFileStream());
+ *this->GetBuildFileStream() << "# Top Level Project File" << std::endl;
+ if (!fBspName.empty())
+ {
+ *this->GetBuildFileStream() << " -bsp " << fBspName << std::endl;
+ }
+ this->WriteCompilerOptions(fOSDir);
+}
+
+void cmGlobalGhsMultiGenerator::CloseBuildFileStream(
+ cmGeneratedFileStream **filestream)
+{
+ if (filestream)
+ {
+ delete *filestream;
+ *filestream = NULL;
+ }
+ else
+ {
+ cmSystemTools::Error("Build file stream was not open.");
+ }
+}
+
+void cmGlobalGhsMultiGenerator::Generate()
+{
+ this->cmGlobalGenerator::Generate();
+
+ if (!this->LocalGenerators.empty())
+ {
+ this->OpenBuildFileStream();
+
+ // Build all the folder build files
+ for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
+ {
+ cmLocalGhsMultiGenerator *lg =
+ static_cast<cmLocalGhsMultiGenerator *>(this->LocalGenerators[i]);
+ cmGeneratorTargetsType tgts = lg->GetMakefile()->GetGeneratorTargets();
+ this->UpdateBuildFiles(&tgts);
+ }
+ }
+
+ cmDeleteAll(TargetFolderBuildStreams);
+ this->TargetFolderBuildStreams.clear();
+}
+
+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)
+{
+ makeCommand.push_back(
+ this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand())
+ );
+
+ makeCommand.insert(makeCommand.end(),
+ makeOptions.begin(), makeOptions.end());
+ if (!targetName.empty())
+ {
+ if (targetName == "clean")
+ {
+ makeCommand.push_back("-clean");
+ }
+ else
+ {
+ makeCommand.push_back(targetName);
+ }
+ }
+}
+
+void cmGlobalGhsMultiGenerator::WriteMacros()
+{
+ char const *ghsGpjMacros =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
+ if (NULL != ghsGpjMacros)
+ {
+ std::vector<std::string> expandedList;
+ cmSystemTools::ExpandListArgument(std::string(ghsGpjMacros), expandedList);
+ for (std::vector<std::string>::const_iterator expandedListI =
+ expandedList.begin();
+ expandedListI != expandedList.end(); ++expandedListI)
+ {
+ *this->GetBuildFileStream() << "macro " << *expandedListI << std::endl;
+ }
+ }
+}
+
+void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives()
+{
+ *this->GetBuildFileStream() << "primaryTarget=arm_integrity.tgt"
+ << std::endl;
+ char const *const customization =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
+ if (NULL != customization && strlen(customization) > 0)
+ {
+ *this->GetBuildFileStream() << "customization="
+ << trimQuotes(customization)
+ << std::endl;
+ this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION");
+ }
+}
+
+void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const &fOSDir)
+{
+ *this->GetBuildFileStream() << " -os_dir=\"" << fOSDir << "\""
+ << std::endl;
+}
+
+void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream *os)
+{
+ (*os) << "#" << std::endl
+ << "# CMAKE generated file: DO NOT EDIT!" << std::endl
+ << "# Generated by \"" << GetActualName() << "\""
+ << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "."
+ << cmVersion::GetMinorVersion() << std::endl
+ << "#" << std::endl;
+}
+
+void cmGlobalGhsMultiGenerator::AddFilesUpToPath(
+ cmGeneratedFileStream *mainBuildFile,
+ std::map<std::string, cmGeneratedFileStream *> *targetFolderBuildStreams,
+ char const *homeOutputDirectory, std::string const &path,
+ GhsMultiGpj::Types projType, std::string const &relPath)
+{
+ std::string workingPath(path);
+ cmSystemTools::ConvertToUnixSlashes(workingPath);
+ std::vector<cmsys::String> splitPath =
+ cmSystemTools::SplitString(workingPath);
+ std::string workingRelPath(relPath);
+ cmSystemTools::ConvertToUnixSlashes(workingRelPath);
+ if (!workingRelPath.empty())
+ {
+ workingRelPath += "/";
+ }
+ std::string pathUpTo;
+ for (std::vector<cmsys::String>::const_iterator splitPathI =
+ splitPath.begin();
+ splitPath.end() != splitPathI; ++splitPathI)
+ {
+ pathUpTo += *splitPathI;
+ if (targetFolderBuildStreams->end() ==
+ targetFolderBuildStreams->find(pathUpTo))
+ {
+ AddFilesUpToPathNewBuildFile(
+ mainBuildFile, targetFolderBuildStreams, homeOutputDirectory,
+ pathUpTo, splitPath.begin() == splitPathI, workingRelPath, projType);
+ }
+ AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo,
+ splitPathI, splitPath.end(), projType);
+ pathUpTo += "/";
+ }
+}
+
+void cmGlobalGhsMultiGenerator::Open(
+ std::string const &mapKeyName, std::string const &fileName,
+ std::map<std::string, cmGeneratedFileStream *> *fileMap)
+{
+ if (fileMap->end() == fileMap->find(fileName))
+ {
+ cmGeneratedFileStream *temp(new cmGeneratedFileStream);
+ temp->open(fileName.c_str());
+ (*fileMap)[mapKeyName] = temp;
+ }
+}
+
+void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile(
+ cmGeneratedFileStream *mainBuildFile,
+ std::map<std::string, cmGeneratedFileStream *> *targetFolderBuildStreams,
+ char const *homeOutputDirectory, std::string const &pathUpTo,
+ bool const isFirst, std::string const &relPath,
+ GhsMultiGpj::Types const projType)
+{
+ // create folders up to file path
+ std::string absPath = std::string(homeOutputDirectory) + "/" + relPath;
+ std::string newPath = absPath + pathUpTo;
+ if (!cmSystemTools::FileExists(newPath.c_str()))
+ {
+ cmSystemTools::MakeDirectory(newPath.c_str());
+ }
+
+ // Write out to filename for first time
+ std::string relFilename(GetFileNameFromPath(pathUpTo));
+ std::string absFilename = absPath + relFilename;
+ Open(pathUpTo, absFilename, targetFolderBuildStreams);
+ OpenBuildFileStream((*targetFolderBuildStreams)[pathUpTo]);
+ GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
+ WriteDisclaimer((*targetFolderBuildStreams)[pathUpTo]);
+
+ // Add to main build file
+ if (isFirst)
+ {
+ *mainBuildFile << relFilename << " ";
+ GhsMultiGpj::WriteGpjTag(projType, mainBuildFile);
+ }
+}
+
+void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile(
+ std::map<std::string, cmGeneratedFileStream *> *targetFolderBuildStreams,
+ std::string const &pathUpTo,
+ std::vector<cmsys::String>::const_iterator splitPathI,
+ std::vector<cmsys::String>::const_iterator end,
+ GhsMultiGpj::Types const projType)
+{
+ std::vector<cmsys::String>::const_iterator splitPathNextI = splitPathI + 1;
+ if (end != splitPathNextI &&
+ targetFolderBuildStreams->end() ==
+ targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI))
+ {
+ std::string nextFilename(*splitPathNextI);
+ nextFilename = GetFileNameFromPath(nextFilename);
+ *(*targetFolderBuildStreams)[pathUpTo] << nextFilename << " ";
+ GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
+ }
+}
+
+std::string
+cmGlobalGhsMultiGenerator::GetFileNameFromPath(std::string const &path)
+{
+ std::string output(path);
+ if (!path.empty())
+ {
+ cmSystemTools::ConvertToUnixSlashes(output);
+ std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output);
+ output += "/" + splitPath.back() + FILE_EXTENSION;
+ }
+ return output;
+}
+
+void cmGlobalGhsMultiGenerator::UpdateBuildFiles(
+ cmGeneratorTargetsType *tgts)
+{
+ for (cmGeneratorTargetsType::iterator tgtsI = tgts->begin();
+ tgtsI != tgts->end(); ++tgtsI)
+ {
+ const cmTarget *tgt(tgtsI->first);
+ if (IsTgtForBuild(tgt))
+ {
+ char const *rawFolderName = tgtsI->first->GetProperty("FOLDER");
+ if (NULL == rawFolderName)
+ {
+ rawFolderName = "";
+ }
+ std::string folderName(rawFolderName);
+ if (this->TargetFolderBuildStreams.end() ==
+ this->TargetFolderBuildStreams.find(folderName))
+ {
+ this->AddFilesUpToPath(
+ GetBuildFileStream(), &this->TargetFolderBuildStreams,
+ this->GetCMakeInstance()->GetHomeOutputDirectory(), folderName,
+ GhsMultiGpj::PROJECT);
+ }
+ std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(
+ cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt));
+ std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" +
+ splitPath.back());
+ *this->TargetFolderBuildStreams[folderName] << foldNameRelBuildFile
+ << " ";
+ GhsMultiGpj::WriteGpjTag(cmGhsMultiTargetGenerator::GetGpjTag(tgt),
+ this->TargetFolderBuildStreams[folderName]);
+ }
+ }
+}
+
+bool cmGlobalGhsMultiGenerator::IsTgtForBuild(const cmTarget *tgt)
+{
+ const std::string config =
+ tgt->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ std::vector<cmSourceFile *> tgtSources;
+ tgt->GetSourceFiles(tgtSources, config);
+ bool tgtInBuild = true;
+ char const *excludeFromAll = tgt->GetProperty("EXCLUDE_FROM_ALL");
+ if (NULL != excludeFromAll && '1' == excludeFromAll[0] &&
+ '\0' == excludeFromAll[1])
+ {
+ tgtInBuild = false;
+ }
+ return !tgtSources.empty() && tgtInBuild;
+}
+
+std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const &str)
+{
+ std::string result;
+ result.reserve(str.size());
+ for (const char *ch = str.c_str(); *ch != '\0'; ++ch)
+ {
+ if (*ch != '"')
+ {
+ result += *ch;
+ }
+ }
+ return result;
+}
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
new file mode 100644
index 0000000..b934c3a
--- /dev/null
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -0,0 +1,127 @@
+/*============================================================================
+ 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.
+============================================================================*/
+#ifndef cmGhsMultiGenerator_h
+#define cmGhsMultiGenerator_h
+
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalGenerator.h"
+#include "cmGhsMultiGpj.h"
+
+class cmGeneratedFileStream;
+
+class cmGlobalGhsMultiGenerator : public cmGlobalGenerator
+{
+public:
+ /// The default name of GHS MULTI's build file. Typically: monolith.gpj.
+ static const char *FILE_EXTENSION;
+
+ cmGlobalGhsMultiGenerator();
+ ~cmGlobalGhsMultiGenerator();
+
+ static cmGlobalGeneratorFactory *NewFactory()
+ { return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>(); }
+
+ ///! create the correct local generator
+ virtual cmLocalGenerator *CreateLocalGenerator();
+
+ /// @return the name of this generator.
+ static std::string GetActualName() { return "Green Hills MULTI"; }
+ ///! Get the name for this generator
+ virtual std::string GetName() const { return this->GetActualName(); }
+
+ /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
+ static void GetDocumentation(cmDocumentationEntry &entry);
+
+ /**
+ * 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);
+ /*
+ * Determine what program to use for building the project.
+ */
+ virtual void FindMakeProgram(cmMakefile *);
+
+ cmGeneratedFileStream *GetBuildFileStream()
+ {
+ return this->TargetFolderBuildStreams[""];
+ }
+
+ static void OpenBuildFileStream(std::string const &filepath,
+ cmGeneratedFileStream **filestream);
+ static void OpenBuildFileStream(cmGeneratedFileStream *filestream);
+ static void CloseBuildFileStream(cmGeneratedFileStream **filestream);
+ /// Write the common disclaimer text at the top of each build file.
+ static void WriteDisclaimer(std::ostream *os);
+ std::vector<std::string> GetLibDirs() { return this->LibDirs; }
+
+ static void AddFilesUpToPath(
+ cmGeneratedFileStream *mainBuildFile,
+ std::map<std::string, cmGeneratedFileStream *> *targetFolderBuildStreams,
+ char const *homeOutputDirectory, std::string const &path,
+ GhsMultiGpj::Types projType, std::string const &relPath = "");
+ static void Open(std::string const &mapKeyName, std::string const &fileName,
+ std::map<std::string, cmGeneratedFileStream *> *fileMap);
+
+ static std::string trimQuotes(std::string const &str);
+ inline bool IsOSDirRelative() { return this->OSDirRelative; }
+
+protected:
+ virtual void Generate();
+ virtual 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 = std::vector<std::string>()
+ );
+
+private:
+ std::string const &GetGhsBuildCommand();
+ std::string FindGhsBuildCommand();
+ std::string GetCompRoot();
+ std::vector<std::string> GetCompRootHardPaths();
+ std::vector<std::string> GetCompRootRegistry();
+ void OpenBuildFileStream();
+
+ void WriteMacros();
+ void WriteHighLevelDirectives();
+ void WriteCompilerOptions(std::string const &fOSDir);
+
+ static void AddFilesUpToPathNewBuildFile(
+ cmGeneratedFileStream *mainBuildFile,
+ std::map<std::string, cmGeneratedFileStream *> *targetFolderBuildStreams,
+ char const *homeOutputDirectory, std::string const &pathUpTo,
+ bool isFirst, std::string const &relPath, GhsMultiGpj::Types projType);
+ static void AddFilesUpToPathAppendNextFile(
+ std::map<std::string, cmGeneratedFileStream *> *targetFolderBuildStreams,
+ std::string const &pathUpTo,
+ std::vector<cmsys::String>::const_iterator splitPathI,
+ std::vector<cmsys::String>::const_iterator end,
+ GhsMultiGpj::Types projType);
+ static std::string GetFileNameFromPath(std::string const &path);
+ void UpdateBuildFiles(cmGeneratorTargetsType *tgts);
+ bool IsTgtForBuild(const cmTarget *tgt);
+
+ std::vector<cmGeneratedFileStream *> TargetSubProjects;
+ std::map<std::string, cmGeneratedFileStream *> TargetFolderBuildStreams;
+
+ std::vector<std::string> LibDirs;
+
+ bool OSDirRelative;
+ bool GhsBuildCommandInitialized;
+ std::string GhsBuildCommand;
+ static const char *DEFAULT_MAKE_PROGRAM;
+};
+
+#endif
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 9a00fa6..505914e 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -576,6 +576,7 @@ bool cmGlobalNinjaGenerator::UsingMinGW = false;
// Implemented by:
// cmGlobalUnixMakefileGenerator3
+// cmGlobalGhsMultiGenerator
// cmGlobalVisualStudio10Generator
// cmGlobalVisualStudio6Generator
// cmGlobalVisualStudio7Generator
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index c143bce..6bce088 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2003,7 +2003,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
//----------------------------------------------------------------------------
void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
const std::string& lang,
const std::string& config)
{
@@ -2190,7 +2190,7 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
//----------------------------------------------------------------------------
void cmLocalGenerator::
-AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
+AddCompilerRequirementFlag(std::string &flags, cmTarget const* target,
const std::string& lang)
{
if (lang.empty())
@@ -2312,7 +2312,8 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
}
}
-static void AddVisibilityCompileOption(std::string &flags, cmTarget* target,
+static void AddVisibilityCompileOption(std::string &flags,
+ cmTarget const* target,
cmLocalGenerator *lg,
const std::string& lang)
{
@@ -2346,7 +2347,7 @@ static void AddVisibilityCompileOption(std::string &flags, cmTarget* target,
}
static void AddInlineVisibilityCompileOption(std::string &flags,
- cmTarget* target,
+ cmTarget const* target,
cmLocalGenerator *lg)
{
std::string compileOption
@@ -2367,7 +2368,7 @@ static void AddInlineVisibilityCompileOption(std::string &flags,
//----------------------------------------------------------------------------
void cmLocalGenerator
-::AddVisibilityPresetFlags(std::string &flags, cmTarget* target,
+::AddVisibilityPresetFlags(std::string &flags, cmTarget const* target,
const std::string& lang)
{
int targetType = target->GetType();
@@ -2393,7 +2394,8 @@ void cmLocalGenerator
}
//----------------------------------------------------------------------------
-void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
+void cmLocalGenerator::AddCMP0018Flags(std::string &flags,
+ cmTarget const* target,
std::string const& lang,
const std::string& config)
{
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 6cdee42..a005f5f 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -138,18 +138,19 @@ public:
std::vector<cmLocalGenerator*>& GetChildren() { return this->Children; }
- void AddArchitectureFlags(std::string& flags, cmGeneratorTarget* target,
+ void AddArchitectureFlags(std::string& flags,
+ cmGeneratorTarget const* target,
const std::string&lang, const std::string& config);
void AddLanguageFlags(std::string& flags, const std::string& lang,
const std::string& config);
- void AddCMP0018Flags(std::string &flags, cmTarget* target,
+ void AddCMP0018Flags(std::string &flags, cmTarget const* target,
std::string const& lang, const std::string& config);
- void AddVisibilityPresetFlags(std::string &flags, cmTarget* target,
+ void AddVisibilityPresetFlags(std::string &flags, cmTarget const* target,
const std::string& lang);
void AddConfigVariableFlags(std::string& flags, const std::string& var,
const std::string& config);
- void AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
+ void AddCompilerRequirementFlag(std::string &flags, cmTarget const* target,
const std::string& lang);
///! Append flags to a string.
virtual void AppendFlags(std::string& flags, const std::string& newFlags);
diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx
new file mode 100644
index 0000000..782fec4
--- /dev/null
+++ b/Source/cmLocalGhsMultiGenerator.cxx
@@ -0,0 +1,55 @@
+/*============================================================================
+ 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 "cmLocalGhsMultiGenerator.h"
+#include "cmGlobalGhsMultiGenerator.h"
+#include "cmGeneratorTarget.h"
+#include "cmMakefile.h"
+#include "cmGhsMultiTargetGenerator.h"
+#include "cmGeneratedFileStream.h"
+
+cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator()
+{
+}
+
+cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() {}
+
+void cmLocalGhsMultiGenerator::Generate()
+{
+ cmGeneratorTargetsType tgts = this->GetMakefile()->GetGeneratorTargets();
+ if (!tgts.empty())
+ {
+ for (cmGeneratorTargetsType::iterator l = tgts.begin(); l != tgts.end();
+ ++l)
+ {
+ cmGhsMultiTargetGenerator tg(l->second->Target);
+ tg.Generate();
+ }
+ }
+}
+
+// Implemented in:
+// cmLocalGenerator.
+// Used in:
+// Source/cmMakefile.cxx
+// Source/cmGlobalGenerator.cxx
+void cmLocalGhsMultiGenerator::Configure()
+{
+ // Compute the path to use when referencing the current output
+ // directory from the top output directory.
+ this->HomeRelativeOutputPath =
+ this->Convert(this->Makefile->GetStartOutputDirectory(), HOME_OUTPUT);
+ if (this->HomeRelativeOutputPath == ".")
+ {
+ this->HomeRelativeOutputPath = "";
+ }
+ this->cmLocalGenerator::Configure();
+}
diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h
new file mode 100644
index 0000000..a8df3e7
--- /dev/null
+++ b/Source/cmLocalGhsMultiGenerator.h
@@ -0,0 +1,56 @@
+/*============================================================================
+ 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.
+============================================================================*/
+#ifndef cmLocalGhsMultiGenerator_h
+#define cmLocalGhsMultiGenerator_h
+
+#include "cmLocalGenerator.h"
+
+class cmGeneratedFileStream;
+
+/** \class cmLocalGhsMultiGenerator
+ * \brief Write Green Hills MULTI project files.
+ *
+ * cmLocalGhsMultiGenerator produces a set of .gpj
+ * file for each target in its mirrored directory.
+ */
+class cmLocalGhsMultiGenerator : public cmLocalGenerator
+{
+public:
+ cmLocalGhsMultiGenerator();
+
+ virtual ~cmLocalGhsMultiGenerator();
+
+ /// @returns the relative path between the HomeOutputDirectory and this
+ /// local generators StartOutputDirectory.
+ std::string GetHomeRelativeOutputPath() const
+ {
+ return this->HomeRelativeOutputPath;
+ }
+
+ /**
+ * Generate the makefile for this directory.
+ */
+ virtual void Generate();
+
+ /// Overloaded methods. @see cmLocalGenerator::Configure()
+ virtual void Configure();
+ const char *GetBuildFileName() { return this->BuildFileName.c_str(); }
+
+protected:
+ virtual bool CustomCommandUseLocal() const { return true; }
+
+private:
+ std::string BuildFileName;
+ std::string HomeRelativeOutputPath;
+};
+
+#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index a542a24..e624a83 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -64,6 +64,7 @@
# include "cmGlobalBorlandMakefileGenerator.h"
# include "cmGlobalNMakeMakefileGenerator.h"
# include "cmGlobalJOMMakefileGenerator.h"
+# include "cmGlobalGhsMultiGenerator.h"
# define CMAKE_HAVE_VS_GENERATORS
# endif
# include "cmGlobalMSYSMakefileGenerator.h"
@@ -1756,6 +1757,8 @@ void cmake::AddDefaultGenerators()
cmGlobalNMakeMakefileGenerator::NewFactory());
this->Generators.push_back(
cmGlobalJOMMakefileGenerator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalGhsMultiGenerator::NewFactory());
# endif
this->Generators.push_back(
cmGlobalMSYSMakefileGenerator::NewFactory());