Coverage Report

Created: 2026-04-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmExportInstallFileGenerator.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmExportInstallFileGenerator.h"
4
5
#include <algorithm>
6
#include <cassert>
7
#include <cstddef>
8
#include <memory>
9
#include <set>
10
#include <sstream>
11
#include <utility>
12
13
#include "cmExportSet.h"
14
#include "cmGeneratedFileStream.h"
15
#include "cmGeneratorFileSet.h"
16
#include "cmGeneratorFileSets.h"
17
#include "cmGeneratorTarget.h"
18
#include "cmGlobalGenerator.h"
19
#include "cmInstallTargetGenerator.h"
20
#include "cmList.h"
21
#include "cmLocalGenerator.h"
22
#include "cmMakefile.h"
23
#include "cmMessageType.h"
24
#include "cmStringAlgorithms.h"
25
#include "cmSystemTools.h"
26
#include "cmTarget.h"
27
#include "cmTargetExport.h"
28
#include "cmValue.h"
29
30
cmExportInstallFileGenerator::cmExportInstallFileGenerator(
31
  cmInstallExportGenerator* iegen)
32
0
  : IEGen(iegen)
33
0
{
34
0
}
35
36
void cmExportInstallFileGenerator::ReplaceInstallPrefix(
37
  std::string& input) const
38
0
{
39
0
  cmGeneratorExpression::ReplaceInstallPrefix(input, this->GetInstallPrefix());
40
0
}
41
42
void cmExportInstallFileGenerator::PopulateImportProperties(
43
  std::string const& config, std::string const& suffix,
44
  cmTargetExport const* targetExport, ImportPropertyMap& properties,
45
  std::set<std::string>& importedLocations)
46
0
{
47
0
  this->SetImportLocationProperty(config, suffix,
48
0
                                  targetExport->ArchiveGenerator, properties,
49
0
                                  importedLocations);
50
0
  this->SetImportLocationProperty(config, suffix,
51
0
                                  targetExport->LibraryGenerator, properties,
52
0
                                  importedLocations);
53
0
  this->SetImportLocationProperty(config, suffix,
54
0
                                  targetExport->RuntimeGenerator, properties,
55
0
                                  importedLocations);
56
0
  this->SetImportLocationProperty(config, suffix,
57
0
                                  targetExport->ObjectsGenerator, properties,
58
0
                                  importedLocations);
59
0
  this->SetImportLocationProperty(config, suffix,
60
0
                                  targetExport->FrameworkGenerator, properties,
61
0
                                  importedLocations);
62
0
  this->SetImportLocationProperty(config, suffix,
63
0
                                  targetExport->BundleGenerator, properties,
64
0
                                  importedLocations);
65
66
  // If any file location was set for the target add it to the
67
  // import file.
68
0
  if (!properties.empty()) {
69
    // Get the rest of the target details.
70
0
    cmGeneratorTarget const* const gtgt = targetExport->Target;
71
0
    this->SetImportDetailProperties(config, suffix, gtgt, properties);
72
73
    // TODO: PUBLIC_HEADER_LOCATION
74
    // This should wait until the build feature propagation stuff is done.
75
    // Then this can be a propagated include directory.
76
    // this->GenerateImportProperty(config, te->HeaderGenerator, properties);
77
0
  }
78
0
}
79
80
std::string cmExportInstallFileGenerator::GetImportXcFrameworkLocation(
81
  std::string const& config, cmTargetExport const* targetExport) const
82
0
{
83
0
  std::string importedXcFrameworkLocation = targetExport->XcFrameworkLocation;
84
0
  if (!importedXcFrameworkLocation.empty()) {
85
0
    importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
86
0
      importedXcFrameworkLocation,
87
0
      cmGeneratorExpression::PreprocessContext::InstallInterface,
88
0
      this->GetImportPrefixWithSlash());
89
0
    importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
90
0
      importedXcFrameworkLocation, targetExport->Target->GetLocalGenerator(),
91
0
      config, targetExport->Target, nullptr, targetExport->Target);
