Coverage Report

Created: 2026-10-28 06:38

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
    cmSystemTools::Error(
127
0
      cmStrCat("cannot write to file \"", fileName, "\": ", se));
128
0
    return false;
129
0
  }
130
0
  exportFileStream.SetCopyIfDifferent(true);
131
0
  std::ostream& os = exportFileStream;
132
133
  // Generate the per-config target information.
134
0
  this->GenerateImportConfig(os, config);
135
136
  // Record this per-config import file.
137
0
  this->ConfigImportFiles[config] = fileName;
138
139
0
  return true;
140
0
}
141
142
void cmExportInstallFileGenerator::SetImportLocationProperty(
143
  std::string const& config, std::string const& suffix,
144
  cmInstallTargetGenerator* itgen, ImportPropertyMap& properties,
145
  std::set<std::string>& importedLocations)
146
0
{
147
  // Skip rules that do not match this configuration.
148
0
  if (!(itgen && itgen->InstallsForConfig(config))) {
149
0
    return;
150
0
  }
151
152
  // Get the target to be installed.
153
0
  cmGeneratorTarget* target = itgen->GetTarget();
154
155
  // Construct the installed location of the target.
156
0
  std::string dest = itgen->GetDestination(config);
157
0
  std::string value;
158
0
  if (!cmSystemTools::FileIsFullPath(dest)) {
159
    // The target is installed relative to the installation prefix.
160
0
    value = std::string{ this->GetImportPrefixWithSlash() };
161
0
  }
162
0
  value += dest;
163
0
  value += "/";
164
165
0
  if (itgen->IsImportLibrary()) {
166
    // Construct the property name.
167
0
    std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
168
169
    // Append the installed file name.
170
0
    value += cmInstallTargetGenerator::GetInstallFilename(
171
0
      target, config, cmInstallTargetGenerator::NameImplibReal);
172
173
    // Store the property.
174
0
    properties[prop] = value;
175
0
    importedLocations.insert(prop);
176
0
  } else if (itgen->GetTarget()->GetType() == cm::TargetType::OBJECT_LIBRARY) {
177
    // Construct the property name.
178
0
    std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
179
180
    // Compute all the object files inside this target and setup
181
    // IMPORTED_OBJECTS as a list of object files
182
0
    std::vector<std::string> objects;
183
0
    itgen->GetInstallObjectNames(config, objects);
184
0
    for (std::string& obj : objects) {
185
0
      obj = cmStrCat(value, std::move(obj));
186
0
    }
187
188
    // Store the property.
189
0
    properties[prop] = cmList::to_string(objects);
190
0
    importedLocations.insert(prop);
191
0
  } else {
192
0
    if (target->IsFrameworkOnApple() && target->HasImportLibrary(config)) {
193
      // store as well IMPLIB value
194
0
      auto importProp = cmStrCat("IMPORTED_IMPLIB", suffix);
195
0
      auto importValue =
196
0
        cmStrCat(value,
197
0
                 cmInstallTargetGenerator::GetInstallFilename(
198
0
                   target, config, cmInstallTargetGenerator::NameImplibReal));
199
200
      // Store the property.
201
0
      properties[importProp] = importValue;
202
0
      importedLocations.insert(importProp);
203
0
    }
204
205
    // Construct the property name.
206
0
    std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
207
208
    // Append the installed file name.
209
0
    if (target->IsAppBundleOnApple()) {
210
0
      value += cmInstallTargetGenerator::GetInstallFilename(target, config);
211
0
      value += ".app/";
212
0
      if (!target->Makefile->PlatformIsAppleEmbedded()) {
213
0
        value += "Contents/MacOS/";
214
0
      }
215
0
      value += cmInstallTargetGenerator::GetInstallFilename(target, config);
216
0
    } else {
217
0
      value += cmInstallTargetGenerator::GetInstallFilename(
218
0
        target, config, cmInstallTargetGenerator::NameReal);
219
0
    }
220
221
    // Store the property.
222
0
    properties[prop] = value;
223
0
    importedLocations.insert(prop);
224
0
  }
225
0
}
226
227
cm::TargetType cmExportInstallFileGenerator::GetExportTargetType(
228
  cmTargetExport const* targetExport) const
