cmTarget.cxx 63.9 KB
Newer Older
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3
#include "cmTarget.h"
Brad King's avatar
Brad King committed
4

5
#include "cmsys/RegularExpression.hxx"
6 7
#include <algorithm>
#include <assert.h>
8
#include <initializer_list>
9
#include <iterator>
10 11 12
#include <set>
#include <sstream>
#include <string.h>
13
#include <unordered_set>
14

15 16
#include "cm_memory.hxx"

17
#include "cmAlgorithms.h"
18
#include "cmCustomCommand.h"
19
#include "cmGeneratorExpression.h"
20
#include "cmGeneratorTarget.h"
21 22 23
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
24
#include "cmMessageType.h"
25
#include "cmMessenger.h"
26
#include "cmProperty.h"
27
#include "cmPropertyMap.h"
28
#include "cmRange.h"
29
#include "cmSourceFile.h"
30
#include "cmSourceFileLocation.h"
31
#include "cmSourceFileLocationKind.h"
32
#include "cmState.h"
33 34
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
35
#include "cmSystemTools.h"
36
#include "cmTargetPropertyComputer.h"
37
#include "cmake.h"
38

39 40 41 42 43 44
template <>
const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>(
  cmTarget const* tgt)
{
  static std::string loc;
  if (tgt->IsImported()) {
45
    loc = tgt->ImportedGetFullPath("", cmStateEnums::RuntimeBinaryArtifact);
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    return loc.c_str();
  }

  cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
  if (!gg->GetConfigureDoneCMP0026()) {
    gg->CreateGenerationObjects();
  }
  cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
  loc = gt->GetLocationForBuild();
  return loc.c_str();
}

template <>
const char* cmTargetPropertyComputer::ComputeLocation<cmTarget>(
  cmTarget const* tgt, const std::string& config)
{
  static std::string loc;
  if (tgt->IsImported()) {
64 65
    loc =
      tgt->ImportedGetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
66 67 68 69 70 71 72 73
    return loc.c_str();
  }

  cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
  if (!gg->GetConfigureDoneCMP0026()) {
    gg->CreateGenerationObjects();
  }
  cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
74
  loc = gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
75 76 77 78 79 80 81 82 83 84
  return loc.c_str();
}

template <>
const char* cmTargetPropertyComputer::GetSources<cmTarget>(
  cmTarget const* tgt, cmMessenger* messenger,
  cmListFileBacktrace const& context)
{
  cmStringRange entries = tgt->GetSourceEntries();
  if (entries.empty()) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
85
    return nullptr;
86 87 88 89
  }

  std::ostringstream ss;
  const char* sep = "";
90
  for (std::string const& entry : entries) {
91
    std::vector<std::string> files;
92
    cmExpandList(entry, files);
93 94
    for (std::string const& file : files) {
      if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") &&
95
          file.back() == '>') {
96
        std::string objLibName = file.substr(17, file.size() - 18);
97 98 99 100

        if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
          ss << sep;
          sep = ";";
101
          ss << file;
102 103 104 105 106 107
          continue;
        }

        bool addContent = false;
        bool noMessage = true;
        std::ostringstream e;
108
        MessageType messageType = MessageType::AUTHOR_WARNING;
109 110 111 112 113 114 115 116 117 118 119 120 121
        switch (context.GetBottom().GetPolicy(cmPolicies::CMP0051)) {
          case cmPolicies::WARN:
            e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
            noMessage = false;
          case cmPolicies::OLD:
            break;
          case cmPolicies::REQUIRED_ALWAYS:
          case cmPolicies::REQUIRED_IF_USED:
          case cmPolicies::NEW:
            addContent = true;
        }
        if (!noMessage) {
          e << "Target \"" << tgt->GetName()
122 123 124 125 126 127
            << "\" contains $<TARGET_OBJECTS> generator expression in its "
               "sources list.  This content was not previously part of the "
               "SOURCES property when that property was read at configure "
               "time.  Code reading that property needs to be adapted to "
               "ignore the generator expression using the string(GENEX_STRIP) "
               "command.";
128 129 130 131 132
          messenger->IssueMessage(messageType, e.str(), context);
        }
        if (addContent) {
          ss << sep;
          sep = ";";
133
          ss << file;
134
        }
135
      } else if (cmGeneratorExpression::Find(file) == std::string::npos) {
136 137
        ss << sep;
        sep = ";";
138
        ss << file;
139
      } else {
140
        cmSourceFile* sf = tgt->GetMakefile()->GetOrCreateSource(file);
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
        // Construct what is known about this source file location.
        cmSourceFileLocation const& location = sf->GetLocation();
        std::string sname = location.GetDirectory();
        if (!sname.empty()) {
          sname += "/";
        }
        sname += location.GetName();

        ss << sep;
        sep = ";";
        // Append this list entry.
        ss << sname;
      }
    }
  }
  static std::string srcs;
  srcs = ss.str();
  return srcs.c_str();
}

