Coverage Report

Created: 2026-07-14 07:09

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() == cm::TargetType::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
cm::TargetType cmExportInstallFileGenerator::GetExportTargetType(
229
  cmTargetExport const* targetExport) const
230
0
{
231
0
  cm::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 == cm::TargetType::OBJECT_LIBRARY &&
235
0
      !targetExport->ObjectsGenerator) {
236
0
    targetType = cm::TargetType::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
  return target->GetLocalGenerator()
269
0
    ->GetGlobalGenerator()
270
0
    ->FindInstallExportInfo(target);
271
0
}
272
273
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
274
  cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
275
  ExportInfo const& exportInfo) const
276
0
{
277
0
  std::ostringstream e;
278
0
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
279
0
    << this->GetExportName() << "\" ...) " << "includes target \""
280
0
    << depender->GetName() << "\" which requires target \""
281
0
    << dependee->GetName() << "\" ";
282
0
  if (exportInfo.Sets.empty()) {
283
0
    e << "that is not in any export set.";
284
0
  } else {
285
0
    if (exportInfo.Sets.size() == 1) {
286
0
      e << "that is not in this export set, but in another export set which "
287
0
           "is "
288
0
           "exported multiple times with different namespaces: ";
289
0
    } else {
290
0
      e << "that is not in this export set, but in multiple other export "
291
0
           "sets: ";
292
0
    }
293
0
    e << cmJoin(exportInfo.Files, ", ") << ".\n"
294
0
      << "An exported target cannot depend upon another target which is "
295
0
         "exported in more than one export set or with more than one "
296
0
         "namespace. "
297
0
         "Consider consolidating the exports of the \""
298
0
      << dependee->GetName() << "\" target to a single export.";
299
0
  }
300
0
  this->ReportError(e.str());
301
0
}
302
303
void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
304
  std::string const& targetName) const
305
0
{
306
0
  std::ostringstream e;
307
0
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
308
0
    << this->GetExportName() << "\" ...) " << "includes target \""
309
0
    << targetName << "\" more than once in the export set.";
310
0
  this->ReportError(e.str());
311
0
}
312
313
void cmExportInstallFileGenerator::IssueMessage(
314
  MessageType type, std::string const& message) const
315
0
{
316
0
  cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
317
0
  lg->GetMakefile()->IssueMessage(type, message);
318
0
}
319
320
void cmExportInstallFileGenerator::IssueDiagnostic(
321
  cmDiagnosticCategory category, std::string const& message) const
322
0
{
323
0
  cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
324
0
  lg->GetMakefile()->IssueDiagnostic(category, message,
325
0
                                     this->IEGen->GetDiagnosticContext());
326
0
}
327
328
std::string cmExportInstallFileGenerator::InstallNameDir(
329
  cmGeneratorTarget const* target, std::string const& config)
330
0
{
331
0
  std::string install_name_dir;
332
333
0
  cmMakefile* mf = target->Target->GetMakefile();
334
0
  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
335
0
    auto const& prefix = this->GetInstallPrefix();
336
0
    install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix);
337
0
  }
338
339
0
  return install_name_dir;
340
0
}
341
342
std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
343
0
{
344
0
  return this->GetCxxModuleFile(this->GetExportSet()->GetName());
345
0
}
346
347
bool cmExportInstallFileGenerator::CollectExports(
348
  std::function<void(cmTargetExport const*)> const& visitor)
349
0
{
350
0
  auto pred = [&](std::unique_ptr<cmTargetExport> const& te) -> bool {
351
0
    if (te->NamelinkOnly) {
352
0
      return true;
353
0
    }
354
0
    if (this->ExportedTargets.insert(te->Target).second) {
355
0
      visitor(te.get());
356
0
      return true;
357
0
    }
358
359
0
    this->ComplainAboutDuplicateTarget(te->Target->GetName());
360
0
    return false;
361
0
  };
362
363
0
  auto const& targets = this->GetExportSet()->GetTargetExports();
364
0
  return std::all_of(targets.begin(), targets.end(), pred);
365
0
}
366
367
bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
368
  cmTargetExport const* targetExport, ImportPropertyMap& properties)
