Coverage Report

Created: 2026-02-09 06:05

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 "cmGeneratorTarget.h"
16
#include "cmGlobalGenerator.h"
17
#include "cmInstallTargetGenerator.h"
18
#include "cmList.h"
19
#include "cmLocalGenerator.h"
20
#include "cmMakefile.h"
21
#include "cmMessageType.h"
22
#include "cmStringAlgorithms.h"
23
#include "cmSystemTools.h"
24
#include "cmTarget.h"
25
#include "cmTargetExport.h"
26
#include "cmValue.h"
27
#include "cmake.h"
28
29
cmExportInstallFileGenerator::cmExportInstallFileGenerator(
30
  cmInstallExportGenerator* iegen)
31
0
  : IEGen(iegen)
32
0
{
33
0
}
34
35
void cmExportInstallFileGenerator::ReplaceInstallPrefix(
36
  std::string& input) const
37
0
{
38
0
  cmGeneratorExpression::ReplaceInstallPrefix(input, this->GetInstallPrefix());
39
0
}
40
41
void cmExportInstallFileGenerator::PopulateImportProperties(
42
  std::string const& config, std::string const& suffix,
43
  cmTargetExport const* targetExport, ImportPropertyMap& properties,
44
  std::set<std::string>& importedLocations)
45
0
{
46
0
  this->SetImportLocationProperty(config, suffix,
47
0
                                  targetExport->ArchiveGenerator, properties,
48
0
                                  importedLocations);
49
0
  this->SetImportLocationProperty(config, suffix,
50
0
                                  targetExport->LibraryGenerator, properties,
51
0
                                  importedLocations);
52
0
  this->SetImportLocationProperty(config, suffix,
53
0
                                  targetExport->RuntimeGenerator, properties,
54
0
                                  importedLocations);
55
0
  this->SetImportLocationProperty(config, suffix,
56
0
                                  targetExport->ObjectsGenerator, properties,
57
0
                                  importedLocations);
58
0
  this->SetImportLocationProperty(config, suffix,
59
0
                                  targetExport->FrameworkGenerator, properties,
60
0
                                  importedLocations);
61
0
  this->SetImportLocationProperty(config, suffix,
62
0
                                  targetExport->BundleGenerator, properties,
63
0
                                  importedLocations);
64
65
  // If any file location was set for the target add it to the
66
  // import file.
67
0
  if (!properties.empty()) {
68
    // Get the rest of the target details.
69
0
    cmGeneratorTarget const* const gtgt = targetExport->Target;
70
0
    this->SetImportDetailProperties(config, suffix, gtgt, properties);
71
72
    // TODO: PUBLIC_HEADER_LOCATION
73
    // This should wait until the build feature propagation stuff is done.
74
    // Then this can be a propagated include directory.
75
    // this->GenerateImportProperty(config, te->HeaderGenerator, properties);
76
0
  }
77
0
}
78
79
std::string cmExportInstallFileGenerator::GetImportXcFrameworkLocation(
80
  std::string const& config, cmTargetExport const* targetExport) const
81
0
{
82
0
  std::string importedXcFrameworkLocation = targetExport->XcFrameworkLocation;
83
0
  if (!importedXcFrameworkLocation.empty()) {
84
0
    importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
85
0
      importedXcFrameworkLocation,
86
0
      cmGeneratorExpression::PreprocessContext::InstallInterface,
87
0
      this->GetImportPrefixWithSlash());
88
0
    importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
89
0
      importedXcFrameworkLocation, targetExport->Target->GetLocalGenerator(),
90
0
      config, targetExport->Target, nullptr, targetExport->Target);
91
0
    if (!importedXcFrameworkLocation.empty() &&
92
0
        !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) &&
93
0
        !cmHasPrefix(importedXcFrameworkLocation,
94
0
                     this->GetImportPrefixWithSlash())) {
95
0
      return cmStrCat(this->GetImportPrefixWithSlash(),
96
0
                      importedXcFrameworkLocation);
97
0
    }
98
0
  }
