CMake/Source/cmGlobalGhsMultiGenerator.cxx

492 lines
17 KiB
C++
Raw Normal View History

Simplify CMake per-source license notices Per-source copyright/license notice headers that spell out copyright holder names and years are hard to maintain and often out-of-date or plain wrong. Precise contributor information is already maintained automatically by the version control tool. Ultimately it is the receiver of a file who is responsible for determining its licensing status, and per-source notices are merely a convenience. Therefore it is simpler and more accurate for each source to have a generic notice of the license name and references to more detailed information on copyright holders and full license terms. Our `Copyright.txt` file now contains a list of Contributors whose names appeared source-level copyright notices. It also references version control history for more precise information. Therefore we no longer need to spell out the list of Contributors in each source file notice. Replace CMake per-source copyright/license notice headers with a short description of the license and links to `Copyright.txt` and online information available from "https://cmake.org/licensing". The online URL also handles cases of modules being copied out of our source into other projects, so we can drop our notices about replacing links with full license text. Run the `Utilities/Scripts/filter-notices.bash` script to perform the majority of the replacements mechanically. Manually fix up shebang lines and trailing newlines in a few files. Manually update the notices in a few files that the script does not handle.
2016-09-27 22:01:08 +03:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalGhsMultiGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGhsMultiTargetGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
#include "cmVersion.h"
#include <cmAlgorithms.h>
#include <cmsys/SystemTools.hxx>
const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
const char* cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild";
cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm)
: cmGlobalGenerator(cm)
, OSDirRelative(false)
{
this->GhsBuildCommandInitialized = false;
}
cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator()
{
cmDeleteAll(TargetFolderBuildStreams);
}
cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator(
cmMakefile* mf)
{
return new cmLocalGhsMultiGenerator(this, mf);
}
void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
{
entry.Name = GetActualName();
entry.Brief =
"Generates Green Hills MULTI files (experimental, work-in-progress).";
}
void cmGlobalGhsMultiGenerator::EnableLanguage(
std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
mf->AddDefinition("CMAKE_SYSTEM_PROCESSOR", "ARM");
const std::string ghsCompRoot(GetCompRoot());
mf->AddDefinition("GHS_COMP_ROOT", ghsCompRoot.c_str());
std::string ghsCompRootStart =
0 == ghsCompRootStart.size() ? "" : ghsCompRoot + "/";
mf->AddDefinition("CMAKE_C_COMPILER",
std::string(ghsCompRootStart + "ccarm.exe").c_str());
mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER",
std::string(ghsCompRootStart + "cxarm.exe").c_str());
mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE");
if (!ghsCompRoot.empty()) {
static const char* compPreFix = "comp_";
std::string compFilename =
cmsys::SystemTools::FindLastString(ghsCompRoot.c_str(), compPreFix);
cmsys::SystemTools::ReplaceString(compFilename, compPreFix, "");
mf->AddDefinition("CMAKE_SYSTEM_VERSION", compFilename.c_str());
}
mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
}
void cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* mf)
{
// The GHS generator knows how to lookup its build tool
// directly instead of needing a helper module to do it, so we
// do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
mf->AddDefinition("CMAKE_MAKE_PROGRAM",
this->GetGhsBuildCommand().c_str());
}
}
std::string const& cmGlobalGhsMultiGenerator::GetGhsBuildCommand()
{
if (!this->GhsBuildCommandInitialized) {
this->GhsBuildCommandInitialized = true;
this->GhsBuildCommand = this->FindGhsBuildCommand();
}
return this->GhsBuildCommand;
}
std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand()
{
std::vector<std::string> userPaths;
userPaths.push_back(this->GetCompRoot());
std::string makeProgram =
cmSystemTools::FindProgram(DEFAULT_MAKE_PROGRAM, userPaths);
if (makeProgram.empty()) {
makeProgram = DEFAULT_MAKE_PROGRAM;
}
return makeProgram;
}
std::string cmGlobalGhsMultiGenerator::GetCompRoot()
{
std::string output;
const std::vector<std::string> potentialDirsHardPaths(
GetCompRootHardPaths());
const std::vector<std::string> potentialDirsRegistry(GetCompRootRegistry());
std::vector<std::string> potentialDirsComplete;
potentialDirsComplete.insert(potentialDirsComplete.end(),
potentialDirsHardPaths.begin(),
potentialDirsHardPaths.end());
potentialDirsComplete.insert(potentialDirsComplete.end(),
potentialDirsRegistry.begin(),
potentialDirsRegistry.end());
// Use latest version
std::string outputDirName;
for (std::vector<std::string>::const_iterator potentialDirsCompleteIt =
potentialDirsComplete.begin();
potentialDirsCompleteIt != potentialDirsComplete.end();
++potentialDirsCompleteIt) {
const std::string dirName(
cmsys::SystemTools::GetFilenameName(*potentialDirsCompleteIt));
if (dirName.compare(outputDirName) > 0) {
output = *potentialDirsCompleteIt;
outputDirName = dirName;
}
}
return output;
}
std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootHardPaths()
{
std::vector<std::string> output;
cmSystemTools::Glob("C:/ghs", "comp_[^;]+", output);
for (std::vector<std::string>::iterator outputIt = output.begin();
outputIt != output.end(); ++outputIt) {
*outputIt = "C:/ghs/" + *outputIt;
}
return output;
}
std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry()
{
std::vector<std::string> output(2);
cmsys::SystemTools::ReadRegistryValue(
"HKEY_LOCAL_"
"MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
"Windows\\CurrentVersion\\Uninstall\\"
"GreenHillsSoftwared771f1b4;InstallLocation",
output[0]);
cmsys::SystemTools::ReadRegistryValue(
"HKEY_LOCAL_"
"MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
"Windows\\CurrentVersion\\Uninstall\\"
"GreenHillsSoftware9881cef6;InstallLocation",
output[1]);
return output;
}
void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
std::string const& filepath, cmGeneratedFileStream** filestream)
{
// Get a stream where to generate things.
if (NULL == *filestream) {
*filestream = new cmGeneratedFileStream(filepath.c_str());
if (NULL != *filestream) {
OpenBuildFileStream(*filestream);
}
}
}
void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
cmGeneratedFileStream* filestream)
{
*filestream << "#!gbuild" << std::endl;
}
void cmGlobalGhsMultiGenerator::OpenBuildFileStream()
{
// Compute GHS MULTI's build file path.
std::string buildFilePath =
this->GetCMakeInstance()->GetHomeOutputDirectory();
buildFilePath += "/";
buildFilePath += "default";
buildFilePath += FILE_EXTENSION;
this->Open(std::string(""), buildFilePath, &this->TargetFolderBuildStreams);
OpenBuildFileStream(GetBuildFileStream());
char const* osDir =
this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR");
if (NULL == osDir) {
osDir = "";
cmSystemTools::Error("GHS_OS_DIR cache variable must be set");
} else {
this->GetCMakeInstance()->MarkCliAsUsed("GHS_OS_DIR");
}
std::string fOSDir(this->trimQuotes(osDir));
std::replace(fOSDir.begin(), fOSDir.end(), '\\', '/');
if (!fOSDir.empty() && ('c' == fOSDir[0] || 'C' == fOSDir[0])) {
this->OSDirRelative = false;
} else {
this->OSDirRelative = true;
}
char const* bspName =
this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
if (NULL == bspName) {
bspName = "";
cmSystemTools::Error("GHS_BSP_NAME cache variable must be set");
} else {
this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME");
}
std::string fBspName(this->trimQuotes(bspName));
std::replace(fBspName.begin(), fBspName.end(), '\\', '/');
this->WriteMacros();
this->WriteHighLevelDirectives();
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream());
this->WriteDisclaimer(this->GetBuildFileStream());
*this->GetBuildFileStream() << "# Top Level Project File" << std::endl;
if (!fBspName.empty()) {
*this->GetBuildFileStream() << " -bsp " << fBspName << std::endl;
}
this->WriteCompilerOptions(fOSDir);
}
void cmGlobalGhsMultiGenerator::CloseBuildFileStream(
cmGeneratedFileStream** filestream)
{
if (filestream) {
delete *filestream;
*filestream = NULL;
} else {
cmSystemTools::Error("Build file stream was not open.");
}
}
void cmGlobalGhsMultiGenerator::Generate()
{
this->cmGlobalGenerator::Generate();
if (!this->LocalGenerators.empty()) {
this->OpenBuildFileStream();
// Build all the folder build files
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
cmLocalGhsMultiGenerator* lg =
static_cast<cmLocalGhsMultiGenerator*>(this->LocalGenerators[i]);
std::vector<cmGeneratorTarget*> tgts = lg->GetGeneratorTargets();
this->UpdateBuildFiles(tgts);
}
}
cmDeleteAll(TargetFolderBuildStreams);
this->TargetFolderBuildStreams.clear();
}
void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& /*projectName*/, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
makeCommand.push_back(
this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand()));
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
if (!targetName.empty()) {
if (targetName == "clean") {
makeCommand.push_back("-clean");
} else {
makeCommand.push_back(targetName);
}
}
}
void cmGlobalGhsMultiGenerator::WriteMacros()
{
char const* ghsGpjMacros =
this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
if (NULL != ghsGpjMacros) {
std::vector<std::string> expandedList;
cmSystemTools::ExpandListArgument(std::string(ghsGpjMacros), expandedList);
for (std::vector<std::string>::const_iterator expandedListI =
expandedList.begin();
expandedListI != expandedList.end(); ++expandedListI) {
*this->GetBuildFileStream() << "macro " << *expandedListI << std::endl;
}
}
}
void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives()
{
*this->GetBuildFileStream() << "primaryTarget=arm_integrity.tgt"
<< std::endl;
char const* const customization =
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
if (NULL != customization && strlen(customization) > 0) {
*this->GetBuildFileStream()
<< "customization=" << trimQuotes(customization) << std::endl;
this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION");
}
}
void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const& fOSDir)
{
*this->GetBuildFileStream() << " -os_dir=\"" << fOSDir << "\""
<< std::endl;
}
void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream* os)
{
(*os) << "#" << std::endl
<< "# CMAKE generated file: DO NOT EDIT!" << std::endl
<< "# Generated by \"" << GetActualName() << "\""
<< " Generator, CMake Version " << cmVersion::GetMajorVersion() << "."
<< cmVersion::GetMinorVersion() << std::endl
<< "#" << std::endl;
}
void cmGlobalGhsMultiGenerator::AddFilesUpToPath(
cmGeneratedFileStream* mainBuildFile,
std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
char const* homeOutputDirectory, std::string const& path,
GhsMultiGpj::Types projType, std::string const& relPath)
{
std::string workingPath(path);
cmSystemTools::ConvertToUnixSlashes(workingPath);
std::vector<cmsys::String> splitPath =
cmSystemTools::SplitString(workingPath);
std::string workingRelPath(relPath);
cmSystemTools::ConvertToUnixSlashes(workingRelPath);
if (!workingRelPath.empty()) {
workingRelPath += "/";
}
std::string pathUpTo;
for (std::vector<cmsys::String>::const_iterator splitPathI =
splitPath.begin();
splitPath.end() != splitPathI; ++splitPathI) {
pathUpTo += *splitPathI;
if (targetFolderBuildStreams->end() ==
targetFolderBuildStreams->find(pathUpTo)) {
AddFilesUpToPathNewBuildFile(
mainBuildFile, targetFolderBuildStreams, homeOutputDirectory, pathUpTo,
splitPath.begin() == splitPathI, workingRelPath, projType);
}
AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo,
splitPathI, splitPath.end(), projType);
pathUpTo += "/";
}
}
void cmGlobalGhsMultiGenerator::Open(
std::string const& mapKeyName, std::string const& fileName,
std::map<std::string, cmGeneratedFileStream*>* fileMap)
{
if (fileMap->end() == fileMap->find(fileName)) {
cmGeneratedFileStream* temp(new cmGeneratedFileStream);
temp->open(fileName.c_str());
(*fileMap)[mapKeyName] = temp;
}
}
void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile(
cmGeneratedFileStream* mainBuildFile,
std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
char const* homeOutputDirectory, std::string const& pathUpTo,
bool const isFirst, std::string const& relPath,
GhsMultiGpj::Types const projType)
{
// create folders up to file path
std::string absPath = std::string(homeOutputDirectory) + "/" + relPath;
std::string newPath = absPath + pathUpTo;
if (!cmSystemTools::FileExists(newPath.c_str())) {
cmSystemTools::MakeDirectory(newPath.c_str());
}
// Write out to filename for first time
std::string relFilename(GetFileNameFromPath(pathUpTo));
std::string absFilename = absPath + relFilename;
Open(pathUpTo, absFilename, targetFolderBuildStreams);
OpenBuildFileStream((*targetFolderBuildStreams)[pathUpTo]);
GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
WriteDisclaimer((*targetFolderBuildStreams)[pathUpTo]);
// Add to main build file
if (isFirst) {
*mainBuildFile << relFilename << " ";
GhsMultiGpj::WriteGpjTag(projType, mainBuildFile);
}
}
void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile(
std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
std::string const& pathUpTo,
std::vector<cmsys::String>::const_iterator splitPathI,
std::vector<cmsys::String>::const_iterator end,
GhsMultiGpj::Types const projType)
{
std::vector<cmsys::String>::const_iterator splitPathNextI = splitPathI + 1;
if (end != splitPathNextI &&
targetFolderBuildStreams->end() ==
targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI)) {
std::string nextFilename(*splitPathNextI);
nextFilename = GetFileNameFromPath(nextFilename);
*(*targetFolderBuildStreams)[pathUpTo] << nextFilename << " ";
GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
}
}
std::string cmGlobalGhsMultiGenerator::GetFileNameFromPath(
std::string const& path)
{
std::string output(path);
if (!path.empty()) {
cmSystemTools::ConvertToUnixSlashes(output);
std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output);
output += "/" + splitPath.back() + FILE_EXTENSION;
}
return output;
}
void cmGlobalGhsMultiGenerator::UpdateBuildFiles(
std::vector<cmGeneratorTarget*> tgts)
{
for (std::vector<cmGeneratorTarget*>::iterator tgtsI = tgts.begin();
tgtsI != tgts.end(); ++tgtsI) {
const cmGeneratorTarget* tgt = *tgtsI;
if (IsTgtForBuild(tgt)) {
char const* rawFolderName = tgt->GetProperty("FOLDER");
if (NULL == rawFolderName) {
rawFolderName = "";
}
std::string folderName(rawFolderName);
if (this->TargetFolderBuildStreams.end() ==
this->TargetFolderBuildStreams.find(folderName)) {
this->AddFilesUpToPath(
GetBuildFileStream(), &this->TargetFolderBuildStreams,
this->GetCMakeInstance()->GetHomeOutputDirectory(), folderName,
GhsMultiGpj::PROJECT);
}
std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(
cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt));
std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" +
splitPath.back());
*this->TargetFolderBuildStreams[folderName] << foldNameRelBuildFile
<< " ";
GhsMultiGpj::WriteGpjTag(cmGhsMultiTargetGenerator::GetGpjTag(tgt),
this->TargetFolderBuildStreams[folderName]);
}
}
}
bool cmGlobalGhsMultiGenerator::IsTgtForBuild(const cmGeneratorTarget* tgt)
{
const std::string config =
2015-10-21 22:31:00 +03:00
tgt->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
std::vector<cmSourceFile*> tgtSources;
2015-10-21 22:31:00 +03:00
tgt->GetSourceFiles(tgtSources, config);
bool tgtInBuild = true;
char const* excludeFromAll = tgt->GetProperty("EXCLUDE_FROM_ALL");
if (NULL != excludeFromAll && '1' == excludeFromAll[0] &&
'\0' == excludeFromAll[1]) {
tgtInBuild = false;
}
return !tgtSources.empty() && tgtInBuild;
}
std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str)
{
std::string result;
result.reserve(str.size());
for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
if (*ch != '"') {
result += *ch;
}
}
return result;
}