summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Baksik <frodak17@gmail.com>2019-01-05 11:01:21 -0500
committerFred Baksik <frodak17@gmail.com>2019-01-16 10:41:20 -0500
commitead7117afda23d7cf0c1466ce5229d06240d3de0 (patch)
treed6f73008a1c387f27d3ef3834681ac5edd8c3897
parente7825386e2e9e69728e5a5c3dcbc94814bb7cb1c (diff)
downloadcmake-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.cxx32
-rw-r--r--Source/cmGhsMultiGpj.h2
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx70
-rw-r--r--Source/cmGhsMultiTargetGenerator.h6
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx191
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h46
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