92
0
    if (!importedXcFrameworkLocation.empty() &&
93
0
        !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) &&
94
0
        !cmHasPrefix(importedXcFrameworkLocation,
95
0
                     this->GetImportPrefixWithSlash())) {
96
0
      return cmStrCat(this->GetImportPrefixWithSlash(),
97
0
                      importedXcFrameworkLocation);
98
0
    }
99
0
  }
100
101
0
  return importedXcFrameworkLocation;
102
0
}
103
104
bool cmExportInstallFileGenerator::GenerateImportFileConfig(
105
  std::string const& config)
106
0
{
107
  // Skip configurations not enabled for this export.
108
0
  if (!this->IEGen->InstallsForConfig(config)) {
109
0
    return true;
110
0
  }
111
112
  // Construct the name of the file to generate.
113
0
  std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase,
114
0
                                  this->GetConfigFileNameSeparator());
115
0
  if (!config.empty()) {
116
0
    fileName += cmSystemTools::LowerCase(config);
117
0
  } else {
118
0
    fileName += "noconfig";
119
0
  }
120
0
  fileName += this->FileExt;
121
122
  // Open the output file to generate it.
123
0
  cmGeneratedFileStream exportFileStream(fileName, true);
124
0
  if (!exportFileStream) {
125
0
    std::string se = cmSystemTools::GetLastSystemError();
126
0
    std::ostringstream e;
127
0
    e << "cannot write to file \"" << fileName << "\": " << se;
128
0
    cmSystemTools::Error(e.str());
129
0
    return false;
130
0
  }
131
0
  exportFileStream.SetCopyIfDifferent(true);
132
0
  std::ostream& os = exportFileStream;
133
134
  // Generate the per-config target information.
135
0
  this->GenerateImportConfig(os, config);
136
137
  // Record this per-config import file.
138
0
  this->ConfigImportFiles[config] = fileName;
139
140
0
  return true;
141
0
}
142
143
void cmExportInstallFileGenerator::SetImportLocationProperty(
144
  std::string const& config, std::string const& suffix,
145
  cmInstallTargetGenerator* itgen, ImportPropertyMap& properties,
146
  std::set<std::string>& importedLocations)
147
0
{
148
  // Skip rules that do not match this configuration.
149
0
  if (!(itgen && itgen->InstallsForConfig(config))) {
150
0
    return;
151
0
  }
152
153
  // Get the target to be installed.
154
0
  cmGeneratorTarget* target = itgen->GetTarget();
155
156
  // Construct the installed location of the target.
157
0
  std::string dest = itgen->GetDestination(config);
158
0
  std::string value;
159
0
  if (!cmSystemTools::FileIsFullPath(dest)) {
160
    // The target is installed relative to the installation prefix.
161
0
    value = std::string{ this->GetImportPrefixWithSlash() };
162
0
  }
163
0
  value += dest;
164
0
  value += "/";
165
166
0
  if (itgen->IsImportLibrary()) {
167
    // Construct the property name.
168
0
    std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
169
170
    // Append the installed file name.
171
0
    value += cmInstallTargetGenerator::GetInstallFilename(
172
0
      target, config, cmInstallTargetGenerator::NameImplibReal);
173
174
    // Store the property.
175
0
    properties[prop] = value;
176
0
    importedLocations.insert(prop);
177
0
  } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
178
    // Construct the property name.
179
0
    std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
180
181
    // Compute all the object files inside this target and setup
182
    // IMPORTED_OBJECTS as a list of object files
183
0
    std::vector<std::string> objects;
184
0
    itgen->GetInstallObjectNames(config, objects);
185
0
    for (std::string& obj : objects) {
186
0
      obj = cmStrCat(value, obj);
187
0
    }
188
189
    // Store the property.
190
0
    properties[prop] = cmList::to_string(objects);
191
0
    importedLocations.insert(prop);
192
0
  } else {
193
0
    if (target->IsFrameworkOnApple() && target->HasImportLibrary(config)) {
194
      // store as well IMPLIB value
195
0
      auto importProp = cmStrCat("IMPORTED_IMPLIB", suffix);
196
0
      auto importValue =
197
0
        cmStrCat(value,
198
0
                 cmInstallTargetGenerator::GetInstallFilename(
199
0
                   target, config, cmInstallTargetGenerator::NameImplibReal));
200
201
      // Store the property.
202
0
      properties[importProp] = importValue;
203
0
      importedLocations.insert(importProp);
204
0
    }
205
206
    // Construct the property name.
207
0
    std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
208
209
    // Append the installed file name.
210
0
    if (target->IsAppBundleOnApple()) {
211
0
      value += cmInstallTargetGenerator::GetInstallFilename(target, config);
212
0
      value += ".app/";
213
0
      if (!target->Makefile->PlatformIsAppleEmbedded()) {
214
0
        value += "Contents/MacOS/";
215
0
      }
216
0
      value += cmInstallTargetGenerator::GetInstallFilename(target, config);
217
0
    } else {
218
0
      value += cmInstallTargetGenerator::GetInstallFilename(
219
0
        target, config, cmInstallTargetGenerator::NameReal);
220
0
    }
221
222
    // Store the property.
223
0
    properties[prop] = value;
224
0
    importedLocations.insert(prop);
225
0
  }
