Skip to content

Commit

Permalink
link commands added
Browse files Browse the repository at this point in the history
  • Loading branch information
Glebuska committed Apr 15, 2021
1 parent 27b5dc3 commit 1a8f576
Show file tree
Hide file tree
Showing 20 changed files with 292 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Source/cmGlobalGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3252,6 +3252,9 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s)
result += i;
}
}
if (result.back() == ' ') {
return result.substr(0, result.size() - 1);
}
return result;
}

Expand Down
1 change: 1 addition & 0 deletions Source/cmGlobalGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ class cmGlobalGenerator
virtual bool SupportsDefaultConfigs() const { return false; }

static std::string EscapeJSON(const std::string& s);
static std::string EscapeJSONArray(const std::string& s);

void ProcessEvaluationFiles();

Expand Down
29 changes: 28 additions & 1 deletion Source/cmGlobalUnixMakefileGenerator3.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <cm/memory>
#include <cmext/algorithm>
#include <cmext/memory>

#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
Expand Down Expand Up @@ -170,6 +169,34 @@ void cmGlobalUnixMakefileGenerator3::Generate()
*this->CommandDatabase << "\n]";
this->CommandDatabase.reset();
}

if (this->LinkCommandDatabase) {
*this->LinkCommandDatabase << linkJsonCommands;
this->LinkCommandDatabase.reset();
}
}

void cmGlobalUnixMakefileGenerator3::AddLinkCommand(
const std::vector<std::string>& sourceFiles,
const std::string& workingDirectory, const std::string& linkCommand)
{
if (!this->LinkCommandDatabase) {
std::string commandDatabaseName =
this->GetCMakeInstance()->GetHomeOutputDirectory() +
"/link_commands.json";
this->LinkCommandDatabase =
cm::make_unique<cmGeneratedFileStream>(commandDatabaseName);
}
Json::Value linkJsonCommand;
linkJsonCommand["directory"] = cmGlobalGenerator::EscapeJSON(workingDirectory);
linkJsonCommand["command"] = cmGlobalGenerator::EscapeJSON(linkCommand);

Json::Value files(Json::arrayValue);
for(const auto & sourceFile : sourceFiles){
files.append(Json::Value(sourceFile));
}
linkJsonCommand["files"] = files;
linkJsonCommands.append(linkJsonCommand);
}

void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
Expand Down
7 changes: 7 additions & 0 deletions Source/cmGlobalUnixMakefileGenerator3.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <string>
#include <vector>

#include "../Utilities/cmjsoncpp/include/json/json.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGeneratorFactory.h"
Expand Down Expand Up @@ -174,6 +175,10 @@ class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator
const std::string& workingDirectory,
const std::string& compileCommand);

void AddLinkCommand(const std::vector<std::string>& sourceFiles,
const std::string& workingDirectory,
const std::string& linkCommand);

/** Does the make tool tolerate .NOTPARALLEL? */
virtual bool AllowNotParallel() const { return true; }

Expand Down Expand Up @@ -275,6 +280,8 @@ class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator
size_t CountProgressMarksInAll(const cmLocalGenerator& lg);

std::unique_ptr<cmGeneratedFileStream> CommandDatabase;
std::unique_ptr<cmGeneratedFileStream> LinkCommandDatabase;
Json::Value linkJsonCommands;

private:
const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; }
Expand Down
20 changes: 20 additions & 0 deletions Source/cmMakefileExecutableTargetGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,13 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(

// Build list of dependencies.
std::vector<std::string> depends;

// Build list of dependencies without .make files, which will be use to get
// json's links command
std::vector<std::string> dependsForJson;

this->AppendLinkDepends(depends, linkLanguage);
this->AppendLinkDependsForJson(dependsForJson, linkLanguage);

// Build a list of compiler flags and linker flags.
std::string langFlags;
Expand Down Expand Up @@ -254,6 +260,9 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
this->LocalGenerator->SetLinkScriptShell(false);
}

this->CreateLinkCommandFile(real_link_commands, dependsForJson,
std::set<int>());

// Optionally convert the build rule to use a script to avoid long
// command lines in the make shell.
if (useLinkScript) {
Expand Down Expand Up @@ -357,9 +366,15 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)

// Build list of dependencies.
std::vector<std::string> depends;
// Build other list of dependencies, which will use to get json's links
// command
std::vector<std::string> dependsForJson;