161 162 163
class cmTargetInternals
{
public:
164
  cmStateEnums::TargetType TargetType;
165
  cmMakefile* Makefile;
166
  cmPolicies::PolicyMap PolicyMap;
167
  std::string Name;
168
  std::string InstallPath;
169
  std::string RuntimeInstallPath;
170
  cmPropertyMap Properties;
171 172
  bool IsGeneratorProvided;
  bool HaveInstallRule;
173
  bool IsDLLPlatform;
174
  bool IsAIX;
175 176 177 178
  bool IsAndroid;
  bool IsImportedTarget;
  bool ImportedGloballyVisible;
  bool BuildInterfaceIncludesAppended;
179
  std::set<BT<std::string>> Utilities;
180 181 182
  std::vector<cmCustomCommand> PreBuildCommands;
  std::vector<cmCustomCommand> PreLinkCommands;
  std::vector<cmCustomCommand> PostBuildCommands;
183
  std::vector<cmInstallTargetGenerator*> InstallGenerators;
184
  std::set<std::string> SystemIncludeDirectories;
185
  cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
186 187
  std::vector<std::string> IncludeDirectoriesEntries;
  std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
188 189
  std::vector<std::string> CompileOptionsEntries;
  std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
190 191
  std::vector<std::string> CompileFeaturesEntries;
  std::vector<cmListFileBacktrace> CompileFeaturesBacktraces;
192 193
  std::vector<std::string> CompileDefinitionsEntries;
  std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
194 195
  std::vector<std::string> SourceEntries;
  std::vector<cmListFileBacktrace> SourceBacktraces;
196 197
  std::vector<std::string> LinkOptionsEntries;
  std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
198 199
  std::vector<std::string> LinkDirectoriesEntries;
  std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
200 201
  std::vector<std::string> LinkImplementationPropertyEntries;
  std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
202 203
  std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
    TLLCommands;
204
  cmListFileBacktrace Backtrace;
205 206

public:
207 208 209
  bool CheckImportedLibName(std::string const& prop,
                            std::string const& value) const;

210
  std::string ProcessSourceItemCMP0049(const std::string& s);
211 212
};

213
cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
214
                   Visibility vis, cmMakefile* mf)
215
  : impl(cm::make_unique<cmTargetInternals>())