229
0
{
230
0
  cm::TargetType targetType = targetExport->Target->GetType();
231
  // An OBJECT library installed with no OBJECTS DESTINATION
232
  // is transformed to an INTERFACE library.
233
0
  if (targetType == cm::TargetType::OBJECT_LIBRARY &&
234
0
      !targetExport->ObjectsGenerator) {
235
0
    targetType = cm::TargetType::INTERFACE_LIBRARY;
236
0
  }
237
0
  return targetType;
238
0
}
239
240
std::string const& cmExportInstallFileGenerator::GetExportName() const
241
0
{
242
0
  return this->GetExportSet()->GetName();
243
0
}
244
245
void cmExportInstallFileGenerator::HandleMissingTarget(
246
  std::string& link_libs, cmGeneratorTarget const* depender,
247
  cmGeneratorTarget* dependee)
248
0
{
249
0
  auto const& exportInfo = this->FindExportInfo(dependee);
250
251
0
  if (exportInfo.Namespaces.size() == 1 && exportInfo.Sets.size() == 1) {
252
0
    std::string missingTarget = *exportInfo.Namespaces.begin();
253
254
0
    missingTarget += dependee->GetExportName();
255
0
    link_libs += missingTarget;
256
0
    this->MissingTargets.emplace_back(std::move(missingTarget));
257
0
  } else {
258
    // All exported targets should be known here and should be unique.
259
    // This is probably user-error.
260
0
    this->ComplainAboutMissingTarget(depender, dependee, exportInfo);
261
0
  }
262
0
}
263
264
cmExportFileGenerator::ExportInfo cmExportInstallFileGenerator::FindExportInfo(
265
  cmGeneratorTarget const* target) const
266
0
{
267
0
  return target->GetLocalGenerator()
268
0
    ->GetGlobalGenerator()
269
0
    ->FindInstallExportInfo(target);
270
0
}
271
272
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
273
  cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
274
  ExportInfo const& exportInfo) const
275
0
{
276
0
  std::ostringstream e;
277
0
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
278
0
    << this->GetExportName() << "\" ...) " << "includes target \""
279
0
    << depender->GetName() << "\" which requires target \""
280
0
    << dependee->GetName() << "\" ";
281
0
  if (exportInfo.Sets.empty()) {
282
0
    e << "that is not in any export set.";
283
0
  } else {
284
0
    if (exportInfo.Sets.size() == 1) {
285
0
      e << "that is not in this export set, but in another export set which "
286
0
           "is "
287
0
           "exported multiple times with different namespaces: ";
288
0
    } else {
289
0
      e << "that is not in this export set, but in multiple other export "
290
0
           "sets: ";
291
0
    }
292
0
    e << cmJoin(exportInfo.Files, ", ") << ".\n"
293
0
      << "An exported target cannot depend upon another target which is "
294
0
         "exported in more than one export set or with more than one "
295
0
         "namespace. "
296
0
         "Consider consolidating the exports of the \""
297
0
      << dependee->GetName() << "\" target to a single export.";
298
0
  }
299
0
  this->ReportError(e.str());
300
0
}
301
302
void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
303
  std::string const& targetName) const
304
0
{
305
0
  this->ReportError(cmStrCat("install(", this->IEGen->InstallSubcommand(),
306
0
                             " \"", this->GetExportName(),
307
0
                             "\" ...) includes target \"", targetName,
308
0
                             "\" more than once in the export set."));
309
0
}
310
311
void cmExportInstallFileGenerator::IssueMessage(
312
  MessageType type, std::string const& message) const
313
0
{
314
0
  cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
315
0
  lg->GetMakefile()->IssueMessage(type, message);
316
0
}
317
318
void cmExportInstallFileGenerator::IssueDiagnostic(
319
  cmDiagnosticCategory category, std::string const& message) const
320
0
{
321
0
  cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator();
322
0
  lg->GetMakefile()->IssueDiagnostic(category, message,
323
0
                                     this->IEGen->GetDiagnosticContext());
324
0
}
325
326
std::string cmExportInstallFileGenerator::InstallNameDir(
327
  cmGeneratorTarget const* target, std::string const& config)
328
0
{
329
0
  std::string install_name_dir;
330
331
0
  cmMakefile* mf = target->Target->GetMakefile();
332
0
  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
333
0
    auto const& prefix = this->GetInstallPrefix();
334
0
    install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix);