226
0
}
227
228
cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
229
  cmTargetExport const* targetExport) const
230
0
{
231
0
  cmStateEnums::TargetType targetType = targetExport->Target->GetType();
232
  // An OBJECT library installed with no OBJECTS DESTINATION
233
  // is transformed to an INTERFACE library.
234
0
  if (targetType == cmStateEnums::OBJECT_LIBRARY &&
235
0
      !targetExport->ObjectsGenerator) {
236
0
    targetType = cmStateEnums::INTERFACE_LIBRARY;
237
0
  }
238
0
  return targetType;
239
0
}
240
241
std::string const& cmExportInstallFileGenerator::GetExportName() const
242
0
{
243
0
  return this->GetExportSet()->GetName();
244
0
}
245
246
void cmExportInstallFileGenerator::HandleMissingTarget(
247
  std::string& link_libs, cmGeneratorTarget const* depender,
248
  cmGeneratorTarget* dependee)
249
0
{
250
0
  auto const& exportInfo = this->FindExportInfo(dependee);
251
252
0
  if (exportInfo.Namespaces.size() == 1 && exportInfo.Sets.size() == 1) {
253
0
    std::string missingTarget = *exportInfo.Namespaces.begin();
254
255
0
    missingTarget += dependee->GetExportName();
256
0
    link_libs += missingTarget;
257
0
    this->MissingTargets.emplace_back(std::move(missingTarget));
258
0
  } else {
259
    // All exported targets should be known here and should be unique.
260
    // This is probably user-error.
261
0
    this->ComplainAboutMissingTarget(depender, dependee, exportInfo);
262
0
  }
263
0
}
264
265
cmExportFileGenerator::ExportInfo cmExportInstallFileGenerator::FindExportInfo(
266
  cmGeneratorTarget const* target) const
267
0
{
268
0
  std::vector<std::string> exportFiles;
269
0
  std::set<std::string> exportSets;
270
0
  std::set<std::string> namespaces;
271
272
0
  auto const& name = target->GetName();
273
0
  auto& allExportSets =
274
0
    target->GetLocalGenerator()->GetGlobalGenerator()->GetExportSets();
275
276
0
  for (auto const& exp : allExportSets) {
277
0
    auto const& exportSet = exp.second;
278
0
    auto const& targets = exportSet.GetTargetExports();
279
280
0
    if (std::any_of(targets.begin(), targets.end(),
281
0
                    [&name](std::unique_ptr<cmTargetExport> const& te) {
282
0
                      return te->TargetName == name;
283
0
                    })) {
284
0
      std::vector<cmInstallExportGenerator const*> const* installs =
285
0
        exportSet.GetInstallations();
286
0
      if (!installs->empty()) {
287
0
        exportSets.insert(exp.first);
288
0
        for (cmInstallExportGenerator const* install : *installs) {
289
0
          exportFiles.push_back(install->GetDestinationFile());
290
0
          namespaces.insert(install->GetNamespace());
291
0
        }
292
0
      }
293
0
    }
294
0
  }
295
0
  return { exportFiles, exportSets, namespaces };
296
0
}
297
298
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
299
  cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