216
{
217
  assert(mf);
218
  impl->TargetType = type;
219
  impl->Makefile = mf;
220
  impl->Name = name;
221 222
  impl->IsGeneratorProvided = false;
  impl->HaveInstallRule = false;
223
  impl->IsDLLPlatform = false;
224
  impl->IsAIX = false;
225 226
  impl->IsAndroid = false;
  impl->IsImportedTarget =
227
    (vis == VisibilityImported || vis == VisibilityImportedGlobally);
228 229
  impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
  impl->BuildInterfaceIncludesAppended = false;
230

231
  // Check whether this is a DLL platform.
232
  impl->IsDLLPlatform =
233
    !impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
234

235 236 237 238
  // Check whether we are targeting AIX.
  impl->IsAIX =
    (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "AIX");

239
  // Check whether we are targeting an Android platform.
240
  impl->IsAndroid =
241
    (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
242

243 244 245 246
  std::string defKey;
  defKey.reserve(128);
  defKey += "CMAKE_";
  auto initProp = [this, mf, &defKey](const std::string& property) {
247
    // Replace everything after "CMAKE_"
248 249 250 251 252 253 254 255 256 257
    defKey.replace(defKey.begin() + 6, defKey.end(), property);
    if (const char* value = mf->GetDefinition(defKey)) {
      this->SetProperty(property, value);
    }
  };
  auto initPropValue = [this, mf, &defKey](const std::string& property,
                                           const char* default_value) {
    // Replace everything after "CMAKE_"
    defKey.replace(defKey.begin() + 6, defKey.end(), property);
    if (const char* value = mf->GetDefinition(defKey)) {
258 259 260 261 262 263
      this->SetProperty(property, value);
    } else if (default_value) {
      this->SetProperty(property, default_value);
    }
  };

264
  // Setup default property values.
265 266
  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetType() != cmStateEnums::UTILITY) {
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    initProp("ANDROID_API");
    initProp("ANDROID_API_MIN");
    initProp("ANDROID_ARCH");
    initProp("ANDROID_STL_TYPE");
    initProp("ANDROID_SKIP_ANT_STEP");
    initProp("ANDROID_PROCESS_MAX");
    initProp("ANDROID_PROGUARD");
    initProp("ANDROID_PROGUARD_CONFIG_PATH");
    initProp("ANDROID_SECURE_PROPS_PATH");
    initProp("ANDROID_NATIVE_LIB_DIRECTORIES");
    initProp("ANDROID_NATIVE_LIB_DEPENDENCIES");
    initProp("ANDROID_JAVA_SOURCE_DIR");
    initProp("ANDROID_JAR_DIRECTORIES");
    initProp("ANDROID_JAR_DEPENDENCIES");
    initProp("ANDROID_ASSETS_DIRECTORIES");
    initProp("ANDROID_ANT_ADDITIONAL_OPTIONS");
    initProp("BUILD_RPATH");
    initProp("BUILD_RPATH_USE_ORIGIN");
    initProp("INSTALL_NAME_DIR");
286
    initProp("INSTALL_REMOVE_ENVIRONMENT_RPATH");
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    initPropValue("INSTALL_RPATH", "");
    initPropValue("INSTALL_RPATH_USE_LINK_PATH", "OFF");
    initProp("INTERPROCEDURAL_OPTIMIZATION");
    initPropValue("SKIP_BUILD_RPATH", "OFF");
    initPropValue("BUILD_WITH_INSTALL_RPATH", "OFF");
    initProp("ARCHIVE_OUTPUT_DIRECTORY");
    initProp("LIBRARY_OUTPUT_DIRECTORY");
    initProp("RUNTIME_OUTPUT_DIRECTORY");
    initProp("PDB_OUTPUT_DIRECTORY");
    initProp("COMPILE_PDB_OUTPUT_DIRECTORY");
    initProp("FRAMEWORK");
    initProp("Fortran_FORMAT");
    initProp("Fortran_MODULE_DIRECTORY");
    initProp("Fortran_COMPILER_LAUNCHER");
    initProp("GNUtoMS");
    initProp("OSX_ARCHITECTURES");
    initProp("IOS_INSTALL_COMBINED");
    initProp("AUTOMOC");
    initProp("AUTOUIC");
    initProp("AUTORCC");
    initProp("AUTOGEN_ORIGIN_DEPENDS");
    initProp("AUTOGEN_PARALLEL");
    initProp("AUTOMOC_COMPILER_PREDEFINES");
    initProp("AUTOMOC_DEPEND_FILTERS");
    initProp("AUTOMOC_MACRO_NAMES");
    initProp("AUTOMOC_MOC_OPTIONS");
    initProp("AUTOUIC_OPTIONS");
    initProp("AUTOUIC_SEARCH_PATHS");
    initProp("AUTORCC_OPTIONS");
    initProp("LINK_DEPENDS_NO_SHARED");
    initProp("LINK_INTERFACE_LIBRARIES");
    initProp("MSVC_RUNTIME_LIBRARY");
    initProp("WIN32_EXECUTABLE");
    initProp("MACOSX_BUNDLE");
    initProp("MACOSX_RPATH");
    initProp("NO_SYSTEM_FROM_IMPORTED");
    initProp("BUILD_WITH_INSTALL_NAME_DIR");
    initProp("C_CLANG_TIDY");
    initProp("C_COMPILER_LAUNCHER");
    initProp("C_CPPLINT");
    initProp("C_CPPCHECK");
    initProp("C_INCLUDE_WHAT_YOU_USE");
    initProp("LINK_WHAT_YOU_USE");
    initProp("C_STANDARD");
    initProp("C_STANDARD_REQUIRED");
    initProp("C_EXTENSIONS");
    initProp("CXX_CLANG_TIDY");
    initProp("CXX_COMPILER_LAUNCHER");
    initProp("CXX_CPPLINT");
    initProp("CXX_CPPCHECK");
    initProp("CXX_INCLUDE_WHAT_YOU_USE");
    initProp("CXX_STANDARD");
    initProp("CXX_STANDARD_REQUIRED");
    initProp("CXX_EXTENSIONS");
    initProp("CUDA_STANDARD");
    initProp("CUDA_STANDARD_REQUIRED");
    initProp("CUDA_EXTENSIONS");
    initProp("CUDA_COMPILER_LAUNCHER");
    initProp("CUDA_SEPARABLE_COMPILATION");
346
    initProp("CUDA_RESOLVE_DEVICE_SYMBOLS");
347 348 349
    initProp("LINK_SEARCH_START_STATIC");
    initProp("LINK_SEARCH_END_STATIC");
    initProp("FOLDER");
350
    initProp("Swift_LANGUAGE_VERSION");
351 352
    initProp("Swift_MODULE_DIRECTORY");
    initProp("VS_JUST_MY_CODE_DEBUGGING");
353 354
#ifdef __APPLE__
    if (this->GetGlobalGenerator()->IsXcode()) {
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
      initProp("XCODE_GENERATE_SCHEME");
      initProp("XCODE_SCHEME_ADDRESS_SANITIZER");
      initProp("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN");
      initProp("XCODE_SCHEME_THREAD_SANITIZER");
      initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP");
      initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
      initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
      initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER");
      initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP");
      initProp("XCODE_SCHEME_MALLOC_SCRIBBLE");
      initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES");
      initProp("XCODE_SCHEME_GUARD_MALLOC");
      initProp("XCODE_SCHEME_ZOMBIE_OBJECTS");
      initProp("XCODE_SCHEME_MALLOC_STACK");
      initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
      initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS");
371 372
    }
#endif
373
  }
374 375

  // Setup per-configuration property default values.
376
  if (this->GetType() != cmStateEnums::UTILITY) {
377
    static const auto configProps = {
378
      /* clang-format needs this comment to break after the opening brace */
379 380 381
      "ARCHIVE_OUTPUT_DIRECTORY_",     "LIBRARY_OUTPUT_DIRECTORY_",
      "RUNTIME_OUTPUT_DIRECTORY_",     "PDB_OUTPUT_DIRECTORY_",
      "COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_",
382
      "INTERPROCEDURAL_OPTIMIZATION_"
383
    };
384 385 386
    // Collect the set of configuration types.
    std::vector<std::string> configNames;
    mf->GetConfigurations(configNames);
387 388
    for (std::string const& configName : configNames) {
      std::string configUpper = cmSystemTools::UpperCase(configName);
389
      for (auto const& prop : configProps) {
390 391
        // Interface libraries have no output locations, so honor only
        // the configuration map.
392
        if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY &&
393
            strcmp(prop, "MAP_IMPORTED_CONFIG_") != 0) {
394
          continue;
395
        }
396
        std::string property = cmStrCat(prop, configUpper);
397
        initProp(property);
398
      }
399

400 401 402 403 404
      // Initialize per-configuration name postfix property from the
      // variable only for non-executable targets.  This preserves
      // compatibility with previous CMake versions in which executables
      // did not support this variable.  Projects may still specify the
      // property directly.
405 406
      if (impl->TargetType != cmStateEnums::EXECUTABLE &&
          impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
407 408
        std::string property =
          cmStrCat(cmSystemTools::UpperCase(configName), "_POSTFIX");
409
        initProp(property);
410 411
      }
    }
412
  }