335
0
  }
336
337
0
  return install_name_dir;
338
0
}
339
340
std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
341
0
{
342
0
  return this->GetCxxModuleFile(this->GetExportSet()->GetName());
343
0
}
344
345
bool cmExportInstallFileGenerator::CollectExports(
346
  std::function<void(cmTargetExport const*)> const& visitor)
347
0
{
348
0
  auto pred = [&](std::unique_ptr<cmTargetExport> const& te) -> bool {
349
0
    if (te->NamelinkOnly) {
350
0
      return true;
351
0
    }
352
0
    if (this->ExportedTargets.insert(te->Target).second) {
353
0
      visitor(te.get());
354
0
      return true;
355
0
    }
356
357
0
    this->ComplainAboutDuplicateTarget(te->Target->GetName());
358
0
    return false;
359
0
  };
360
361
0
  auto const& targets = this->GetExportSet()->GetTargetExports();
362
0
  return std::all_of(targets.begin(), targets.end(), pred);
363
0
}
364
365
bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
366
  cmTargetExport const* targetExport, ImportPropertyMap& properties)
367
0
{
368
0
  cmGeneratorTarget const* const gt = targetExport->Target;
369
370
0
  std::string includesDestinationDirs;
371
0
  this->PopulateSystemIncludeDirectoriesInterface(
372
0
    gt, cmGeneratorExpression::InstallInterface, properties);
373
0
  this->PopulateIncludeDirectoriesInterface(
374
0
    gt, cmGeneratorExpression::InstallInterface, properties, *targetExport,
375
0
    includesDestinationDirs);
376
0
  this->PopulateLinkDirectoriesInterface(
377
0
    gt, cmGeneratorExpression::InstallInterface, properties);
378
0
  this->PopulateLinkDependsInterface(
379
0
    gt, cmGeneratorExpression::InstallInterface, properties);
380
0
  this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
381
0
                                 properties);
382
383
0
  return this->PopulateInterfaceProperties(
384
0
    gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface,
385
0
    properties);
386
0
}
387
388
bool cmExportInstallFileGenerator::PopulateFileSetInterfaceProperties(
389
  cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties)
390
0
{
391
0
  cmGeneratorTarget const* const gt = targetExport->Target;
392
0
  cmGeneratorFileSets const* const gfs = gt->GetGeneratorFileSets();
393
394
0
  bool result = true;
395
396
0
  for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
397
0
    for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
398
0
      ImportPropertyMap& fsProperties = properties[fileSet->GetName()];
399
0
      this->PopulateFileSetIncludeDirectoriesInterface(
400
0
        gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
401
0
      result = result &&
402
0
        this->PopulateFileSetInterfaceProperties(
403
0
          gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
404
0
    }
405
0
  }
406
0
  return result;
407
0
}
408
409
namespace {
410
bool isSubDirectory(std::string const& a, std::string const& b)
411
0
{
412
0
  return (cmSystemTools::ComparePath(a, b) ||
413
0
          cmSystemTools::IsSubDirectory(a, b));
414
0
}
415
}
416
417
bool cmExportInstallFileGenerator::CheckInterfaceDirs(
418
  std::string const& prepro, cmGeneratorTarget const* target,
419
  std::string const& prop) const
