mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-02 12:19:54 -05:00
Merge topic 'ghs_custom'
2bae6a1346GHS: Update tests and notes3b415c60c1GHS: Update ExternalProject for GHS tools83c47ef5b8GHS: Update project layout to accommodate gbuild inconsistencies5d2e1404bdGHS: Update project layout to build targets correctlyb6bfa7eeb2GHS: Support add_dependencies() command39ee9718d9GHS: Support add_custom_target() command8d3dad9a76GHS: Support add_custom_command( OUTPUT ) signature37acc9e229GHS: Update custom command build events Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Narendhar Manimohan <narendhar15@gmail.com> Merge-request: !3119
This commit is contained in:
@@ -9,7 +9,8 @@ static const char* GHS_TAG[] = { "[INTEGRITY Application]",
|
||||
"[Project]",
|
||||
"[Program]",
|
||||
"[Reference]",
|
||||
"[Subproject]" };
|
||||
"[Subproject]",
|
||||
"[Custom Target]" };
|
||||
|
||||
const char* GhsMultiGpj::GetGpjTag(Types gpjType)
|
||||
{
|
||||
@@ -21,6 +22,7 @@ const char* GhsMultiGpj::GetGpjTag(Types gpjType)
|
||||
case PROGRAM:
|
||||
case REFERENCE:
|
||||
case SUBPROJECT:
|
||||
case CUSTOM_TARGET:
|
||||
tag = GHS_TAG[gpjType];
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -16,7 +16,8 @@ public:
|
||||
PROJECT,
|
||||
PROGRAM,
|
||||
REFERENCE,
|
||||
SUBPROJECT
|
||||
SUBPROJECT,
|
||||
CUSTOM_TARGET
|
||||
};
|
||||
|
||||
static void WriteGpjTag(Types gpjType, std::ostream& fout);
|
||||
|
||||
@@ -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,17 +11,17 @@
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmLocalGhsMultiGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmSourceFileLocation.h"
|
||||
#include "cmSourceGroup.h"
|
||||
#include "cmStateDirectory.h"
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#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")) {
|
||||
@@ -85,10 +90,19 @@ void cmGhsMultiTargetGenerator::Generate()
|
||||
return;
|
||||
}
|
||||
case cmStateEnums::UTILITY: {
|
||||
std::string msg = "add_custom_target(<name> ...) not supported: ";
|
||||
msg += this->Name;
|
||||
cmSystemTools::Message(msg);
|
||||
return;
|
||||
this->TargetNameReal = this->GeneratorTarget->GetName();
|
||||
this->TagType = GhsMultiGpj::CUSTOM_TARGET;
|
||||
break;
|
||||
}
|
||||
case cmStateEnums::GLOBAL_TARGET: {
|
||||
this->TargetNameReal = this->GeneratorTarget->GetName();
|
||||
if (this->TargetNameReal ==
|
||||
this->GetGlobalGenerator()->GetInstallTargetName()) {
|
||||
this->TagType = GhsMultiGpj::CUSTOM_TARGET;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
@@ -105,29 +119,29 @@ void cmGhsMultiTargetGenerator::Generate()
|
||||
|
||||
void cmGhsMultiTargetGenerator::GenerateTarget()
|
||||
{
|
||||
// Open the filestream in copy-if-different mode.
|
||||
std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory();
|
||||
fname += "/";
|
||||
fname += this->Name;
|
||||
fname += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
|
||||
cmGeneratedFileStream fout(fname);
|
||||
// Open the target file in copy-if-different mode.
|
||||
std::string fproj = this->LocalGenerator->GetCurrentBinaryDirectory();
|
||||
fproj += "/";
|
||||
fproj += this->Name;
|
||||
fproj += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
|
||||
cmGeneratedFileStream fout(fproj);
|
||||
fout.SetCopyIfDifferent(true);
|
||||
|
||||
this->GetGlobalGenerator()->WriteFileHeader(fout);
|
||||
GhsMultiGpj::WriteGpjTag(this->TagType, fout);
|
||||
|
||||
const std::string language(
|
||||
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName));
|
||||
|
||||
this->WriteTargetSpecifics(fout, this->ConfigName);
|
||||
this->SetCompilerFlags(this->ConfigName, language);
|
||||
this->WriteCompilerFlags(fout, this->ConfigName, language);
|
||||
this->WriteCompilerDefinitions(fout, this->ConfigName, language);
|
||||
this->WriteIncludes(fout, this->ConfigName, language);
|
||||
this->WriteTargetLinkLine(fout, this->ConfigName);
|
||||
this->WriteCustomCommands(fout);
|
||||
if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
|
||||
const std::string language(
|
||||
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName));
|
||||
this->WriteTargetSpecifics(fout, this->ConfigName);
|
||||
this->SetCompilerFlags(this->ConfigName, language);
|
||||
this->WriteCompilerFlags(fout, this->ConfigName, language);
|
||||
this->WriteCompilerDefinitions(fout, this->ConfigName, language);
|
||||
this->WriteIncludes(fout, this->ConfigName, language);
|
||||
this->WriteTargetLinkLine(fout, this->ConfigName);
|
||||
this->WriteBuildEvents(fout);
|
||||
}
|
||||
this->WriteSources(fout);
|
||||
this->WriteReferences(fout);
|
||||
fout.Close();
|
||||
}
|
||||
|
||||
@@ -304,47 +318,145 @@ 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"));
|
||||
|
||||
if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
|
||||
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();
|
||||
if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
|
||||
fout << " :" << cmd << "=\"" << fname << "\"" << std::endl;
|
||||
} else {
|
||||
fout << fname << std::endl;
|
||||
fout << " :outputName=\"" << fname << ".rule\"" << 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(
|
||||
@@ -385,7 +497,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
|
||||
|
||||
/* list of known groups and the order they are displayed in a project file */
|
||||
const std::vector<std::string> standardGroups = {
|
||||
"Header Files", "Source Files", "CMake Rules",
|
||||
"CMake Rules", "Header Files", "Source Files",
|
||||
"Object Files", "Object Libraries", "Resources"
|
||||
};
|
||||
|
||||
@@ -403,6 +515,14 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
|
||||
groupFilesList[i] = *n;
|
||||
i += 1;
|
||||
groupNames.erase(gn);
|
||||
} else if (this->TagType == GhsMultiGpj::CUSTOM_TARGET &&
|
||||
gn == "CMake Rules") {
|
||||
/* make sure that rules folder always exists in case of custom targets
|
||||
* that have no custom commands except for pre or post build events.
|
||||
*/
|
||||
groupFilesList.resize(groupFilesList.size() + 1);
|
||||
groupFilesList[i] = gn;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +553,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,33 +592,98 @@ 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 */
|
||||
for (const cmSourceFile* si : groupFiles[sg]) {
|
||||
if (sg != "CMake Rules") {
|
||||
/* output rule for each source file */
|
||||
for (const cmSourceFile* si : groupFiles[sg]) {
|
||||
bool compile = true;
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
/* For custom targets list any associated sources,
|
||||
* comment out source code to prevent it from being
|
||||
* compiled when processing this target.
|
||||
* Otherwise, comment out any custom command (main) dependencies that
|
||||
* are listed as source files to prevent them from being considered
|
||||
* part of the build.
|
||||
*/
|
||||
std::string comment;
|
||||
if ((this->TagType == GhsMultiGpj::CUSTOM_TARGET &&
|
||||
!si->GetLanguage().empty()) ||
|
||||
si->GetCustomCommand()) {
|
||||
comment = "{comment} ";
|
||||
compile = false;
|
||||
}
|
||||
|
||||
if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
|
||||
"bsp" != si->GetExtension()) {
|
||||
WriteObjectLangOverride(*fout, si);
|
||||
*fout << comment << fname << std::endl;
|
||||
if (compile) {
|
||||
if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
|
||||
"bsp" != si->GetExtension()) {
|
||||
WriteObjectLangOverride(*fout, si);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
// 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);
|
||||
f.SetCopyIfDifferent(true);
|
||||
this->WriteCustomCommandsHelper(f, ccg);
|
||||
f.Close();
|
||||
this->WriteCustomCommandLine(*fout, fname, ccg);
|
||||
}
|
||||
}
|
||||
if (this->TagType == GhsMultiGpj::CUSTOM_TARGET) {
|
||||
this->WriteBuildEvents(*fout);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -508,6 +693,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)
|
||||
{
|
||||
@@ -521,35 +733,6 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
|
||||
}
|
||||
}
|
||||
|
||||
void cmGhsMultiTargetGenerator::WriteReferences(std::ostream& fout)
|
||||
{
|
||||
// This only applies to INTEGRITY Applications
|
||||
if (this->TagType != GhsMultiGpj::INTERGRITY_APPLICATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the targets that this one depends upon
|
||||
cmTargetDependSet unordered =
|
||||
this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget);
|
||||
cmGlobalGhsMultiGenerator::OrderedTargetDependSet ordered(unordered,
|
||||
this->Name);
|
||||
for (auto& t : ordered) {
|
||||
std::string tname = t->GetName();
|
||||
std::string tpath = t->LocalGenerator->GetCurrentBinaryDirectory();
|
||||
std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
|
||||
std::string outpath =
|
||||
this->LocalGenerator->MaybeConvertToRelativePath(rootpath, tpath) + "/" +
|
||||
tname + "REF" + cmGlobalGhsMultiGenerator::FILE_EXTENSION;
|
||||
|
||||
fout << outpath;
|
||||
fout << " ";
|
||||
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fout);
|
||||
|
||||
// Tell the global generator that a refernce project needs to be created
|
||||
t->Target->SetProperty("GHS_REFERENCE_PROJECT", "ON");
|
||||
}
|
||||
}
|
||||
|
||||
bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()
|
||||
{
|
||||
const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app");
|
||||
@@ -566,3 +749,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;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
#include "cmGhsMultiGpj.h"
|
||||
|
||||
#include "cmTarget.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmCustomCommand;
|
||||
class cmCustomCommandGenerator;
|
||||
class cmGeneratorTarget;
|
||||
class cmGlobalGhsMultiGenerator;
|
||||
class cmLocalGhsMultiGenerator;
|
||||
@@ -49,15 +49,23 @@ 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 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,
|
||||
std::string const& propFlag);
|
||||
void WriteReferences(std::ostream& fout);
|
||||
static void WriteObjectLangOverride(std::ostream& fout,
|
||||
const cmSourceFile* sourceFile);
|
||||
|
||||
@@ -71,7 +79,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
|
||||
|
||||
@@ -265,14 +265,68 @@ void cmGlobalGhsMultiGenerator::WriteFileHeader(std::ostream& fout)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::WriteTopLevelProject(
|
||||
std::ostream& fout, cmLocalGenerator* root,
|
||||
std::vector<cmLocalGenerator*>& generators)
|
||||
void cmGlobalGhsMultiGenerator::WriteCustomRuleBOD(std::ostream& fout)
|
||||
{
|
||||
WriteFileHeader(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";
|
||||
|
||||
this->WriteMacros(fout);
|
||||
this->WriteHighLevelDirectives(fout);
|
||||
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::WriteCustomTargetBOD(std::ostream& fout)
|
||||
{
|
||||
fout << "FileTypes {\n"
|
||||
" CmakeTarget {\n"
|
||||
" name = \"Custom Target\"\n"
|
||||
" action = \"&Execute\"\n"
|
||||
" grepable = false\n"
|
||||
" outputType = \"None\"\n"
|
||||
" color = \"#800080\"\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout,
|
||||
cmLocalGenerator* root)
|
||||
{
|
||||
this->WriteFileHeader(fout);
|
||||
this->WriteMacros(fout, root);
|
||||
this->WriteHighLevelDirectives(root, fout);
|
||||
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout);
|
||||
|
||||
fout << "# Top Level Project File" << std::endl;
|
||||
@@ -298,71 +352,152 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(
|
||||
}
|
||||
fout << "\"" << this->OsDir << "\"" << std::endl;
|
||||
}
|
||||
|
||||
WriteSubProjects(fout, root, generators);
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::WriteSubProjects(
|
||||
std::ostream& fout, cmLocalGenerator* root,
|
||||
std::vector<cmLocalGenerator*>& generators)
|
||||
void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout,
|
||||
std::string& all_target)
|
||||
{
|
||||
fout << "CMakeFiles/" << all_target << " [Project]" << std::endl;
|
||||
// All known targets
|
||||
for (cmGeneratorTarget const* target : this->ProjectTargets) {
|
||||
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
|
||||
target->GetType() == cmStateEnums::MODULE_LIBRARY ||
|
||||
target->GetType() == cmStateEnums::SHARED_LIBRARY ||
|
||||
(target->GetType() == cmStateEnums::GLOBAL_TARGET &&
|
||||
target->GetName() != GetInstallTargetName())) {
|
||||
continue;
|
||||
}
|
||||
fout << "CMakeFiles/" << target->GetName() + ".tgt" + FILE_EXTENSION
|
||||
<< " [Project]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::WriteProjectLine(
|
||||
std::ostream& fout, cmGeneratorTarget const* target, cmLocalGenerator* root,
|
||||
std::string& rootBinaryDir)
|
||||
{
|
||||
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->MaybeConvertToRelativePath(rootBinaryDir, dir);
|
||||
if (dir == ".") {
|
||||
dir.clear();
|
||||
} else {
|
||||
if (dir.back() != '/') {
|
||||
dir += "/";
|
||||
}
|
||||
}
|
||||
|
||||
std::string projFile = dir + projName + FILE_EXTENSION;
|
||||
fout << projFile;
|
||||
fout << " " << projType << std::endl;
|
||||
} else {
|
||||
/* Should never happen */
|
||||
std::string message =
|
||||
"The project file for target [" + target->GetName() + "] is missing.\n";
|
||||
cmSystemTools::Error(message);
|
||||
fout << "{comment} " << target->GetName() << " [missing project file]\n";
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
|
||||
{
|
||||
std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
|
||||
rootBinaryDir += "/CMakeFiles";
|
||||
|
||||
// All known targets
|
||||
for (cmGeneratorTarget const* target : this->ProjectTargets) {
|
||||
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
|
||||
target->GetType() == cmStateEnums::MODULE_LIBRARY ||
|
||||
target->GetType() == cmStateEnums::SHARED_LIBRARY ||
|
||||
(target->GetType() == cmStateEnums::GLOBAL_TARGET &&
|
||||
target->GetName() != GetInstallTargetName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// create target build file
|
||||
std::string name = target->GetName() + ".tgt" + FILE_EXTENSION;
|
||||
std::string fname = rootBinaryDir + "/" + name;
|
||||
cmGeneratedFileStream fbld(fname);
|
||||
fbld.SetCopyIfDifferent(true);
|
||||
this->WriteFileHeader(fbld);
|
||||
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld);
|
||||
std::vector<cmGeneratorTarget const*> build;
|
||||
if (ComputeTargetBuildOrder(target, build)) {
|
||||
std::string message = "The inter-target dependency graph for target [" +
|
||||
target->GetName() + "] had a cycle.\n";
|
||||
cmSystemTools::Error(message);
|
||||
} else {
|
||||
for (auto& tgt : build) {
|
||||
WriteProjectLine(fbld, tgt, root, rootBinaryDir);
|
||||
}
|
||||
}
|
||||
fbld.Close();
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::WriteAllTarget(
|
||||
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators,
|
||||
std::string& all_target)
|
||||
{
|
||||
this->ProjectTargets.clear();
|
||||
|
||||
// create target build file
|
||||
all_target = root->GetProjectName() + "." + this->GetAllTargetName() +
|
||||
".tgt" + FILE_EXTENSION;
|
||||
std::string fname =
|
||||
root->GetCurrentBinaryDirectory() + "/CMakeFiles/" + all_target;
|
||||
cmGeneratedFileStream fbld(fname);
|
||||
fbld.SetCopyIfDifferent(true);
|
||||
this->WriteFileHeader(fbld);
|
||||
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld);
|
||||
|
||||
// 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) {
|
||||
OrderedTargetDependSet sortedProjectTargets(projectTargets, "");
|
||||
std::vector<cmGeneratorTarget const*> defaultTargets;
|
||||
for (cmGeneratorTarget const* t : sortedProjectTargets) {
|
||||
/* save list of all targets in sorted order */
|
||||
this->ProjectTargets.push_back(t);
|
||||
}
|
||||
for (cmGeneratorTarget const* t : sortedProjectTargets) {
|
||||
if (t->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->MaybeConvertToRelativePath(rootBinaryDir, dir);
|
||||
if (dir == ".") {
|
||||
dir.clear();
|
||||
} else {
|
||||
if (dir.back() != '/') {
|
||||
dir += "/";
|
||||
}
|
||||
}
|
||||
|
||||
if (cmSystemTools::IsOn(target->GetProperty("EXCLUDE_FROM_ALL"))) {
|
||||
fout << "{comment} ";
|
||||
}
|
||||
std::string projFile = dir + projName + FILE_EXTENSION;
|
||||
fout << projFile;
|
||||
fout << " " << projType << std::endl;
|
||||
|
||||
if (cmSystemTools::IsOn(target->GetProperty("GHS_REFERENCE_PROJECT"))) {
|
||||
// create reference project
|
||||
std::string fname = dir;
|
||||
fname += target->GetName();
|
||||
fname += "REF";
|
||||
fname += FILE_EXTENSION;
|
||||
|
||||
cmGeneratedFileStream fref(fname);
|
||||
fref.SetCopyIfDifferent(true);
|
||||
|
||||
this->WriteFileHeader(fref);
|
||||
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fref);
|
||||
fref << " :reference=" << projFile << std::endl;
|
||||
|
||||
fref.Close();
|
||||
}
|
||||
if (!cmSystemTools::IsOn(t->GetProperty("EXCLUDE_FROM_ALL"))) {
|
||||
defaultTargets.push_back(t);
|
||||
}
|
||||
}
|
||||
std::vector<cmGeneratorTarget const*> build;
|
||||
if (ComputeTargetBuildOrder(defaultTargets, build)) {
|
||||
std::string message = "The inter-target dependency graph for project [" +
|
||||
root->GetProjectName() + "] had a cycle.\n";
|
||||
cmSystemTools::Error(message);
|
||||
} else {
|
||||
// determine the targets for ALL target
|
||||
std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
|
||||
rootBinaryDir += "/CMakeFiles";
|
||||
for (cmGeneratorTarget const* target : build) {
|
||||
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
|
||||
target->GetType() == cmStateEnums::MODULE_LIBRARY ||
|
||||
target->GetType() == cmStateEnums::SHARED_LIBRARY) {
|
||||
continue;
|
||||
}
|
||||
this->WriteProjectLine(fbld, target, root, rootBinaryDir);
|
||||
}
|
||||
}
|
||||
fbld.Close();
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::Generate()
|
||||
{
|
||||
std::string fname;
|
||||
|
||||
// first do the superclass method
|
||||
this->cmGlobalGenerator::Generate();
|
||||
|
||||
@@ -370,11 +505,32 @@ 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();
|
||||
|
||||
// create custom target BOD file
|
||||
fname = this->GetCMakeInstance()->GetHomeOutputDirectory() +
|
||||
"/CMakeFiles/custom_target.bod";
|
||||
cmGeneratedFileStream ftarget(fname);
|
||||
ftarget.SetCopyIfDifferent(true);
|
||||
this->WriteFileHeader(ftarget);
|
||||
this->WriteCustomTargetBOD(ftarget);
|
||||
ftarget.Close();
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
|
||||
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
|
||||
{
|
||||
std::string fname;
|
||||
std::string all_target;
|
||||
|
||||
if (generators.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -383,18 +539,21 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
|
||||
* with target projects. This avoid the issue where the project has
|
||||
* the same name as the executable target.
|
||||
*/
|
||||
std::string fname = root->GetCurrentBinaryDirectory();
|
||||
fname = root->GetCurrentBinaryDirectory();
|
||||
fname += "/";
|
||||
fname += root->GetProjectName();
|
||||
fname += ".top";
|
||||
fname += FILE_EXTENSION;
|
||||
|
||||
cmGeneratedFileStream fout(fname);
|
||||
fout.SetCopyIfDifferent(true);
|
||||
cmGeneratedFileStream top(fname);
|
||||
top.SetCopyIfDifferent(true);
|
||||
this->WriteTopLevelProject(top, root);
|
||||
|
||||
this->WriteTopLevelProject(fout, root, generators);
|
||||
this->WriteAllTarget(root, generators, all_target);
|
||||
this->WriteTargets(root);
|
||||
|
||||
fout.Close();
|
||||
this->WriteSubProjects(top, all_target);
|
||||
top.Close();
|
||||
}
|
||||
|
||||
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
|
||||
@@ -426,6 +585,9 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand(
|
||||
std::vector<std::string> files;
|
||||
cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files);
|
||||
if (!files.empty()) {
|
||||
/* if multiple top-projects are found in build directory
|
||||
* then prefer projectName top-project.
|
||||
*/
|
||||
auto p = std::find(files.begin(), files.end(), proj);
|
||||
if (p == files.end()) {
|
||||
proj = files.at(0);
|
||||
@@ -440,20 +602,24 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand(
|
||||
} else {
|
||||
for (const auto& tname : targetNames) {
|
||||
if (!tname.empty()) {
|
||||
if (tname.compare(tname.size() - 4, 4, ".gpj") == 0) {
|
||||
makeCommand.Add(tname);
|
||||
} else {
|
||||
makeCommand.Add(tname + ".gpj");
|
||||
}
|
||||
makeCommand.Add(tname + ".tgt.gpj");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* transform name to default build */;
|
||||
std::string all = proj;
|
||||
all.replace(all.end() - 7, all.end(),
|
||||
std::string(this->GetAllTargetName()) + ".tgt.gpj");
|
||||
makeCommand.Add(all);
|
||||
}
|
||||
return { makeCommand };
|
||||
}
|
||||
|
||||
void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout)
|
||||
void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout,
|
||||
cmLocalGenerator* root)
|
||||
{
|
||||
fout << "macro PROJ_NAME=" << root->GetProjectName() << std::endl;
|
||||
char const* ghsGpjMacros =
|
||||
this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
|
||||
if (nullptr != ghsGpjMacros) {
|
||||
@@ -465,13 +631,14 @@ 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;
|
||||
const char* t =
|
||||
this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET");
|
||||
if (t) {
|
||||
if (t && *t != '\0') {
|
||||
tgt = t;
|
||||
this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET");
|
||||
} else {
|
||||
@@ -486,16 +653,20 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout)
|
||||
}
|
||||
|
||||
fout << "primaryTarget=" << tgt << std::endl;
|
||||
fout << "customization=" << root->GetBinaryDirectory()
|
||||
<< "/CMakeFiles/custom_rule.bod" << std::endl;
|
||||
fout << "customization=" << root->GetBinaryDirectory()
|
||||
<< "/CMakeFiles/custom_target.bod" << std::endl;
|
||||
|
||||
char const* const customization =
|
||||
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
|
||||
if (nullptr != customization && strlen(customization) > 0) {
|
||||
fout << "customization=" << trimQuotes(customization) << std::endl;
|
||||
fout << "customization=" << this->TrimQuotes(customization) << std::endl;
|
||||
this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION");
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str)
|
||||
std::string cmGlobalGhsMultiGenerator::TrimQuotes(std::string const& str)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(str.size());
|
||||
@@ -528,3 +699,56 @@ cmGlobalGhsMultiGenerator::OrderedTargetDependSet::OrderedTargetDependSet(
|
||||
{
|
||||
this->insert(targets.begin(), targets.end());
|
||||
}
|
||||
|
||||
bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
|
||||
cmGeneratorTarget const* tgt, std::vector<cmGeneratorTarget const*>& build)
|
||||
{
|
||||
std::vector<cmGeneratorTarget const*> t{ tgt };
|
||||
return ComputeTargetBuildOrder(t, build);
|
||||
}
|
||||
|
||||
bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
|
||||
std::vector<cmGeneratorTarget const*>& tgt,
|
||||
std::vector<cmGeneratorTarget const*>& build)
|
||||
{
|
||||
std::set<cmGeneratorTarget const*> temp;
|
||||
std::set<cmGeneratorTarget const*> perm;
|
||||
|
||||
for (auto ti : tgt) {
|
||||
bool r = VisitTarget(temp, perm, build, ti);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmGlobalGhsMultiGenerator::VisitTarget(
|
||||
std::set<cmGeneratorTarget const*>& temp,
|
||||
std::set<cmGeneratorTarget const*>& perm,
|
||||
std::vector<cmGeneratorTarget const*>& order, cmGeneratorTarget const* ti)
|
||||
{
|
||||
/* check if permanent mark is set*/
|
||||
if (perm.find(ti) == perm.end()) {
|
||||
/* set temporary mark; check if revisit*/
|
||||
if (temp.insert(ti).second) {
|
||||
/* sort targets lexicographically to ensure that nodes are always visited
|
||||
* in the same order */
|
||||
OrderedTargetDependSet sortedTargets(this->GetTargetDirectDepends(ti),
|
||||
"");
|
||||
for (auto& di : sortedTargets) {
|
||||
if (this->VisitTarget(temp, perm, order, di)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* mark as complete; insert into beginning of list*/
|
||||
perm.insert(ti);
|
||||
order.push_back(ti);
|
||||
return false;
|
||||
}
|
||||
/* revisiting item - not a DAG */
|
||||
return true;
|
||||
}
|
||||
/* already complete */
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -78,23 +78,7 @@ public:
|
||||
// Write the common disclaimer text at the top of each build file.
|
||||
void WriteFileHeader(std::ostream& fout);
|
||||
|
||||
// Target dependency sorting
|
||||
class TargetSet : public std::set<cmGeneratorTarget const*>
|
||||
{
|
||||
};
|
||||
class TargetCompare
|
||||
{
|
||||
std::string First;
|
||||
|
||||
public:
|
||||
TargetCompare(std::string first)
|
||||
: First(std::move(first))
|
||||
{
|
||||
}
|
||||
bool operator()(cmGeneratorTarget const* l,
|
||||
cmGeneratorTarget const* r) const;
|
||||
};
|
||||
class OrderedTargetDependSet;
|
||||
const char* GetInstallTargetName() const override { return "install"; }
|
||||
|
||||
protected:
|
||||
void Generate() override;
|
||||
@@ -111,18 +95,53 @@ private:
|
||||
/* 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);
|
||||
void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root);
|
||||
void WriteMacros(std::ostream& fout, cmLocalGenerator* root);
|
||||
void WriteHighLevelDirectives(cmLocalGenerator* root, std::ostream& fout);
|
||||
void WriteSubProjects(std::ostream& fout, std::string& all_target);
|
||||
void WriteTargets(cmLocalGenerator* root);
|
||||
void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target,
|
||||
cmLocalGenerator* root, std::string& rootBinaryDir);
|
||||
void WriteCustomRuleBOD(std::ostream& fout);
|
||||
void WriteCustomTargetBOD(std::ostream& fout);
|
||||
void WriteAllTarget(cmLocalGenerator* root,
|
||||
std::vector<cmLocalGenerator*>& generators,
|
||||
std::string& all_target);
|
||||
|
||||
std::string trimQuotes(std::string const& str);
|
||||
std::string TrimQuotes(std::string const& str);
|
||||
|
||||
std::string OsDir;
|
||||
static const char* DEFAULT_BUILD_PROGRAM;
|
||||
static const char* DEFAULT_TOOLSET_ROOT;
|
||||
|
||||
bool ComputeTargetBuildOrder(cmGeneratorTarget const* tgt,
|
||||
std::vector<cmGeneratorTarget const*>& build);
|
||||
bool ComputeTargetBuildOrder(std::vector<cmGeneratorTarget const*>& tgt,
|
||||
std::vector<cmGeneratorTarget const*>& build);
|
||||
bool VisitTarget(std::set<cmGeneratorTarget const*>& temp,
|
||||
std::set<cmGeneratorTarget const*>& perm,
|
||||
std::vector<cmGeneratorTarget const*>& order,
|
||||
cmGeneratorTarget const* ti);
|
||||
|
||||
std::vector<cmGeneratorTarget const*> ProjectTargets;
|
||||
|
||||
// Target sorting
|
||||
class TargetSet : public std::set<cmGeneratorTarget const*>
|
||||
{
|
||||
};
|
||||
class TargetCompare
|
||||
{
|
||||
std::string First;
|
||||
|
||||
public:
|
||||
TargetCompare(std::string first)
|
||||
: First(std::move(first))
|
||||
{
|
||||
}
|
||||
bool operator()(cmGeneratorTarget const* l,
|
||||
cmGeneratorTarget const* r) const;
|
||||
};
|
||||
class OrderedTargetDependSet;
|
||||
};
|
||||
|
||||
class cmGlobalGhsMultiGenerator::OrderedTargetDependSet
|
||||
|
||||
Reference in New Issue
Block a user