413 414

  // Save the backtrace of target construction.
415
  impl->Backtrace = impl->Makefile->GetBacktrace();
416

417
  if (!this->IsImported()) {
418 419
    // Initialize the INCLUDE_DIRECTORIES property based on the current value
    // of the same directory property:
420 421 422 423
    cmAppend(impl->IncludeDirectoriesEntries,
             impl->Makefile->GetIncludeDirectoriesEntries());
    cmAppend(impl->IncludeDirectoriesBacktraces,
             impl->Makefile->GetIncludeDirectoriesBacktraces());
424 425

    {
426
      auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories();
427
      impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end());
428
    }
429

430 431 432 433
    cmAppend(impl->CompileOptionsEntries,
             impl->Makefile->GetCompileOptionsEntries());
    cmAppend(impl->CompileOptionsBacktraces,
             impl->Makefile->GetCompileOptionsBacktraces());
434

435 436 437 438
    cmAppend(impl->LinkOptionsEntries,
             impl->Makefile->GetLinkOptionsEntries());
    cmAppend(impl->LinkOptionsBacktraces,
             impl->Makefile->GetLinkOptionsBacktraces());
439

440 441 442 443
    cmAppend(impl->LinkDirectoriesEntries,
             impl->Makefile->GetLinkDirectoriesEntries());
    cmAppend(impl->LinkDirectoriesBacktraces,
             impl->Makefile->GetLinkDirectoriesBacktraces());
444
  }
445

446 447
  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetType() != cmStateEnums::UTILITY) {
448 449 450 451
    initProp("C_VISIBILITY_PRESET");
    initProp("CXX_VISIBILITY_PRESET");
    initProp("CUDA_VISIBILITY_PRESET");
    initProp("VISIBILITY_INLINES_HIDDEN");
452
  }