99
100
0
  return importedXcFrameworkLocation;
101
0
}
102
103
bool cmExportInstallFileGenerator::GenerateImportFileConfig(
104
  std::string const& config)
105
0
{
106
  // Skip configurations not enabled for this export.
107
0
  if (!this->IEGen->InstallsForConfig(config)) {
108
0
    return true;
109
0
  }
110
111
  // Construct the name of the file to generate.
112
0
  std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase,
113
0
                                  this->GetConfigFileNameSeparator());
114
0
  if (!config.empty()) {
115
0
    fileName += cmSystemTools::LowerCase(config);
116
0
  } else {
117
0
    fileName += "noconfig";
118
0
  }
119
0
  fileName += this->FileExt;
120
121
  // Open the output file to generate it.
122
0
  cmGeneratedFileStream exportFileStream(fileName, true);
123
0
  if (!exportFileStream) {
124
0
    std::string se = cmSystemTools::GetLastSystemError();
125
0
    std::ostringstream e;
126
0
    e << "cannot write to file \"" << fileName << "\": " << se;
127
0
    cmSystemTools::Error(e.str());
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() == cmStateEnums::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, 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
cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
228
  cmTargetExport const* targetExport) const
229
0
{
230
0
  cmStateEnums::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 == cmStateEnums::OBJECT_LIBRARY &&
234
0
      !targetExport->ObjectsGenerator) {
235
0
    targetType = cmStateEnums::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
  std::vector<std::string> exportFiles;
268
0
  std::set<std::string> exportSets;
269
0
  std::set<std::string> namespaces;
270
271
0
  auto const& name = target->GetName();
272
0
  auto& allExportSets =
273
0
    target->GetLocalGenerator()->GetGlobalGenerator()->GetExportSets();
274
275
0
  for (auto const& exp : allExportSets) {
276
0
    auto const& exportSet = exp.second;
277
0
    auto const& targets = exportSet.GetTargetExports();
278
279
0
    if (std::any_of(targets.begin(), targets.end(),
280
0
                    [&name](std::unique_ptr<cmTargetExport> const& te) {
281
0
                      return te->TargetName == name;
282
0
                    })) {
283
0
      std::vector<cmInstallExportGenerator const*> const* installs =
284
0
        exportSet.GetInstallations();
285
0
      if (!installs->empty()) {
286
0
        exportSets.insert(exp.first);
287
0
        for (cmInstallExportGenerator const* install : *installs) {
288
0
          exportFiles.push_back(install->GetDestinationFile());
289
0
          namespaces.insert(install->GetNamespace());
290
0
        }
291
0
      }
292
0
    }
293
0
  }
294
0
  return { exportFiles, exportSets, namespaces };
295
0
}
296
297
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
298
  cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
299
  ExportInfo const& exportInfo) const
300
0
{
301
0
  std::ostringstream e;
302
0
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
303
0
    << this->GetExportName() << "\" ...) "
304
0
    << "includes target \"" << depender->GetName()
305
0
    << "\" which requires target \"" << dependee->GetName() << "\" ";
306
0
  if (exportInfo.Sets.empty()) {
307
0
    e << "that is not in any export set.";
308
0
  } else {
309
0
    if (exportInfo.Sets.size() == 1) {
310
0
      e << "that is not in this export set, but in another export set which "
311
0
           "is "
312
0
           "exported multiple times with different namespaces: ";
313
0
    } else {
314
0
      e << "that is not in this export set, but in multiple other export "
315
0
           "sets: ";
316
0
    }
317
0
    e << cmJoin(exportInfo.Files, ", ") << ".\n"
318
0
      << "An exported target cannot depend upon another target which is "
319
0
         "exported in more than one export set or with more than one "
320
0
         "namespace. "
321
0
         "Consider consolidating the exports of the \""
322
0
      << dependee->GetName() << "\" target to a single export.";
323
0
  }
324
0
  this->ReportError(e.str());
325
0
}
326
327
void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
328
  std::string const& targetName) const
