summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorFred Baksik <frodak17@gmail.com>2019-04-08 09:55:34 -0400
committerFred Baksik <frodak17@gmail.com>2019-04-11 13:15:50 -0400
commit8d3dad9a76591ae0426335d039b8aaacb95862cd (patch)
tree712f4ab345d62c7858b879c86838f508036ede8f /Source
parent37acc9e2299713b9b23c767e72b0e0169697e510 (diff)
downloadcmake-8d3dad9a76591ae0426335d039b8aaacb95862cd.tar.gz
GHS: Support add_custom_command( OUTPUT ) signature
-- add new file type to run a shell script -- gbuild does not compute interfile dependencies like other build tools. Therefore calculate the required build order of custom commands and list all of them in the CMake Rules subproject.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx174
-rw-r--r--Source/cmGhsMultiTargetGenerator.h8
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx61
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h3
4 files changed, 219 insertions, 27 deletions
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 9f9ef183f3..9d0d1950d2 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -572,31 +572,82 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
*fout << "{comment} Others" << std::endl;
}
- /* output rule for each source file */
- for (const cmSourceFile* si : groupFiles[sg]) {
-
- // Convert filename to native system
- // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on
- // windows when opening some files from the search window.
- std::string fname(si->GetFullPath());
- cmSystemTools::ConvertToOutputSlashes(fname);
- *fout << fname << std::endl;
-
- if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
- "bsp" != si->GetExtension()) {
- WriteObjectLangOverride(*fout, si);
- }
+ if (sg != "CMake Rules") {
+ /* output rule for each source file */
+ for (const cmSourceFile* si : groupFiles[sg]) {
+
+ // Convert filename to native system
+ // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on
+ // windows when opening some files from the search window.
+ std::string fname(si->GetFullPath());
+ cmSystemTools::ConvertToOutputSlashes(fname);
+
+ /* Comment out any custom command dependencies to prevent from
+ * being considered part of the build.
+ */
+ std::string comment;
+ if (si->GetCustomCommand()) {
+ comment = "{comment} ";
+ }
+ *fout << comment << fname << std::endl;
- this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
- this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
- this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
+ if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
+ "bsp" != si->GetExtension()) {
+ WriteObjectLangOverride(*fout, si);
+ }
- /* to avoid clutter in the gui only print out the objectName if it has
- * been renamed */
- std::string objectName = this->GeneratorTarget->GetObjectName(si);
- if (!objectName.empty() &&
- this->GeneratorTarget->HasExplicitObjectName(si)) {
- *fout << " -o " << objectName << std::endl;
+ this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
+ this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
+ this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
+
+ /* to avoid clutter in the gui only print out the objectName if it has
+ * been renamed */
+ std::string objectName = this->GeneratorTarget->GetObjectName(si);
+ if (!objectName.empty() &&
+ this->GeneratorTarget->HasExplicitObjectName(si)) {
+ *fout << " -o " << objectName << std::endl;
+ }
+ }
+ } else {
+ std::vector<cmSourceFile const*> customCommands;
+ if (ComputeCustomCommandOrder(customCommands)) {
+ std::string message = "The custom commands for target [" +
+ this->GeneratorTarget->GetName() + "] had a cycle.\n";
+ cmSystemTools::Error(message);
+ } else {
+ /* Custom targets do not have a dependency on SOURCES files.
+ * Therefore the dependency list may include SOURCES files after the
+ * custom target. Because nothing can depend on the custom target just
+ * move it to the last item.
+ */
+ for (auto sf = customCommands.begin(); sf != customCommands.end();
+ ++sf) {
+ if (((*sf)->GetLocation()).GetName() == this->Name + ".rule") {
+ std::rotate(sf, sf + 1, customCommands.end());
+ break;
+ }
+ }
+ int cmdcount = 0;
+ for (auto& sf : customCommands) {
+ const cmCustomCommand* cc = sf->GetCustomCommand();
+ cmCustomCommandGenerator ccg(*cc, this->ConfigName,
+ this->LocalGenerator);
+
+ // Open the filestream for this custom command
+ std::string fname =
+ this->LocalGenerator->GetCurrentBinaryDirectory();
+ fname += "/" +
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ fname += "/" + this->Name + "_cc";
+ fname += std::to_string(cmdcount++) + "_";
+ fname += (sf->GetLocation()).GetName();
+ fname += this->CmdWindowsShell ? ".bat" : ".sh";
+ cmGeneratedFileStream f(fname.c_str());
+ f.SetCopyIfDifferent(true);
+ this->WriteCustomCommandsHelper(f, ccg);
+ f.Close();
+ this->WriteCustomCommandLine(*fout, fname, ccg);
+ }
}
}
}
@@ -606,6 +657,33 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
}
}
+void cmGhsMultiTargetGenerator::WriteCustomCommandLine(
+ std::ostream& fout, std::string& fname, cmCustomCommandGenerator const& ccg)
+{
+ /* NOTE: Customization Files are not well documented. Testing showed
+ * that ":outputName=file" can only be used once per script. The
+ * script will only run if ":outputName=file" is missing or just run
+ * once if ":outputName=file" is not specified. If there are
+ * multiple outputs then the script needs to be listed multiple times
+ * for each output. Otherwise it won't rerun the script if one of
+ * the outputs is manually deleted.
+ */
+ bool specifyExtra = true;
+ for (auto& out : ccg.GetOutputs()) {
+ fout << fname << std::endl;
+ fout << " :outputName=\"" << out << "\"" << std::endl;
+ if (specifyExtra) {
+ for (auto& byp : ccg.GetByproducts()) {
+ fout << " :extraOutputFile=\"" << byp << "\"" << std::endl;
+ }
+ for (auto& dep : ccg.GetDepends()) {
+ fout << " :depends=\"" << dep << "\"" << std::endl;
+ }
+ specifyExtra = false;
+ }
+ }
+}
+
void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
std::ostream& fout, const cmSourceFile* sourceFile)
{
@@ -643,7 +721,7 @@ void cmGhsMultiTargetGenerator::WriteReferences(std::ostream& fout)
fout << " ";
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fout);
- // Tell the global generator that a refernce project needs to be created
+ // Tell the global generator that a reference project needs to be created
t->Target->SetProperty("GHS_REFERENCE_PROJECT", "ON");
}
}
@@ -664,3 +742,51 @@ bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()
}
return false;
}
+
+bool cmGhsMultiTargetGenerator::ComputeCustomCommandOrder(
+ std::vector<cmSourceFile const*>& order)
+{
+ std::set<cmSourceFile const*> temp;
+ std::set<cmSourceFile const*> perm;
+
+ // Collect all custom commands for this target
+ std::vector<cmSourceFile const*> customCommands;
+ this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
+
+ for (cmSourceFile const* si : customCommands) {
+ bool r = VisitCustomCommand(temp, perm, order, si);
+ if (r) {
+ return r;
+ }
+ }
+ return false;
+}
+
+bool cmGhsMultiTargetGenerator::VisitCustomCommand(
+ std::set<cmSourceFile const*>& temp, std::set<cmSourceFile const*>& perm,
+ std::vector<cmSourceFile const*>& order, cmSourceFile const* si)
+{
+ /* check if permanent mark is set*/
+ if (perm.find(si) == perm.end()) {
+ /* set temporary mark; check if revisit*/
+ if (temp.insert(si).second) {
+ for (auto& di : si->GetCustomCommand()->GetDepends()) {
+ cmSourceFile const* sf = this->GeneratorTarget->GetLocalGenerator()
+ ->GetMakefile()
+ ->GetSourceFileWithOutput(di);
+ /* if sf exists then visit */
+ if (sf && this->VisitCustomCommand(temp, perm, order, sf)) {
+ return true;
+ }
+ }
+ /* mark as complete; insert into beginning of list*/
+ perm.insert(si);
+ order.push_back(si);
+ return false;
+ }
+ /* revisiting item - not a DAG */
+ return true;
+ }
+ /* already complete */
+ return false;
+}
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
index fa251b01fc..3ba3884719 100644
--- a/Source/cmGhsMultiTargetGenerator.h
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -7,6 +7,7 @@
#include <iosfwd>
#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -54,6 +55,13 @@ private:
std::string const& name, std::string const& cmd);
void WriteCustomCommandsHelper(std::ostream& fout,
cmCustomCommandGenerator const& ccg);
+ void WriteCustomCommandLine(std::ostream& fout, std::string& fname,
+ cmCustomCommandGenerator const& ccg);
+ bool ComputeCustomCommandOrder(std::vector<cmSourceFile const*>& order);
+ bool VisitCustomCommand(std::set<cmSourceFile const*>& temp,
+ std::set<cmSourceFile const*>& perm,
+ std::vector<cmSourceFile const*>& order,
+ cmSourceFile const* sf);
void WriteSources(std::ostream& fout_proj);
void WriteSourceProperty(std::ostream& fout, const cmSourceFile* sf,
std::string const& propName,
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 9f361f6182..a2138d17bd 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -265,6 +265,49 @@ void cmGlobalGhsMultiGenerator::WriteFileHeader(std::ostream& fout)
<< std::endl;
}
+void cmGlobalGhsMultiGenerator::WriteCustomRuleBOD(std::ostream& fout)
+{
+ fout << "Commands {\n"
+ " Custom_Rule_Command {\n"
+ " name = \"Custom Rule Command\"\n"
+ " exec = \"";
+#ifdef _WIN32
+ fout << "cmd.exe";
+#else
+ fout << "/bin/sh";
+#endif
+ fout << "\"\n"
+ " options = {\"SpecialOptions\"}\n"
+ " }\n"
+ "}\n";
+
+ fout << "\n\n";
+ fout << "FileTypes {\n"
+ " CmakeRule {\n"
+ " name = \"Custom Rule\"\n"
+ " action = \"&Run\"\n"
+ " extensions = {\"";
+#ifdef _WIN32
+ fout << "bat";
+#else
+ fout << "sh";
+#endif
+ fout << "\"}\n"
+ " grepable = false\n"
+ " command = \"Custom Rule Command\"\n"
+ " commandLine = \"$COMMAND ";
+#ifdef _WIN32
+ fout << "/c";
+#endif
+ fout << " $INPUTFILE\"\n"
+ " progress = \"Processing Custom Rule\"\n"
+ " promoteToFirstPass = true\n"
+ " outputType = \"None\"\n"
+ " color = \"#800080\"\n"
+ " }\n"
+ "}\n";
+}
+
void cmGlobalGhsMultiGenerator::WriteTopLevelProject(
std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators)
@@ -272,7 +315,7 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(
WriteFileHeader(fout);
this->WriteMacros(fout);
- this->WriteHighLevelDirectives(fout);
+ this->WriteHighLevelDirectives(root, fout);
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout);
fout << "# Top Level Project File" << std::endl;
@@ -363,6 +406,8 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(
void cmGlobalGhsMultiGenerator::Generate()
{
+ std::string fname;
+
// first do the superclass method
this->cmGlobalGenerator::Generate();
@@ -370,6 +415,15 @@ void cmGlobalGhsMultiGenerator::Generate()
for (auto& it : this->ProjectMap) {
this->OutputTopLevelProject(it.second[0], it.second);
}
+
+ // create custom rule BOD file
+ fname = this->GetCMakeInstance()->GetHomeOutputDirectory() +
+ "/CMakeFiles/custom_rule.bod";
+ cmGeneratedFileStream frule(fname);
+ frule.SetCopyIfDifferent(true);
+ this->WriteFileHeader(frule);
+ this->WriteCustomRuleBOD(frule);
+ frule.Close();
}
void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
@@ -465,7 +519,8 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout)
}
}
-void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout)
+void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
+ cmLocalGenerator* root, std::ostream& fout)
{
/* set primary target */
std::string tgt;
@@ -486,6 +541,8 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout)
}
fout << "primaryTarget=" << tgt << std::endl;
+ fout << "customization=" << root->GetBinaryDirectory()
+ << "/CMakeFiles/custom_rule.bod" << std::endl;
char const* const customization =
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index 1aeb1dc8a1..1dd951ad7e 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -114,9 +114,10 @@ private:
void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
void WriteMacros(std::ostream& fout);
- void WriteHighLevelDirectives(std::ostream& fout);
+ void WriteHighLevelDirectives(cmLocalGenerator* root, std::ostream& fout);
void WriteSubProjects(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
+ void WriteCustomRuleBOD(std::ostream& fout);
std::string trimQuotes(std::string const& str);