453

454
  if (impl->TargetType == cmStateEnums::EXECUTABLE) {
455 456 457
    initProp("ANDROID_GUI");
    initProp("CROSSCOMPILING_EMULATOR");
    initProp("ENABLE_EXPORTS");
458
  }
459 460
  if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
      impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
461
    this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
462
  }
463 464
  if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
      impl->TargetType == cmStateEnums::EXECUTABLE) {
465
    initProp("WINDOWS_EXPORT_ALL_SYMBOLS");
466
  }
467

468 469
  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetType() != cmStateEnums::UTILITY) {
470
    initProp("POSITION_INDEPENDENT_CODE");
471
  }
472

473
  // Record current policies for later use.
474
  impl->Makefile->RecordPolicies(impl->PolicyMap);
475

476
  if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY) {
477
    // This policy is checked in a few conditions. The properties relevant
478 479
    // to the policy are always ignored for cmStateEnums::INTERFACE_LIBRARY
    // targets,
480
    // so ensure that the conditions don't lead to nonsense.
481
    impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
482
  }
483

484 485
  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetType() != cmStateEnums::UTILITY) {
486 487
    initProp("JOB_POOL_COMPILE");
    initProp("JOB_POOL_LINK");
488
  }
489

490
  if (impl->TargetType <= cmStateEnums::UTILITY) {
491
    initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
492
  }
493 494 495 496 497 498 499 500 501 502 503

  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetType() != cmStateEnums::UTILITY) {

    // check for "CMAKE_VS_GLOBALS" variable and set up target properties
    // if any
    const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
    if (globals) {
      const std::string genName = mf->GetGlobalGenerator()->GetName();
      if (cmHasLiteralPrefix(genName, "Visual Studio")) {
        std::vector<std::string> props;
504
        cmExpandList(globals, props);
505 506 507 508 509 510 511
        const std::string vsGlobal = "VS_GLOBAL_";
        for (const std::string& i : props) {
          // split NAME=VALUE
          const std::string::size_type assignment = i.find('=');
          if (assignment != std::string::npos) {
            const std::string propName = vsGlobal + i.substr(0, assignment);
            const std::string propValue = i.substr(assignment + 1);
512
            initPropValue(propName, propValue.c_str());
513 514 515 516 517
          }
        }
      }
    }
  }
518 519
}

520 521 522 523 524
cmTarget::cmTarget(cmTarget&&) noexcept = default;
cmTarget::~cmTarget() = default;

cmTarget& cmTarget::operator=(cmTarget&&) noexcept = default;

525 526 527 528 529
cmStateEnums::TargetType cmTarget::GetType() const
{
  return impl->TargetType;
}

530 531 532 533 534
cmMakefile* cmTarget::GetMakefile() const
{
  return impl->Makefile;
}

535 536 537 538 539
cmPolicies::PolicyMap const& cmTarget::GetPolicyMap() const
{
  return impl->PolicyMap;
}

540 541 542 543 544
const std::string& cmTarget::GetName() const
{
  return impl->Name;
}

545 546 547 548 549 550
cmPolicies::PolicyStatus cmTarget::GetPolicyStatus(
  cmPolicies::PolicyID policy) const
{
  return impl->PolicyMap.Get(policy);
}

551 552
cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
{
553
  return impl->Makefile->GetGlobalGenerator();
554 555
}

556
void cmTarget::AddUtility(std::string const& name, cmMakefile* mf)
557
{
558 559 560 561 562 563 564
  impl->Utilities.insert(
    BT<std::string>(name, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
}

std::set<BT<std::string>> const& cmTarget::GetUtilities() const
{
  return impl->Utilities;
565 566
}

567 568
cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
569
  return impl->Backtrace;
570
}
571

572
bool cmTarget::IsExecutableWithExports() const
573
{
574
  return (this->GetType() == cmStateEnums::EXECUTABLE &&
575 576 577
          this->GetPropertyAsBool("ENABLE_EXPORTS"));
}

578
bool cmTarget::IsFrameworkOnApple() const
579
{
580 581
  return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
           this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
582
          impl->Makefile->IsOn("APPLE") &&
583
          this->GetPropertyAsBool("FRAMEWORK"));
584 585
}

586
bool cmTarget::IsAppBundleOnApple() const
587
{
588
  return (this->GetType() == cmStateEnums::EXECUTABLE &&
589
          impl->Makefile->IsOn("APPLE") &&
590 591 592
          this->GetPropertyAsBool("MACOSX_BUNDLE"));
}

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const
{
  return impl->PreBuildCommands;
}