this->AppendLinkDepends(depends, linkLanguage);
this->AppendLinkDependsForJson(dependsForJson, linkLanguage);
if (!this->DeviceLinkObject.empty()) {
depends.push_back(this->DeviceLinkObject);
dependsForJson.push_back(this->DeviceLinkObject);
}

this->NumberOfProgressActions++;
Expand Down Expand Up @@ -616,6 +631,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->LocalGenerator->SetLinkScriptShell(false);
}

this->CreateLinkCommandFile(real_link_commands, dependsForJson,
std::set<int>());

// Optionally convert the build rule to use a script to avoid long
// command lines in the make shell.
if (useLinkScript) {
Expand Down Expand Up @@ -662,8 +680,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// symlink.
if (targetFullPath != targetFullPathReal) {
depends.clear();
dependsForJson.clear();
commands.clear();
depends.push_back(targetFullPathReal);
dependsForJson.push_back(targetFullPathReal);
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
targetFullPath, depends, commands,
false);
Expand Down
19 changes: 18 additions & 1 deletion Source/cmMakefileLibraryTargetGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
std::vector<std::string> depends;
this->AppendLinkDepends(depends, linkLanguage);

std::vector<std::string> dependsForJson;
this->AppendLinkDependsForJson(dependsForJson, linkLanguage);

// Add language-specific flags.
std::string langFlags;
this->LocalGenerator->AddLanguageFlagsForLinking(
Expand Down Expand Up @@ -395,6 +398,10 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
}

std::vector<std::string> commands1;

this->CreateLinkCommandFile(real_link_commands, dependsForJson,
std::set<int>());

// Optionally convert the build rule to use a script to avoid long
// command lines in the make shell.
if (useLinkScript) {
Expand Down Expand Up @@ -444,8 +451,13 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Build list of dependencies.
std::vector<std::string> depends;
this->AppendLinkDepends(depends, linkLanguage);

std::vector<std::string> dependsForJson;
this->AppendLinkDependsForJson(dependsForJson, linkLanguage);

if (!this->DeviceLinkObject.empty()) {
depends.push_back(this->DeviceLinkObject);
dependsForJson.push_back(this->DeviceLinkObject);
}

// Create set of linking flags.
Expand Down Expand Up @@ -689,6 +701,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
}

// To skip unused in ranlib commands when creating json
std::set<int> ranlibIndex;
// Expand the rule variables.
std::vector<std::string> real_link_commands;
{
Expand All @@ -701,7 +715,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Collect up flags to link in needed libraries.
std::string linkLibs;
if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {

std::unique_ptr<cmLinkLineComputer> linkLineComputer =
this->CreateLinkLineComputer(
this->LocalGenerator,
Expand Down Expand Up @@ -875,6 +888,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// If there is no ranlib the command will be ":". Skip it.
if (!cmd.empty() && cmd[0] != ':') {
real_link_commands.push_back(std::move(cmd));
ranlibIndex.insert(real_link_commands.size() - 1);
}
}
} else {
Expand Down Expand Up @@ -902,6 +916,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
this->LocalGenerator->SetLinkScriptShell(false);
}

this->CreateLinkScriptJSON(real_link_commands, dependsForJson,
ranlibIndex);

// Optionally convert the build rule to use a script to avoid long
// command lines in the make shell.
if (useLinkScript) {
Expand Down
68 changes: 67 additions & 1 deletion Source/cmMakefileTargetGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ void cmMakefileTargetGenerator::CreateRuleFile()
this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
}

void cmMakefileTargetGenerator::CreateLinkCommandFile(std::vector<std::string> const& link_commands,
const std::vector<std::string>& makefile_depends,
const std::set<int>& ranlibIndexes)
{
if (this->Makefile->IsOn("CMAKE_EXPORT_LINK_COMMANDS")) {
cmMakefileTargetGenerator::CreateLinkScriptJSON(link_commands, makefile_depends, ranlibIndexes);
}

}

void cmMakefileTargetGenerator::WriteTargetBuildRules()
{
// -- Write the custom commands for this target
Expand Down Expand Up @@ -1914,11 +1924,47 @@ void cmMakefileTargetGenerator::AppendObjectDepends(
this->BuildFileNameFull.c_str());
}

void cmMakefileTargetGenerator::AppendLinkDependsForJson(
std::vector<std::string>& depends, const std::string& linkLanguage)
{

// Add dependencies on the compiled object files.
std::string const& buildDirFullPath = this->LocalGenerator->ConvertToFullPath("");
for (std::string const& obj : this->Objects) {
std::string objTarget = cmStrCat(buildDirFullPath, obj);
depends.emplace_back(std::move(objTarget));
}

// Add dependencies on the external object files.
cm::append(depends, this->ExternalObjects);

// Add dependencies on targets that must be built first.
this->AppendTargetDepends(depends);

// Add a dependency on the link definitions file, if any.
if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(
this->GetConfigName())) {
for (cmSourceFile const* src : mdi->Sources) {
depends.emplace_back(src->GetFullPath());
}
}
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->GetConfigName());
for (cmSourceFile const* manifest_src : manifest_srcs) {
depends.emplace_back(manifest_src->GetFullPath());
}

// Add user-specified dependencies.
this->GeneratorTarget->GetLinkDepends(depends, this->GetConfigName(),
linkLanguage);
}