300
  ExportInfo const& exportInfo) const
301
0
{
302
0
  std::ostringstream e;
303
0
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
304
0
    << this->GetExportName() << "\" ...) "
305
0
    << "includes target \"" << depender->GetName()
306
0
    << "\" which requires target \"" << dependee->GetName() << "\" ";
307
0
  if (exportInfo.Sets.empty()) {
308
0
    e << "that is not in any export set.";
309
0
  } else {
310
0
    if (exportInfo.Sets.size() == 1) {
311
0
      e << "that is not in this export set, but in another export set which "
312
0
           "is "
313
0
           "exported multiple times with different namespaces: ";
314
0
    } else {
315
0
      e << "that is not in this export set, but in multiple other export "
316
0
           "sets: ";
317
0
    }
318
0
    e << cmJoin(exportInfo.Files, ", ") << ".\n"
319
0
      << "An exported target cannot depend upon another target which is "
320
0
         "exported in more than one export set or with more than one "
321
0
         "namespace. "
322
0
         "Consider consolidating the exports of the \""
323
0
      << dependee->GetName() << "\" target to a single export.";
324
0
  }
325
0
  this->ReportError(e.str());
326
0
}
327
328
void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
329
  std::string const& targetName) const
330
0
{
331
0
  std::ostringstream e;
332
0
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
333
0
    << this->GetExportName() << "\" ...) "
334
0
    << "includes target \"" << targetName
335
0
    << "\" more than once in the export set.";
336
0
  this->ReportError(e.str());
337
0
}
338
339
void cmExportInstallFileGenerator::IssueMessage(
340
  MessageType type, std::string const& message) const
341
0
{
342
0
  cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
343
0
  lg->GetMakefile()->IssueMessage(type, message);
344
0
}
345
346
void cmExportInstallFileGenerator::IssueDiagnostic(
347
  cmDiagnosticCategory category, std::string const& message) const
348
0
{
349
0
  cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
350
0
  lg->GetMakefile()->IssueDiagnostic(category, message);
351
0
}
352
353
std::string cmExportInstallFileGenerator::InstallNameDir(
354
  cmGeneratorTarget const* target, std::string const& config)
355
0
{
356
0
  std::string install_name_dir;
357
358
0
  cmMakefile* mf = target->Target->GetMakefile();
359
0
  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
360
0
    auto const& prefix = this->GetInstallPrefix();
361
0
    install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix);
362
0
  }
363
364
0
  return install_name_dir;
365
0
}
366
367
std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
368
0
{
369
0
  return this->GetCxxModuleFile(this->GetExportSet()->GetName());
370
0
}
371
372
bool cmExportInstallFileGenerator::CollectExports(
373
  std::function<void(cmTargetExport const*)> const& visitor)
374
0
{
375
0
  auto pred = [&](std::unique_ptr<cmTargetExport> const& te) -> bool {
376
0
    if (te->NamelinkOnly) {
377
0
      return true;
378
0
    }
379
0
    if (this->ExportedTargets.insert(te->Target).second) {
380
0
      visitor(te.get());
381
0
      return true;
382
0
    }
383
384
0
    this->ComplainAboutDuplicateTarget(te->Target->GetName());
385
0
    return false;
386
0
  };
387
388
0
  auto const& targets = this->GetExportSet()->GetTargetExports();
389
0
  return std::all_of(targets.begin(), targets.end(), pred);
390
0
}
391
392
bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
393
  cmTargetExport const* targetExport, ImportPropertyMap& properties)