329
0
{
330
0
  std::ostringstream e;
331
0
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
332
0
    << this->GetExportName() << "\" ...) "
333
0
    << "includes target \"" << targetName
334
0
    << "\" more than once in the export set.";
335
0
  this->ReportError(e.str());
336
0
}
337
338
void cmExportInstallFileGenerator::IssueMessage(
339
  MessageType type, std::string const& message) const
340
0
{
341
0
  this->IEGen->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
342
0
    type, message,
343
0
    this->IEGen->GetLocalGenerator()->GetMakefile()->GetBacktrace());
344
0
}
345
346
std::string cmExportInstallFileGenerator::InstallNameDir(
347
  cmGeneratorTarget const* target, std::string const& config)
348
0
{
349
0
  std::string install_name_dir;
350
351
0
  cmMakefile* mf = target->Target->GetMakefile();
352
0
  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
353
0
    auto const& prefix = this->GetInstallPrefix();
354
0
    install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix);
355
0
  }
356
357
0
  return install_name_dir;
358
0
}
359
360
std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
361
0
{
362
0
  return this->GetCxxModuleFile(this->GetExportSet()->GetName());
363
0
}
364
365
bool cmExportInstallFileGenerator::CollectExports(
366
  std::function<void(cmTargetExport const*)> const& visitor)
367
0
{
368
0
  auto pred = [&](std::unique_ptr<cmTargetExport> const& te) -> bool {
369
0
    if (te->NamelinkOnly) {
370
0
      return true;
371
0
    }
372
0
    if (this->ExportedTargets.insert(te->Target).second) {
373
0
      visitor(te.get());
374
0
      return true;
375
0
    }
376
377
0
    this->ComplainAboutDuplicateTarget(te->Target->GetName());
378
0
    return false;
379
0
  };
380
381
0
  auto const& targets = this->GetExportSet()->GetTargetExports();
382
0
  return std::all_of(targets.begin(), targets.end(), pred);
383
0
}
384
385
bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
386
  cmTargetExport const* targetExport, ImportPropertyMap& properties)
387
0
{
388
0
  cmGeneratorTarget const* const gt = targetExport->Target;
389
390
0
  std::string includesDestinationDirs;
391
0
  this->PopulateSystemIncludeDirectoriesInterface(
392
0
    gt, cmGeneratorExpression::InstallInterface, properties);
393
0
  this->PopulateIncludeDirectoriesInterface(
394
0
    gt, cmGeneratorExpression::InstallInterface, properties, *targetExport,
395
0
    includesDestinationDirs);
396
0
  this->PopulateLinkDirectoriesInterface(
397
0
    gt, cmGeneratorExpression::InstallInterface, properties);
398
0
  this->PopulateLinkDependsInterface(
399
0
    gt, cmGeneratorExpression::InstallInterface, properties);
400
0
  this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
401
0
                                 properties);
402
403
0
  return this->PopulateInterfaceProperties(
404
0
    gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface,
405
0
    properties);
406
0
}
407
408
namespace {
409
bool isSubDirectory(std::string const& a, std::string const& b)
410
0
{
411
0
  return (cmSystemTools::ComparePath(a, b) ||
412
0
          cmSystemTools::IsSubDirectory(a, b));
413
0
}
414
}
415
416
bool cmExportInstallFileGenerator::CheckInterfaceDirs(
417
  std::string const& prepro, cmGeneratorTarget const* target,
418
  std::string const& prop) const
