| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmGhsMultiTargetGenerator.h"
- #include "cmComputeLinkInformation.h"
- #include "cmGeneratedFileStream.h"
- #include "cmGeneratorTarget.h"
- #include "cmGlobalGhsMultiGenerator.h"
- #include "cmLinkLineComputer.h"
- #include "cmLocalGhsMultiGenerator.h"
- #include "cmMakefile.h"
- #include "cmSourceFile.h"
- #include "cmSourceGroup.h"
- #include "cmTarget.h"
- cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target)
- : GeneratorTarget(target)
- , LocalGenerator(
- static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator()))
- , Makefile(target->Target->GetMakefile())
- , Name(target->GetName())
- {
- // Store the configuration name that is being used
- if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
- // Use the build type given by the user.
- this->ConfigName = config;
- } else {
- // No configuration type given.
- this->ConfigName.clear();
- }
- }
- cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator()
- {
- }
- void cmGhsMultiTargetGenerator::Generate()
- {
- // Determine type of target for this project
- switch (this->GeneratorTarget->GetType()) {
- case cmStateEnums::EXECUTABLE: {
- // Get the name of the executable to generate.
- std::string targetName;
- std::string targetNameImport;
- std::string targetNamePDB;
- this->GeneratorTarget->GetExecutableNames(
- targetName, this->TargetNameReal, targetNameImport, targetNamePDB,
- this->ConfigName);
- if (cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) {
- this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION;
- } else {
- this->TagType = GhsMultiGpj::PROGRAM;
- }
- break;
- }
- case cmStateEnums::STATIC_LIBRARY: {
- std::string targetName;
- std::string targetNameSO;
- std::string targetNameImport;
- std::string targetNamePDB;
- this->GeneratorTarget->GetLibraryNames(
- targetName, targetNameSO, this->TargetNameReal, targetNameImport,
- targetNamePDB, this->ConfigName);
- this->TagType = GhsMultiGpj::LIBRARY;
- break;
- }
- case cmStateEnums::SHARED_LIBRARY: {
- std::string msg = "add_library(<name> SHARED ...) not supported: ";
- msg += this->Name;
- cmSystemTools::Message(msg);
- return;
- }
- case cmStateEnums::OBJECT_LIBRARY: {
- std::string targetName;
- std::string targetNameSO;
- std::string targetNameImport;
- std::string targetNamePDB;
- this->GeneratorTarget->GetLibraryNames(
- targetName, targetNameSO, this->TargetNameReal, targetNameImport,
- targetNamePDB, this->ConfigName);
- this->TagType = GhsMultiGpj::SUBPROJECT;
- break;
- }
- case cmStateEnums::MODULE_LIBRARY: {
- std::string msg = "add_library(<name> MODULE ...) not supported: ";
- msg += this->Name;
- cmSystemTools::Message(msg);
- return;
- }
- case cmStateEnums::UTILITY: {
- std::string msg = "add_custom_target(<name> ...) not supported: ";
- msg += this->Name;
- cmSystemTools::Message(msg);
- return;
- }
- default:
- return;
- }
- // Tell the global generator the name of the project file
- this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
- this->Name.c_str());
- this->GeneratorTarget->Target->SetProperty(
- "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType));
- this->GenerateTarget();
- }
- 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.c_str());
- 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);
- this->WriteSources(fout);
- this->WriteReferences(fout);
- fout.Close();
- }
- cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator()
- const
- {
- return static_cast<cmGlobalGhsMultiGenerator*>(
- this->LocalGenerator->GetGlobalGenerator());
- }
- void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout,
- const std::string& config)
- {
- std::string outpath;
- std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
- if (this->TagType != GhsMultiGpj::SUBPROJECT) {
- // set target binary file destination
- outpath = this->GeneratorTarget->GetDirectory(config);
- outpath =
- this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath);
- fout << " :binDirRelative=\"" << outpath << "\"" << std::endl;
- fout << " -o \"" << this->TargetNameReal << "\"" << std::endl;
- }
- // set target object file destination
- outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- fout << " :outputDirRelative=\"" << outpath << "\"" << std::endl;
- }
- void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config,
- const std::string& language)
- {
- std::map<std::string, std::string>::iterator i =
- this->FlagsByLanguage.find(language);
- if (i == this->FlagsByLanguage.end()) {
- std::string flags;
- const char* lang = language.c_str();
- this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, lang,
- config);
- this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang,
- config);
- this->LocalGenerator->AddVisibilityPresetFlags(
- flags, this->GeneratorTarget, lang);
- // Append old-style preprocessor definition flags.
- if (this->Makefile->GetDefineFlags() != " ") {
- this->LocalGenerator->AppendFlags(flags,
- this->Makefile->GetDefineFlags());
- }
- // Add target-specific flags.
- this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, lang,
- config);
- std::map<std::string, std::string>::value_type entry(language, flags);
- i = this->FlagsByLanguage.insert(entry).first;
- }
- }
- std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language,
- std::string const& config)
- {
- std::map<std::string, std::string>::iterator i =
- this->DefinesByLanguage.find(language);
- if (i == this->DefinesByLanguage.end()) {
- std::set<std::string> defines;
- const char* lang = language.c_str();
- // Add preprocessor definitions for this target and configuration.
- this->LocalGenerator->GetTargetDefines(this->GeneratorTarget, config,
- language, defines);
- std::string definesString;
- this->LocalGenerator->JoinDefines(defines, definesString, lang);
- std::map<std::string, std::string>::value_type entry(language,
- definesString);
- i = this->DefinesByLanguage.insert(entry).first;
- }
- return i->second;
- }
- void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::ostream& fout,
- std::string const&,
- const std::string& language)
- {
- std::map<std::string, std::string>::iterator flagsByLangI =
- this->FlagsByLanguage.find(language);
- if (flagsByLangI != this->FlagsByLanguage.end()) {
- if (!flagsByLangI->second.empty()) {
- std::vector<std::string> ghsCompFlags =
- cmSystemTools::ParseArguments(flagsByLangI->second.c_str());
- for (auto& f : ghsCompFlags) {
- fout << " " << f << std::endl;
- }
- }
- }
- }
- void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
- std::ostream& fout, const std::string& config, const std::string& language)
- {
- std::vector<std::string> compileDefinitions;
- this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, config,
- language);
- for (std::vector<std::string>::const_iterator cdI =
- compileDefinitions.begin();
- cdI != compileDefinitions.end(); ++cdI) {
- fout << " -D" << (*cdI) << std::endl;
- }
- }
- void cmGhsMultiTargetGenerator::WriteIncludes(std::ostream& fout,
- const std::string& config,
- const std::string& language)
- {
- std::vector<std::string> includes;
- this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
- language, config);
- for (std::vector<std::string>::const_iterator includes_i = includes.begin();
- includes_i != includes.end(); ++includes_i) {
- fout << " -I\"" << *includes_i << "\"" << std::endl;
- }
- }
- void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout,
- std::string const& config)
- {
- if (this->TagType == GhsMultiGpj::INTERGRITY_APPLICATION) {
- return;
- }
- std::string linkLibraries;
- std::string flags;
- std::string linkFlags;
- std::string frameworkPath;
- std::string linkPath;
- std::unique_ptr<cmLinkLineComputer> linkLineComputer(
- this->GetGlobalGenerator()->CreateLinkLineComputer(
- this->LocalGenerator,
- this->LocalGenerator->GetStateSnapshot().GetDirectory()));
- this->LocalGenerator->GetTargetFlags(
- linkLineComputer.get(), config, linkLibraries, flags, linkFlags,
- frameworkPath, linkPath, this->GeneratorTarget);
- // write out link options
- std::vector<std::string> lopts =
- cmSystemTools::ParseArguments(linkFlags.c_str());
- for (auto& l : lopts) {
- fout << " " << l << std::endl;
- }
- // write out link search paths
- // must be quoted for paths that contain spaces
- std::vector<std::string> lpath =
- cmSystemTools::ParseArguments(linkPath.c_str());
- for (auto& l : lpath) {
- fout << " -L\"" << l << "\"" << std::endl;
- }
- // write out link libs
- // must be quoted for filepaths that contains spaces
- std::string cbd = this->LocalGenerator->GetCurrentBinaryDirectory();
- std::vector<std::string> llibs =
- cmSystemTools::ParseArguments(linkLibraries.c_str());
- for (auto& l : llibs) {
- if (l.compare(0, 2, "-l") == 0) {
- fout << " \"" << l << "\"" << std::endl;
- } else {
- std::string rl = cmSystemTools::CollapseCombinedPath(cbd, l);
- fout << " -l\"" << rl << "\"" << std::endl;
- }
- }
- }
- void cmGhsMultiTargetGenerator::WriteCustomCommands(std::ostream& fout)
- {
- WriteCustomCommandsHelper(fout, this->GeneratorTarget->GetPreBuildCommands(),
- cmTarget::PRE_BUILD);
- WriteCustomCommandsHelper(
- fout, this->GeneratorTarget->GetPostBuildCommands(), cmTarget::POST_BUILD);
- }
- void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
- std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet,
- cmTarget::CustomCommandType const commandType)
- {
- for (std::vector<cmCustomCommand>::const_iterator commandsSetI =
- commandsSet.begin();
- commandsSetI != commandsSet.end(); ++commandsSetI) {
- cmCustomCommandLines const& commands = commandsSetI->GetCommandLines();
- for (cmCustomCommandLines::const_iterator commandI = commands.begin();
- commandI != commands.end(); ++commandI) {
- switch (commandType) {
- case cmTarget::PRE_BUILD:
- fout << " :preexecShellSafe=";
- break;
- case cmTarget::POST_BUILD:
- fout << " :postexecShellSafe=";
- break;
- default:
- assert("Only pre and post are supported");
- }
- cmCustomCommandLine const& command = *commandI;
- for (cmCustomCommandLine::const_iterator commandLineI = command.begin();
- commandLineI != command.end(); ++commandLineI) {
- std::string subCommandE =
- this->LocalGenerator->EscapeForShell(*commandLineI, true);
- if (!command.empty()) {
- fout << (command.begin() == commandLineI ? "'" : " ");
- // Need to double escape backslashes
- cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
- }
- fout << subCommandE;
- }
- if (!command.empty()) {
- fout << "'" << std::endl;
- }
- }
- }
- }
- void cmGhsMultiTargetGenerator::WriteSourceProperty(std::ostream& fout,
- const cmSourceFile* sf,
- std::string propName,
- std::string propFlag)
- {
- const char* prop = sf->GetProperty(propName);
- if (prop) {
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(prop, list);
- for (auto& p : list) {
- fout << " " << propFlag << p << std::endl;
- }
- }
- }
- void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
- {
- /* vector of all sources for this target */
- std::vector<cmSourceFile*> sources;
- this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName);
- /* vector of all groups defined for this target
- * -- but the vector is not expanded with sub groups or in any useful order
- */
- std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
- /* for each source file assign it to its group */
- std::map<std::string, std::vector<cmSourceFile*>> groupFiles;
- std::set<std::string> groupNames;
- for (auto& sf : sources) {
- cmSourceGroup* sourceGroup =
- this->Makefile->FindSourceGroup(sf->GetFullPath(), sourceGroups);
- std::string gn = sourceGroup->GetFullName();
- groupFiles[gn].push_back(sf);
- groupNames.insert(gn);
- }
- /* 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",
- "Object Files", "Object Libraries", "Resources"
- };
- /* list of groups in the order they are displayed in a project file*/
- std::vector<std::string> groupFilesList(groupFiles.size());
- /* put the groups in the order they should be listed
- * - standard groups first, and then everything else
- * in the order used by std::map.
- */
- int i = 0;
- for (const std::string& gn : standardGroups) {
- auto n = groupNames.find(gn);
- if (n != groupNames.end()) {
- groupFilesList[i] = *n;
- i += 1;
- groupNames.erase(gn);
- }
- }
- { /* catch-all group - is last item */
- std::string gn = "";
- auto n = groupNames.find(gn);
- if (n != groupNames.end()) {
- groupFilesList.back() = *n;
- groupNames.erase(gn);
- }
- }
- for (auto& n : groupNames) {
- groupFilesList[i] = n;
- i += 1;
- }
- /* sort the files within each group */
- for (auto& n : groupFilesList) {
- std::sort(groupFiles[n].begin(), groupFiles[n].end(),
- [](cmSourceFile* l, cmSourceFile* r) {
- return l->GetFullPath() < r->GetFullPath();
- });
- }
- /* list of open project files */
- std::vector<cmGeneratedFileStream*> gfiles;
- /* write files into the proper project file
- * -- groups go into main project file
- * unless FOLDER property or variable is set.
- */
- for (auto& sg : groupFilesList) {
- std::ostream* fout;
- bool useProjectFile =
- cmSystemTools::IsOn(
- this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) ||
- cmSystemTools::IsOn(
- this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE"));
- if (useProjectFile || sg.empty()) {
- fout = &fout_proj;
- } else {
- // Open the filestream in copy-if-different mode.
- std::string gname = sg;
- cmsys::SystemTools::ReplaceString(gname, "\\", "_");
- std::string lpath =
- this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- lpath += "/";
- lpath += gname;
- lpath += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
- std::string fpath = this->LocalGenerator->GetCurrentBinaryDirectory();
- fpath += "/";
- fpath += lpath;
- cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath.c_str());
- f->SetCopyIfDifferent(true);
- gfiles.push_back(f);
- fout = f;
- this->GetGlobalGenerator()->WriteFileHeader(*f);
- GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, *f);
- fout_proj << lpath << " ";
- GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, fout_proj);
- }
- if (useProjectFile) {
- if (sg.empty()) {
- *fout << "{comment} Others" << std::endl;
- } else {
- *fout << "{comment} " << sg << 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()) {
- this->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;
- }
- }
- }
- for (cmGeneratedFileStream* f : gfiles) {
- f->Close();
- }
- }
- void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
- std::ostream& fout, const cmSourceFile* sourceFile)
- {
- const char* rawLangProp = sourceFile->GetProperty("LANGUAGE");
- if (NULL != rawLangProp) {
- std::string sourceLangProp(rawLangProp);
- std::string extension(sourceFile->GetExtension());
- if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) {
- fout << " -dotciscxx" << std::endl;
- }
- }
- }
- 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(void)
- {
- const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app");
- if (p) {
- return cmSystemTools::IsOn(
- this->GeneratorTarget->GetProperty("ghs_integrity_app"));
- } else {
- std::vector<cmSourceFile*> sources;
- this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName);
- for (auto& sf : sources) {
- if ("int" == sf->GetExtension()) {
- return true;
- }
- }
- return false;
- }
- }
|