void cmTarget::AddPreBuildCommand(cmCustomCommand const& cmd)
{
  impl->PreBuildCommands.push_back(cmd);
}

std::vector<cmCustomCommand> const& cmTarget::GetPreLinkCommands() const
{
  return impl->PreLinkCommands;
}

void cmTarget::AddPreLinkCommand(cmCustomCommand const& cmd)
{
  impl->PreLinkCommands.push_back(cmd);
}

std::vector<cmCustomCommand> const& cmTarget::GetPostBuildCommands() const
{
  return impl->PostBuildCommands;
}

void cmTarget::AddPostBuildCommand(cmCustomCommand const& cmd)
{
  impl->PostBuildCommands.push_back(cmd);
}

623 624
void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
625
  if (!srcs.empty()) {
626
    cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
627 628
    impl->SourceEntries.push_back(cmJoin(srcs, ";"));
    impl->SourceBacktraces.push_back(lfbt);
629
  }
630 631
}

632 633
void cmTarget::AddSources(std::vector<std::string> const& srcs)
{
634 635
  std::string srcFiles;
  const char* sep = "";
636
  for (auto filename : srcs) {
637
    if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
638
      if (!filename.empty()) {
639
        filename = impl->ProcessSourceItemCMP0049(filename);
640
        if (filename.empty()) {
641
          return;
642
        }
643
      }
644
      impl->Makefile->GetOrCreateSource(filename);
645
    }
646 647 648
    srcFiles += sep;
    srcFiles += filename;
    sep = ";";
649 650
  }
  if (!srcFiles.empty()) {
651
    cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
652 653
    impl->SourceEntries.push_back(std::move(srcFiles));
    impl->SourceBacktraces.push_back(lfbt);
654
  }
655
}
656

657
std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
658 659 660
{
  std::string src = s;

luz.paz's avatar
luz.paz committed
661
  // For backwards compatibility replace variables in source names.
662
  // This should eventually be removed.
663
  this->Makefile->ExpandVariablesInString(src);
664
  if (src != s) {
665
    std::ostringstream e;
666
    bool noMessage = false;
667
    MessageType messageType = MessageType::AUTHOR_WARNING;
668
    switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0049)) {
669
      case cmPolicies::WARN:
670
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n";
671 672 673 674 675 676 677
        break;
      case cmPolicies::OLD:
        noMessage = true;
        break;
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::NEW:
678
        messageType = MessageType::FATAL_ERROR;
679 680 681
    }
    if (!noMessage) {
      e << "Legacy variable expansion in source file \"" << s
682
        << "\" expanded to \"" << src << "\" in target \"" << this->Name
683 684
        << "\".  This behavior will be removed in a "
           "future version of CMake.";
685
      this->Makefile->IssueMessage(messageType, e.str());
686
      if (messageType == MessageType::FATAL_ERROR) {
687
        return "";
688 689
      }
    }
690
  }
691 692 693 694 695
  return src;
}

cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
{
696
  std::string src = impl->ProcessSourceItemCMP0049(s);
697
  if (!s.empty() && src.empty()) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
698
    return nullptr;
699
  }
700
  return this->AddSource(src);
701 702
}

703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
struct CreateLocation
{
  cmMakefile const* Makefile;

  CreateLocation(cmMakefile const* mf)
    : Makefile(mf)
  {
  }

  cmSourceFileLocation operator()(const std::string& filename)
  {
    return cmSourceFileLocation(this->Makefile, filename);
  }
};

struct LocationMatcher
719
{
720 721 722 723 724 725 726
  const cmSourceFileLocation& Needle;

  LocationMatcher(const cmSourceFileLocation& needle)
    : Needle(needle)
  {
  }

727
  bool operator()(cmSourceFileLocation& loc)
728 729 730 731 732 733 734 735 736
  {
    return loc.Matches(this->Needle);
  }
};

struct TargetPropertyEntryFinder
{
private:
  const cmSourceFileLocation& Needle;
737

738 739 740 741 742 743
public:
  TargetPropertyEntryFinder(const cmSourceFileLocation& needle)
    : Needle(needle)
  {
  }

744
  bool operator()(std::string const& entry)
745 746
  {
    std::vector<std::string> files;
747
    cmExpandList(entry, files);
748 749 750
    std::vector<cmSourceFileLocation> locations;
    locations.reserve(files.size());
    std::transform(files.begin(), files.end(), std::back_inserter(locations),
751 752 753
                   CreateLocation(this->Needle.GetMakefile()));

    return std::find_if(locations.begin(), locations.end(),
754
                        LocationMatcher(this->Needle)) != locations.end();
755 756 757
  }
};

