diff options
Diffstat (limited to 'Source/cmGlobalGhsMultiGenerator.cxx')
-rw-r--r-- | Source/cmGlobalGhsMultiGenerator.cxx | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx new file mode 100644 index 0000000..788a179 --- /dev/null +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -0,0 +1,490 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmGlobalGhsMultiGenerator.h" + +#include "cmsys/SystemTools.hxx" + +#include "cmAlgorithms.h" +#include "cmDocumentationEntry.h" +#include "cmGeneratedFileStream.h" +#include "cmGeneratorTarget.h" +#include "cmGhsMultiTargetGenerator.h" +#include "cmLocalGhsMultiGenerator.h" +#include "cmMakefile.h" +#include "cmVersion.h" + +const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj"; +const char* cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild"; + +cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) + : cmGlobalGenerator(cm) + , OSDirRelative(false) +{ + this->GhsBuildCommandInitialized = false; +} + +cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() +{ + cmDeleteAll(TargetFolderBuildStreams); +} + +cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator( + cmMakefile* mf) +{ + return new cmLocalGhsMultiGenerator(this, mf); +} + +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); +} + +bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* mf) +{ + // The GHS generator knows how to lookup its build tool + // directly instead of needing a helper module to do it, so we + // do not actually need to put CMAKE_MAKE_PROGRAM into the cache. + if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + mf->AddDefinition("CMAKE_MAKE_PROGRAM", + this->GetGhsBuildCommand().c_str()); + } + return true; +} + +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)); + std::replace(fOSDir.begin(), fOSDir.end(), '\\', '/'); + 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)); + std::replace(fBspName.begin(), fBspName.end(), '\\', '/'); + 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]); + const std::vector<cmGeneratorTarget*>& tgts = lg->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( + const std::vector<cmGeneratorTarget*>& tgts) +{ + for (std::vector<cmGeneratorTarget*>::const_iterator tgtsI = tgts.begin(); + tgtsI != tgts.end(); ++tgtsI) { + const cmGeneratorTarget* tgt = *tgtsI; + if (IsTgtForBuild(tgt)) { + std::string folderName = tgt->GetEffectiveFolderName(); + 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 cmGeneratorTarget* tgt) +{ + const std::string config = + tgt->Target->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; +} |