summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalGhsMultiGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGlobalGhsMultiGenerator.cxx')
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx548
1 files changed, 548 insertions, 0 deletions
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;
+}