758
cmSourceFile* cmTarget::AddSource(const std::string& src, bool before)
759
{
760
  cmSourceFileLocation sfl(impl->Makefile, src,
761
                           cmSourceFileLocationKind::Known);
762
  if (std::find_if(impl->SourceEntries.begin(), impl->SourceEntries.end(),
763
                   TargetPropertyEntryFinder(sfl)) ==
764
      impl->SourceEntries.end()) {
765
    cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
766 767 768 769 770
    impl->SourceEntries.insert(
      before ? impl->SourceEntries.begin() : impl->SourceEntries.end(), src);
    impl->SourceBacktraces.insert(before ? impl->SourceBacktraces.begin()
                                         : impl->SourceBacktraces.end(),
                                  lfbt);
771 772
  }
  if (cmGeneratorExpression::Find(src) != std::string::npos) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
773
    return nullptr;
774
  }
775
  return impl->Makefile->GetOrCreateSource(src, false,
776
                                           cmSourceFileLocationKind::Known);
777 778
}

779
void cmTarget::ClearDependencyInformation(cmMakefile& mf)
780
{
781
  std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS");
782
  mf.RemoveCacheDefinition(depname);
783 784
}

785 786
std::string cmTarget::GetDebugGeneratorExpressions(
  const std::string& value, cmTargetLinkLibraryType llt) const
787
{
788
  if (llt == GENERAL_LibraryType) {
789
    return value;
790
  }
791 792

  // Get the list of configurations considered to be DEBUG.
793
  std::vector<std::string> debugConfigs =
794
    impl->Makefile->GetCMakeInstance()->GetDebugConfigs();
795 796 797

  std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";

798
  if (debugConfigs.size() > 1) {
799 800
    for (std::string const& conf : cmMakeRange(debugConfigs).advance(1)) {
      configString += ",$<CONFIG:" + conf + ">";
801
    }
802 803
    configString = "$<OR:" + configString + ">";
  }
804

805
  if (llt == OPTIMIZED_LibraryType) {
806
    configString = "$<NOT:" + configString + ">";
807
  }
808 809 810
  return "$<" + configString + ":" + value + ">";
}

811
static std::string targetNameGenex(const std::string& lib)
812
{
813
  return "$<TARGET_NAME:" + lib + ">";
814 815
}

816 817
bool cmTarget::PushTLLCommandTrace(TLLSignature signature,
                                   cmListFileContext const& lfc)
818 819
{
  bool ret = true;
820 821
  if (!impl->TLLCommands.empty()) {
    if (impl->TLLCommands.back().first != signature) {
822 823
      ret = false;
    }
824
  }
825 826
  if (impl->TLLCommands.empty() || impl->TLLCommands.back().second != lfc) {
    impl->TLLCommands.emplace_back(signature, lfc);
827
  }
828 829 830
  return ret;
}

831
void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
832
{
833 834
  const char* sigString =
    (sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain");
835
  s << "The uses of the " << sigString << " signature are here:\n";
836
  cmStateDirectory cmDir = impl->Makefile->GetStateSnapshot().GetDirectory();
837
  for (auto const& cmd : impl->TLLCommands) {
838 839
    if (cmd.first == sig) {
      cmListFileContext lfc = cmd.second;
840
      lfc.FilePath = cmDir.ConvertToRelPathIfNotContained(
841
        impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
842
      s << " * " << lfc << std::endl;
843
    }
844
  }
845 846
}

847 848 849 850 851 852 853 854 855 856
std::string const& cmTarget::GetInstallPath() const
{
  return impl->InstallPath;
}

void cmTarget::SetInstallPath(std::string const& name)
{
  impl->InstallPath = name;
}

857 858 859 860 861 862 863 864 865 866
std::string const& cmTarget::GetRuntimeInstallPath() const
{
  return impl->RuntimeInstallPath;
}

void cmTarget::SetRuntimeInstallPath(std::string const& name)
{
  impl->RuntimeInstallPath = name;
}

867 868 869 870 871 872 873 874 875 876
bool cmTarget::GetHaveInstallRule() const
{
  return impl->HaveInstallRule;
}

void cmTarget::SetHaveInstallRule(bool hir)
{
  impl->HaveInstallRule = hir;
}

877 878 879 880 881 882 883 884 885 886 887
void cmTarget::AddInstallGenerator(cmInstallTargetGenerator* g)
{
  impl->InstallGenerators.emplace_back(g);
}

std::vector<cmInstallTargetGenerator*> const& cmTarget::GetInstallGenerators()
  const
{
  return impl->InstallGenerators;
}

888 889 890 891 892 893 894 895 896 897
bool cmTarget::GetIsGeneratorProvided() const
{
  return impl->IsGeneratorProvided;
}

void cmTarget::SetIsGeneratorProvided(bool igp)
{
  impl->IsGeneratorProvided = igp;
}

898 899 900 901 902 903
cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries()
  const
{
  return impl->OriginalLinkLibraries;
}

904
void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
905
                              cmTargetLinkLibraryType llt)
906 907 908 909 910 911 912
{
  this->AddLinkLibrary(mf, lib, lib, llt);
}

void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
                              std::string const& libRef,
                              cmTargetLinkLibraryType llt)
