1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
8 #include <initializer_list>
13 #include <unordered_set>
16 #include <cm/string_view>
17 #include <cmext/algorithm>
18 #include <cmext/string_view>
20 #include "cmsys/RegularExpression.hxx"
22 #include "cmAlgorithms.h"
23 #include "cmCustomCommand.h"
24 #include "cmFileSet.h"
25 #include "cmGeneratorExpression.h"
26 #include "cmGeneratorTarget.h"
27 #include "cmGlobalGenerator.h"
28 #include "cmListFileCache.h"
29 #include "cmMakefile.h"
30 #include "cmMessageType.h"
31 #include "cmProperty.h"
32 #include "cmPropertyDefinition.h"
33 #include "cmPropertyMap.h"
35 #include "cmSourceFile.h"
36 #include "cmSourceFileLocation.h"
37 #include "cmSourceFileLocationKind.h"
39 #include "cmStateDirectory.h"
40 #include "cmStateSnapshot.h"
41 #include "cmSystemTools.h"
42 #include "cmTargetPropertyComputer.h"
47 const std::string& cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>(
50 static std::string loc;
51 if (tgt->IsImported()) {
52 loc = tgt->ImportedGetFullPath("", cmStateEnums::RuntimeBinaryArtifact);
56 cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
57 if (!gg->GetConfigureDoneCMP0026()) {
58 gg->CreateGenerationObjects();
60 cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
61 loc = gt->GetLocationForBuild();
66 const std::string& cmTargetPropertyComputer::ComputeLocation<cmTarget>(
67 cmTarget const* tgt, const std::string& config)
69 static std::string loc;
70 if (tgt->IsImported()) {
72 tgt->ImportedGetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
76 cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
77 if (!gg->GetConfigureDoneCMP0026()) {
78 gg->CreateGenerationObjects();
80 cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
81 loc = gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
86 cmValue cmTargetPropertyComputer::GetSources<cmTarget>(cmTarget const* tgt,
89 cmBTStringRange entries = tgt->GetSourceEntries();
90 if (entries.empty()) {
94 std::ostringstream ss;
96 for (auto const& entry : entries) {
97 std::vector<std::string> files = cmExpandedList(entry.Value);
98 for (std::string const& file : files) {
99 if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") &&
100 file.back() == '>') {
101 std::string objLibName = file.substr(17, file.size() - 18);
103 if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
110 bool addContent = false;
111 bool noMessage = true;
112 std::ostringstream e;
113 MessageType messageType = MessageType::AUTHOR_WARNING;
114 switch (mf.GetPolicyStatus(cmPolicies::CMP0051)) {
115 case cmPolicies::WARN:
116 e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
119 case cmPolicies::OLD:
121 case cmPolicies::REQUIRED_ALWAYS:
122 case cmPolicies::REQUIRED_IF_USED:
123 case cmPolicies::NEW:
128 e << "Target \"" << tgt->GetName()
129 << "\" contains $<TARGET_OBJECTS> generator expression in its "
130 "sources list. This content was not previously part of the "
131 "SOURCES property when that property was read at configure "
132 "time. Code reading that property needs to be adapted to "
133 "ignore the generator expression using the string(GENEX_STRIP) "
135 mf.IssueMessage(messageType, e.str());
142 } else if (cmGeneratorExpression::Find(file) == std::string::npos) {
147 cmSourceFile* sf = tgt->GetMakefile()->GetOrCreateSource(file);
148 // Construct what is known about this source file location.
149 cmSourceFileLocation const& location = sf->GetLocation();
150 std::string sname = location.GetDirectory();
151 if (!sname.empty()) {
154 sname += location.GetName();
158 // Append this list entry.
163 static std::string srcs;
165 return cmValue(srcs);
169 struct FileSetEntries
171 FileSetEntries(cm::static_string_view propertyName)
172 : PropertyName(propertyName)
176 cm::static_string_view const PropertyName;
177 std::vector<BT<std::string>> Entries;
182 FileSetType(cm::static_string_view typeName,
183 cm::static_string_view defaultDirectoryProperty,
184 cm::static_string_view defaultPathProperty,
185 cm::static_string_view directoryPrefix,
186 cm::static_string_view pathPrefix,
187 cm::static_string_view typeDescription,
188 cm::static_string_view defaultDescription,
189 cm::static_string_view arbitraryDescription,
190 FileSetEntries selfEntries, FileSetEntries interfaceEntries)
192 , DefaultDirectoryProperty(defaultDirectoryProperty)
193 , DefaultPathProperty(defaultPathProperty)
194 , DirectoryPrefix(directoryPrefix)
195 , PathPrefix(pathPrefix)
196 , TypeDescription(typeDescription)
197 , DefaultDescription(defaultDescription)
198 , ArbitraryDescription(arbitraryDescription)
199 , SelfEntries(std::move(selfEntries))
200 , InterfaceEntries(std::move(interfaceEntries))
204 cm::static_string_view const TypeName;
205 cm::static_string_view const DefaultDirectoryProperty;
206 cm::static_string_view const DefaultPathProperty;
207 cm::static_string_view const DirectoryPrefix;
208 cm::static_string_view const PathPrefix;
209 cm::static_string_view const TypeDescription;
210 cm::static_string_view const DefaultDescription;
211 cm::static_string_view const ArbitraryDescription;
213 FileSetEntries SelfEntries;
214 FileSetEntries InterfaceEntries;
216 template <typename ValueType>
217 bool WriteProperties(cmTarget* tgt, cmTargetInternals* impl,
218 const std::string& prop, ValueType value, bool clear);
219 std::pair<bool, cmValue> ReadProperties(cmTarget const* tgt,
220 cmTargetInternals const* impl,
221 const std::string& prop) const;
223 void AddFileSet(const std::string& name, cmFileSetVisibility vis,
224 cmListFileBacktrace bt);
228 class cmTargetInternals
231 cmStateEnums::TargetType TargetType;
232 cmMakefile* Makefile;
233 cmPolicies::PolicyMap PolicyMap;
235 std::string InstallPath;
236 std::string RuntimeInstallPath;
237 cmPropertyMap Properties;
238 bool IsGeneratorProvided;
239 bool HaveInstallRule;
243 bool IsImportedTarget;
244 bool ImportedGloballyVisible;
245 bool BuildInterfaceIncludesAppended;
247 std::set<BT<std::pair<std::string, bool>>> Utilities;
248 std::vector<cmCustomCommand> PreBuildCommands;
249 std::vector<cmCustomCommand> PreLinkCommands;
250 std::vector<cmCustomCommand> PostBuildCommands;
251 std::vector<cmInstallTargetGenerator*> InstallGenerators;
252 std::set<std::string> SystemIncludeDirectories;
253 cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
254 std::map<std::string, BTs<std::string>> LanguageStandardProperties;
255 std::vector<BT<std::string>> IncludeDirectoriesEntries;
256 std::map<cmTargetExport const*, std::vector<std::string>>
257 InstallIncludeDirectoriesEntries;
258 std::vector<BT<std::string>> CompileOptionsEntries;
259 std::vector<BT<std::string>> CompileFeaturesEntries;
260 std::vector<BT<std::string>> CompileDefinitionsEntries;
261 std::vector<BT<std::string>> PrecompileHeadersEntries;
262 std::vector<BT<std::string>> SourceEntries;
263 std::vector<BT<std::string>> LinkOptionsEntries;
264 std::vector<BT<std::string>> LinkDirectoriesEntries;
265 std::vector<BT<std::string>> LinkImplementationPropertyEntries;
266 std::vector<BT<std::string>> LinkInterfacePropertyEntries;
267 std::vector<BT<std::string>> LinkInterfaceDirectPropertyEntries;
268 std::vector<BT<std::string>> LinkInterfaceDirectExcludePropertyEntries;
269 std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
271 std::map<std::string, cmFileSet> FileSets;
272 cmListFileBacktrace Backtrace;
274 FileSetType HeadersFileSets;
275 FileSetType CxxModulesFileSets;
276 FileSetType CxxModuleHeadersFileSets;
280 bool CheckImportedLibName(std::string const& prop,
281 std::string const& value) const;
283 std::string ProcessSourceItemCMP0049(const std::string& s) const;
285 template <typename ValueType>
286 void AddDirectoryToFileSet(cmTarget* self, std::string const& fileSetName,
287 ValueType value, cm::string_view fileSetType,
288 cm::string_view description, bool clear);
289 template <typename ValueType>
290 void AddPathToFileSet(cmTarget* self, std::string const& fileSetName,
291 ValueType value, cm::string_view fileSetType,
292 cm::string_view description, bool clear);
293 cmValue GetFileSetDirectories(cmTarget const* self,
294 std::string const& fileSetName,
295 cm::string_view fileSetType) const;
296 cmValue GetFileSetPaths(cmTarget const* self, std::string const& fileSetName,
297 cm::string_view fileSetType) const;
299 cmListFileBacktrace GetBacktrace(
300 cm::optional<cmListFileBacktrace> const& bt) const
302 return bt ? *bt : this->Makefile->GetBacktrace();
306 cmTargetInternals::cmTargetInternals()
307 : HeadersFileSets("HEADERS"_s, "HEADER_DIRS"_s, "HEADER_SET"_s,
308 "HEADER_DIRS_"_s, "HEADER_SET_"_s, "Header"_s,
309 "The default header set"_s, "Header set"_s,
310 FileSetEntries("HEADER_SETS"_s),
311 FileSetEntries("INTERFACE_HEADER_SETS"_s))
312 , CxxModulesFileSets("CXX_MODULES"_s, "CXX_MODULE_DIRS"_s,
313 "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s,
314 "CXX_MODULE_SET_"_s, "C++ module"_s,
315 "The default C++ module set"_s, "C++ module set"_s,
316 FileSetEntries("CXX_MODULE_SETS"_s),
317 FileSetEntries("INTERFACE_CXX_MODULE_SETS"_s))
318 , CxxModuleHeadersFileSets(
319 "CXX_MODULE_HEADER_UNITS"_s, "CXX_MODULE_HEADER_UNIT_DIRS"_s,
320 "CXX_MODULE_HEADER_UNIT_SET"_s, "CXX_MODULE_HEADER_UNIT_DIRS_"_s,
321 "CXX_MODULE_HEADER_UNIT_SET_"_s, "C++ module header"_s,
322 "The default C++ module header set"_s, "C++ module header set"_s,
323 FileSetEntries("CXX_MODULE_HEADER_UNIT_SETS"_s),
324 FileSetEntries("INTERFACE_CXX_MODULE_HEADER_UNIT_SETS"_s))
328 template <typename ValueType>
329 bool FileSetType::WriteProperties(cmTarget* tgt, cmTargetInternals* impl,
330 const std::string& prop, ValueType value,
333 if (prop == this->DefaultDirectoryProperty) {
334 impl->AddDirectoryToFileSet(tgt, std::string(this->TypeName), value,
335 this->TypeName, this->DefaultDescription,
339 if (prop == this->DefaultPathProperty) {
340 impl->AddPathToFileSet(tgt, std::string(this->TypeName), value,
341 this->TypeName, this->DefaultDescription, clear);
344 if (cmHasPrefix(prop, this->DirectoryPrefix)) {
345 auto fileSetName = prop.substr(this->DirectoryPrefix.size());
346 if (fileSetName.empty()) {
347 impl->Makefile->IssueMessage(
348 MessageType::FATAL_ERROR,
349 cmStrCat(this->ArbitraryDescription, " name cannot be empty."));
351 impl->AddDirectoryToFileSet(
352 tgt, fileSetName, value, this->TypeName,
353 cmStrCat(this->ArbitraryDescription, " \"", fileSetName, "\""), clear);
357 if (cmHasPrefix(prop, this->PathPrefix)) {
358 auto fileSetName = prop.substr(this->PathPrefix.size());
359 if (fileSetName.empty()) {
360 impl->Makefile->IssueMessage(
361 MessageType::FATAL_ERROR,
362 cmStrCat(this->ArbitraryDescription, " name cannot be empty."));
364 impl->AddPathToFileSet(
365 tgt, fileSetName, value, this->TypeName,
366 cmStrCat(this->ArbitraryDescription, " \"", fileSetName, "\""), clear);
370 if (prop == this->SelfEntries.PropertyName) {
371 impl->Makefile->IssueMessage(
372 MessageType::FATAL_ERROR,
373 cmStrCat(this->SelfEntries.PropertyName, " property is read-only\n"));
376 if (prop == this->InterfaceEntries.PropertyName) {
377 impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
378 cmStrCat(this->InterfaceEntries.PropertyName,
379 " property is read-only\n"));
385 std::pair<bool, cmValue> FileSetType::ReadProperties(
386 cmTarget const* tgt, cmTargetInternals const* impl,
387 const std::string& prop) const
389 bool did_read = false;
390 cmValue value = nullptr;
391 if (prop == this->DefaultDirectoryProperty) {
392 value = impl->GetFileSetDirectories(tgt, std::string(this->TypeName),
395 } else if (prop == this->DefaultPathProperty) {
397 impl->GetFileSetPaths(tgt, std::string(this->TypeName), this->TypeName);
399 } else if (prop == this->SelfEntries.PropertyName) {
400 static std::string output;
401 output = cmJoin(this->SelfEntries.Entries, ";"_s);
402 value = cmValue(output);
404 } else if (prop == this->InterfaceEntries.PropertyName) {
405 static std::string output;
406 output = cmJoin(this->InterfaceEntries.Entries, ";"_s);
407 value = cmValue(output);
409 } else if (cmHasPrefix(prop, this->DirectoryPrefix)) {
410 std::string fileSetName = prop.substr(this->DirectoryPrefix.size());
411 if (!fileSetName.empty()) {
412 value = impl->GetFileSetDirectories(tgt, fileSetName, this->TypeName);
415 } else if (cmHasPrefix(prop, this->PathPrefix)) {
416 std::string fileSetName = prop.substr(this->PathPrefix.size());
417 if (!fileSetName.empty()) {
418 value = impl->GetFileSetPaths(tgt, fileSetName, this->TypeName);
422 return { did_read, value };
425 void FileSetType::AddFileSet(const std::string& name, cmFileSetVisibility vis,
426 cmListFileBacktrace bt)
428 if (cmFileSetVisibilityIsForSelf(vis)) {
429 this->SelfEntries.Entries.emplace_back(name, bt);
431 if (cmFileSetVisibilityIsForInterface(vis)) {
432 this->InterfaceEntries.Entries.emplace_back(name, std::move(bt));
437 #define SETUP_COMMON_LANGUAGE_PROPERTIES(lang) \
438 initProp(#lang "_COMPILER_LAUNCHER"); \
439 initProp(#lang "_STANDARD"); \
440 initProp(#lang "_STANDARD_REQUIRED"); \
441 initProp(#lang "_EXTENSIONS"); \
442 initProp(#lang "_VISIBILITY_PRESET")
445 cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
446 Visibility vis, cmMakefile* mf, PerConfig perConfig)
447 : impl(cm::make_unique<cmTargetInternals>())
450 this->impl->TargetType = type;
451 this->impl->Makefile = mf;
452 this->impl->Name = name;
453 this->impl->IsGeneratorProvided = false;
454 this->impl->HaveInstallRule = false;
455 this->impl->IsDLLPlatform = false;
456 this->impl->IsAIX = false;
457 this->impl->IsAndroid = false;
458 this->impl->IsImportedTarget =
459 (vis == VisibilityImported || vis == VisibilityImportedGlobally);
460 this->impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
461 this->impl->BuildInterfaceIncludesAppended = false;
462 this->impl->PerConfig = (perConfig == PerConfig::Yes);
464 // Check whether this is a DLL platform.
465 this->impl->IsDLLPlatform =
466 !this->impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")
469 // Check whether we are targeting AIX.
471 std::string const& systemName =
472 this->impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
473 this->impl->IsAIX = (systemName == "AIX" || systemName == "OS400");
476 // Check whether we are targeting an Android platform.
477 this->impl->IsAndroid = (this->impl->Makefile->GetSafeDefinition(
478 "CMAKE_SYSTEM_NAME") == "Android");
483 auto initProp = [this, mf, &defKey](const std::string& property) {
484 // Replace everything after "CMAKE_"
485 defKey.replace(defKey.begin() + 6, defKey.end(), property);
486 if (cmValue value = mf->GetDefinition(defKey)) {
487 this->SetProperty(property, value);
490 auto initPropValue = [this, mf, &defKey](const std::string& property,
491 const char* default_value) {
492 // Replace everything after "CMAKE_"
493 defKey.replace(defKey.begin() + 6, defKey.end(), property);
494 if (cmValue value = mf->GetDefinition(defKey)) {
495 this->SetProperty(property, value);
496 } else if (default_value) {
497 this->SetProperty(property, default_value);
501 // Setup default property values.
502 if (this->CanCompileSources()) {
504 SETUP_COMMON_LANGUAGE_PROPERTIES(C);
505 SETUP_COMMON_LANGUAGE_PROPERTIES(OBJC);
506 SETUP_COMMON_LANGUAGE_PROPERTIES(CXX);
507 SETUP_COMMON_LANGUAGE_PROPERTIES(OBJCXX);
508 SETUP_COMMON_LANGUAGE_PROPERTIES(CUDA);
509 SETUP_COMMON_LANGUAGE_PROPERTIES(HIP);
511 initProp("ANDROID_API");
512 initProp("ANDROID_API_MIN");
513 initProp("ANDROID_ARCH");
514 initProp("ANDROID_STL_TYPE");
515 initProp("ANDROID_SKIP_ANT_STEP");
516 initProp("ANDROID_PROCESS_MAX");
517 initProp("ANDROID_PROGUARD");
518 initProp("ANDROID_PROGUARD_CONFIG_PATH");
519 initProp("ANDROID_SECURE_PROPS_PATH");
520 initProp("ANDROID_NATIVE_LIB_DIRECTORIES");
521 initProp("ANDROID_NATIVE_LIB_DEPENDENCIES");
522 initProp("ANDROID_JAVA_SOURCE_DIR");
523 initProp("ANDROID_JAR_DIRECTORIES");
524 initProp("ANDROID_JAR_DEPENDENCIES");
525 initProp("ANDROID_ASSETS_DIRECTORIES");
526 initProp("ANDROID_ANT_ADDITIONAL_OPTIONS");
527 initProp("BUILD_RPATH");
528 initProp("BUILD_RPATH_USE_ORIGIN");
529 initProp("INSTALL_NAME_DIR");
530 initProp("INSTALL_REMOVE_ENVIRONMENT_RPATH");
531 initPropValue("INSTALL_RPATH", "");
532 initPropValue("INSTALL_RPATH_USE_LINK_PATH", "OFF");
533 initProp("INTERPROCEDURAL_OPTIMIZATION");
534 initPropValue("SKIP_BUILD_RPATH", "OFF");
535 initPropValue("BUILD_WITH_INSTALL_RPATH", "OFF");
536 initProp("ARCHIVE_OUTPUT_DIRECTORY");
537 initProp("LIBRARY_OUTPUT_DIRECTORY");
538 initProp("RUNTIME_OUTPUT_DIRECTORY");
539 initProp("PDB_OUTPUT_DIRECTORY");
540 initProp("COMPILE_PDB_OUTPUT_DIRECTORY");
541 initProp("FRAMEWORK");
542 initProp("FRAMEWORK_MULTI_CONFIG_POSTFIX");
543 initProp("Fortran_FORMAT");
544 initProp("Fortran_MODULE_DIRECTORY");
545 initProp("Fortran_COMPILER_LAUNCHER");
546 initProp("Fortran_PREPROCESS");
547 initProp("Fortran_VISIBILITY_PRESET");
549 initProp("OSX_ARCHITECTURES");
550 initProp("IOS_INSTALL_COMBINED");
554 initProp("AUTOGEN_ORIGIN_DEPENDS");
555 initProp("AUTOGEN_PARALLEL");
556 initProp("AUTOMOC_COMPILER_PREDEFINES");
557 initProp("AUTOMOC_DEPEND_FILTERS");
558 initProp("AUTOMOC_MACRO_NAMES");
559 initProp("AUTOMOC_MOC_OPTIONS");
560 initProp("AUTOUIC_OPTIONS");
561 initProp("AUTOMOC_PATH_PREFIX");
562 initProp("AUTOUIC_SEARCH_PATHS");
563 initProp("AUTORCC_OPTIONS");
564 initProp("LINK_DEPENDS_NO_SHARED");
565 initProp("LINK_INTERFACE_LIBRARIES");
566 initProp("MSVC_DEBUG_INFORMATION_FORMAT");
567 initProp("MSVC_RUNTIME_LIBRARY");
568 initProp("WATCOM_RUNTIME_LIBRARY");
569 initProp("WIN32_EXECUTABLE");
570 initProp("MACOSX_BUNDLE");
571 initProp("MACOSX_RPATH");
572 initProp("NO_SYSTEM_FROM_IMPORTED");
573 initProp("BUILD_WITH_INSTALL_NAME_DIR");
574 initProp("C_CLANG_TIDY");
575 initProp("C_CPPLINT");
576 initProp("C_CPPCHECK");
577 initProp("C_INCLUDE_WHAT_YOU_USE");
578 initProp("C_LINKER_LAUNCHER");
579 initProp("LINK_WHAT_YOU_USE");
580 initProp("CXX_CLANG_TIDY");
581 initProp("CXX_CPPLINT");
582 initProp("CXX_CPPCHECK");
583 initProp("CXX_INCLUDE_WHAT_YOU_USE");
584 initProp("CXX_LINKER_LAUNCHER");
585 initProp("CUDA_SEPARABLE_COMPILATION");
586 initProp("CUDA_RESOLVE_DEVICE_SYMBOLS");
587 initProp("CUDA_RUNTIME_LIBRARY");
588 initProp("CUDA_ARCHITECTURES");
589 initProp("HIP_RUNTIME_LIBRARY");
590 initProp("HIP_ARCHITECTURES");
591 initProp("VISIBILITY_INLINES_HIDDEN");
592 initProp("JOB_POOL_COMPILE");
593 initProp("JOB_POOL_LINK");
594 initProp("JOB_POOL_PRECOMPILE_HEADER");
595 initProp("ISPC_COMPILER_LAUNCHER");
596 initProp("ISPC_HEADER_DIRECTORY");
597 initPropValue("ISPC_HEADER_SUFFIX", "_ispc.h");
598 initProp("ISPC_INSTRUCTION_SETS");
599 initProp("LINK_SEARCH_START_STATIC");
600 initProp("LINK_SEARCH_END_STATIC");
601 initProp("OBJC_CLANG_TIDY");
602 initProp("OBJC_LINKER_LAUNCHER");
603 initProp("OBJCXX_CLANG_TIDY");
604 initProp("OBJCXX_LINKER_LAUNCHER");
605 initProp("Swift_LANGUAGE_VERSION");
606 initProp("Swift_MODULE_DIRECTORY");
607 initProp("VS_JUST_MY_CODE_DEBUGGING");
608 initProp("VS_NO_COMPILE_BATCHING");
609 initProp("DISABLE_PRECOMPILE_HEADERS");
610 initProp("UNITY_BUILD");
611 initProp("UNITY_BUILD_UNIQUE_ID");
612 initProp("OPTIMIZE_DEPENDENCIES");
613 initProp("EXPORT_COMPILE_COMMANDS");
614 initProp("COMPILE_WARNING_AS_ERROR");
615 initPropValue("UNITY_BUILD_BATCH_SIZE", "8");
616 initPropValue("UNITY_BUILD_MODE", "BATCH");
617 initPropValue("PCH_WARN_INVALID", "ON");
618 initPropValue("PCH_INSTANTIATE_TEMPLATES", "ON");
621 if (this->GetGlobalGenerator()->IsXcode()) {
622 initProp("XCODE_SCHEME_ADDRESS_SANITIZER");
623 initProp("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN");
624 initProp("XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING");
625 initProp("XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE");
626 initProp("XCODE_SCHEME_THREAD_SANITIZER");
627 initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP");
628 initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
629 initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
630 initProp("XCODE_SCHEME_LAUNCH_CONFIGURATION");
631 initProp("XCODE_SCHEME_ENABLE_GPU_API_VALIDATION");
632 initProp("XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION");
633 initProp("XCODE_SCHEME_WORKING_DIRECTORY");
634 initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER");
635 initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP");
636 initProp("XCODE_SCHEME_MALLOC_SCRIBBLE");
637 initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES");
638 initProp("XCODE_SCHEME_GUARD_MALLOC");
639 initProp("XCODE_SCHEME_LAUNCH_MODE");
640 initProp("XCODE_SCHEME_ZOMBIE_OBJECTS");
641 initProp("XCODE_SCHEME_MALLOC_STACK");
642 initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
643 initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS");
644 initProp("XCODE_SCHEME_ENVIRONMENT");
645 initPropValue("XCODE_LINK_BUILD_PHASE_MODE", "NONE");
651 initProp("VERIFY_INTERFACE_HEADER_SETS");
653 if (this->GetGlobalGenerator()->IsXcode()) {
654 initProp("XCODE_GENERATE_SCHEME");
657 // Setup per-configuration property default values.
658 if (this->GetType() != cmStateEnums::UTILITY &&
659 this->GetType() != cmStateEnums::GLOBAL_TARGET) {
660 static const auto configProps = {
661 /* clang-format needs this comment to break after the opening brace */
662 "ARCHIVE_OUTPUT_DIRECTORY_", "LIBRARY_OUTPUT_DIRECTORY_",
663 "RUNTIME_OUTPUT_DIRECTORY_", "PDB_OUTPUT_DIRECTORY_",
664 "COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_",
665 "INTERPROCEDURAL_OPTIMIZATION_"
667 // Collect the set of configuration types.
668 std::vector<std::string> configNames =
669 mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
670 for (std::string const& configName : configNames) {
671 std::string configUpper = cmSystemTools::UpperCase(configName);
672 for (auto const& prop : configProps) {
673 // Interface libraries have no output locations, so honor only
674 // the configuration map.
675 if (this->impl->TargetType == cmStateEnums::INTERFACE_LIBRARY &&
676 strcmp(prop, "MAP_IMPORTED_CONFIG_") != 0) {
679 std::string property = cmStrCat(prop, configUpper);
683 // Initialize per-configuration name postfix property from the
684 // variable only for non-executable targets. This preserves
685 // compatibility with previous CMake versions in which executables
686 // did not support this variable. Projects may still specify the
687 // property directly.
688 if (this->impl->TargetType != cmStateEnums::EXECUTABLE &&
689 this->impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
690 std::string property =
691 cmStrCat(cmSystemTools::UpperCase(configName), "_POSTFIX");
695 if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
696 this->impl->TargetType == cmStateEnums::STATIC_LIBRARY) {
697 std::string property = cmStrCat("FRAMEWORK_MULTI_CONFIG_POSTFIX_",
698 cmSystemTools::UpperCase(configName));
702 if (!this->IsImported()) {
703 initProp("LINK_LIBRARIES_ONLY_TARGETS");
707 // Save the backtrace of target construction.
708 this->impl->Backtrace = this->impl->Makefile->GetBacktrace();
710 if (!this->IsImported()) {
711 // Initialize the INCLUDE_DIRECTORIES property based on the current value
712 // of the same directory property:
713 cm::append(this->impl->IncludeDirectoriesEntries,
714 this->impl->Makefile->GetIncludeDirectoriesEntries());
717 auto const& sysInc = this->impl->Makefile->GetSystemIncludeDirectories();
718 this->impl->SystemIncludeDirectories.insert(sysInc.begin(),
722 cm::append(this->impl->CompileOptionsEntries,
723 this->impl->Makefile->GetCompileOptionsEntries());
725 cm::append(this->impl->LinkOptionsEntries,
726 this->impl->Makefile->GetLinkOptionsEntries());
728 cm::append(this->impl->LinkDirectoriesEntries,
729 this->impl->Makefile->GetLinkDirectoriesEntries());
732 if (this->impl->TargetType == cmStateEnums::EXECUTABLE) {
733 initProp("ANDROID_GUI");
734 initProp("CROSSCOMPILING_EMULATOR");
735 initProp("ENABLE_EXPORTS");
737 if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
738 this->impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
739 this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
740 } else if (this->CanCompileSources()) {
741 initProp("POSITION_INDEPENDENT_CODE");
743 if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
744 this->impl->TargetType == cmStateEnums::EXECUTABLE) {
745 initProp("AIX_EXPORT_ALL_SYMBOLS");
746 initProp("WINDOWS_EXPORT_ALL_SYMBOLS");
749 // Record current policies for later use.
750 this->impl->Makefile->RecordPolicies(this->impl->PolicyMap);
752 if (this->impl->TargetType == cmStateEnums::INTERFACE_LIBRARY) {
753 // This policy is checked in a few conditions. The properties relevant
754 // to the policy are always ignored for cmStateEnums::INTERFACE_LIBRARY
756 // so ensure that the conditions don't lead to nonsense.
757 this->impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
760 if (!this->IsImported()) {
761 initProp("DOTNET_SDK");
764 if (this->impl->TargetType <= cmStateEnums::GLOBAL_TARGET) {
765 initProp("DOTNET_TARGET_FRAMEWORK");
766 initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
769 // check for "CMAKE_VS_GLOBALS" variable and set up target properties
771 cmValue globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
773 const std::string genName = mf->GetGlobalGenerator()->GetName();
774 if (cmHasLiteralPrefix(genName, "Visual Studio")) {
775 std::vector<std::string> props = cmExpandedList(*globals);
776 const std::string vsGlobal = "VS_GLOBAL_";
777 for (const std::string& i : props) {
779 const std::string::size_type assignment = i.find('=');
780 if (assignment != std::string::npos) {
781 const std::string propName = vsGlobal + i.substr(0, assignment);
782 const std::string propValue = i.substr(assignment + 1);
783 initPropValue(propName, propValue.c_str());
789 if (this->IsImported() || mf->GetPropertyAsBool("SYSTEM")) {
790 this->SetProperty("SYSTEM", "ON");
793 for (auto const& prop : mf->GetState()->GetPropertyDefinitions().GetMap()) {
794 if (prop.first.second == cmProperty::TARGET &&
795 !prop.second.GetInitializeFromVariable().empty()) {
797 mf->GetDefinition(prop.second.GetInitializeFromVariable())) {
798 this->SetProperty(prop.first.first, value);
804 cmTarget::cmTarget(cmTarget&&) noexcept = default;
805 cmTarget::~cmTarget() = default;
807 cmTarget& cmTarget::operator=(cmTarget&&) noexcept = default;
809 cmStateEnums::TargetType cmTarget::GetType() const
811 return this->impl->TargetType;
814 cmMakefile* cmTarget::GetMakefile() const
816 return this->impl->Makefile;
819 cmPolicies::PolicyMap const& cmTarget::GetPolicyMap() const
821 return this->impl->PolicyMap;
824 const std::string& cmTarget::GetName() const
826 return this->impl->Name;
829 cmPolicies::PolicyStatus cmTarget::GetPolicyStatus(
830 cmPolicies::PolicyID policy) const
832 return this->impl->PolicyMap.Get(policy);
835 cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
837 return this->impl->Makefile->GetGlobalGenerator();
840 BTs<std::string> const* cmTarget::GetLanguageStandardProperty(
841 const std::string& propertyName) const
843 auto entry = this->impl->LanguageStandardProperties.find(propertyName);
844 if (entry != this->impl->LanguageStandardProperties.end()) {
845 return &entry->second;
851 void cmTarget::SetLanguageStandardProperty(std::string const& lang,
852 std::string const& value,
853 const std::string& feature)
855 cmListFileBacktrace featureBacktrace;
856 for (auto const& entry : this->impl->CompileFeaturesEntries) {
857 if (entry.Value == feature) {
858 featureBacktrace = entry.Backtrace;
863 BTs<std::string>& languageStandardProperty =
864 this->impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")];
865 if (languageStandardProperty.Value != value) {
866 languageStandardProperty.Value = value;
867 languageStandardProperty.Backtraces.clear();
869 languageStandardProperty.Backtraces.emplace_back(featureBacktrace);
872 void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf)
874 this->impl->Utilities.insert(BT<std::pair<std::string, bool>>(
875 { name, cross }, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
878 void cmTarget::AddUtility(BT<std::pair<std::string, bool>> util)
880 this->impl->Utilities.emplace(std::move(util));
883 std::set<BT<std::pair<std::string, bool>>> const& cmTarget::GetUtilities()
886 return this->impl->Utilities;
889 cmListFileBacktrace const& cmTarget::GetBacktrace() const
891 return this->impl->Backtrace;
894 bool cmTarget::IsExecutableWithExports() const
896 return (this->GetType() == cmStateEnums::EXECUTABLE &&
897 this->GetPropertyAsBool("ENABLE_EXPORTS"));
900 bool cmTarget::IsFrameworkOnApple() const
902 return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
903 this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
904 this->impl->Makefile->IsOn("APPLE") &&
905 this->GetPropertyAsBool("FRAMEWORK"));
908 bool cmTarget::IsAppBundleOnApple() const
910 return (this->GetType() == cmStateEnums::EXECUTABLE &&
911 this->impl->Makefile->IsOn("APPLE") &&
912 this->GetPropertyAsBool("MACOSX_BUNDLE"));
915 bool cmTarget::IsAndroidGuiExecutable() const
917 return (this->GetType() == cmStateEnums::EXECUTABLE &&
918 this->impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI"));
921 bool cmTarget::HasKnownObjectFileLocation(std::string* reason) const
923 return this->GetGlobalGenerator()->HasKnownObjectFileLocation(*this, reason);
926 std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const
928 return this->impl->PreBuildCommands;
931 void cmTarget::AddPreBuildCommand(cmCustomCommand const& cmd)
933 this->impl->PreBuildCommands.push_back(cmd);
936 void cmTarget::AddPreBuildCommand(cmCustomCommand&& cmd)
938 this->impl->PreBuildCommands.push_back(std::move(cmd));
941 std::vector<cmCustomCommand> const& cmTarget::GetPreLinkCommands() const
943 return this->impl->PreLinkCommands;
946 void cmTarget::AddPreLinkCommand(cmCustomCommand const& cmd)
948 this->impl->PreLinkCommands.push_back(cmd);
951 void cmTarget::AddPreLinkCommand(cmCustomCommand&& cmd)
953 this->impl->PreLinkCommands.push_back(std::move(cmd));
956 std::vector<cmCustomCommand> const& cmTarget::GetPostBuildCommands() const
958 return this->impl->PostBuildCommands;
961 void cmTarget::AddPostBuildCommand(cmCustomCommand const& cmd)
963 this->impl->PostBuildCommands.push_back(cmd);
966 void cmTarget::AddPostBuildCommand(cmCustomCommand&& cmd)
968 this->impl->PostBuildCommands.push_back(std::move(cmd));
971 void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
974 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
975 this->impl->SourceEntries.emplace_back(cmJoin(srcs, ";"), lfbt);
979 void cmTarget::AddSources(std::vector<std::string> const& srcs)
981 std::string srcFiles;
982 const char* sep = "";
983 for (auto filename : srcs) {
984 if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
985 if (!filename.empty()) {
986 filename = this->impl->ProcessSourceItemCMP0049(filename);
987 if (filename.empty()) {
991 this->impl->Makefile->GetOrCreateSource(filename);
994 srcFiles += filename;
997 if (!srcFiles.empty()) {
998 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
999 this->impl->SourceEntries.emplace_back(std::move(srcFiles), lfbt);
1003 std::string cmTargetInternals::ProcessSourceItemCMP0049(
1004 const std::string& s) const
1006 std::string src = s;
1008 // For backwards compatibility replace variables in source names.
1009 // This should eventually be removed.
1010 this->Makefile->ExpandVariablesInString(src);
1012 std::ostringstream e;
1013 bool noMessage = false;
1014 MessageType messageType = MessageType::AUTHOR_WARNING;
1015 switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0049)) {
1016 case cmPolicies::WARN:
1017 e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n";
1019 case cmPolicies::OLD:
1022 case cmPolicies::REQUIRED_ALWAYS:
1023 case cmPolicies::REQUIRED_IF_USED:
1024 case cmPolicies::NEW:
1025 messageType = MessageType::FATAL_ERROR;
1028 e << "Legacy variable expansion in source file \"" << s
1029 << "\" expanded to \"" << src << "\" in target \"" << this->Name
1030 << "\". This behavior will be removed in a "
1031 "future version of CMake.";
1032 this->Makefile->IssueMessage(messageType, e.str());
1033 if (messageType == MessageType::FATAL_ERROR) {
1041 std::string cmTarget::GetSourceCMP0049(const std::string& s)
1043 return this->impl->ProcessSourceItemCMP0049(s);
1046 struct CreateLocation
1048 cmMakefile const* Makefile;
1050 CreateLocation(cmMakefile const* mf)
1055 cmSourceFileLocation operator()(const std::string& filename) const
1057 return cmSourceFileLocation(this->Makefile, filename);
1061 struct LocationMatcher
1063 const cmSourceFileLocation& Needle;
1065 LocationMatcher(const cmSourceFileLocation& needle)
1070 bool operator()(cmSourceFileLocation& loc)
1072 return loc.Matches(this->Needle);
1076 struct TargetPropertyEntryFinder
1079 const cmSourceFileLocation& Needle;
1082 TargetPropertyEntryFinder(const cmSourceFileLocation& needle)
1087 bool operator()(BT<std::string> const& entry)
1089 std::vector<std::string> files = cmExpandedList(entry.Value);
1090 std::vector<cmSourceFileLocation> locations;
1091 locations.reserve(files.size());
1092 std::transform(files.begin(), files.end(), std::back_inserter(locations),
1093 CreateLocation(this->Needle.GetMakefile()));
1095 return std::find_if(locations.begin(), locations.end(),
1096 LocationMatcher(this->Needle)) != locations.end();
1100 cmSourceFile* cmTarget::AddSource(const std::string& src, bool before)
1102 cmSourceFileLocation sfl(this->impl->Makefile, src,
1103 cmSourceFileLocationKind::Known);
1105 this->impl->SourceEntries.begin(), this->impl->SourceEntries.end(),
1106 TargetPropertyEntryFinder(sfl)) == this->impl->SourceEntries.end()) {
1107 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1108 this->impl->SourceEntries.insert(before ? this->impl->SourceEntries.begin()
1109 : this->impl->SourceEntries.end(),
1110 BT<std::string>(src, lfbt));
1112 if (cmGeneratorExpression::Find(src) != std::string::npos) {
1115 return this->impl->Makefile->GetOrCreateSource(
1116 src, false, cmSourceFileLocationKind::Known);
1119 void cmTarget::ClearDependencyInformation(cmMakefile& mf) const
1121 std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS");
1122 mf.RemoveCacheDefinition(depname);
1125 std::string cmTarget::GetDebugGeneratorExpressions(
1126 const std::string& value, cmTargetLinkLibraryType llt) const
1128 if (llt == GENERAL_LibraryType) {
1132 // Get the list of configurations considered to be DEBUG.
1133 std::vector<std::string> debugConfigs =
1134 this->impl->Makefile->GetCMakeInstance()->GetDebugConfigs();
1136 std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
1138 if (debugConfigs.size() > 1) {
1139 for (std::string const& conf : cmMakeRange(debugConfigs).advance(1)) {
1140 configString += ",$<CONFIG:" + conf + ">";
1142 configString = "$<OR:" + configString + ">";
1145 if (llt == OPTIMIZED_LibraryType) {
1146 configString = "$<NOT:" + configString + ">";
1148 return "$<" + configString + ":" + value + ">";
1151 static std::string targetNameGenex(const std::string& lib)
1153 return "$<TARGET_NAME:" + lib + ">";
1156 bool cmTarget::PushTLLCommandTrace(TLLSignature signature,
1157 cmListFileContext const& lfc)
1160 if (!this->impl->TLLCommands.empty()) {
1161 if (this->impl->TLLCommands.back().first != signature) {
1165 if (this->impl->TLLCommands.empty() ||
1166 this->impl->TLLCommands.back().second != lfc) {
1167 this->impl->TLLCommands.emplace_back(signature, lfc);
1172 void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
1174 const char* sigString =
1175 (sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain");
1176 s << "The uses of the " << sigString << " signature are here:\n";
1177 for (auto const& cmd : this->impl->TLLCommands) {
1178 if (cmd.first == sig) {
1179 cmListFileContext lfc = cmd.second;
1180 lfc.FilePath = cmSystemTools::RelativeIfUnder(
1181 this->impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
1182 s << " * " << lfc << '\n';
1187 std::string const& cmTarget::GetInstallPath() const
1189 return this->impl->InstallPath;
1192 void cmTarget::SetInstallPath(std::string const& name)
1194 this->impl->InstallPath = name;
1197 std::string const& cmTarget::GetRuntimeInstallPath() const
1199 return this->impl->RuntimeInstallPath;
1202 void cmTarget::SetRuntimeInstallPath(std::string const& name)
1204 this->impl->RuntimeInstallPath = name;
1207 bool cmTarget::GetHaveInstallRule() const
1209 return this->impl->HaveInstallRule;
1212 void cmTarget::SetHaveInstallRule(bool hir)
1214 this->impl->HaveInstallRule = hir;
1217 void cmTarget::AddInstallGenerator(cmInstallTargetGenerator* g)
1219 this->impl->InstallGenerators.emplace_back(g);
1222 std::vector<cmInstallTargetGenerator*> const& cmTarget::GetInstallGenerators()
1225 return this->impl->InstallGenerators;
1228 bool cmTarget::GetIsGeneratorProvided() const
1230 return this->impl->IsGeneratorProvided;
1233 void cmTarget::SetIsGeneratorProvided(bool igp)
1235 this->impl->IsGeneratorProvided = igp;
1238 cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries()
1241 return this->impl->OriginalLinkLibraries;
1244 void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
1245 cmTargetLinkLibraryType llt)
1247 cmTarget* tgt = mf.FindTargetToUse(lib);
1249 const bool isNonImportedTarget = tgt && !tgt->IsImported();
1251 const std::string libName =
1252 (isNonImportedTarget && llt != GENERAL_LibraryType)
1253 ? targetNameGenex(lib)
1255 this->AppendProperty("LINK_LIBRARIES",
1256 this->GetDebugGeneratorExpressions(libName, llt),
1260 if (cmGeneratorExpression::Find(lib) != std::string::npos ||
1262 (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
1263 tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
1264 (this->impl->Name == lib)) {
1268 this->impl->OriginalLinkLibraries.emplace_back(lib, llt);
1270 // Add the explicit dependency information for libraries. This is
1271 // simply a set of libraries separated by ";". There should always
1272 // be a trailing ";". These library names are not canonical, in that
1273 // they may be "-framework x", "-ly", "/path/libz.a", etc.
1274 // We shouldn't remove duplicates here because external libraries
1275 // may be purposefully duplicated to handle recursive dependencies,
1276 // and we removing one instance will break the link line. Duplicates
1277 // will be appropriately eliminated at emit time.
1278 if (this->impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
1279 this->impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
1280 (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
1281 this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
1282 std::string targetEntry = cmStrCat(this->impl->Name, "_LIB_DEPENDS");
1283 std::string dependencies;
1284 cmValue old_val = mf.GetDefinition(targetEntry);
1286 dependencies += *old_val;
1289 case GENERAL_LibraryType:
1290 dependencies += "general";
1292 case DEBUG_LibraryType:
1293 dependencies += "debug";
1295 case OPTIMIZED_LibraryType:
1296 dependencies += "optimized";
1299 dependencies += ";";
1300 dependencies += lib;
1301 dependencies += ";";
1302 mf.AddCacheDefinition(targetEntry, dependencies,
1303 "Dependencies for the target", cmStateEnums::STATIC);
1307 void cmTarget::AddSystemIncludeDirectories(const std::set<std::string>& incs)
1309 this->impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
1312 std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
1314 return this->impl->SystemIncludeDirectories;
1317 void cmTarget::AddInstallIncludeDirectories(cmTargetExport const& te,
1318 cmStringRange const& incs)
1321 incs.begin(), incs.end(),
1322 std::back_inserter(this->impl->InstallIncludeDirectoriesEntries[&te]));
1325 cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries(
1326 cmTargetExport const& te) const
1328 auto i = this->impl->InstallIncludeDirectoriesEntries.find(&te);
1329 if (i == this->impl->InstallIncludeDirectoriesEntries.end()) {
1330 decltype(i->second) empty;
1331 return cmMakeRange(empty);
1333 return cmMakeRange(i->second);
1336 cmBTStringRange cmTarget::GetIncludeDirectoriesEntries() const
1338 return cmMakeRange(this->impl->IncludeDirectoriesEntries);
1341 cmBTStringRange cmTarget::GetCompileOptionsEntries() const
1343 return cmMakeRange(this->impl->CompileOptionsEntries);
1346 cmBTStringRange cmTarget::GetCompileFeaturesEntries() const
1348 return cmMakeRange(this->impl->CompileFeaturesEntries);
1351 cmBTStringRange cmTarget::GetCompileDefinitionsEntries() const
1353 return cmMakeRange(this->impl->CompileDefinitionsEntries);
1356 cmBTStringRange cmTarget::GetPrecompileHeadersEntries() const
1358 return cmMakeRange(this->impl->PrecompileHeadersEntries);
1361 cmBTStringRange cmTarget::GetSourceEntries() const
1363 return cmMakeRange(this->impl->SourceEntries);
1366 cmBTStringRange cmTarget::GetLinkOptionsEntries() const
1368 return cmMakeRange(this->impl->LinkOptionsEntries);
1371 cmBTStringRange cmTarget::GetLinkDirectoriesEntries() const
1373 return cmMakeRange(this->impl->LinkDirectoriesEntries);
1376 cmBTStringRange cmTarget::GetLinkImplementationEntries() const
1378 return cmMakeRange(this->impl->LinkImplementationPropertyEntries);
1381 cmBTStringRange cmTarget::GetLinkInterfaceEntries() const
1383 return cmMakeRange(this->impl->LinkInterfacePropertyEntries);
1386 cmBTStringRange cmTarget::GetLinkInterfaceDirectEntries() const
1388 return cmMakeRange(this->impl->LinkInterfaceDirectPropertyEntries);
1391 cmBTStringRange cmTarget::GetLinkInterfaceDirectExcludeEntries() const
1393 return cmMakeRange(this->impl->LinkInterfaceDirectExcludePropertyEntries);
1396 cmBTStringRange cmTarget::GetHeaderSetsEntries() const
1398 return cmMakeRange(this->impl->HeadersFileSets.SelfEntries.Entries);
1401 cmBTStringRange cmTarget::GetCxxModuleSetsEntries() const
1403 return cmMakeRange(this->impl->CxxModulesFileSets.SelfEntries.Entries);
1406 cmBTStringRange cmTarget::GetCxxModuleHeaderSetsEntries() const
1408 return cmMakeRange(this->impl->CxxModuleHeadersFileSets.SelfEntries.Entries);
1411 cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const
1413 return cmMakeRange(this->impl->HeadersFileSets.InterfaceEntries.Entries);
1416 cmBTStringRange cmTarget::GetInterfaceCxxModuleSetsEntries() const
1418 return cmMakeRange(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
1421 cmBTStringRange cmTarget::GetInterfaceCxxModuleHeaderSetsEntries() const
1424 this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries);
1428 #define MAKE_PROP(PROP) const std::string prop##PROP = #PROP
1429 MAKE_PROP(C_STANDARD);
1430 MAKE_PROP(CXX_STANDARD);
1431 MAKE_PROP(CUDA_STANDARD);
1432 MAKE_PROP(HIP_STANDARD);
1433 MAKE_PROP(OBJC_STANDARD);
1434 MAKE_PROP(OBJCXX_STANDARD);
1435 MAKE_PROP(COMPILE_DEFINITIONS);
1436 MAKE_PROP(COMPILE_FEATURES);
1437 MAKE_PROP(COMPILE_OPTIONS);
1438 MAKE_PROP(PRECOMPILE_HEADERS);
1439 MAKE_PROP(PRECOMPILE_HEADERS_REUSE_FROM);
1440 MAKE_PROP(CUDA_PTX_COMPILATION);
1441 MAKE_PROP(EXPORT_NAME);
1442 MAKE_PROP(IMPORTED);
1443 MAKE_PROP(IMPORTED_GLOBAL);
1444 MAKE_PROP(INCLUDE_DIRECTORIES);
1445 MAKE_PROP(LINK_OPTIONS);
1446 MAKE_PROP(LINK_DIRECTORIES);
1447 MAKE_PROP(LINK_LIBRARIES);
1448 MAKE_PROP(MANUALLY_ADDED_DEPENDENCIES);
1452 MAKE_PROP(BINARY_DIR);
1453 MAKE_PROP(SOURCE_DIR);
1456 MAKE_PROP(INTERFACE_LINK_LIBRARIES);
1457 MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT);
1458 MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE);
1463 // to workaround bug on GCC/AIX
1464 // Define a template to force conversion to std::string
1465 template <typename ValueType>
1466 std::string ConvertToString(ValueType value);
1469 std::string ConvertToString<const char*>(const char* value)
1471 return std::string(value);
1474 std::string ConvertToString<cmValue>(cmValue value)
1476 return std::string(*value);
1479 template <typename ValueType>
1480 bool StringIsEmpty(ValueType const& value);
1483 bool StringIsEmpty<const char*>(const char* const& value)
1485 return cmValue::IsEmpty(value);
1489 bool StringIsEmpty<cmValue>(cmValue const& value)
1491 return value.IsEmpty();
1495 bool StringIsEmpty<std::string>(std::string const& value)
1497 return value.empty();
1501 template <typename ValueType>
1502 void cmTarget::StoreProperty(const std::string& prop, ValueType value)
1504 if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
1505 this->impl->Makefile->IssueMessage(
1506 MessageType::FATAL_ERROR,
1507 "MANUALLY_ADDED_DEPENDENCIES property is read-only\n");
1510 if (prop == propNAME) {
1511 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
1512 "NAME property is read-only\n");
1515 if (prop == propTYPE) {
1516 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
1517 "TYPE property is read-only\n");
1520 if (prop == propEXPORT_NAME && this->IsImported()) {
1521 std::ostringstream e;
1522 e << "EXPORT_NAME property can't be set on imported targets (\""
1523 << this->impl->Name << "\")\n";
1524 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1527 if (prop == propSOURCES && this->IsImported()) {
1528 std::ostringstream e;
1529 e << "SOURCES property can't be set on imported targets (\""
1530 << this->impl->Name << "\")\n";
1531 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1534 if (prop == propIMPORTED_GLOBAL && !this->IsImported()) {
1535 std::ostringstream e;
1536 e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\""
1537 << this->impl->Name << "\")\n";
1538 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1542 if (prop == propINCLUDE_DIRECTORIES) {
1543 this->impl->IncludeDirectoriesEntries.clear();
1545 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1546 this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt);
1548 } else if (prop == propCOMPILE_OPTIONS) {
1549 this->impl->CompileOptionsEntries.clear();
1551 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1552 this->impl->CompileOptionsEntries.emplace_back(value, lfbt);
1554 } else if (prop == propCOMPILE_FEATURES) {
1555 this->impl->CompileFeaturesEntries.clear();
1557 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1558 this->impl->CompileFeaturesEntries.emplace_back(value, lfbt);
1560 } else if (prop == propCOMPILE_DEFINITIONS) {
1561 this->impl->CompileDefinitionsEntries.clear();
1563 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1564 this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt);
1566 } else if (prop == propLINK_OPTIONS) {
1567 this->impl->LinkOptionsEntries.clear();
1569 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1570 this->impl->LinkOptionsEntries.emplace_back(value, lfbt);
1572 } else if (prop == propLINK_DIRECTORIES) {
1573 this->impl->LinkDirectoriesEntries.clear();
1575 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1576 this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt);
1578 } else if (prop == propPRECOMPILE_HEADERS) {
1579 this->impl->PrecompileHeadersEntries.clear();
1581 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1582 this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt);
1584 } else if (prop == propLINK_LIBRARIES) {
1585 this->impl->LinkImplementationPropertyEntries.clear();
1587 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1588 this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt);
1590 } else if (prop == propINTERFACE_LINK_LIBRARIES) {
1591 this->impl->LinkInterfacePropertyEntries.clear();
1593 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1594 this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt);
1596 } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
1597 this->impl->LinkInterfaceDirectPropertyEntries.clear();
1599 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1600 this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt);
1602 } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
1603 this->impl->LinkInterfaceDirectExcludePropertyEntries.clear();
1605 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1606 this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value,
1609 } else if (prop == propSOURCES) {
1610 this->impl->SourceEntries.clear();
1612 cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
1613 this->impl->SourceEntries.emplace_back(value, lfbt);
1615 } else if (prop == propIMPORTED_GLOBAL) {
1616 if (!cmIsOn(value)) {
1617 std::ostringstream e;
1618 e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
1619 << this->impl->Name << "\")\n";
1620 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1623 /* no need to change anything if value does not change */
1624 if (!this->impl->ImportedGloballyVisible) {
1625 this->impl->ImportedGloballyVisible = true;
1626 this->GetGlobalGenerator()->IndexTarget(this);
1628 } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
1629 !this->impl->CheckImportedLibName(
1632 : std::string{})) { // NOLINT(bugprone-branch-clone)
1633 /* error was reported by check method */
1634 } else if (prop == propCUDA_PTX_COMPILATION &&
1635 this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
1636 std::ostringstream e;
1637 e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT "
1639 << this->impl->Name << "\")\n";
1640 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1642 } else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) {
1643 if (this->GetProperty("PRECOMPILE_HEADERS")) {
1644 std::ostringstream e;
1645 e << "PRECOMPILE_HEADERS property is already set on target (\""
1646 << this->impl->Name << "\")\n";
1647 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1650 auto* reusedTarget = this->impl->Makefile->GetCMakeInstance()
1651 ->GetGlobalGenerator()
1652 ->FindTarget(value);
1653 if (!reusedTarget) {
1654 const std::string e(
1655 "PRECOMPILE_HEADERS_REUSE_FROM set with non existing target");
1656 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
1660 std::string reusedFrom = reusedTarget->GetSafeProperty(prop);
1661 if (reusedFrom.empty()) {
1662 reusedFrom = ConvertToString(value);
1665 this->impl->Properties.SetProperty(prop, reusedFrom);
1667 reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom);
1668 reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
1669 cmStrCat(reusedFrom, ".dir/"));
1671 cmValue tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME");
1672 this->SetProperty("COMPILE_PDB_NAME", tmp);
1673 this->AddUtility(reusedFrom, false, this->impl->Makefile);
1674 } else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
1675 prop == propCUDA_STANDARD || prop == propHIP_STANDARD ||
1676 prop == propOBJC_STANDARD || prop == propOBJCXX_STANDARD) {
1678 this->impl->LanguageStandardProperties[prop] =
1679 BTs<std::string>(value, this->impl->Makefile->GetBacktrace());
1681 this->impl->LanguageStandardProperties.erase(prop);
1683 } else if (this->impl->HeadersFileSets.WriteProperties(
1684 this, this->impl.get(), prop, value, true)) {
1685 /* Handled in the `if` condition. */
1686 } else if (this->impl->CxxModulesFileSets.WriteProperties(
1687 this, this->impl.get(), prop, value, true)) {
1688 /* Handled in the `if` condition. */
1689 } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties(
1690 this, this->impl.get(), prop, value, true)) {
1691 /* Handled in the `if` condition. */
1693 this->impl->Properties.SetProperty(prop, value);
1697 void cmTarget::AppendProperty(const std::string& prop,
1698 const std::string& value,
1699 cm::optional<cmListFileBacktrace> const& bt,
1702 if (prop == "NAME") {
1703 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
1704 "NAME property is read-only\n");
1707 if (prop == "EXPORT_NAME" && this->IsImported()) {
1708 std::ostringstream e;
1709 e << "EXPORT_NAME property can't be set on imported targets (\""
1710 << this->impl->Name << "\")\n";
1711 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1714 if (prop == "SOURCES" && this->IsImported()) {
1715 std::ostringstream e;
1716 e << "SOURCES property can't be set on imported targets (\""
1717 << this->impl->Name << "\")\n";
1718 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1721 if (prop == "IMPORTED_GLOBAL") {
1722 std::ostringstream e;
1723 e << "IMPORTED_GLOBAL property can't be appended, only set on imported "
1725 << this->impl->Name << "\")\n";
1726 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1729 if (prop == "INCLUDE_DIRECTORIES") {
1730 if (!value.empty()) {
1731 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1732 this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt);
1734 } else if (prop == "COMPILE_OPTIONS") {
1735 if (!value.empty()) {
1736 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1737 this->impl->CompileOptionsEntries.emplace_back(value, lfbt);
1739 } else if (prop == "COMPILE_FEATURES") {
1740 if (!value.empty()) {
1741 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1742 this->impl->CompileFeaturesEntries.emplace_back(value, lfbt);
1744 } else if (prop == "COMPILE_DEFINITIONS") {
1745 if (!value.empty()) {
1746 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1747 this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt);
1749 } else if (prop == "LINK_OPTIONS") {
1750 if (!value.empty()) {
1751 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1752 this->impl->LinkOptionsEntries.emplace_back(value, lfbt);
1754 } else if (prop == "LINK_DIRECTORIES") {
1755 if (!value.empty()) {
1756 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1757 this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt);
1759 } else if (prop == "PRECOMPILE_HEADERS") {
1760 if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
1761 std::ostringstream e;
1762 e << "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target "
1764 << this->impl->Name << "\")\n";
1765 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
1768 if (!value.empty()) {
1769 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1770 this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt);
1772 } else if (prop == "LINK_LIBRARIES") {
1773 if (!value.empty()) {
1774 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1775 this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt);
1777 } else if (prop == propINTERFACE_LINK_LIBRARIES) {
1778 if (!value.empty()) {
1779 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1780 this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt);
1782 } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
1783 if (!value.empty()) {
1784 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1785 this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt);
1787 } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
1788 if (!value.empty()) {
1789 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1790 this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value,
1793 } else if (prop == "SOURCES") {
1794 cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
1795 this->impl->SourceEntries.emplace_back(value, lfbt);
1796 } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
1797 this->impl->Makefile->IssueMessage(
1798 MessageType::FATAL_ERROR, prop + " property may not be APPENDed.");
1799 } else if (prop == "C_STANDARD" || prop == "CXX_STANDARD" ||
1800 prop == "CUDA_STANDARD" || prop == "HIP_STANDARD" ||
1801 prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") {
1802 this->impl->Makefile->IssueMessage(
1803 MessageType::FATAL_ERROR, prop + " property may not be appended.");
1804 } else if (this->impl->HeadersFileSets.WriteProperties(
1805 this, this->impl.get(), prop, value,
1806 false)) { // NOLINT(bugprone-branch-clone)
1807 /* Handled in the `if` condition. */
1808 } else if (this->impl->CxxModulesFileSets.WriteProperties(
1809 this, this->impl.get(), prop, value, false)) {
1810 /* Handled in the `if` condition. */
1811 } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties(
1812 this, this->impl.get(), prop, value, false)) {
1813 /* Handled in the `if` condition. */
1815 this->impl->Properties.AppendProperty(prop, value, asString);
1819 void cmTarget::SetProperty(const std::string& prop, const char* value)
1821 this->StoreProperty(prop, value);
1823 void cmTarget::SetProperty(const std::string& prop, cmValue value)
1825 this->StoreProperty(prop, value);
1828 template <typename ValueType>
1829 void cmTargetInternals::AddDirectoryToFileSet(
1830 cmTarget* self, std::string const& fileSetName, ValueType value,
1831 cm::string_view fileSetType, cm::string_view description, bool clear)
1833 auto* fileSet = self->GetFileSet(fileSetName);
1835 this->Makefile->IssueMessage(
1836 MessageType::FATAL_ERROR,
1837 cmStrCat(description, "has not yet been created."));
1840 if (fileSet->GetType() != fileSetType) {
1841 this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
1842 cmStrCat("File set \"", fileSetName,
1843 "\" is not of type \"", fileSetType,
1848 fileSet->ClearDirectoryEntries();
1850 if (!StringIsEmpty(value)) {
1851 fileSet->AddDirectoryEntry(
1852 BT<std::string>(value, this->Makefile->GetBacktrace()));
1856 template <typename ValueType>
1857 void cmTargetInternals::AddPathToFileSet(
1858 cmTarget* self, std::string const& fileSetName, ValueType value,
1859 cm::string_view fileSetType, cm::string_view description, bool clear)
1861 auto* fileSet = self->GetFileSet(fileSetName);
1863 this->Makefile->IssueMessage(
1864 MessageType::FATAL_ERROR,
1865 cmStrCat(description, "has not yet been created."));
1868 if (fileSet->GetType() != fileSetType) {
1869 this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
1870 cmStrCat("File set \"", fileSetName,
1871 "\" is not of type \"", fileSetType,
1876 fileSet->ClearFileEntries();
1878 if (!StringIsEmpty(value)) {
1879 fileSet->AddFileEntry(
1880 BT<std::string>(value, this->Makefile->GetBacktrace()));
1884 cmValue cmTargetInternals::GetFileSetDirectories(
1885 cmTarget const* self, std::string const& fileSetName,
1886 cm::string_view fileSetType) const
1888 auto const* fileSet = self->GetFileSet(fileSetName);
1892 if (fileSet->GetType() != fileSetType) {
1893 this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
1894 cmStrCat("File set \"", fileSetName,
1895 "\" is not of type \"", fileSetType,
1899 static std::string output;
1900 output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s);
1901 return cmValue(output);
1904 cmValue cmTargetInternals::GetFileSetPaths(cmTarget const* self,
1905 std::string const& fileSetName,
1906 cm::string_view fileSetType) const
1908 auto const* fileSet = self->GetFileSet(fileSetName);
1912 if (fileSet->GetType() != fileSetType) {
1913 this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
1914 cmStrCat("File set \"", fileSetName,
1915 "\" is not of type \"", fileSetType,
1919 static std::string output;
1920 output = cmJoin(fileSet->GetFileEntries(), ";"_s);
1921 return cmValue(output);
1924 void cmTarget::AppendBuildInterfaceIncludes()
1926 if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
1927 this->GetType() != cmStateEnums::STATIC_LIBRARY &&
1928 this->GetType() != cmStateEnums::MODULE_LIBRARY &&
1929 this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
1930 !this->IsExecutableWithExports()) {
1933 if (this->impl->BuildInterfaceIncludesAppended) {
1936 this->impl->BuildInterfaceIncludesAppended = true;
1938 if (this->impl->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
1939 std::string dirs = this->impl->Makefile->GetCurrentBinaryDirectory();
1940 if (!dirs.empty()) {
1943 dirs += this->impl->Makefile->GetCurrentSourceDirectory();
1944 if (!dirs.empty()) {
1945 this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
1946 ("$<BUILD_INTERFACE:" + dirs + ">"));
1952 bool CheckLinkLibraryPattern(cm::string_view property,
1953 const std::vector<BT<std::string>>& value,
1956 // Look for <LINK_LIBRARY:> and </LINK_LIBRARY:> internal tags
1957 static cmsys::RegularExpression linkPattern(
1958 "(^|;)(</?LINK_(LIBRARY|GROUP):[^;>]*>)(;|$)");
1960 bool isValid = true;
1962 for (const auto& item : value) {
1963 if (!linkPattern.find(item.Value)) {
1970 context->IssueMessage(
1971 MessageType::FATAL_ERROR,
1973 "Property ", property, " contains the invalid item \"",
1974 linkPattern.match(2), "\". The ", property,
1975 " property may contain the generator-expression \"$<LINK_",
1976 linkPattern.match(3),
1977 ":...>\" which may be used to specify how the libraries are linked."),
1985 void cmTarget::FinalizeTargetConfiguration(
1986 const cmBTStringRange& noConfigCompileDefinitions,
1987 cm::optional<std::map<std::string, cmValue>>& perConfigCompileDefinitions)
1989 if (this->GetType() == cmStateEnums::GLOBAL_TARGET) {
1993 if (!CheckLinkLibraryPattern("LINK_LIBRARIES"_s,
1994 this->impl->LinkImplementationPropertyEntries,
1995 this->GetMakefile()->GetCMakeInstance()) ||
1996 !CheckLinkLibraryPattern("INTERFACE_LINK_LIBRARIES"_s,
1997 this->impl->LinkInterfacePropertyEntries,
1998 this->GetMakefile()->GetCMakeInstance()) ||
1999 !CheckLinkLibraryPattern("INTERFACE_LINK_LIBRARIES_DIRECT"_s,
2000 this->impl->LinkInterfaceDirectPropertyEntries,
2001 this->GetMakefile()->GetCMakeInstance())) {
2005 this->AppendBuildInterfaceIncludes();
2007 if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
2011 for (auto const& def : noConfigCompileDefinitions) {
2012 this->InsertCompileDefinition(def);
2015 auto* mf = this->GetMakefile();
2016 cmPolicies::PolicyStatus polSt = mf->GetPolicyStatus(cmPolicies::CMP0043);
2017 if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
2018 if (perConfigCompileDefinitions) {
2019 for (auto const& it : *perConfigCompileDefinitions) {
2020 if (cmValue val = it.second) {
2021 this->AppendProperty(it.first, *val);
2025 perConfigCompileDefinitions.emplace();
2026 std::vector<std::string> configs =
2027 mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
2029 for (std::string const& c : configs) {
2030 std::string defPropName =
2031 cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c));
2032 cmValue val = mf->GetProperty(defPropName);
2033 (*perConfigCompileDefinitions)[defPropName] = val;
2035 this->AppendProperty(defPropName, *val);
2042 void cmTarget::InsertInclude(BT<std::string> const& entry, bool before)
2044 auto position = before ? this->impl->IncludeDirectoriesEntries.begin()
2045 : this->impl->IncludeDirectoriesEntries.end();
2047 this->impl->IncludeDirectoriesEntries.insert(position, entry);
2050 void cmTarget::InsertCompileOption(BT<std::string> const& entry, bool before)
2052 auto position = before ? this->impl->CompileOptionsEntries.begin()
2053 : this->impl->CompileOptionsEntries.end();
2055 this->impl->CompileOptionsEntries.insert(position, entry);
2058 void cmTarget::InsertCompileDefinition(BT<std::string> const& entry)
2060 this->impl->CompileDefinitionsEntries.push_back(entry);
2063 void cmTarget::InsertLinkOption(BT<std::string> const& entry, bool before)
2065 auto position = before ? this->impl->LinkOptionsEntries.begin()
2066 : this->impl->LinkOptionsEntries.end();
2068 this->impl->LinkOptionsEntries.insert(position, entry);
2071 void cmTarget::InsertLinkDirectory(BT<std::string> const& entry, bool before)
2073 auto position = before ? this->impl->LinkDirectoriesEntries.begin()
2074 : this->impl->LinkDirectoriesEntries.end();
2076 this->impl->LinkDirectoriesEntries.insert(position, entry);
2079 void cmTarget::InsertPrecompileHeader(BT<std::string> const& entry)
2081 this->impl->PrecompileHeadersEntries.push_back(entry);
2085 void CheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
2086 const std::string& value,
2087 cmMakefile* context, bool imported)
2089 // Support imported and non-imported versions of the property.
2090 const char* base = (imported ? "IMPORTED_LINK_INTERFACE_LIBRARIES"
2091 : "LINK_INTERFACE_LIBRARIES");
2093 // Look for link-type keywords in the value.
2094 static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)");
2095 if (keys.find(value)) {
2097 std::ostringstream e;
2098 e << "Property " << prop << " may not contain link-type keyword \""
2099 << keys.match(2) << "\". "
2100 << "The " << base << " property has a per-configuration "
2101 << "version called " << base << "_<CONFIG> which may be "
2102 << "used to specify per-configuration rules.";
2105 << "Alternatively, an IMPORTED library may be created, configured "
2106 << "with a per-configuration location, and then named in the "
2107 << "property value. "
2108 << "See the add_library command's IMPORTED mode for details."
2110 << "If you have a list of libraries that already contains the "
2111 << "keyword, use the target_link_libraries command with its "
2112 << "LINK_INTERFACE_LIBRARIES mode to set the property. "
2113 << "The command automatically recognizes link-type keywords and sets "
2114 << "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG "
2115 << "properties accordingly.";
2117 context->IssueMessage(MessageType::FATAL_ERROR, e.str());
2121 void CheckINTERFACE_LINK_LIBRARIES(const std::string& value,
2122 cmMakefile* context)
2124 // Look for link-type keywords in the value.
2125 static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)");
2126 if (keys.find(value)) {
2128 std::ostringstream e;
2130 e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type "
2133 << "\". The INTERFACE_LINK_LIBRARIES "
2134 "property may contain configuration-sensitive generator-expressions "
2135 "which may be used to specify per-configuration rules.";
2137 context->IssueMessage(MessageType::FATAL_ERROR, e.str());
2141 void CheckIMPORTED_GLOBAL(const cmTarget* target, cmMakefile* context)
2143 const auto& targets = context->GetOwnedImportedTargets();
2145 std::find_if(targets.begin(), targets.end(),
2146 [&](const std::unique_ptr<cmTarget>& importTarget) -> bool {
2147 return target == importTarget.get();
2149 if (it == targets.end()) {
2150 std::ostringstream e;
2151 e << "Attempt to promote imported target \"" << target->GetName()
2152 << "\" to global scope (by setting IMPORTED_GLOBAL) "
2153 "which is not built in this directory.";
2154 context->IssueMessage(MessageType::FATAL_ERROR, e.str());
2159 void cmTarget::CheckProperty(const std::string& prop,
2160 cmMakefile* context) const
2162 // Certain properties need checking.
2163 if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) {
2164 if (cmValue value = this->GetProperty(prop)) {
2165 CheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false);
2167 } else if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) {
2168 if (cmValue value = this->GetProperty(prop)) {
2169 CheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true);
2171 } else if (prop == "INTERFACE_LINK_LIBRARIES") {
2172 if (cmValue value = this->GetProperty(prop)) {
2173 CheckINTERFACE_LINK_LIBRARIES(*value, context);
2175 } else if (prop == "IMPORTED_GLOBAL") {
2176 if (this->IsImported()) {
2177 CheckIMPORTED_GLOBAL(this, context);
2182 cmValue cmTarget::GetComputedProperty(const std::string& prop,
2183 cmMakefile& mf) const
2185 return cmTargetPropertyComputer::GetProperty(this, prop, mf);
2188 cmValue cmTarget::GetProperty(const std::string& prop) const
2190 static std::unordered_set<std::string> const specialProps{
2195 propOBJCXX_STANDARD,
2198 propINCLUDE_DIRECTORIES,
2199 propCOMPILE_FEATURES,
2200 propCOMPILE_OPTIONS,
2201 propCOMPILE_DEFINITIONS,
2202 propPRECOMPILE_HEADERS,
2204 propLINK_DIRECTORIES,
2206 propIMPORTED_GLOBAL,
2207 propMANUALLY_ADDED_DEPENDENCIES,
2212 propINTERFACE_LINK_LIBRARIES,
2213 propINTERFACE_LINK_LIBRARIES_DIRECT,
2214 propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
2216 if (specialProps.count(prop)) {
2217 if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
2218 prop == propCUDA_STANDARD || prop == propOBJC_STANDARD ||
2219 prop == propOBJCXX_STANDARD) {
2220 auto propertyIter = this->impl->LanguageStandardProperties.find(prop);
2221 if (propertyIter == this->impl->LanguageStandardProperties.end()) {
2224 return cmValue(propertyIter->second.Value);
2226 if (prop == propLINK_LIBRARIES) {
2227 if (this->impl->LinkImplementationPropertyEntries.empty()) {
2231 static std::string output;
2232 output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";");
2233 return cmValue(output);
2235 if (prop == propINTERFACE_LINK_LIBRARIES) {
2236 if (this->impl->LinkInterfacePropertyEntries.empty()) {
2240 static std::string output;
2241 output = cmJoin(this->impl->LinkInterfacePropertyEntries, ";");
2242 return cmValue(output);
2244 if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
2245 if (this->impl->LinkInterfaceDirectPropertyEntries.empty()) {
2249 static std::string output;
2250 output = cmJoin(this->impl->LinkInterfaceDirectPropertyEntries, ";");
2251 return cmValue(output);
2253 if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
2254 if (this->impl->LinkInterfaceDirectExcludePropertyEntries.empty()) {
2258 static std::string output;
2260 cmJoin(this->impl->LinkInterfaceDirectExcludePropertyEntries, ";");
2261 return cmValue(output);
2263 // the type property returns what type the target is
2264 if (prop == propTYPE) {
2265 return cmValue(cmState::GetTargetTypeName(this->GetType()));
2267 if (prop == propINCLUDE_DIRECTORIES) {
2268 if (this->impl->IncludeDirectoriesEntries.empty()) {
2272 static std::string output;
2273 output = cmJoin(this->impl->IncludeDirectoriesEntries, ";");
2274 return cmValue(output);
2276 if (prop == propCOMPILE_FEATURES) {
2277 if (this->impl->CompileFeaturesEntries.empty()) {
2281 static std::string output;
2282 output = cmJoin(this->impl->CompileFeaturesEntries, ";");
2283 return cmValue(output);
2285 if (prop == propCOMPILE_OPTIONS) {
2286 if (this->impl->CompileOptionsEntries.empty()) {
2290 static std::string output;
2291 output = cmJoin(this->impl->CompileOptionsEntries, ";");
2292 return cmValue(output);
2294 if (prop == propCOMPILE_DEFINITIONS) {
2295 if (this->impl->CompileDefinitionsEntries.empty()) {
2299 static std::string output;
2300 output = cmJoin(this->impl->CompileDefinitionsEntries, ";");
2301 return cmValue(output);
2303 if (prop == propLINK_OPTIONS) {
2304 if (this->impl->LinkOptionsEntries.empty()) {
2308 static std::string output;
2309 output = cmJoin(this->impl->LinkOptionsEntries, ";");
2310 return cmValue(output);
2312 if (prop == propLINK_DIRECTORIES) {
2313 if (this->impl->LinkDirectoriesEntries.empty()) {
2317 static std::string output;
2318 output = cmJoin(this->impl->LinkDirectoriesEntries, ";");
2320 return cmValue(output);
2322 if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
2323 if (this->impl->Utilities.empty()) {
2327 static std::string output;
2328 static std::vector<std::string> utilities;
2329 utilities.resize(this->impl->Utilities.size());
2331 this->impl->Utilities.cbegin(), this->impl->Utilities.cend(),
2333 [](const BT<std::pair<std::string, bool>>& item) -> std::string {
2334 return item.Value.first;
2336 output = cmJoin(utilities, ";");
2337 return cmValue(output);
2339 if (prop == propPRECOMPILE_HEADERS) {
2340 if (this->impl->PrecompileHeadersEntries.empty()) {
2344 static std::string output;
2345 output = cmJoin(this->impl->PrecompileHeadersEntries, ";");
2346 return cmValue(output);
2348 if (prop == propIMPORTED) {
2349 return this->IsImported() ? cmValue(propTRUE) : cmValue(propFALSE);
2351 if (prop == propIMPORTED_GLOBAL) {
2352 return this->IsImportedGloballyVisible() ? cmValue(propTRUE)
2353 : cmValue(propFALSE);
2355 if (prop == propNAME) {
2356 return cmValue(this->GetName());
2358 if (prop == propBINARY_DIR) {
2359 return cmValue(this->impl->Makefile->GetStateSnapshot()
2361 .GetCurrentBinary());
2363 if (prop == propSOURCE_DIR) {
2364 return cmValue(this->impl->Makefile->GetStateSnapshot()
2366 .GetCurrentSource());
2370 // Check fileset properties.
2373 this->impl->HeadersFileSets.ReadProperties(this, this->impl.get(), prop);
2374 if (headers.first) {
2375 return headers.second;
2377 auto cxx_modules = this->impl->CxxModulesFileSets.ReadProperties(
2378 this, this->impl.get(), prop);
2379 if (cxx_modules.first) {
2380 return cxx_modules.second;
2382 auto cxx_module_headers =
2383 this->impl->CxxModuleHeadersFileSets.ReadProperties(
2384 this, this->impl.get(), prop);
2385 if (cxx_module_headers.first) {
2386 return cxx_module_headers.second;
2390 cmValue retVal = this->impl->Properties.GetPropertyValue(prop);
2392 const bool chain = this->impl->Makefile->GetState()->IsPropertyChained(
2393 prop, cmProperty::TARGET);
2395 return this->impl->Makefile->GetStateSnapshot()
2397 .GetProperty(prop, chain);
2404 std::string const& cmTarget::GetSafeProperty(std::string const& prop) const
2406 cmValue ret = this->GetProperty(prop);
2411 static std::string const s_empty;
2415 bool cmTarget::GetPropertyAsBool(const std::string& prop) const
2417 return cmIsOn(this->GetProperty(prop));
2420 cmPropertyMap const& cmTarget::GetProperties() const
2422 return this->impl->Properties;
2425 bool cmTarget::IsDLLPlatform() const
2427 return this->impl->IsDLLPlatform;
2430 bool cmTarget::IsAIX() const
2432 return this->impl->IsAIX;
2435 bool cmTarget::IsImported() const
2437 return this->impl->IsImportedTarget;
2440 bool cmTarget::IsImportedGloballyVisible() const
2442 return this->impl->ImportedGloballyVisible;
2445 bool cmTarget::IsPerConfig() const
2447 return this->impl->PerConfig;
2450 bool cmTarget::CanCompileSources() const
2452 if (this->IsImported()) {
2455 switch (this->GetType()) {
2456 case cmStateEnums::EXECUTABLE:
2457 case cmStateEnums::STATIC_LIBRARY:
2458 case cmStateEnums::SHARED_LIBRARY:
2459 case cmStateEnums::MODULE_LIBRARY:
2460 case cmStateEnums::OBJECT_LIBRARY:
2462 case cmStateEnums::UTILITY:
2463 case cmStateEnums::INTERFACE_LIBRARY:
2464 case cmStateEnums::GLOBAL_TARGET:
2465 case cmStateEnums::UNKNOWN_LIBRARY:
2471 const char* cmTarget::GetSuffixVariableInternal(
2472 cmStateEnums::ArtifactType artifact) const
2474 switch (this->GetType()) {
2475 case cmStateEnums::STATIC_LIBRARY:
2476 return "CMAKE_STATIC_LIBRARY_SUFFIX";
2477 case cmStateEnums::SHARED_LIBRARY:
2479 case cmStateEnums::RuntimeBinaryArtifact:
2480 return "CMAKE_SHARED_LIBRARY_SUFFIX";
2481 case cmStateEnums::ImportLibraryArtifact:
2482 return "CMAKE_IMPORT_LIBRARY_SUFFIX";
2485 case cmStateEnums::MODULE_LIBRARY:
2487 case cmStateEnums::RuntimeBinaryArtifact:
2488 return "CMAKE_SHARED_MODULE_SUFFIX";
2489 case cmStateEnums::ImportLibraryArtifact:
2490 return "CMAKE_IMPORT_LIBRARY_SUFFIX";
2493 case cmStateEnums::EXECUTABLE:
2495 case cmStateEnums::RuntimeBinaryArtifact:
2496 // Android GUI application packages store the native
2497 // binary as a shared library.
2498 return (this->IsAndroidGuiExecutable()
2499 ? "CMAKE_SHARED_LIBRARY_SUFFIX"
2500 : "CMAKE_EXECUTABLE_SUFFIX");
2501 case cmStateEnums::ImportLibraryArtifact:
2502 return (this->impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_SUFFIX"
2503 : "CMAKE_IMPORT_LIBRARY_SUFFIX");
2512 const char* cmTarget::GetPrefixVariableInternal(
2513 cmStateEnums::ArtifactType artifact) const
2515 switch (this->GetType()) {
2516 case cmStateEnums::STATIC_LIBRARY:
2517 return "CMAKE_STATIC_LIBRARY_PREFIX";
2518 case cmStateEnums::SHARED_LIBRARY:
2520 case cmStateEnums::RuntimeBinaryArtifact:
2521 return "CMAKE_SHARED_LIBRARY_PREFIX";
2522 case cmStateEnums::ImportLibraryArtifact:
2523 return "CMAKE_IMPORT_LIBRARY_PREFIX";
2526 case cmStateEnums::MODULE_LIBRARY:
2528 case cmStateEnums::RuntimeBinaryArtifact:
2529 return "CMAKE_SHARED_MODULE_PREFIX";
2530 case cmStateEnums::ImportLibraryArtifact:
2531 return "CMAKE_IMPORT_LIBRARY_PREFIX";
2534 case cmStateEnums::EXECUTABLE:
2536 case cmStateEnums::RuntimeBinaryArtifact:
2537 // Android GUI application packages store the native
2538 // binary as a shared library.
2539 return (this->IsAndroidGuiExecutable()
2540 ? "CMAKE_SHARED_LIBRARY_PREFIX"
2542 case cmStateEnums::ImportLibraryArtifact:
2543 return (this->impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_PREFIX"
2544 : "CMAKE_IMPORT_LIBRARY_PREFIX");
2553 std::string cmTarget::ImportedGetFullPath(
2554 const std::string& config, cmStateEnums::ArtifactType artifact) const
2556 assert(this->IsImported());
2558 // Lookup/compute/cache the import information for this
2560 std::string desired_config = config;
2561 if (config.empty()) {
2562 desired_config = "NOCONFIG";
2567 cmValue loc = nullptr;
2568 cmValue imp = nullptr;
2571 if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
2572 this->GetMappedConfig(desired_config, loc, imp, suffix)) {
2574 case cmStateEnums::RuntimeBinaryArtifact:
2578 std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
2579 if (cmValue config_location = this->GetProperty(impProp)) {
2580 result = *config_location;
2581 } else if (cmValue location =
2582 this->GetProperty("IMPORTED_LOCATION")) {
2588 case cmStateEnums::ImportLibraryArtifact:
2591 } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
2592 this->IsExecutableWithExports()) {
2593 std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
2594 if (cmValue config_implib = this->GetProperty(impProp)) {
2595 result = *config_implib;
2596 } else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) {
2604 if (result.empty()) {
2605 if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
2606 auto message = [&]() -> std::string {
2608 std::string configuration;
2610 if (artifact == cmStateEnums::RuntimeBinaryArtifact) {
2611 unset = "IMPORTED_LOCATION";
2612 } else if (artifact == cmStateEnums::ImportLibraryArtifact) {
2613 unset = "IMPORTED_IMPLIB";
2616 if (!config.empty()) {
2617 configuration = cmStrCat(" configuration \"", config, "\"");
2620 return cmStrCat(unset, " not set for imported target \"",
2621 this->GetName(), "\"", configuration, ".");
2624 switch (this->GetPolicyStatus(cmPolicies::CMP0111)) {
2625 case cmPolicies::WARN:
2626 this->impl->Makefile->IssueMessage(
2627 MessageType::AUTHOR_WARNING,
2628 cmPolicies::GetPolicyWarning(cmPolicies::CMP0111) + "\n" +
2631 case cmPolicies::OLD:
2634 this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
2639 result = cmStrCat(this->GetName(), "-NOTFOUND");
2644 const cmFileSet* cmTarget::GetFileSet(const std::string& name) const
2646 auto it = this->impl->FileSets.find(name);
2647 return it == this->impl->FileSets.end() ? nullptr : &it->second;
2650 cmFileSet* cmTarget::GetFileSet(const std::string& name)
2652 auto it = this->impl->FileSets.find(name);
2653 return it == this->impl->FileSets.end() ? nullptr : &it->second;
2656 std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
2657 const std::string& name, const std::string& type, cmFileSetVisibility vis)
2659 auto result = this->impl->FileSets.emplace(
2660 std::make_pair(name, cmFileSet(name, type, vis)));
2661 if (result.second) {
2662 auto bt = this->impl->Makefile->GetBacktrace();
2663 if (type == this->impl->HeadersFileSets.TypeName) {
2664 this->impl->HeadersFileSets.AddFileSet(name, vis, std::move(bt));
2665 } else if (type == this->impl->CxxModulesFileSets.TypeName) {
2666 this->impl->CxxModulesFileSets.AddFileSet(name, vis, std::move(bt));
2667 } else if (type == this->impl->CxxModuleHeadersFileSets.TypeName) {
2668 this->impl->CxxModuleHeadersFileSets.AddFileSet(name, vis,
2672 return std::make_pair(&result.first->second, result.second);
2675 std::string cmTarget::GetFileSetsPropertyName(const std::string& type)
2677 if (type == "HEADERS") {
2678 return "HEADER_SETS";
2680 if (type == "CXX_MODULES") {
2681 return "CXX_MODULE_SETS";
2683 if (type == "CXX_MODULE_HEADER_UNITS") {
2684 return "CXX_MODULE_HEADER_UNIT_SETS";
2689 std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type)
2691 if (type == "HEADERS") {
2692 return "INTERFACE_HEADER_SETS";
2694 if (type == "CXX_MODULES") {
2695 return "INTERFACE_CXX_MODULE_SETS";
2697 if (type == "CXX_MODULE_HEADER_UNITS") {
2698 return "INTERFACE_CXX_MODULE_HEADER_UNIT_SETS";
2703 std::vector<std::string> cmTarget::GetAllFileSetNames() const
2705 std::vector<std::string> result;
2707 for (auto const& it : this->impl->FileSets) {
2708 result.push_back(it.first);
2714 std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
2716 std::vector<std::string> result;
2717 auto inserter = std::back_inserter(result);
2719 auto appendEntries = [=](const std::vector<BT<std::string>>& entries) {
2720 for (auto const& entry : entries) {
2721 auto expanded = cmExpandedList(entry.Value);
2722 std::copy(expanded.begin(), expanded.end(), inserter);
2726 appendEntries(this->impl->HeadersFileSets.InterfaceEntries.Entries);
2727 appendEntries(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
2728 appendEntries(this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries);
2733 bool cmTargetInternals::CheckImportedLibName(std::string const& prop,
2734 std::string const& value) const
2736 if (this->TargetType != cmStateEnums::INTERFACE_LIBRARY ||
2737 !this->IsImportedTarget) {
2738 this->Makefile->IssueMessage(
2739 MessageType::FATAL_ERROR,
2741 " property may be set only on imported INTERFACE library targets.");
2744 if (!value.empty()) {
2745 if (value[0] == '-') {
2746 this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
2747 prop + " property value\n " + value +
2748 "\nmay not start with '-'.");
2751 std::string::size_type bad = value.find_first_of(":/\\;");
2752 if (bad != std::string::npos) {
2753 this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
2754 prop + " property value\n " + value +
2755 "\nmay not contain '" +
2756 value.substr(bad, 1) + "'.");
2763 bool cmTarget::GetMappedConfig(std::string const& desired_config, cmValue& loc,
2764 cmValue& imp, std::string& suffix) const
2766 std::string config_upper;
2767 if (!desired_config.empty()) {
2768 config_upper = cmSystemTools::UpperCase(desired_config);
2771 std::string locPropBase;
2772 if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
2773 locPropBase = "IMPORTED_LIBNAME";
2774 } else if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
2775 locPropBase = "IMPORTED_OBJECTS";
2777 locPropBase = "IMPORTED_LOCATION";
2780 // Track the configuration-specific property suffix.
2781 suffix = cmStrCat('_', config_upper);
2783 std::vector<std::string> mappedConfigs;
2785 std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper);
2786 if (cmValue mapValue = this->GetProperty(mapProp)) {
2787 cmExpandList(*mapValue, mappedConfigs, true);
2791 // If we needed to find one of the mapped configurations but did not
2792 // On a DLL platform there may be only IMPORTED_IMPLIB for a shared
2793 // library or an executable with exports.
2794 bool allowImp = (this->IsDLLPlatform() &&
2795 (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
2796 this->IsExecutableWithExports())) ||
2797 (this->IsAIX() && this->IsExecutableWithExports());
2799 // If a mapping was found, check its configurations.
2800 for (auto mci = mappedConfigs.begin();
2801 !loc && !imp && mci != mappedConfigs.end(); ++mci) {
2802 // Look for this configuration.
2804 // An empty string in the mapping has a special meaning:
2805 // look up the config-less properties.
2806 loc = this->GetProperty(locPropBase);
2808 imp = this->GetProperty("IMPORTED_IMPLIB");
2810 // If it was found, set the suffix.
2815 std::string mcUpper = cmSystemTools::UpperCase(*mci);
2816 std::string locProp = cmStrCat(locPropBase, '_', mcUpper);
2817 loc = this->GetProperty(locProp);
2819 std::string impProp = cmStrCat("IMPORTED_IMPLIB_", mcUpper);
2820 imp = this->GetProperty(impProp);
2823 // If it was found, use it for all properties below.
2825 suffix = cmStrCat('_', mcUpper);
2830 // If we needed to find one of the mapped configurations but did not
2831 // then the target location is not found. The project does not want
2832 // any other configuration.
2833 if (!mappedConfigs.empty() && !loc && !imp) {
2834 // Interface libraries are always available because their
2835 // library name is optional so it is okay to leave loc empty.
2836 return this->GetType() == cmStateEnums::INTERFACE_LIBRARY;
2839 // If we have not yet found it then there are no mapped
2840 // configurations. Look for an exact-match.
2842 std::string locProp = cmStrCat(locPropBase, suffix);
2843 loc = this->GetProperty(locProp);
2845 std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
2846 imp = this->GetProperty(impProp);
2850 // If we have not yet found it then there are no mapped
2851 // configurations and no exact match.
2853 // The suffix computed above is not useful.
2856 // Look for a configuration-less location. This may be set by
2857 // manually-written code.
2858 loc = this->GetProperty(locPropBase);
2860 imp = this->GetProperty("IMPORTED_IMPLIB");
2864 // If we have not yet found it then the project is willing to try
2865 // any available configuration.
2867 std::vector<std::string> availableConfigs;
2868 if (cmValue iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
2869 cmExpandList(*iconfigs, availableConfigs);
2871 for (auto aci = availableConfigs.begin();
2872 !loc && !imp && aci != availableConfigs.end(); ++aci) {
2873 suffix = cmStrCat('_', cmSystemTools::UpperCase(*aci));
2874 std::string locProp = cmStrCat(locPropBase, suffix);
2875 loc = this->GetProperty(locProp);
2877 std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
2878 imp = this->GetProperty(impProp);
2882 // If we have not yet found it then the target location is not available.
2884 // Interface libraries are always available because their
2885 // library name is optional so it is okay to leave loc empty.
2886 return this->GetType() == cmStateEnums::INTERFACE_LIBRARY;