420
0
{
421
0
  std::string const& installDir =
422
0
    target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
423
0
  std::string const& topSourceDir =
424
0
    target->GetLocalGenerator()->GetSourceDirectory();
425
0
  std::string const& topBinaryDir =
426
0
    target->GetLocalGenerator()->GetBinaryDirectory();
427
428
0
  std::vector<std::string> parts;
429
0
  cmGeneratorExpression::Split(prepro, parts);
430
431
0
  bool const inSourceBuild = topSourceDir == topBinaryDir;
432
433
0
  bool hadFatalError = false;
434
435
0
  for (std::string const& li : parts) {
436
0
    size_t genexPos = cmGeneratorExpression::Find(li);
437
0
    if (genexPos == 0) {
438
0
      continue;
439
0
    }
440
0
    if (cmHasPrefix(li, this->GetImportPrefixWithSlash())) {
441
0
      continue;
442
0
    }
443
0
    if (genexPos != std::string::npos) {
444
0
      hadFatalError = true;
445
0
    }
446
0
    if (!cmSystemTools::FileIsFullPath(li)) {
447
0
      target->GetLocalGenerator()->IssueMessage(
448
0
        MessageType::FATAL_ERROR,
449
0
        cmStrCat("Target \"", target->GetName(), "\" ", prop,
450
0
                 " property contains relative path:\n"
451
0
                 "  \"",
452
0
                 li, '"'));
453
0
    }
454
0
    bool inBinary = isSubDirectory(li, topBinaryDir);
455
0
    bool inSource = isSubDirectory(li, topSourceDir);
456
0
    if (isSubDirectory(li, installDir)) {
457
      // The include directory is inside the install tree.  If the
458
      // install tree is inside the source tree or build tree then do not
459
      // fall through to the checks below that the include directory is not
460
      // also inside the source tree or build tree.
461
0
      if ((!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
462
0
          (!inSource || isSubDirectory(installDir, topSourceDir))) {
463
0
        continue;
464
0
      }
465
0
    }
466
0
    if (inBinary) {
467
0
      target->GetLocalGenerator()->IssueMessage(
468
0
        MessageType::FATAL_ERROR,
469
0
        cmStrCat("Target \"", target->GetName(), "\" ", prop,
470
0
                 " property contains path:\n"
471
0
                 "  \"",
472
0
                 li, "\"\nwhich is prefixed in the build directory."));
473
0
    }
474
0
    if (!inSourceBuild) {
475
0
      if (inSource) {
476
0
        target->GetLocalGenerator()->IssueMessage(
477
0
          MessageType::FATAL_ERROR,
478
0
          cmStrCat("Target \"", target->GetName(), "\" ", prop,
479
0
                   " property contains path:\n"
480
0
                   "  \"",
481
0
                   li, "\"\nwhich is prefixed in the source directory."));
482
0
      }
483
0
    }
484
0
  }
485
0
  return !hadFatalError;
486
0
}
487
488
void cmExportInstallFileGenerator::PopulateSourcesInterface(
489
  cmGeneratorTarget const* gt,
490
  cmGeneratorExpression::PreprocessContext preprocessRule,
491
  ImportPropertyMap& properties)
492
0
{
493
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
494
495
0
  char const* const propName = "INTERFACE_SOURCES";
496
0
  cmValue input = gt->GetProperty(propName);
497
498
0
  if (!input) {
499
0
    return;
500
0
  }
501
502
0
  if (input->empty()) {
503
0
    properties[propName].clear();
504
0
    return;
505
0
  }
506
507
0
  std::string prepro = cmGeneratorExpression::Preprocess(
508
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
509
0
  if (!prepro.empty()) {
510
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
511
512
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
513
0
      return;
514
0
    }
515
0
    properties[propName] = prepro;
516
0
  }
517
0
}
518
519
void cmExportInstallFileGenerator::PopulateSystemIncludeDirectoriesInterface(
520
  cmGeneratorTarget const* target,
521
  cmGeneratorExpression::PreprocessContext preprocessRule,
522
  ImportPropertyMap& properties)
523
0
{
524
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
525
526
0
  char const* const propName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
527
0
  cmValue input = target->GetProperty(propName);
528
529
0
  if (!input) {
530
0
    return;
531
0
  }
532
0
  if (input->empty()) {
533
    // Set to empty
534
0
    properties[propName].clear();
535
0
    return;
536
0
  }
537
538
0
  std::string includes = (input ? *input : "");
539
0
  std::string prepro = cmGeneratorExpression::Preprocess(
540
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
541
0
  if (!prepro.empty()) {
542
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
543
544
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
545
0
      return;
546
0
    }
547
0
    properties[propName] = prepro;
548
0
  }
549
0
}
550
551
void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
552
  cmGeneratorTarget const* target,
553
  cmGeneratorExpression::PreprocessContext preprocessRule,
554
  ImportPropertyMap& properties, cmTargetExport const& te,
555
  std::string& includesDestinationDirs)