913
{
914
  cmTarget* tgt = mf.FindTargetToUse(lib);
915
  {
916
    const bool isNonImportedTarget = tgt && !tgt->IsImported();
917

918
    const std::string libName =
919
      (isNonImportedTarget && llt != GENERAL_LibraryType)
920 921
      ? targetNameGenex(libRef)
      : libRef;
922 923 924
    this->AppendProperty(
      "LINK_LIBRARIES",
      this->GetDebugGeneratorExpressions(libName, llt).c_str());
925 926
  }

927
  if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef ||
928 929 930
      (tgt &&
       (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
        tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
931
      (impl->Name == lib)) {
932
    return;
933
  }
934

935
  impl->OriginalLinkLibraries.emplace_back(lib, llt);
936

937
  // Add the explicit dependency information for libraries. This is
938 939 940
  // simply a set of libraries separated by ";". There should always
  // be a trailing ";". These library names are not canonical, in that
  // they may be "-framework x", "-ly", "/path/libz.a", etc.
941 942 943 944
  // We shouldn't remove duplicates here because external libraries
  // may be purposefully duplicated to handle recursive dependencies,
  // and we removing one instance will break the link line. Duplicates
  // will be appropriately eliminated at emit time.
945 946
  if (impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
      impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
947 948
      (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
       this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
949
    std::string targetEntry = cmStrCat(impl->Name, "_LIB_DEPENDS");
950
    std::string dependencies;
951 952
    const char* old_val = mf.GetDefinition(targetEntry);
    if (old_val) {
953
      dependencies += old_val;
954 955
    }
    switch (llt) {
956
      case GENERAL_LibraryType:
957 958
        dependencies += "general";
        break;
959
      case DEBUG_LibraryType:
960 961
        dependencies += "debug";
        break;
962
      case OPTIMIZED_LibraryType:
963 964
        dependencies += "optimized";
        break;
965
    }
966
    dependencies += ";";
967 968
    dependencies += lib;
    dependencies += ";";
969
    mf.AddCacheDefinition(targetEntry, dependencies.c_str(),
970
                          "Dependencies for the target", cmStateEnums::STATIC);
971
  }
972 973
}

974
void cmTarget::AddSystemIncludeDirectories(const std::set<std::string>& incs)
975
{
976 977 978 979 980 981
  impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
}

std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
{
  return impl->SystemIncludeDirectories;
982 983
}

984 985
cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
986
  return cmMakeRange(impl->IncludeDirectoriesEntries);
987 988 989 990
}

cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const
{
991
  return cmMakeRange(impl->IncludeDirectoriesBacktraces);
992 993
}

994 995
cmStringRange cmTarget::GetCompileOptionsEntries() const
{
996
  return cmMakeRange(impl->CompileOptionsEntries);
997 998 999 1000
}

cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const
{
1001
  return cmMakeRange(impl->CompileOptionsBacktraces);
1002 1003
}

1004 1005
cmStringRange cmTarget::GetCompileFeaturesEntries() const
{
1006
  return cmMakeRange(impl->CompileFeaturesEntries);
1007 1008 1009 1010
}

cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const
{
1011
  return cmMakeRange(impl->CompileFeaturesBacktraces);
1012 1013
}

1014 1015
cmStringRange cmTarget::GetCompileDefinitionsEntries() const
{
1016
  return cmMakeRange(impl->CompileDefinitionsEntries);
1017 1018 1019 1020
}

cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const
{
1021
  return cmMakeRange(impl->CompileDefinitionsBacktraces);
1022 1023
}

1024 1025
cmStringRange cmTarget::GetSourceEntries() const
{
1026
  return cmMakeRange(impl->SourceEntries);
1027 1028 1029 1030
}

cmBacktraceRange cmTarget::GetSourceBacktraces() const
{
1031
  return cmMakeRange(impl->SourceBacktraces);
1032 1033
}