cmTarget.cxx 63.7 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"
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 92
    std::vector<std::string> files;
    cmSystemTools::ExpandListArgument(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::set<std::string> SystemIncludeDirectories;
184
  cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
185 186
  std::vector<std::string> IncludeDirectoriesEntries;
  std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
187 188
  std::vector<std::string> CompileOptionsEntries;
  std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
189 190
  std::vector<std::string> CompileFeaturesEntries;
  std::vector<cmListFileBacktrace> CompileFeaturesBacktraces;
191 192
  std::vector<std::string> CompileDefinitionsEntries;
  std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
193 194
  std::vector<std::string> SourceEntries;
  std::vector<cmListFileBacktrace> SourceBacktraces;
195 196
  std::vector<std::string> LinkOptionsEntries;
  std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
197 198
  std::vector<std::string> LinkDirectoriesEntries;
  std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
199 200
  std::vector<std::string> LinkImplementationPropertyEntries;
  std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
201 202
  std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
    TLLCommands;
203
  cmListFileBacktrace Backtrace;
204 205

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

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

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

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

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

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

242 243 244 245
  std::string defKey;
  defKey.reserve(128);
  defKey += "CMAKE_";
  auto initProp = [this, mf, &defKey](const std::string& property) {
246
    // Replace everything after "CMAKE_"
247 248 249 250 251 252 253 254 255 256
    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)) {
257 258 259 260 261 262
      this->SetProperty(property, value);
    } else if (default_value) {
      this->SetProperty(property, default_value);
    }
  };

263
  // Setup default property values.
264 265
  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetType() != cmStateEnums::UTILITY) {
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 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 346 347 348
    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");
    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");
    initProp("LINK_SEARCH_START_STATIC");
    initProp("LINK_SEARCH_END_STATIC");
    initProp("FOLDER");
    initProp("Swift_MODULE_DIRECTORY");
    initProp("VS_JUST_MY_CODE_DEBUGGING");
349 350
#ifdef __APPLE__
    if (this->GetGlobalGenerator()->IsXcode()) {
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
      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");
367 368
    }
#endif
369
  }
370 371

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

397 398 399 400 401
      // 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.
402 403
      if (impl->TargetType != cmStateEnums::EXECUTABLE &&
          impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
404
        std::string property = cmSystemTools::UpperCase(configName);
405
        property += "_POSTFIX";
406
        initProp(property);
407 408
      }
    }
409
  }
410 411

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

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

    {
423
      auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories();
424
      impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end());
425
    }
426

427 428 429 430
    cmAppend(impl->CompileOptionsEntries,
             impl->Makefile->GetCompileOptionsEntries());
    cmAppend(impl->CompileOptionsBacktraces,
             impl->Makefile->GetCompileOptionsBacktraces());
431

432 433 434 435
    cmAppend(impl->LinkOptionsEntries,
             impl->Makefile->GetLinkOptionsEntries());
    cmAppend(impl->LinkOptionsBacktraces,
             impl->Makefile->GetLinkOptionsBacktraces());
436

437 438 439 440
    cmAppend(impl->LinkDirectoriesEntries,
             impl->Makefile->GetLinkDirectoriesEntries());
    cmAppend(impl->LinkDirectoriesBacktraces,
             impl->Makefile->GetLinkDirectoriesBacktraces());
441
  }
442

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

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

465 466
  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetType() != cmStateEnums::UTILITY) {
467
    initProp("POSITION_INDEPENDENT_CODE");
468
  }
469

470
  // Record current policies for later use.
471
  impl->Makefile->RecordPolicies(impl->PolicyMap);
472

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

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

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

  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;
        cmSystemTools::ExpandListArgument(globals, props);
        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);
509
            initPropValue(propName, propValue.c_str());
510 511 512 513 514
          }
        }
      }
    }
  }
515 516
}

517 518 519 520 521
cmTarget::cmTarget(cmTarget&&) noexcept = default;
cmTarget::~cmTarget() = default;

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

522 523 524 525 526
cmStateEnums::TargetType cmTarget::GetType() const
{
  return impl->TargetType;
}

527 528 529 530 531
cmMakefile* cmTarget::GetMakefile() const
{
  return impl->Makefile;
}

532 533 534 535 536
cmPolicies::PolicyMap const& cmTarget::GetPolicyMap() const
{
  return impl->PolicyMap;
}

537 538 539 540 541
const std::string& cmTarget::GetName() const
{
  return impl->Name;
}

542 543 544 545 546 547
cmPolicies::PolicyStatus cmTarget::GetPolicyStatus(
  cmPolicies::PolicyID policy) const
{
  return impl->PolicyMap.Get(policy);
}

548 549
cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
{
550
  return impl->Makefile->GetGlobalGenerator();
551 552
}

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

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

564 565
cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
566
  return impl->Backtrace;
567
}
568

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

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

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

590 591 592 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
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);
}

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

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