394
0
{
395
0
  cmGeneratorTarget const* const gt = targetExport->Target;
396
397
0
  std::string includesDestinationDirs;
398
0
  this->PopulateSystemIncludeDirectoriesInterface(
399
0
    gt, cmGeneratorExpression::InstallInterface, properties);
400
0
  this->PopulateIncludeDirectoriesInterface(
401
0
    gt, cmGeneratorExpression::InstallInterface, properties, *targetExport,
402
0
    includesDestinationDirs);
403
0
  this->PopulateLinkDirectoriesInterface(
404
0
    gt, cmGeneratorExpression::InstallInterface, properties);
405
0
  this->PopulateLinkDependsInterface(
406
0
    gt, cmGeneratorExpression::InstallInterface, properties);
407
0
  this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
408
0
                                 properties);
409
410
0
  return this->PopulateInterfaceProperties(
411
0
    gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface,
412
0
    properties);
413
0
}
414
415
bool cmExportInstallFileGenerator::PopulateFileSetInterfaceProperties(
416
  cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties)
417
0
{
418
0
  cmGeneratorTarget const* const gt = targetExport->Target;
419
0
  cmGeneratorFileSets const* const gfs = gt->GetGeneratorFileSets();
420
421
0
  bool result = true;
422
423
0
  for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
424
0
    for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
425
0
      ImportPropertyMap& fsProperties = properties[fileSet->GetName()];
426
0
      this->PopulateFileSetIncludeDirectoriesInterface(
427
0
        gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
428
0
      result = result &&
429
0
        this->PopulateFileSetInterfaceProperties(
430
0
          gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
431
0
    }
432
0
  }
433
0
  return result;
434
0
}
435
436
namespace {
437
bool isSubDirectory(std::string const& a, std::string const& b)
438
0
{
439
0
  return (cmSystemTools::ComparePath(a, b) ||
440
0
          cmSystemTools::IsSubDirectory(a, b));
441
0
}
442
}
443
444
bool cmExportInstallFileGenerator::CheckInterfaceDirs(
445
  std::string const& prepro, cmGeneratorTarget const* target,
446
  std::string const& prop) const
447
0
{
448
0
  std::string const& installDir =
449
0
    target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
450
0
  std::string const& topSourceDir =
451
0
    target->GetLocalGenerator()->GetSourceDirectory();
452
0
  std::string const& topBinaryDir =
453
0
    target->GetLocalGenerator()->GetBinaryDirectory();
454
455
0
  std::vector<std::string> parts;
456
0
  cmGeneratorExpression::Split(prepro, parts);
457
458
0
  bool const inSourceBuild = topSourceDir == topBinaryDir;
459
460
0
  bool hadFatalError = false;
461
462
0
  for (std::string const& li : parts) {
463
0
    size_t genexPos = cmGeneratorExpression::Find(li);
464
0
    if (genexPos == 0) {
465
0
      continue;
466
0
    }
467
0
    if (cmHasPrefix(li, this->GetImportPrefixWithSlash())) {
468
0
      continue;
469
0
    }
470
0
    if (genexPos != std::string::npos) {
471
0
      hadFatalError = true;
472
0
    }
473
0
    if (!cmSystemTools::FileIsFullPath(li)) {
474
0
      std::ostringstream e;
475
      /* clang-format off */
476
0
      e << "Target \"" << target->GetName() << "\" " << prop <<
477
0
           " property contains relative path:\n"
478
0
           "  \"" << li << "\"";
479
      /* clang-format on */
480
0
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
481
0
                                                e.str());
482
0
    }
483
0
    bool inBinary = isSubDirectory(li, topBinaryDir);
484
0
    bool inSource = isSubDirectory(li, topSourceDir);
485
0
    if (isSubDirectory(li, installDir)) {
486
      // The include directory is inside the install tree.  If the
487
      // install tree is inside the source tree or build tree then do not
488
      // fall through to the checks below that the include directory is not
489
      // also inside the source tree or build tree.
490
0
      if ((!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
491
0
          (!inSource || isSubDirectory(installDir, topSourceDir))) {
492
0
        continue;
493
0
      }
494
0
    }
495
0
    if (inBinary) {
496
0
      std::ostringstream e;
497
      /* clang-format off */
498
0
      e << "Target \"" << target->GetName() << "\" " << prop <<
499
0
           " property contains path:\n"
500
0
           "  \"" << li << "\"\nwhich is prefixed in the build directory.";
501
      /* clang-format on */
502
0
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
503
0
                                                e.str());
504
0
    }
505
0
    if (!inSourceBuild) {
506
0
      if (inSource) {
507
0
        std::ostringstream e;
508
0
        e << "Target \"" << target->GetName() << "\" " << prop
509
0
          << " property contains path:\n"
510
0
             "  \""
511
0
          << li << "\"\nwhich is prefixed in the source directory.";
512
0
        target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
513
0
                                                  e.str());
514
0
      }
515
0
    }