556
0
{
557
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
558
559
0
  includesDestinationDirs.clear();
560
561
0
  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
562
0
  cmValue input = target->GetProperty(propName);
563
564
0
  cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
565
566
0
  std::string dirs = cmGeneratorExpression::Preprocess(
567
0
    cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
568
0
    preprocessRule, this->GetImportPrefixWithSlash());
569
0
  this->ReplaceInstallPrefix(dirs);
570
0
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
571
0
  std::string exportDirs =
572
0
    cge->Evaluate(target->GetLocalGenerator(), "", target);
573
574
0
  if (cge->GetHadContextSensitiveCondition()) {
575
0
    cmLocalGenerator* lg = target->GetLocalGenerator();
576
0
    lg->IssueMessage(
577
0
      MessageType::FATAL_ERROR,
578
0
      cmStrCat("Target \"", target->GetName(),
579
0
               "\" is installed with "
580
0
               "INCLUDES DESTINATION set to a context sensitive path.  Paths "
581
0
               "which depend on the configuration, policy values or the link "
582
0
               "interface are not supported.  Consider using "
583
0
               "target_include_directories instead."));
584
0
    return;
585
0
  }
586
587
0
  if (!input && exportDirs.empty()) {
588
0
    return;
589
0
  }
590
0
  if ((input && input->empty()) && exportDirs.empty()) {
591
    // Set to empty
592
0
    properties[propName].clear();
593
0
    return;
594
0
  }
595
596
0
  this->AddImportPrefix(exportDirs);
597
0
  includesDestinationDirs = exportDirs;
598
599
0
  std::string includes = (input ? *input : "");
600
0
  char const* const sep = input ? ";" : "";
601
0
  includes = cmStrCat(std::move(includes), sep, exportDirs);
602
0
  std::string prepro = cmGeneratorExpression::Preprocess(
603
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
604
0
  if (!prepro.empty()) {
605
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
606
607
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
608
0
      return;
609
0
    }
610
0
    properties[propName] = prepro;
611
0
  }
612
0
}
613
614
void cmExportInstallFileGenerator::PopulateFileSetIncludeDirectoriesInterface(
615
  cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
616
  cmGeneratorExpression::PreprocessContext preprocessRule,
617
  ImportPropertyMap& properties)
618
0
{
619
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
620
621
0
  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
622
0
  cmValue includes = fileSet->GetProperty(propName);
623
624
0
  if (!includes) {
625
0
    return;
626
0
  }
627
0
  if (includes && includes->empty()) {
628
    // Set to empty
629
0
    properties[propName].clear();
630
0
    return;
631
0
  }
632
633
0
  std::string prepro = cmGeneratorExpression::Preprocess(
634
0
    *includes, preprocessRule, this->GetImportPrefixWithSlash());
635
0
  if (!prepro.empty()) {
636
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
637
638
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
639
0
      return;
640
0
    }
641
0
    properties[propName] = prepro;
642
0
  }
643
0
}
644
645
void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
646
  cmGeneratorTarget const* gt,
647
  cmGeneratorExpression::PreprocessContext preprocessRule,
648
  ImportPropertyMap& properties)
649
0
{
650
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
651
652
0
  char const* const propName = "INTERFACE_LINK_DEPENDS";
653
0
  cmValue input = gt->GetProperty(propName);
654
655
0
  if (!input) {
656
0
    return;
657
0
  }
658
659
0
  if (input->empty()) {
660
0
    properties[propName].clear();
661
0
    return;
662
0
  }
663
664
0
  std::string prepro = cmGeneratorExpression::Preprocess(
665
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
666
0
  if (!prepro.empty()) {
667
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
668
669
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
670
0
      return;
671
0
    }
672
0
    properties[propName] = prepro;
673
0
  }
674
0
}
675
676
void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface(
677
  cmGeneratorTarget const* gt,
678
  cmGeneratorExpression::PreprocessContext preprocessRule,
679
  ImportPropertyMap& properties)
680
0
{
681
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
682
683
0
  char const* const propName = "INTERFACE_LINK_DIRECTORIES";
684
0
  cmValue input = gt->GetProperty(propName);
685
686
0
  if (!input) {
687
0
    return;
688
0
  }
689
690
0
  if (input->empty()) {
691
0
    properties[propName].clear();
692
0
    return;
693
0
  }
694
695
0
  std::string prepro = cmGeneratorExpression::Preprocess(
696
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
697
0
  if (!prepro.empty()) {
698
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
699
700
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
701
0
      return;
702
0
    }
703
0
    properties[propName] = prepro;
704
0
  }
705
0
}