void cmMakefileTargetGenerator::AppendLinkDepends(
std::vector<std::string>& depends, const std::string& linkLanguage)
{
this->AppendObjectDepends(depends);

// Add dependencies on targets that must be built first.
this->AppendTargetDepends(depends);

Expand Down Expand Up @@ -1966,6 +2012,25 @@ void cmMakefileTargetGenerator::CloseFileStreams()
this->FlagFileStream.reset();
}

void cmMakefileTargetGenerator::CreateLinkScriptJSON(
std::vector<std::string> const& link_commands,
const std::vector<std::string>& makefile_depends,
const std::set<int>& ranlibIndexes)
{
std::string workingDirectory = cmSystemTools::CollapseFullPath(
this->LocalGenerator->GetCurrentBinaryDirectory());

for (size_t i = 0; i < link_commands.size(); i++) {
if (ranlibIndexes.find(i) != ranlibIndexes.end()) { // for runlib command
this->GlobalGenerator->AddLinkCommand(
std::vector<std::string>(), workingDirectory, link_commands[i]);
} else {
this->GlobalGenerator->AddLinkCommand(makefile_depends, workingDirectory,
link_commands[i]);
}
}
}

void cmMakefileTargetGenerator::CreateLinkScript(
const char* name, std::vector<std::string> const& link_commands,
std::vector<std::string>& makefile_commands,
Expand All @@ -1974,6 +2039,7 @@ void cmMakefileTargetGenerator::CreateLinkScript(
// Create the link script file.
std::string linkScriptName =
cmStrCat(this->TargetBuildDirectoryFull, '/', name);

cmGeneratedFileStream linkScriptStream(linkScriptName);
linkScriptStream.SetCopyIfDifferent(true);
for (std::string const& link_command : link_commands) {
Expand Down
12 changes: 12 additions & 0 deletions Source/cmMakefileTargetGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ class cmMakefileTargetGenerator : public cmCommonTargetGenerator
// create the file and directory etc
void CreateRuleFile();

// create JSon file if this option is enable;
void CreateLinkCommandFile(std::vector<std::string> const& link_commands,
const std::vector<std::string>& makefile_depends,
const std::set<int>& ranlibIndexes);

// outputs the rules for object files and custom commands used by
// this target
void WriteTargetBuildRules();
Expand Down Expand Up @@ -137,13 +142,20 @@ class cmMakefileTargetGenerator : public cmCommonTargetGenerator
// Append object file dependencies.
void AppendObjectDepends(std::vector<std::string>& depends);

void AppendLinkDependsForJson(std::vector<std::string>& depends,
const std::string& linkLanguage);

// Append link rule dependencies (objects, etc.).
void AppendLinkDepends(std::vector<std::string>& depends,
const std::string& linkLanguage);

// Lookup the link rule for this target.
std::string GetLinkRule(const std::string& linkRuleVar);

void CreateLinkScriptJSON(std::vector<std::string> const& link_commands,
const std::vector<std::string>& makefile_depends,
const std::set<int>& ranlibIndexes);

/** Create a script to hold link rules and a command to invoke the
script at build time. */
void CreateLinkScript(const char* name,
Expand Down
5 changes: 5 additions & 0 deletions Tests/CMakeLib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ if(TEST_CompileCommandOutput)
target_link_libraries(runcompilecommands CMakeLib)
endif()

if(TEST_LinkCommandOutput)
add_executable(runlinkcommands run_link_commands.cpp)
target_link_libraries(runlinkcommands CMakeLib)
endif()

add_subdirectory(PseudoMemcheck)

add_executable(testAffinity testAffinity.cxx)
Expand Down
Loading

0 comments on commit 1a8f576

Please sign in to comment.