654
std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
655 656 657
{
  std::string src = s;

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

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

700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
struct CreateLocation
{
  cmMakefile const* Makefile;

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

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

struct LocationMatcher
716
{
717 718 719 720 721 722 723
  const cmSourceFileLocation& Needle;

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

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

struct TargetPropertyEntryFinder
{
private:
  const cmSourceFileLocation& Needle;
734

735 736 737 738 739 740
public:
  TargetPropertyEntryFinder(const cmSourceFileLocation& needle)
    : Needle(needle)
  {
  }

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

    return std::find_if(locations.begin(), locations.end(),
751
                        LocationMatcher(this->Needle)) != locations.end();
752 753 754
  }
};

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

776
void cmTarget::ClearDependencyInformation(cmMakefile& mf)
777
{
778
  std::string depname = this->GetName();
779
  depname += "_LIB_DEPENDS";
780
  mf.RemoveCacheDefinition(depname);
781 782
}

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

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

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

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

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

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

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

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

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

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

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

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

865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
bool cmTarget::GetHaveInstallRule() const
{
  return impl->HaveInstallRule;
}

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

bool cmTarget::GetIsGeneratorProvided() const
{
  return impl->IsGeneratorProvided;
}

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

885 886 887 888 889 890
cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries()
  const
{
  return impl->OriginalLinkLibraries;
}

891
void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
892
                              cmTargetLinkLibraryType llt)
893 894 895 896 897 898 899
{
  this->AddLinkLibrary(mf, lib, lib, llt);
}

void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
                              std::string const& libRef,
                              cmTargetLinkLibraryType llt)
