summaryrefslogtreecommitdiffstats
path: root/Source/cmGhsMultiTargetGenerator.cxx
diff options
context:
space:
mode:
authorFred Baksik <frodak17@gmail.com>2019-04-08 13:55:34 (GMT)
committerFred Baksik <frodak17@gmail.com>2019-04-11 17:15:50 (GMT)
commit8d3dad9a76591ae0426335d039b8aaacb95862cd (patch)
tree712f4ab345d62c7858b879c86838f508036ede8f /Source/cmGhsMultiTargetGenerator.cxx
parent37acc9e2299713b9b23c767e72b0e0169697e510 (diff)
downloadCMake-8d3dad9a76591ae0426335d039b8aaacb95862cd.zip
CMake-8d3dad9a76591ae0426335d039b8aaacb95862cd.tar.gz
CMake-8d3dad9a76591ae0426335d039b8aaacb95862cd.tar.bz2
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/cmGhsMultiTargetGenerator.cxx')
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx174
1 files changed, 150 insertions, 24 deletions
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 9f9ef18..9d0d195 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;
+}