diff options
author | Fred Baksik <frodak17@gmail.com> | 2019-01-05 11:01:21 -0500 |
---|---|---|
committer | Fred Baksik <frodak17@gmail.com> | 2019-01-16 10:41:20 -0500 |
commit | ead7117afda23d7cf0c1466ce5229d06240d3de0 (patch) | |
tree | d6f73008a1c387f27d3ef3834681ac5edd8c3897 | |
parent | e7825386e2e9e69728e5a5c3dcbc94814bb7cb1c (diff) | |
download | cmake-ead7117afda23d7cf0c1466ce5229d06240d3de0.tar.gz |
GHS: Update the top-level project generation
-- Sort targets by name
-- Generate a top-level project for each project command named as project.top.gpj
Use the target set for the current project instead of assuming all targets
-- Add support for building projects not in binary root
-- Directly create files and pass ostream
-- Do no generate project files for UTILITY targets; this was never supported
-- Do no generate project files for OBJECT, SHARED, or MODULE libraries; this was never supported
-- Update GHS tags to support project types
NOTE: The default tag is changed to "" because "[ ]" is an invalid token in project file
-rw-r--r-- | Source/cmGhsMultiGpj.cxx | 32 | ||||
-rw-r--r-- | Source/cmGhsMultiGpj.h | 2 | ||||
-rw-r--r-- | Source/cmGhsMultiTargetGenerator.cxx | 70 | ||||
-rw-r--r-- | Source/cmGhsMultiTargetGenerator.h | 6 | ||||
-rw-r--r-- | Source/cmGlobalGhsMultiGenerator.cxx | 191 | ||||
-rw-r--r-- | Source/cmGlobalGhsMultiGenerator.h | 46 |
6 files changed, 241 insertions, 106 deletions
diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx index f58cfc1e55..c0f37ba0c2 100644 --- a/Source/cmGhsMultiGpj.cxx +++ b/Source/cmGhsMultiGpj.cxx @@ -4,31 +4,35 @@ #include "cmGeneratedFileStream.h" -void GhsMultiGpj::WriteGpjTag(Types const gpjType, - cmGeneratedFileStream* const filestream) +static const char* GHS_TAG[] = { "[INTEGRITY Application]", + "[Library]", + "[Project]", + "[Program]", + "[Reference]", + "[Subproject]" }; + +const char* GhsMultiGpj::GetGpjTag(Types const gpjType) { 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"; + tag = GHS_TAG[gpjType]; break; default: tag = ""; } - *filestream << "[" << tag << "]" << std::endl; + return tag; +} + +void GhsMultiGpj::WriteGpjTag(Types const gpjType, + cmGeneratedFileStream* const filestream) +{ + char const* tag; + tag = GhsMultiGpj::GetGpjTag(gpjType); + *filestream << tag << std::endl; } diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h index b1eead1016..014f6b6163 100644 --- a/Source/cmGhsMultiGpj.h +++ b/Source/cmGhsMultiGpj.h @@ -22,6 +22,8 @@ public: static void WriteGpjTag(Types const gpjType, cmGeneratedFileStream* filestream); + + static const char* GetGpjTag(Types const gpjType); }; #endif // ! cmGhsMultiGpjType_h diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 4fcc63d1cf..0e0607df0c 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -101,10 +101,59 @@ std::string cmGhsMultiTargetGenerator::AddSlashIfNeededToPath( void cmGhsMultiTargetGenerator::Generate() { + // Determine type of target for this project + switch (this->GeneratorTarget->GetType()) { + case cmStateEnums::EXECUTABLE: { + if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup( + this->GeneratorTarget)) { + this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION; + } else { + this->TagType = GhsMultiGpj::PROGRAM; + } + break; + } + case cmStateEnums::STATIC_LIBRARY: { + this->TagType = GhsMultiGpj::LIBRARY; + break; + } + case cmStateEnums::SHARED_LIBRARY: { + std::string msg = "add_library(<name> SHARED ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg.c_str()); + return; + } + case cmStateEnums::OBJECT_LIBRARY: { + std::string msg = "add_library(<name> OBJECT ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg.c_str()); + return; + } + case cmStateEnums::MODULE_LIBRARY: { + std::string msg = "add_library(<name> MODULE ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg.c_str()); + return; + } + case cmStateEnums::UTILITY: { + std::string msg = "add_custom_target(<name> ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg.c_str()); + return; + } + default: + return; + } // Tell the global generator the name of the project file this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", this->Name.c_str()); + this->GeneratorTarget->Target->SetProperty( + "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); + + this->GenerateTarget(); +} +void cmGhsMultiTargetGenerator::GenerateTarget() +{ // Skip if empty or not included in build if (!this->GetSources().empty() && this->IncludeThisTarget()) { @@ -129,7 +178,7 @@ void cmGhsMultiTargetGenerator::Generate() if (this->DynamicDownload) { fout << "#component integrity_dynamic_download" << std::endl; } - GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), &fout); + GhsMultiGpj::WriteGpjTag(this->TagType, &fout); cmGlobalGhsMultiGenerator::WriteDisclaimer(&fout); bool const notKernel = this->IsNotKernel(config, language); @@ -168,25 +217,6 @@ std::vector<cmSourceFile*> cmGhsMultiTargetGenerator::GetSources() const return output; } -GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const -{ - return cmGhsMultiTargetGenerator::GetGpjTag(this->GeneratorTarget); -} - -GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag( - const cmGeneratorTarget* target) -{ - GhsMultiGpj::Types output; - if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup(target)) { - output = GhsMultiGpj::INTERGRITY_APPLICATION; - } else if (target->GetType() == cmStateEnums::STATIC_LIBRARY) { - output = GhsMultiGpj::LIBRARY; - } else { - output = GhsMultiGpj::PROGRAM; - } - return output; -} - cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator() const { diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h index a54901d7cc..6ba110aa68 100644 --- a/Source/cmGhsMultiTargetGenerator.h +++ b/Source/cmGhsMultiTargetGenerator.h @@ -26,8 +26,6 @@ public: bool IncludeThisTarget(); std::vector<cmSourceFile*> GetSources() const; - GhsMultiGpj::Types GetGpjTag() const; - static GhsMultiGpj::Types GetGpjTag(const cmGeneratorTarget* target); const char* GetAbsBuildFilePath() const { return this->AbsBuildFilePath.c_str(); @@ -58,6 +56,8 @@ private: { return this->FolderBuildStreams[""]; }; + void GenerateTarget(); + bool IsTargetGroup() const { return this->TargetGroup; } void WriteTypeSpecifics(std::ostream& fout, const std::string& config, @@ -114,6 +114,8 @@ private: static std::string const DDOption; std::map<std::string, std::string> FlagsByLanguage; std::map<std::string, std::string> DefinesByLanguage; + + GhsMultiGpj::Types TagType; std::string const Name; }; diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 92b7661a22..f0f1154a09 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -209,25 +209,24 @@ void cmGlobalGhsMultiGenerator::OpenBuildFileStream( { *filestream << "#!gbuild" << std::endl; } +/* temporary until all file handling is cleaned up */ +void cmGlobalGhsMultiGenerator::OpenBuildFileStream(std::ostream& fout) +{ + fout << "#!gbuild" << std::endl; +} -void cmGlobalGhsMultiGenerator::OpenBuildFileStream() +void cmGlobalGhsMultiGenerator::WriteTopLevelProject( + std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators) { - // Compute GHS MULTI's build file path. - std::string buildFilePath = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - buildFilePath += "/"; - buildFilePath += - this->GetCMakeInstance()->GetCurrentSnapshot().GetProjectName(); - buildFilePath += FILE_EXTENSION; - - this->Open(std::string(""), buildFilePath, &this->TargetFolderBuildStreams); - OpenBuildFileStream(GetBuildFileStream()); - - this->WriteMacros(); - this->WriteHighLevelDirectives(); - GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream()); - this->WriteDisclaimer(this->GetBuildFileStream()); - *this->GetBuildFileStream() << "# Top Level Project File" << std::endl; + OpenBuildFileStream(fout); + + this->WriteMacros(fout); + this->WriteHighLevelDirectives(fout); + // GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, &fout); + fout << "[Project]" << std::endl; + this->WriteDisclaimer(&fout); + fout << "# Top Level Project File" << std::endl; // Specify BSP option if supplied by user // -- not all platforms require this entry in the project file @@ -256,7 +255,7 @@ void cmGlobalGhsMultiGenerator::OpenBuildFileStream() } if (!cmSystemTools::IsOff(bspName.c_str())) { - *this->GetBuildFileStream() << " -bsp " << bspName << std::endl; + fout << " -bsp " << bspName << std::endl; } // Specify OS DIR if supplied by user @@ -276,8 +275,46 @@ void cmGlobalGhsMultiGenerator::OpenBuildFileStream() if (!cmSystemTools::IsOff(osDir.c_str()) || platform.find("integrity") != std::string::npos) { std::replace(osDir.begin(), osDir.end(), '\\', '/'); - *this->GetBuildFileStream() - << " " << osDirOption << "\"" << osDir << "\"" << std::endl; + fout << " " << osDirOption << "\"" << osDir << "\"" << std::endl; + } + + WriteSubProjects(fout, root, generators); +} + +void cmGlobalGhsMultiGenerator::WriteSubProjects( + std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators) +{ + // Collect all targets under this root generator and the transitive + // closure of their dependencies. + TargetDependSet projectTargets; + TargetDependSet originalTargets; + this->GetTargetSets(projectTargets, originalTargets, root, generators); + OrderedTargetDependSet orderedProjectTargets(projectTargets, ""); + + // write out all the sub-projects + std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); + for (cmGeneratorTarget const* target : orderedProjectTargets) { + if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + continue; + } + + const char* projName = target->GetProperty("GENERATOR_FILE_NAME"); + const char* projType = target->GetProperty("GENERATOR_FILE_NAME_EXT"); + if (projName && projType) { + cmLocalGenerator* lg = target->GetLocalGenerator(); + std::string dir = lg->GetCurrentBinaryDirectory(); + dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str()); + if (dir == ".") { + dir.clear(); + } else { + if (dir.back() != '/') { + dir += "/"; + } + } + fout << dir << projName << FILE_EXTENSION; + fout << " " << projType << std::endl; + } } } @@ -294,27 +331,43 @@ void cmGlobalGhsMultiGenerator::CloseBuildFileStream( void cmGlobalGhsMultiGenerator::Generate() { + // first do the superclass method this->cmGlobalGenerator::Generate(); - if (!this->LocalGenerators.empty()) { - this->OpenBuildFileStream(); + // output top-level projects + for (auto& it : this->ProjectMap) { + this->OutputTopLevelProject(it.second[0], it.second); + } +} - // 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); - } +void cmGlobalGhsMultiGenerator::OutputTopLevelProject( + cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) +{ + if (generators.empty()) { + return; } - cmDeleteAll(TargetFolderBuildStreams); - this->TargetFolderBuildStreams.clear(); + /* Name top-level projects as filename.top.gpj to avoid name clashes + * with target projects. This avoid the issue where the project has + * the same name as the executable target. + */ + std::string fname = root->GetCurrentBinaryDirectory(); + fname += "/"; + fname += root->GetProjectName(); + fname += ".top"; + fname += FILE_EXTENSION; + + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); + + this->WriteTopLevelProject(fout, root, generators); + + fout.Close(); } void cmGlobalGhsMultiGenerator::GenerateBuildCommand( std::vector<std::string>& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& /*projectDir*/, + const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& /*config*/, bool /*fast*/, int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) { @@ -332,8 +385,20 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand( makeCommand.insert(makeCommand.end(), makeOptions.begin(), makeOptions.end()); + + /* determine which top-project file to use */ + std::string proj = projectName + ".top" + FILE_EXTENSION; + std::vector<std::string> files; + cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files); + if (!files.empty()) { + auto p = std::find(files.begin(), files.end(), proj); + if (p == files.end()) { + proj = files.at(0); + } + } + makeCommand.push_back("-top"); - makeCommand.push_back(projectName + FILE_EXTENSION); + makeCommand.push_back(proj); if (!targetName.empty()) { if (targetName == "clean") { makeCommand.push_back("-clean"); @@ -343,7 +408,7 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand( } } -void cmGlobalGhsMultiGenerator::WriteMacros() +void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout) { char const* ghsGpjMacros = this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS"); @@ -353,12 +418,12 @@ void cmGlobalGhsMultiGenerator::WriteMacros() for (std::vector<std::string>::const_iterator expandedListI = expandedList.begin(); expandedListI != expandedList.end(); ++expandedListI) { - *this->GetBuildFileStream() << "macro " << *expandedListI << std::endl; + fout << "macro " << *expandedListI << std::endl; } } } -void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() +void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout) { /* set primary target */ std::string tgt; @@ -378,13 +443,12 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() tgt += ".tgt"; } - *this->GetBuildFileStream() << "primaryTarget=" << tgt << std::endl; + fout << "primaryTarget=" << 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; + fout << "customization=" << trimQuotes(customization) << std::endl; this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION"); } } @@ -499,33 +563,6 @@ std::string cmGlobalGhsMultiGenerator::GetFileNameFromPath( 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().c_str(), - folderName, GhsMultiGpj::PROJECT); - } - std::vector<std::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 = @@ -552,3 +589,25 @@ std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str) } return result; } + +bool cmGlobalGhsMultiGenerator::TargetCompare::operator()( + cmGeneratorTarget const* l, cmGeneratorTarget const* r) const +{ + // Make sure a given named target is ordered first, + // e.g. to set ALL_BUILD as the default active project. + // When the empty string is named this is a no-op. + if (r->GetName() == this->First) { + return false; + } + if (l->GetName() == this->First) { + return true; + } + return l->GetName() < r->GetName(); +} + +cmGlobalGhsMultiGenerator::OrderedTargetDependSet::OrderedTargetDependSet( + TargetDependSet const& targets, std::string const& first) + : derived(TargetCompare(first)) +{ + this->insert(targets.begin(), targets.end()); +} diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index e0d428e1fd..8b81ba3da4 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -71,6 +71,7 @@ public: static void OpenBuildFileStream(std::string const& filepath, cmGeneratedFileStream** filestream); static void OpenBuildFileStream(cmGeneratedFileStream* filestream); + void OpenBuildFileStream(std::ostream& fout); static void CloseBuildFileStream(cmGeneratedFileStream** filestream); /// Write the common disclaimer text at the top of each build file. static void WriteDisclaimer(std::ostream* os); @@ -86,6 +87,24 @@ public: static std::string trimQuotes(std::string const& str); + // Target dependency sorting + class TargetSet : public std::set<cmGeneratorTarget const*> + { + }; + class TargetCompare + { + std::string First; + + public: + TargetCompare(std::string const& first) + : First(first) + { + } + bool operator()(cmGeneratorTarget const* l, + cmGeneratorTarget const* r) const; + }; + class OrderedTargetDependSet; + protected: void Generate() override; void GenerateBuildCommand(std::vector<std::string>& makeCommand, @@ -100,10 +119,16 @@ protected: private: void GetToolset(cmMakefile* mf, std::string& tsd, std::string& ts); - void OpenBuildFileStream(); - void WriteMacros(); - void WriteHighLevelDirectives(); + /* top-level project */ + void OutputTopLevelProject(cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + void WriteMacros(std::ostream& fout); + void WriteHighLevelDirectives(std::ostream& fout); + void WriteSubProjects(std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); static void AddFilesUpToPathNewBuildFile( cmGeneratedFileStream* mainBuildFile, @@ -116,7 +141,7 @@ private: std::vector<std::string>::const_iterator splitPathI, std::vector<std::string>::const_iterator end, GhsMultiGpj::Types projType); static std::string GetFileNameFromPath(std::string const& path); - void UpdateBuildFiles(const std::vector<cmGeneratorTarget*>& tgts); + bool IsTgtForBuild(const cmGeneratorTarget* tgt); std::vector<cmGeneratedFileStream*> TargetSubProjects; @@ -128,4 +153,17 @@ private: static const char* DEFAULT_TOOLSET_ROOT; }; +class cmGlobalGhsMultiGenerator::OrderedTargetDependSet + : public std::multiset<cmTargetDepend, + cmGlobalGhsMultiGenerator::TargetCompare> +{ + typedef std::multiset<cmTargetDepend, + cmGlobalGhsMultiGenerator::TargetCompare> + derived; + +public: + typedef cmGlobalGenerator::TargetDependSet TargetDependSet; + OrderedTargetDependSet(TargetDependSet const&, std::string const& first); +}; + #endif |