1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmExportTryCompileFileGenerator.h"
10 #include "cmFileSet.h"
11 #include "cmGeneratorExpression.h"
12 #include "cmGeneratorExpressionDAGChecker.h"
13 #include "cmGeneratorTarget.h"
14 #include "cmGlobalGenerator.h"
15 #include "cmListFileCache.h"
16 #include "cmLocalGenerator.h"
17 #include "cmMakefile.h"
18 #include "cmOutputConverter.h"
19 #include "cmStateTypes.h"
20 #include "cmStringAlgorithms.h"
26 cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
27 cmGlobalGenerator* gg, const std::vector<std::string>& targets,
28 cmMakefile* mf, std::set<std::string> const& langs)
29 : Languages(langs.begin(), langs.end())
31 gg->CreateImportedGenerationObjects(mf, targets, this->Exports);
34 bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
36 std::set<cmGeneratorTarget const*> emitted;
37 std::set<cmGeneratorTarget const*> emittedDeps;
38 while (!this->Exports.empty()) {
39 cmGeneratorTarget const* te = this->Exports.back();
40 this->Exports.pop_back();
41 if (emitted.insert(te).second) {
42 emittedDeps.insert(te);
43 this->GenerateImportTargetCode(os, te, te->GetType());
45 ImportPropertyMap properties;
47 for (std::string const& lang : this->Languages) {
48 #define FIND_TARGETS(PROPERTY) \
49 this->FindTargets("INTERFACE_" #PROPERTY, te, lang, emittedDeps);
51 CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS)
56 this->PopulateProperties(te, properties, emittedDeps);
58 this->GenerateInterfaceProperties(te, os, properties);
64 std::string cmExportTryCompileFileGenerator::FindTargets(
65 const std::string& propName, cmGeneratorTarget const* tgt,
66 std::string const& language, std::set<cmGeneratorTarget const*>& emitted)
68 cmValue prop = tgt->GetProperty(propName);
73 cmGeneratorExpression ge;
75 std::unique_ptr<cmGeneratorExpressionDAGChecker> parentDagChecker;
76 if (propName == "INTERFACE_LINK_OPTIONS") {
77 // To please constraint checks of DAGChecker, this property must have
78 // LINK_OPTIONS property as parent
79 parentDagChecker = cm::make_unique<cmGeneratorExpressionDAGChecker>(
80 tgt, "LINK_OPTIONS", nullptr, nullptr);
82 cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr,
83 parentDagChecker.get());
85 std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*prop);
87 cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE,
88 cmTarget::VisibilityNormal, tgt->Target->GetMakefile(),
89 cmTarget::PerConfig::Yes);
91 cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
93 std::string result = cge->Evaluate(tgt->GetLocalGenerator(), this->Config,
94 &gDummyHead, &dagChecker, tgt, language);
96 const std::set<cmGeneratorTarget const*>& allTargets =
97 cge->GetAllTargetsSeen();
98 for (cmGeneratorTarget const* target : allTargets) {
99 if (emitted.insert(target).second) {
100 this->Exports.push_back(target);
106 void cmExportTryCompileFileGenerator::PopulateProperties(
107 const cmGeneratorTarget* target, ImportPropertyMap& properties,
108 std::set<cmGeneratorTarget const*>& emitted)
110 // Look through all non-special properties.
111 std::vector<std::string> props = target->GetPropertyKeys();
112 // Include special properties that might be relevant here.
113 props.emplace_back("INTERFACE_LINK_LIBRARIES");
114 props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT");
115 props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE");
116 for (std::string const& p : props) {
117 cmValue v = target->GetProperty(p);
123 if (cmHasLiteralPrefix(p, "IMPORTED_LINK_INTERFACE_LIBRARIES") ||
124 cmHasLiteralPrefix(p, "IMPORTED_LINK_DEPENDENT_LIBRARIES") ||
125 cmHasLiteralPrefix(p, "INTERFACE_LINK_LIBRARIES")) {
126 std::string evalResult =
127 this->FindTargets(p, target, std::string(), emitted);
129 std::vector<std::string> depends = cmExpandedList(evalResult);
130 for (std::string const& li : depends) {
131 cmGeneratorTarget* tgt =
132 target->GetLocalGenerator()->FindGeneratorTargetToUse(li);
133 if (tgt && emitted.insert(tgt).second) {
134 this->Exports.push_back(tgt);
141 std::string cmExportTryCompileFileGenerator::InstallNameDir(
142 cmGeneratorTarget const* target, const std::string& config)
144 std::string install_name_dir;
146 cmMakefile* mf = target->Target->GetMakefile();
147 if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
148 install_name_dir = target->GetInstallNameDirForBuildTree(config);
151 return install_name_dir;
154 std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
155 cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
157 return cmOutputConverter::EscapeForCMake(
158 cmJoin(fileSet->GetDirectoryEntries(), ";"));
161 std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
162 cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
164 return cmOutputConverter::EscapeForCMake(
165 cmJoin(fileSet->GetFileEntries(), ";"));