419
0
{
420
0
  std::string const& installDir =
421
0
    target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
422
0
  std::string const& topSourceDir =
423
0
    target->GetLocalGenerator()->GetSourceDirectory();
424
0
  std::string const& topBinaryDir =
425
0
    target->GetLocalGenerator()->GetBinaryDirectory();
426
427
0
  std::vector<std::string> parts;
428
0
  cmGeneratorExpression::Split(prepro, parts);
429
430
0
  bool const inSourceBuild = topSourceDir == topBinaryDir;
431
432
0
  bool hadFatalError = false;
433
434
0
  for (std::string const& li : parts) {
435
0
    size_t genexPos = cmGeneratorExpression::Find(li);
436
0
    if (genexPos == 0) {
437
0
      continue;
438
0
    }
439
0
    if (cmHasPrefix(li, this->GetImportPrefixWithSlash())) {
440
0
      continue;
441
0
    }
442
0
    std::ostringstream e;
443
0
    if (genexPos != std::string::npos) {
444
0
      hadFatalError = true;
445
0
    }
446
0
    if (!cmSystemTools::FileIsFullPath(li)) {
447
      /* clang-format off */
448
0
      e << "Target \"" << target->GetName() << "\" " << prop <<
449
0
           " property contains relative path:\n"
450
0
           "  \"" << li << "\"";
451
      /* clang-format on */
452
0
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
453
0
                                                e.str());
454
0
    }
455
0
    bool inBinary = isSubDirectory(li, topBinaryDir);
456
0
    bool inSource = isSubDirectory(li, topSourceDir);
457
0
    if (isSubDirectory(li, installDir)) {
458
      // The include directory is inside the install tree.  If the
459
      // install tree is inside the source tree or build tree then do not
460
      // fall through to the checks below that the include directory is not
461
      // also inside the source tree or build tree.
462
0
      if ((!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
463
0
          (!inSource || isSubDirectory(installDir, topSourceDir))) {
464
0
        continue;
465
0
      }
466
0
    }
467
0
    if (inBinary) {
468
      /* clang-format off */
469
0
      e << "Target \"" << target->GetName() << "\" " << prop <<
470
0
           " property contains path:\n"
471
0
           "  \"" << li << "\"\nwhich is prefixed in the build directory.";
472
      /* clang-format on */
473
0
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
474
0
                                                e.str());
475
0
    }
476
0
    if (!inSourceBuild) {
477
0
      if (inSource) {
478
0
        e << "Target \"" << target->GetName() << "\" " << prop
479
0
          << " property contains path:\n"
480
0
             "  \""
481
0
          << li << "\"\nwhich is prefixed in the source directory.";
482
0
        target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
483
0
                                                  e.str());
484
0
      }
485
0
    }
486
0
  }
487
0
  return !hadFatalError;
488
0
}
489
490
void cmExportInstallFileGenerator::PopulateSourcesInterface(
491
  cmGeneratorTarget const* gt,
492
  cmGeneratorExpression::PreprocessContext preprocessRule,
493
  ImportPropertyMap& properties)
494
0
{
495
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
496
497
0
  char const* const propName = "INTERFACE_SOURCES";
498
0
  cmValue input = gt->GetProperty(propName);
499
500
0
  if (!input) {
501
0
    return;
502
0
  }
503
504
0
  if (input->empty()) {
505
0
    properties[propName].clear();
506
0
    return;
507
0
  }
508
509
0
  std::string prepro = cmGeneratorExpression::Preprocess(
510
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
511
0
  if (!prepro.empty()) {
512
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
513
514
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
515
0
      return;
516
0
    }
517
0
    properties[propName] = prepro;
518
0
  }
519
0
}
520
521
void cmExportInstallFileGenerator::PopulateSystemIncludeDirectoriesInterface(
522
  cmGeneratorTarget const* target,
523
  cmGeneratorExpression::PreprocessContext preprocessRule,
524
  ImportPropertyMap& properties)
525
0
{
526
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
527
528
0
  char const* const propName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
529
0
  cmValue input = target->GetProperty(propName);
530
531
0
  if (!input) {
532
0
    return;
533
0
  }
534
0
  if (input->empty()) {
535
    // Set to empty
536
0
    properties[propName].clear();
537
0
    return;
538
0
  }
539
540
0
  std::string includes = (input ? *input : "");
541
0
  std::string prepro = cmGeneratorExpression::Preprocess(
542
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
543
0
  if (!prepro.empty()) {
544
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
545
546
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
547
0
      return;
548
0
    }
549
0
    properties[propName] = prepro;
550
0
  }
551
0
}
552
553
void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
554
  cmGeneratorTarget const* target,