369
0
{
370
0
  cmGeneratorTarget const* const gt = targetExport->Target;
371
372
0
  std::string includesDestinationDirs;
373
0
  this->PopulateSystemIncludeDirectoriesInterface(
374
0
    gt, cmGeneratorExpression::InstallInterface, properties);
375
0
  this->PopulateIncludeDirectoriesInterface(
376
0
    gt, cmGeneratorExpression::InstallInterface, properties, *targetExport,
377
0
    includesDestinationDirs);
378
0
  this->PopulateLinkDirectoriesInterface(
379
0
    gt, cmGeneratorExpression::InstallInterface, properties);
380
0
  this->PopulateLinkDependsInterface(
381
0
    gt, cmGeneratorExpression::InstallInterface, properties);
382
0
  this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
383
0
                                 properties);
384
385
0
  return this->PopulateInterfaceProperties(
386
0
    gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface,
387
0
    properties);
388
0
}
389
390
bool cmExportInstallFileGenerator::PopulateFileSetInterfaceProperties(
391
  cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties)
392
0
{
393
0
  cmGeneratorTarget const* const gt = targetExport->Target;
394
0
  cmGeneratorFileSets const* const gfs = gt->GetGeneratorFileSets();
395
396
0
  bool result = true;
397
398
0
  for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
399
0
    for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
400
0
      ImportPropertyMap& fsProperties = properties[fileSet->GetName()];
401
0
      this->PopulateFileSetIncludeDirectoriesInterface(
402
0
        gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
403
0
      result = result &&
404
0
        this->PopulateFileSetInterfaceProperties(
405
0
          gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
406
0
    }
407
0
  }
408
0
  return result;
409
0
}
410
411
namespace {
412
bool isSubDirectory(std::string const& a, std::string const& b)
413
0
{
414
0
  return (cmSystemTools::ComparePath(a, b) ||
415
0
          cmSystemTools::IsSubDirectory(a, b));
416
0
}
417
}
418
419
bool cmExportInstallFileGenerator::CheckInterfaceDirs(
420
  std::string const& prepro, cmGeneratorTarget const* target,
421
  std::string const& prop) const
422
0
{
423
0
  std::string const& installDir =
424
0
    target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
425
0
  std::string const& topSourceDir =
426
0
    target->GetLocalGenerator()->GetSourceDirectory();
427
0
  std::string const& topBinaryDir =
428
0
    target->GetLocalGenerator()->GetBinaryDirectory();
429
430
0
  std::vector<std::string> parts;
431
0
  cmGeneratorExpression::Split(prepro, parts);
432
433
0
  bool const inSourceBuild = topSourceDir == topBinaryDir;
434
435
0
  bool hadFatalError = false;
436
437
0
  for (std::string const& li : parts) {
438
0
    size_t genexPos = cmGeneratorExpression::Find(li);
439
0
    if (genexPos == 0) {
440
0
      continue;
441
0
    }
442
0
    if (cmHasPrefix(li, this->GetImportPrefixWithSlash())) {
443
0
      continue;
444
0
    }
445
0
    if (genexPos != std::string::npos) {
446
0
      hadFatalError = true;
447
0
    }
448
0
    if (!cmSystemTools::FileIsFullPath(li)) {
449
0
      std::ostringstream e;
450
      /* clang-format off */
451
0
      e << "Target \"" << target->GetName() << "\" " << prop <<
452
0
           " property contains relative path:\n"
453
0
           "  \"" << li << "\"";
454
      /* clang-format on */
455
0
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
456
0
                                                e.str());
457
0
    }
458
0
    bool inBinary = isSubDirectory(li, topBinaryDir);
459
0
    bool inSource = isSubDirectory(li, topSourceDir);
460
0
    if (isSubDirectory(li, installDir)) {
461
      // The include directory is inside the install tree.  If the
462
      // install tree is inside the source tree or build tree then do not
463
      // fall through to the checks below that the include directory is not
464
      // also inside the source tree or build tree.
465
0
      if ((!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
466
0
          (!inSource || isSubDirectory(installDir, topSourceDir))) {
467
0
        continue;
468
0
      }
469
0
    }
470
0
    if (inBinary) {
471
0
      std::ostringstream e;
472
      /* clang-format off */
473
0
      e << "Target \"" << target->GetName() << "\" " << prop <<
474
0
           " property contains path:\n"
475
0
           "  \"" << li << "\"\nwhich is prefixed in the build directory.";
476
      /* clang-format on */
477
0
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
478
0
                                                e.str());
479
0
    }
480
0
    if (!inSourceBuild) {
481
0
      if (inSource) {
482
0
        std::ostringstream e;
483
0
        e << "Target \"" << target->GetName() << "\" " << prop
484
0
          << " property contains path:\n"
485
0
             "  \""
486
0
          << li << "\"\nwhich is prefixed in the source directory.";
487
0
        target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
488
0
                                                  e.str());
489
0
      }
490
0
    }