516
0
  }
517
0
  return !hadFatalError;
518
0
}
519
520
void cmExportInstallFileGenerator::PopulateSourcesInterface(
521
  cmGeneratorTarget const* gt,
522
  cmGeneratorExpression::PreprocessContext preprocessRule,
523
  ImportPropertyMap& properties)
524
0
{
525
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
526
527
0
  char const* const propName = "INTERFACE_SOURCES";
528
0
  cmValue input = gt->GetProperty(propName);
529
530
0
  if (!input) {
531
0
    return;
532
0
  }
533
534
0
  if (input->empty()) {
535
0
    properties[propName].clear();
536
0
    return;
537
0
  }
538
539
0
  std::string prepro = cmGeneratorExpression::Preprocess(
540
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
541
0
  if (!prepro.empty()) {
542
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
543
544
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
545
0
      return;
546
0
    }
547
0
    properties[propName] = prepro;
548
0
  }
549
0
}
550
551
void cmExportInstallFileGenerator::PopulateSystemIncludeDirectoriesInterface(
552
  cmGeneratorTarget const* target,
553
  cmGeneratorExpression::PreprocessContext preprocessRule,
554
  ImportPropertyMap& properties)
555
0
{
556
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
557
558
0
  char const* const propName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
559
0
  cmValue input = target->GetProperty(propName);
560
561
0
  if (!input) {
562
0
    return;
563
0
  }
564
0
  if (input->empty()) {
565
    // Set to empty
566
0
    properties[propName].clear();
567
0
    return;
568
0
  }
569
570
0
  std::string includes = (input ? *input : "");
571
0
  std::string prepro = cmGeneratorExpression::Preprocess(
572
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
573
0
  if (!prepro.empty()) {
574
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
575
576
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
577
0
      return;
578
0
    }
579
0
    properties[propName] = prepro;
580
0
  }
581
0
}
582
583
void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
584
  cmGeneratorTarget const* target,
585
  cmGeneratorExpression::PreprocessContext preprocessRule,
586
  ImportPropertyMap& properties, cmTargetExport const& te,
587
  std::string& includesDestinationDirs)
