diff options
author | Fred Baksik <frodak17@gmail.com> | 2019-04-08 13:55:34 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2019-04-10 15:54:56 (GMT) |
commit | 37acc9e2299713b9b23c767e72b0e0169697e510 (patch) | |
tree | 032aa59f3aa79911f455ed96fe4c5d7908ed98e8 | |
parent | 7e60e77c3c2a09eb11750616db50d2dc149a9c54 (diff) | |
download | CMake-37acc9e2299713b9b23c767e72b0e0169697e510.zip CMake-37acc9e2299713b9b23c767e72b0e0169697e510.tar.gz CMake-37acc9e2299713b9b23c767e72b0e0169697e510.tar.bz2 |
GHS: Update custom command build events
-- Fixes issue where commands run out of order; Run commands as single script
Do not allow build events to run in parallel
-- Use command generator to parse the commands
-- Support pre-link build events
-- Support more options: COMMENT, BYPRODUCTS, WORKING_DIRECTORY
-rw-r--r-- | Source/cmGhsMultiTargetGenerator.cxx | 166 | ||||
-rw-r--r-- | Source/cmGhsMultiTargetGenerator.h | 16 |
2 files changed, 141 insertions, 41 deletions
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 668bcbd..9f9ef18 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -3,7 +3,7 @@ #include "cmGhsMultiTargetGenerator.h" #include "cmCustomCommand.h" -#include "cmCustomCommandLines.h" +#include "cmCustomCommandGenerator.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGhsMultiGenerator.h" @@ -11,6 +11,7 @@ #include "cmLocalGenerator.h" #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" +#include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmStateDirectory.h" @@ -21,7 +22,6 @@ #include "cmTargetDepend.h" #include <algorithm> -#include <assert.h> #include <ostream> #include <set> #include <utility> @@ -32,6 +32,11 @@ cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator())) , Makefile(target->Target->GetMakefile()) , Name(target->GetName()) +#ifdef _WIN32 + , CmdWindowsShell(true) +#else + , CmdWindowsShell(false) +#endif { // Store the configuration name that is being used if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { @@ -125,7 +130,7 @@ void cmGhsMultiTargetGenerator::GenerateTarget() this->WriteCompilerDefinitions(fout, this->ConfigName, language); this->WriteIncludes(fout, this->ConfigName, language); this->WriteTargetLinkLine(fout, this->ConfigName); - this->WriteCustomCommands(fout); + this->WriteBuildEvents(fout); this->WriteSources(fout); this->WriteReferences(fout); fout.Close(); @@ -304,47 +309,138 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, } } -void cmGhsMultiTargetGenerator::WriteCustomCommands(std::ostream& fout) +void cmGhsMultiTargetGenerator::WriteBuildEvents(std::ostream& fout) { - WriteCustomCommandsHelper(fout, this->GeneratorTarget->GetPreBuildCommands(), - cmTarget::PRE_BUILD); - WriteCustomCommandsHelper( - fout, this->GeneratorTarget->GetPostBuildCommands(), cmTarget::POST_BUILD); + this->WriteBuildEventsHelper( + fout, this->GeneratorTarget->GetPreBuildCommands(), + std::string("prebuild"), std::string("preexecShell")); + + this->WriteBuildEventsHelper( + fout, this->GeneratorTarget->GetPreLinkCommands(), std::string("prelink"), + std::string("preexecShell")); + + this->WriteBuildEventsHelper( + fout, this->GeneratorTarget->GetPostBuildCommands(), + std::string("postbuild"), std::string("postexecShell")); +} + +void cmGhsMultiTargetGenerator::WriteBuildEventsHelper( + std::ostream& fout, const std::vector<cmCustomCommand>& ccv, + std::string const& name, std::string const& cmd) +{ + int cmdcount = 0; + + for (cmCustomCommand const& cc : ccv) { + 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 + "_" + name; + fname += std::to_string(cmdcount++); + fname += this->CmdWindowsShell ? ".bat" : ".sh"; + cmGeneratedFileStream f(fname); + f.SetCopyIfDifferent(true); + this->WriteCustomCommandsHelper(f, ccg); + f.Close(); + fout << " :" << cmd << "=\"" << fname << "\"" << std::endl; + for (auto& byp : ccg.GetByproducts()) { + fout << " :extraOutputFile=\"" << byp << "\"" << std::endl; + } + } } void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( - std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet, - cmTarget::CustomCommandType const commandType) + std::ostream& fout, cmCustomCommandGenerator const& ccg) { - for (cmCustomCommand const& customCommand : commandsSet) { - cmCustomCommandLines const& commandLines = customCommand.GetCommandLines(); - for (cmCustomCommandLine const& command : commandLines) { - switch (commandType) { - case cmTarget::PRE_BUILD: - fout << " :preexecShellSafe="; - break; - case cmTarget::POST_BUILD: - fout << " :postexecShellSafe="; - break; - default: - assert("Only pre and post are supported"); + std::vector<std::string> cmdLines; + + // if the command specified a working directory use it. + std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory(); + std::string currentBinDir = dir; + std::string workingDir = ccg.GetWorkingDirectory(); + if (!workingDir.empty()) { + dir = workingDir; + } + + // Line to check for error between commands. +#ifdef _WIN32 + std::string check_error = "if %errorlevel% neq 0 exit /b %errorlevel%"; +#else + std::string check_error = "if [[ $? -ne 0 ]]; then exit 1; fi"; +#endif + +#ifdef _WIN32 + cmdLines.push_back("@echo off"); +#endif + // Echo the custom command's comment text. + const char* comment = ccg.GetComment(); + if (comment && *comment) { + std::string echocmd = "echo "; + echocmd += comment; + cmdLines.push_back(std::move(echocmd)); + } + + // Switch to working directory + std::string cdCmd; +#ifdef _WIN32 + std::string cdStr = "cd /D "; +#else + std::string cdStr = "cd "; +#endif + cdCmd = cdStr + + this->LocalGenerator->ConvertToOutputFormat(dir, cmOutputConverter::SHELL); + cmdLines.push_back(std::move(cdCmd)); + + for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) { + // Build the command line in a single string. + std::string cmd = ccg.GetCommand(c); + if (!cmd.empty()) { + // Use "call " before any invocations of .bat or .cmd files + // invoked as custom commands in the WindowsShell. + // + bool useCall = false; + + if (this->CmdWindowsShell) { + std::string suffix; + if (cmd.size() > 4) { + suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4)); + if (suffix == ".bat" || suffix == ".cmd") { + useCall = true; + } + } } - bool firstIteration = true; - for (std::string const& commandLine : command) { - std::string subCommandE = - this->LocalGenerator->EscapeForShell(commandLine, true); - fout << (firstIteration ? "'" : " "); - // Need to double escape backslashes - cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\"); - fout << subCommandE; - firstIteration = false; + cmSystemTools::ReplaceString(cmd, "/./", "/"); + // Convert the command to a relative path only if the current + // working directory will be the start-output directory. + bool had_slash = cmd.find('/') != std::string::npos; + if (workingDir.empty()) { + cmd = + this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, cmd); } - if (!command.empty()) { - fout << "'" << std::endl; + bool has_slash = cmd.find('/') != std::string::npos; + if (had_slash && !has_slash) { + // This command was specified as a path to a file in the + // current directory. Add a leading "./" so it can run + // without the current directory being in the search path. + cmd = "./" + cmd; } + cmd = this->LocalGenerator->ConvertToOutputFormat( + cmd, cmOutputConverter::SHELL); + if (useCall) { + cmd = "call " + cmd; + } + ccg.AppendArguments(c, cmd); + cmdLines.push_back(std::move(cmd)); } } + + // push back the custom commands + for (auto const& c : cmdLines) { + fout << c << std::endl; + fout << check_error << std::endl; + } } void cmGhsMultiTargetGenerator::WriteSourceProperty( @@ -433,7 +529,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) /* write files into the proper project file * -- groups go into main project file - * unless FOLDER property or variable is set. + * unless NO_SOURCE_GROUP_FILE property or variable is set. */ for (auto& sg : groupFilesList) { std::ostream* fout; @@ -472,6 +568,8 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) } else { *fout << "{comment} " << sg << std::endl; } + } else if (sg.empty()) { + *fout << "{comment} Others" << std::endl; } /* output rule for each source file */ diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h index a4e23d9..fa251b0 100644 --- a/Source/cmGhsMultiTargetGenerator.h +++ b/Source/cmGhsMultiTargetGenerator.h @@ -5,14 +5,13 @@ #include "cmGhsMultiGpj.h" -#include "cmTarget.h" - #include <iosfwd> #include <map> #include <string> #include <vector> class cmCustomCommand; +class cmCustomCommandGenerator; class cmGeneratorTarget; class cmGlobalGhsMultiGenerator; class cmLocalGhsMultiGenerator; @@ -49,10 +48,12 @@ private: void WriteIncludes(std::ostream& fout, const std::string& config, const std::string& language); void WriteTargetLinkLine(std::ostream& fout, std::string const& config); - void WriteCustomCommands(std::ostream& fout); - void WriteCustomCommandsHelper( - std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet, - cmTarget::CustomCommandType commandType); + void WriteBuildEvents(std::ostream& fout); + void WriteBuildEventsHelper(std::ostream& fout, + const std::vector<cmCustomCommand>& ccv, + std::string const& name, std::string const& cmd); + void WriteCustomCommandsHelper(std::ostream& fout, + cmCustomCommandGenerator const& ccg); void WriteSources(std::ostream& fout_proj); void WriteSourceProperty(std::ostream& fout, const cmSourceFile* sf, std::string const& propName, @@ -71,7 +72,8 @@ private: std::string TargetNameReal; GhsMultiGpj::Types TagType; std::string const Name; - std::string ConfigName; /* CMAKE_BUILD_TYPE */ + std::string ConfigName; /* CMAKE_BUILD_TYPE */ + bool const CmdWindowsShell; /* custom commands run in cmd.exe or /bin/sh */ }; #endif // ! cmGhsMultiTargetGenerator_h |