491
0
  }
492
0
  return !hadFatalError;
493
0
}
494
495
void cmExportInstallFileGenerator::PopulateSourcesInterface(
496
  cmGeneratorTarget const* gt,
497
  cmGeneratorExpression::PreprocessContext preprocessRule,
498
  ImportPropertyMap& properties)
499
0
{
500
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
501
502
0
  char const* const propName = "INTERFACE_SOURCES";
503
0
  cmValue input = gt->GetProperty(propName);
504
505
0
  if (!input) {
506
0
    return;
507
0
  }
508
509
0
  if (input->empty()) {
510
0
    properties[propName].clear();
511
0
    return;
512
0
  }
513
514
0
  std::string prepro = cmGeneratorExpression::Preprocess(
515
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
516
0
  if (!prepro.empty()) {
517
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
518
519
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
520
0
      return;
521
0
    }
522
0
    properties[propName] = prepro;
523
0
  }
524
0
}
525
526
void cmExportInstallFileGenerator::PopulateSystemIncludeDirectoriesInterface(
527
  cmGeneratorTarget const* target,
528
  cmGeneratorExpression::PreprocessContext preprocessRule,
529
  ImportPropertyMap& properties)
530
0
{
531
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
532
533
0
  char const* const propName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
534
0
  cmValue input = target->GetProperty(propName);
535
536
0
  if (!input) {
537
0
    return;
538
0
  }
539
0
  if (input->empty()) {
540
    // Set to empty
541
0
    properties[propName].clear();
542
0
    return;
543
0
  }
544
545
0
  std::string includes = (input ? *input : "");
546
0
  std::string prepro = cmGeneratorExpression::Preprocess(
547
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
548
0
  if (!prepro.empty()) {
549
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
550
551
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
552
0
      return;
553
0
    }
554
0
    properties[propName] = prepro;
555
0
  }
556
0
}
557
558
void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
559
  cmGeneratorTarget const* target,
560
  cmGeneratorExpression::PreprocessContext preprocessRule,
561
  ImportPropertyMap& properties, cmTargetExport const& te,
562
  std::string& includesDestinationDirs)