588
0
{
589
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
590
591
0
  includesDestinationDirs.clear();
592
593
0
  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
594
0
  cmValue input = target->GetProperty(propName);
595
596
0
  cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
597
598
0
  std::string dirs = cmGeneratorExpression::Preprocess(
599
0
    cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
600
0
    preprocessRule, this->GetImportPrefixWithSlash());
601
0
  this->ReplaceInstallPrefix(dirs);
602
0
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
603
0
  std::string exportDirs =
604
0
    cge->Evaluate(target->GetLocalGenerator(), "", target);
605
606
0
  if (cge->GetHadContextSensitiveCondition()) {
607
0
    cmLocalGenerator* lg = target->GetLocalGenerator();
608
0
    std::ostringstream e;
609
0
    e << "Target \"" << target->GetName()
610
0
      << "\" is installed with "
611
0
         "INCLUDES DESTINATION set to a context sensitive path.  Paths which "
612
0
         "depend on the configuration, policy values or the link interface "
613
0
         "are "
614
0
         "not supported.  Consider using target_include_directories instead.";
615
0
    lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
616
0
    return;
617
0
  }
618
619
0
  if (!input && exportDirs.empty()) {
620
0
    return;
621
0
  }
622
0
  if ((input && input->empty()) && exportDirs.empty()) {
623
    // Set to empty
624
0
    properties[propName].clear();
625
0
    return;
626
0
  }
627
628
0
  this->AddImportPrefix(exportDirs);
629
0
  includesDestinationDirs = exportDirs;
630
631
0
  std::string includes = (input ? *input : "");
632
0
  char const* const sep = input ? ";" : "";
633
0
  includes += sep + exportDirs;
634
0
  std::string prepro = cmGeneratorExpression::Preprocess(
635
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
636
0
  if (!prepro.empty()) {
637
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
638
639
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
640
0
      return;
641
0
    }
642
0
    properties[propName] = prepro;
643
0
  }
644
0
}
645
646
void cmExportInstallFileGenerator::PopulateFileSetIncludeDirectoriesInterface(
647
  cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
648
  cmGeneratorExpression::PreprocessContext preprocessRule,
649
  ImportPropertyMap& properties)
650
0
{
651
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
652
653
0
  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
654
0
  cmValue includes = fileSet->GetProperty(propName);
655
656
0
  if (!includes) {
657
0
    return;
658
0
  }
659
0
  if (includes && includes->empty()) {
660
    // Set to empty
661
0
    properties[propName].clear();
662
0
    return;
663
0
  }
664
665
0
  std::string prepro = cmGeneratorExpression::Preprocess(
666
0
    *includes, preprocessRule, this->GetImportPrefixWithSlash());
667
0
  if (!prepro.empty()) {
668
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
669
670
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
671
0
      return;
672
0
    }
673
0
    properties[propName] = prepro;
674
0
  }
675
0
}
676
677
void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
678
  cmGeneratorTarget const* gt,
679
  cmGeneratorExpression::PreprocessContext preprocessRule,
680
  ImportPropertyMap& properties)
681
0
{
682
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
683
684
0
  char const* const propName = "INTERFACE_LINK_DEPENDS";
685
0
  cmValue input = gt->GetProperty(propName);
686
687
0
  if (!input) {
688
0
    return;
689
0
  }
690
691
0
  if (input->empty()) {
692
0
    properties[propName].clear();
693
0
    return;
694
0
  }
695
696
0
  std::string prepro = cmGeneratorExpression::Preprocess(
697
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
698
0
  if (!prepro.empty()) {
699
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
700
701
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
702
0
      return;
703
0
    }
704
0
    properties[propName] = prepro;
705
0
  }
706
0
}
707
708
void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface(
709
  cmGeneratorTarget const* gt,
710
  cmGeneratorExpression::PreprocessContext preprocessRule,
711
  ImportPropertyMap& properties)
712
0
{
713
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
714
715
0
  char const* const propName = "INTERFACE_LINK_DIRECTORIES";
716
0
  cmValue input = gt->GetProperty(propName);
717
718
0
  if (!input) {
719
0
    return;
720
0
  }
721
722
0
  if (input->empty()) {
723
0
    properties[propName].clear();
724
0
    return;
725
0
  }
726
727
0
  std::string prepro = cmGeneratorExpression::Preprocess(
728
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
729
0
  if (!prepro.empty()) {
730
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
731
732
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
733
0
      return;
734
0
    }
735
0
    properties[propName] = prepro;
736
0
  }
737
0
}