900
{
901
  cmTarget* tgt = mf.FindTargetToUse(lib);
902
  {
903
    const bool isNonImportedTarget = tgt && !tgt->IsImported();
904

905
    const std::string libName =
906
      (isNonImportedTarget && llt != GENERAL_LibraryType)
907 908
      ? targetNameGenex(libRef)
      : libRef;
909 910 911
    this->AppendProperty(
      "LINK_LIBRARIES",
      this->GetDebugGeneratorExpressions(libName, llt).c_str());
912 913
  }

914
  if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef ||
915 916 917
      (tgt &&
       (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
        tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
918
      (impl->Name == lib)) {
919
    return;
920
  }
921

922
  impl->OriginalLinkLibraries.emplace_back(lib, llt);
923

924
  // Add the explicit dependency information for libraries. This is
925 926 927
  // 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.
928 929 930 931
  // 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.
932 933
  if (impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
      impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
934 935
      (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
       this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
936
    std::string targetEntry = impl->Name;
937 938
    targetEntry += "_LIB_DEPENDS";
    std::string dependencies;
939 940
    const char* old_val = mf.GetDefinition(targetEntry);
    if (old_val) {
941
      dependencies += old_val;
942 943
    }
    switch (llt) {
944
      case GENERAL_LibraryType:
945 946
        dependencies += "general";
        break;
947
      case DEBUG_LibraryType:
948 949
        dependencies += "debug";
        break;
950
      case OPTIMIZED_LibraryType:
951 952
        dependencies += "optimized";
        break;
953
    }
954
    dependencies += ";";
955 956
    dependencies += lib;
    dependencies += ";";
957
    mf.AddCacheDefinition(targetEntry, dependencies.c_str(),
958
                          "Dependencies for the target", cmStateEnums::STATIC);
959
  }
960 961
}

962
void cmTarget::AddSystemIncludeDirectories(const std::set<std::string>& incs)
963
{
964 965 966 967 968 969
  impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
}

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

972 973
cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
974
  return cmMakeRange(impl->IncludeDirectoriesEntries);
975 976 977 978
}

cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const
{
979
  return cmMakeRange(impl->IncludeDirectoriesBacktraces);
980 981
}

982 983
cmStringRange cmTarget::GetCompileOptionsEntries() const
{
984
  return cmMakeRange(impl->CompileOptionsEntries);
985 986 987 988
}

cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const
{
989
  return cmMakeRange(impl->CompileOptionsBacktraces);
990 991
}

992 993
cmStringRange cmTarget::GetCompileFeaturesEntries() const
{
994
  return cmMakeRange(impl->CompileFeaturesEntries);
995 996 997 998
}

cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const
{
999
  return cmMakeRange(impl->CompileFeaturesBacktraces);
1000 1001
}

1002 1003
cmStringRange cmTarget::GetCompileDefinitionsEntries() const
{
1004
  return cmMakeRange(impl->CompileDefinitionsEntries);
1005 1006 1007 1008
}

cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const
{
1009
  return cmMakeRange(impl->CompileDefinitionsBacktraces);
1010 1011
}

1012 1013
cmStringRange cmTarget::GetSourceEntries() const
{
1014
  return cmMakeRange(impl->SourceEntries);
1015 1016 1017 1018
}

cmBacktraceRange cmTarget::GetSourceBacktraces() const
{
1019
  return cmMakeRange(impl->SourceBacktraces);
1020 1021
}

1022 1023
cmStringRange cmTarget::GetLinkOptionsEntries() const
{
1024
  return cmMakeRange(impl->LinkOptionsEntries);
1025 1026 1027 1028
}

cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const
{
1029
  return cmMakeRange(impl->LinkOptionsBacktraces);
1030 1031
}

1032 1033
cmStringRange cmTarget::GetLinkDirectoriesEntries() const
{
1034
  return cmMakeRange(impl->LinkDirectoriesEntries);
1035 1036 1037 1038
}

cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const
{
1039
  return cmMakeRange(impl->LinkDirectoriesBacktraces);
1040 1041
}

1042 1043
cmStringRange cmTarget::GetLinkImplementationEntries() const
{
1044
  return cmMakeRange(impl->LinkImplementationPropertyEntries);
1045 1046 1047 1048
}

cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
{
1049
  return cmMakeRange(impl->LinkImplementationPropertyBacktraces);
1050 1051
}

1052
void cmTarget::SetProperty(const std::string& prop, const char* value)
1053
{
1054
  if (!cmTargetPropertyComputer::PassesWhitelist(
1055 1056
        this->GetType(), prop, impl->Makefile->GetMessenger(),
        impl->Makefile->GetBacktrace())) {
1057
    return;
1058
  }
1059 1060 1061 1062 1063 1064 1065 1066
#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
  MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
  MAKE_STATIC_PROP(COMPILE_FEATURES);
  MAKE_STATIC_PROP(COMPILE_OPTIONS);
  MAKE_STATIC_PROP(CUDA_PTX_COMPILATION);
  MAKE_STATIC_PROP(EXPORT_NAME);
  MAKE_STATIC_PROP(IMPORTED_GLOBAL);
  MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
1067
  MAKE_STATIC_PROP(LINK_OPTIONS);
1068
  MAKE_STATIC_PROP(LINK_DIRECTORIES);
1069 1070 1071 1072 1073 1074 1075
  MAKE_STATIC_PROP(LINK_LIBRARIES);
  MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
  MAKE_STATIC_PROP(NAME);
  MAKE_STATIC_PROP(SOURCES);
  MAKE_STATIC_PROP(TYPE);
#undef MAKE_STATIC_PROP
  if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
1076 1077
    std::ostringstream e;
    e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n";
1078
    impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1079 1080
    return;
  }
1081
  if (prop == propNAME) {
1082
    std::ostringstream e;
1083
    e << "NAME property is read-only\n";
1084
    impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1085 1086
    return;
  }
1087
  if (prop == propTYPE) {
1088 1089
    std::ostringstream e;
    e << "TYPE property is read-only\n";
1090
    impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1091
    return;
1092
  }
1093
  if (prop == propEXPORT_NAME && this->IsImported()) {
1094 1095
    std::ostringstream e;
    e << "EXPORT_NAME property can't be set on imported targets (\""
1096
      << impl->Name << "\")\n";
1097
    impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1098
    return;
1099
  }
1100
  if (prop == propSOURCES && this->IsImported()) {
1101
    std::ostringstream e;
1102
    e << "SOURCES property can't be set on imported targets (\"" << impl->Name
1103
      << "\")\n";
1104
    impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1105
    return;
1106
  }
1107
  if (prop == propIMPORTED_GLOBAL && !this->IsImported()) {
1108 1109
    std::ostringstream e;
    e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\""
1110
      << impl->Name << "\")\n";
1111
    impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1112 1113
    return;
  }
1114

1115
  if (prop == propINCLUDE_DIRECTORIES) {
1116 1117
    impl->IncludeDirectoriesEntries.clear();
    impl->IncludeDirectoriesBacktraces.clear();
1118
    if (value) {
1119
      impl->IncludeDirectoriesEntries.emplace_back(value);
1120
      cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
1121
      impl->IncludeDirectoriesBacktraces.push_back(lfbt);
1122
    }
1123
  } else if (prop == propCOMPILE_OPTIONS) {
1124 1125
    impl->CompileOptionsEntries.clear();
    impl->CompileOptionsBacktraces.clear();
1126
    if (value) {
1127
      impl->CompileOptionsEntries.emplace_back(value);
1128
      cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
1129
      impl->CompileOptionsBacktraces.push_back(lfbt);
1130
    }
1131
  } else if (prop == propCOMPILE_FEATURES) {
1132 1133
    impl->CompileFeaturesEntries.clear();
    impl->CompileFeaturesBacktraces.clear();
1134
    if (value) {
1135
      impl->CompileFeaturesEntries.emplace_back(value);
1136
      cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
1137
      impl->CompileFeaturesBacktraces.push_back(lfbt);
1138
    }
1139
  } else if (prop == propCOMPILE_DEFINITIONS) {
1140 1141
    impl->CompileDefinitionsEntries.clear();
    impl->CompileDefinitionsBacktraces.clear();
1142
    if (value) {
1143
      impl->CompileDefinitionsEntries.emplace_back(value);
1144
      cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
1145
      impl->CompileDefinitionsBacktraces.push_back(lfbt);
1146
    }
1147
  } else if (prop == propLINK_OPTIONS) {
1148 1149
    impl->LinkOptionsEntries.clear();
    impl->LinkOptionsBacktraces.clear();
1150
    if (value) {
1151
      impl->LinkOptionsEntries.emplace_back(value);
1152
      cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
1153
      impl->LinkOptionsBacktraces.push_back(lfbt);