563
0
{
564
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
565
566
0
  includesDestinationDirs.clear();
567
568
0
  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
569
0
  cmValue input = target->GetProperty(propName);
570
571
0
  cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
572
573
0
  std::string dirs = cmGeneratorExpression::Preprocess(
574
0
    cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
575
0
    preprocessRule, this->GetImportPrefixWithSlash());
576
0
  this->ReplaceInstallPrefix(dirs);
577
0
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
578
0
  std::string exportDirs =
579
0
    cge->Evaluate(target->GetLocalGenerator(), "", target);
580
581
0
  if (cge->GetHadContextSensitiveCondition()) {
582
0
    cmLocalGenerator* lg = target->GetLocalGenerator();
583
0
    std::ostringstream e;
584
0
    e << "Target \"" << target->GetName()
585
0
      << "\" is installed with "
586
0
         "INCLUDES DESTINATION set to a context sensitive path.  Paths which "
587
0
         "depend on the configuration, policy values or the link interface "
588
0
         "are "
589
0
         "not supported.  Consider using target_include_directories instead.";
590
0
    lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
591
0
    return;
592
0
  }
593
594
0
  if (!input && exportDirs.empty()) {
595
0
    return;
596
0
  }
597
0
  if ((input && input->empty()) && exportDirs.empty()) {
598
    // Set to empty
599
0
    properties[propName].clear();
600
0
    return;
601
0
  }
602
603
0
  this->AddImportPrefix(exportDirs);
604
0
  includesDestinationDirs = exportDirs;
605
606
0
  std::string includes = (input ? *input : "");
607
0
  char const* const sep = input ? ";" : "";
608
0
  includes += sep + exportDirs;
609
0
  std::string prepro = cmGeneratorExpression::Preprocess(
610
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
611
0
  if (!prepro.empty()) {
612
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
613
614
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
615
0
      return;
616
0
    }
617
0
    properties[propName] = prepro;
618
0
  }
619
0
}
620
621
void cmExportInstallFileGenerator::PopulateFileSetIncludeDirectoriesInterface(
622
  cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
623
  cmGeneratorExpression::PreprocessContext preprocessRule,
624
  ImportPropertyMap& properties)
625
0
{
626
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
627
628
0
  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
629
0
  cmValue includes = fileSet->GetProperty(propName);
630
631
0
  if (!includes) {
632
0
    return;
633
0
  }
634
0
  if (includes && includes->empty()) {
635
    // Set to empty
636
0
    properties[propName].clear();
637
0
    return;
638
0
  }
639
640
0
  std::string prepro = cmGeneratorExpression::Preprocess(
641
0
    *includes, preprocessRule, this->GetImportPrefixWithSlash());
642
0
  if (!prepro.empty()) {
643
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
644
645
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
646
0
      return;
647
0
    }
648
0
    properties[propName] = prepro;
649
0
  }
650
0
}
651
652
void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
653
  cmGeneratorTarget const* gt,
654
  cmGeneratorExpression::PreprocessContext preprocessRule,
655
  ImportPropertyMap& properties)
656
0
{
657
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
658
659
0
  char const* const propName = "INTERFACE_LINK_DEPENDS";
660
0
  cmValue input = gt->GetProperty(propName);
661
662
0
  if (!input) {
663
0
    return;
664
0
  }
665
666
0
  if (input->empty()) {
667
0
    properties[propName].clear();
668
0
    return;
669
0
  }
670
671
0
  std::string prepro = cmGeneratorExpression::Preprocess(
672
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
673
0
  if (!prepro.empty()) {
674
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
675
676
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
677
0
      return;
678
0
    }
679
0
    properties[propName] = prepro;
680
0
  }
681
0
}
682
683
void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface(
684
  cmGeneratorTarget const* gt,
685
  cmGeneratorExpression::PreprocessContext preprocessRule,
686
  ImportPropertyMap& properties)
687
0
{
688
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
689
690
0
  char const* const propName = "INTERFACE_LINK_DIRECTORIES";
691
0
  cmValue input = gt->GetProperty(propName);
692
693
0
  if (!input) {
694
0
    return;
695
0
  }
696
697
0
  if (input->empty()) {
698
0
    properties[propName].clear();
699
0
    return;
700
0
  }
701
702
0
  std::string prepro = cmGeneratorExpression::Preprocess(
703
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
704
0
  if (!prepro.empty()) {
705
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
706
707
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
708
0
      return;
709
0
    }
710
0
    properties[propName] = prepro;
711
0
  }
712
0
}