555
  cmGeneratorExpression::PreprocessContext preprocessRule,
556
  ImportPropertyMap& properties, cmTargetExport const& te,
557
  std::string& includesDestinationDirs)
558
0
{
559
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
560
561
0
  includesDestinationDirs.clear();
562
563
0
  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
564
0
  cmValue input = target->GetProperty(propName);
565
566
0
  cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
567
568
0
  std::string dirs = cmGeneratorExpression::Preprocess(
569
0
    cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
570
0
    preprocessRule, this->GetImportPrefixWithSlash());
571
0
  this->ReplaceInstallPrefix(dirs);
572
0
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
573
0
  std::string exportDirs =
574
0
    cge->Evaluate(target->GetLocalGenerator(), "", target);
575
576
0
  if (cge->GetHadContextSensitiveCondition()) {
577
0
    cmLocalGenerator* lg = target->GetLocalGenerator();
578
0
    std::ostringstream e;
579
0
    e << "Target \"" << target->GetName()
580
0
      << "\" is installed with "
581
0
         "INCLUDES DESTINATION set to a context sensitive path.  Paths which "
582
0
         "depend on the configuration, policy values or the link interface "
583
0
         "are "
584
0
         "not supported.  Consider using target_include_directories instead.";
585
0
    lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
586
0
    return;
587
0
  }
588
589
0
  if (!input && exportDirs.empty()) {
590
0
    return;
591
0
  }
592
0
  if ((input && input->empty()) && exportDirs.empty()) {
593
    // Set to empty
594
0
    properties[propName].clear();
595
0
    return;
596
0
  }
597
598
0
  this->AddImportPrefix(exportDirs);
599
0
  includesDestinationDirs = exportDirs;
600
601
0
  std::string includes = (input ? *input : "");
602
0
  char const* const sep = input ? ";" : "";
603
0
  includes += sep + exportDirs;
604
0
  std::string prepro = cmGeneratorExpression::Preprocess(
605
0
    includes, preprocessRule, this->GetImportPrefixWithSlash());
606
0
  if (!prepro.empty()) {
607
0
    this->ResolveTargetsInGeneratorExpressions(prepro, target);
608
609
0
    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
610
0
      return;
611
0
    }
612
0
    properties[propName] = prepro;
613
0
  }
614
0
}
615
616
void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
617
  cmGeneratorTarget const* gt,
618
  cmGeneratorExpression::PreprocessContext preprocessRule,
619
  ImportPropertyMap& properties)
620
0
{
621
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
622
623
0
  char const* const propName = "INTERFACE_LINK_DEPENDS";
624
0
  cmValue input = gt->GetProperty(propName);
625
626
0
  if (!input) {
627
0
    return;
628
0
  }
629
630
0
  if (input->empty()) {
631
0
    properties[propName].clear();
632
0
    return;
633
0
  }
634
635
0
  std::string prepro = cmGeneratorExpression::Preprocess(
636
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
637
0
  if (!prepro.empty()) {
638
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
639
640
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
641
0
      return;
642
0
    }
643
0
    properties[propName] = prepro;
644
0
  }
645
0
}
646
647
void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface(
648
  cmGeneratorTarget const* gt,
649
  cmGeneratorExpression::PreprocessContext preprocessRule,
650
  ImportPropertyMap& properties)
651
0
{
652
0
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);
653
654
0
  char const* const propName = "INTERFACE_LINK_DIRECTORIES";
655
0
  cmValue input = gt->GetProperty(propName);
656
657
0
  if (!input) {
658
0
    return;
659
0
  }
660
661
0
  if (input->empty()) {
662
0
    properties[propName].clear();
663
0
    return;
664
0
  }
665
666
0
  std::string prepro = cmGeneratorExpression::Preprocess(
667
0
    *input, preprocessRule, this->GetImportPrefixWithSlash());
668
0
  if (!prepro.empty()) {
669
0
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);
670
671
0
    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
672
0
      return;
673
0
    }
674
0
    properties[propName] = prepro;
675
0
  }
676
0
}