get_property: Refactor logic to shared function

This commit is contained in:
Tom Osika
2026-08-10 17:29:13 -04:00
parent ba5c653337
commit 72ae7352d5
23 changed files with 610 additions and 349 deletions
+8
View File
@@ -195,6 +195,8 @@ add_library(
cmDiagnosticContext.cxx
cmDiagnostics.h
cmDiagnostics.cxx
cmDirectoryPropertyHelper.cxx
cmDirectoryPropertyHelper.h
cmDocumentation.cxx
cmDocumentationFormatter.cxx
cmDyndepCollation.cxx
@@ -496,6 +498,8 @@ add_library(
cmSourceFileLocation.cxx
cmSourceFileLocation.h
cmSourceFileLocationKind.h
cmSourceFilePropertyHelper.cxx
cmSourceFilePropertyHelper.h
cmSourceGroup.cxx
cmSourceGroup.h
cmStandardLevel.h
@@ -527,6 +531,8 @@ add_library(
cmTargetPropertyComputer.h
cmTargetPropertyEntry.cxx
cmTargetPropertyEntry.h
cmTargetPropertyHelper.cxx
cmTargetPropertyHelper.h
cmTargetTraceDependencies.cxx
cmTargetTraceDependencies.h
cmTargetTypes.h
@@ -534,6 +540,8 @@ add_library(
cmTest.h
cmTestGenerator.cxx
cmTestGenerator.h
cmTestPropertyHelper.cxx
cmTestPropertyHelper.h
cmTransformDepfile.cxx
cmTransformDepfile.h
cmUuid.cxx
+1 -1
View File
@@ -290,7 +290,7 @@ std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
target->GetPolicyMap()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "Properties", supportsVariableType,
target->GetProperties().GetList()));
target->GetDirectProperties().GetList()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "IncludeDirectories", supportsVariableType,
+37
View File
@@ -0,0 +1,37 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmDirectoryPropertyHelper.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmValue.h"
cmMakefile* cmResolveDirectoryMakefile(cmMakefile& callerMf,
std::string const& dirName)
{
if (dirName.empty()) {
return &callerMf;
}
std::string const dir = cmSystemTools::CollapseFullPath(
dirName, callerMf.GetCurrentSourceDirectory());
return callerMf.GetGlobalGenerator()->FindMakefile(dir);
}
cmGetDirectoryPropertyResult cmGetDirectoryProperty(
std::string const& dirName, std::string const& propertyName,
cmMakefile& callerMf, cmValue& propertyValue)
{
cmMakefile* mf = cmResolveDirectoryMakefile(callerMf, dirName);
if (!mf) {
return cmGetDirectoryPropertyResult::DirectoryNotFound;
}
return cmGetDirectoryProperty(*mf, propertyName, propertyValue);
}
cmGetDirectoryPropertyResult cmGetDirectoryProperty(
cmMakefile& mf, std::string const& propertyName, cmValue& propertyValue)
{
propertyValue = mf.GetProperty(propertyName);
return cmGetDirectoryPropertyResult::Success;
}
+29
View File
@@ -0,0 +1,29 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include <string>
#include "cmValue.h"
class cmMakefile;
enum class cmGetDirectoryPropertyResult
{
Success,
DirectoryNotFound,
};
// Resolve a DIRECTORY scope name to its makefile. Returns nullptr if
// no such directory has been processed. An empty dirName returns
// &callerMf (i.e. the current directory's makefile).
cmMakefile* cmResolveDirectoryMakefile(cmMakefile& callerMf,
std::string const& dirName);
cmGetDirectoryPropertyResult cmGetDirectoryProperty(
std::string const& dirName, std::string const& propertyName,
cmMakefile& callerMf, cmValue& propertyValue);
// Overload for callers that have already resolved the target directory.
cmGetDirectoryPropertyResult cmGetDirectoryProperty(
cmMakefile& mf, std::string const& propertyName, cmValue& propertyValue);
+1 -1
View File
@@ -835,7 +835,7 @@ bool cmExportFileGenerator::PopulateExportProperties(
cmGeneratorTarget const* gte, ImportPropertyMap& properties,
std::string& errorMessage) const
{
auto const& targetProperties = gte->Target->GetProperties();
auto const& targetProperties = gte->Target->GetDirectProperties();
if (cmValue exportProperties =
targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) {
for (auto& prop : cmList{ *exportProperties }) {
+1 -1
View File
@@ -4631,7 +4631,7 @@ std::string cmGeneratorTarget::ComputeVersionedName(std::string const& prefix,
std::vector<std::string> cmGeneratorTarget::GetPropertyKeys() const
{
return this->Target->GetProperties().GetKeys();
return this->Target->GetDirectProperties().GetKeys();
}
void cmGeneratorTarget::ReportPropertyOrigin(
+14 -30
View File
@@ -2,17 +2,11 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmGetDirectoryPropertyCommand.h"
#include "cmDirectoryPropertyHelper.h"
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmValue.h"
namespace {
void StoreResult(cmMakefile& makefile, std::string const& variable,
cmValue prop);
}
// cmGetDirectoryPropertyCommand
bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
@@ -26,8 +20,8 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
std::string const& variable = *i;
++i;
// get the directory argument if there is one
cmMakefile* dir = &status.GetMakefile();
// Get the directory argument if there is one.
cmMakefile* mf = &status.GetMakefile();
if (*i == "DIRECTORY") {
++i;
if (i == args.end()) {
@@ -35,12 +29,8 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
"DIRECTORY argument provided without subsequent arguments");
return false;
}
std::string sd = cmSystemTools::CollapseFullPath(
*i, status.GetMakefile().GetCurrentSourceDirectory());
// lookup the makefile from the directory name
dir = status.GetMakefile().GetGlobalGenerator()->FindMakefile(sd);
if (!dir) {
mf = cmResolveDirectoryMakefile(status.GetMakefile(), *i);
if (!mf) {
status.SetError(
"DIRECTORY argument provided but requested directory not found. "
"This could be because the directory argument was invalid or, "
@@ -54,9 +44,6 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
}
}
// OK, now we have the directory to process, we just get the requested
// information out of it
if (*i == "DEFINITION") {
++i;
if (i == args.end()) {
@@ -64,8 +51,7 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
"providing the name of the variable to get.");
return false;
}
std::string const& output = dir->GetSafeDefinition(*i);
status.GetMakefile().AddDefinition(variable, output);
status.GetMakefile().AddDefinition(variable, mf->GetSafeDefinition(*i));
return true;
}
@@ -74,14 +60,12 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
return false;
}
StoreResult(status.GetMakefile(), variable, dir->GetProperty(*i));
return true;
}
namespace {
void StoreResult(cmMakefile& makefile, std::string const& variable,
cmValue prop)
{
makefile.AddDefinition(variable, prop);
}
cmValue prop;
auto result = cmGetDirectoryProperty(*mf, *i, prop);
if (result == cmGetDirectoryPropertyResult::Success) {
status.GetMakefile().AddDefinition(variable, prop);
return true;
}
status.SetError("unknown error retrieving directory property");
return false;
}
+154 -186
View File
@@ -3,26 +3,24 @@
#include "cmGetPropertyCommand.h"
#include <cstddef>
#include <functional>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmDirectoryPropertyHelper.h"
#include "cmExecutionStatus.h"
#include "cmFileSet.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyDefinition.h"
#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
#include "cmSourceFilePropertyHelper.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTest.h"
#include "cmTargetPropertyHelper.h"
#include "cmTestPropertyHelper.h"
#include "cmValue.h"
#include "cmake.h"
@@ -52,12 +50,15 @@ bool HandleFileSetMode(cmExecutionStatus& status, std::string const& name,
bool HandleSourceMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName,
cmMakefile& directory_makefile,
bool source_file_paths_should_be_absolute);
bool sourceFileDirectoryOptionEnabled,
bool sourceFileTargetOptionEnabled,
std::vector<std::string>& sourceFileDirectories,
std::vector<std::string>& sourceFileTargetDirectories);
bool HandleTestMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName,
cmMakefile& directory_makefile);
bool testDirectoryOptionEnabled,
std::string& testDirectory);
bool HandleVariableMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName);
@@ -253,33 +254,15 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
return HandleFileSetMode(status, name, infoType, variable,
propertyName, file_set_target);
}
case cmProperty::SOURCE_FILE: {
std::vector<cmMakefile*> source_file_directory_makefiles;
if (!SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
status, source_file_directory_option_enabled,
source_file_target_option_enabled, source_file_directories,
source_file_target_directories,
source_file_directory_makefiles)) {
return false;
}
bool source_file_paths_should_be_absolute =
source_file_directory_option_enabled ||
source_file_target_option_enabled;
cmMakefile& directory_scope_mf = *(source_file_directory_makefiles[0]);
case cmProperty::SOURCE_FILE:
return HandleSourceMode(status, name, infoType, variable, propertyName,
directory_scope_mf,
source_file_paths_should_be_absolute);
}
case cmProperty::TEST: {
cmMakefile* test_directory_makefile;
if (!SetPropertyCommand::HandleAndValidateTestDirectoryScopes(
status, test_directory_option_enabled, test_directory,
test_directory_makefile)) {
return false;
}
source_file_directory_option_enabled,
source_file_target_option_enabled,
source_file_directories,
source_file_target_directories);
case cmProperty::TEST:
return HandleTestMode(status, name, infoType, variable, propertyName,
*test_directory_makefile);
}
test_directory_option_enabled, test_directory);
case cmProperty::VARIABLE:
return HandleVariableMode(status, name, infoType, variable,
propertyName);
@@ -297,38 +280,6 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
return true;
}
namespace GetPropertyCommand {
bool GetSourceFilePropertyGENERATED(
std::string const& name, cmMakefile& mf,
std::function<bool(bool)> const& storeResult)
{
// Globally set as generated?
// Note: If the given "name" only contains a filename or a relative path
// the file's location is ambiguous. In general, one would expect
// it in the source-directory, because that is where source files
// are located normally. However, generated files are normally
// generated in the build-directory. Therefore, we first check for
// a generated file in the build-directory before we check for a
// generated file in the source-directory.
{
auto file =
cmSystemTools::CollapseFullPath(name, mf.GetCurrentBinaryDirectory());
if (mf.GetGlobalGenerator()->IsGeneratedFile(file)) {
return storeResult(true);
}
}
{
auto file =
cmSystemTools::CollapseFullPath(name, mf.GetCurrentSourceDirectory());
if (mf.GetGlobalGenerator()->IsGeneratedFile(file)) {
return storeResult(true);
}
}
// Skip checking the traditional/local property.
return storeResult(false);
}
}
namespace {
// Implementation of result storage.
@@ -348,12 +299,6 @@ bool StoreResult(OutType infoType, cmMakefile& makefile,
}
return true;
}
template <>
bool StoreResult(OutType infoType, cmMakefile& makefile,
std::string const& variable, std::nullptr_t value)
{
return StoreResult(infoType, makefile, variable, cmValue(value));
}
bool HandleGlobalMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
@@ -374,70 +319,24 @@ bool HandleDirectoryMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName)
{
// Default to the current directory.
cmMakefile* mf = &status.GetMakefile();
// Lookup the directory if given.
if (!name.empty()) {
// Construct the directory name. Interpret relative paths with
// respect to the current directory.
std::string dir = cmSystemTools::CollapseFullPath(
name, status.GetMakefile().GetCurrentSourceDirectory());
// Lookup the generator.
mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir);
if (!mf) {
// Could not find the directory.
status.SetError(
"DIRECTORY scope provided but requested directory was not found. "
"This could be because the directory argument was invalid or, "
"it is valid but has not been processed yet.");
return false;
}
cmValue prop;
if (!GetPropertyCommand::LookupDirectoryProperty(status, name, propertyName,
prop)) {
return false;
}
// Get the property.
return StoreResult(infoType, status.GetMakefile(), variable,
mf->GetProperty(propertyName));
return StoreResult(infoType, status.GetMakefile(), variable, prop);
}
bool HandleTargetMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName)
{
if (name.empty()) {
status.SetError("not given name for TARGET scope.");
cmValue prop;
if (!GetPropertyCommand::LookupTargetProperty(status, name, propertyName,
prop)) {
return false;
}
if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
if (propertyName == "ALIASED_TARGET" || propertyName == "ALIAS_GLOBAL") {
if (status.GetMakefile().IsAlias(name)) {
if (propertyName == "ALIASED_TARGET") {
return StoreResult(infoType, status.GetMakefile(), variable,
target->GetName().c_str());
}
if (propertyName == "ALIAS_GLOBAL") {
return StoreResult(
infoType, status.GetMakefile(), variable,
status.GetMakefile().GetGlobalGenerator()->IsAlias(name)
? "TRUE"
: "FALSE");
}
}
return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
}
cmValue prop =
target->GetComputedProperty(propertyName, status.GetMakefile());
if (!prop) {
prop = target->GetProperty(propertyName);
}
return StoreResult(infoType, status.GetMakefile(), variable, prop);
}
status.SetError(cmStrCat("could not find TARGET ", name,
". Perhaps it has not yet been created."));
return false;
return StoreResult(infoType, status.GetMakefile(), variable, prop);
}
bool HandleFileSetMode(cmExecutionStatus& status, std::string const& name,
@@ -462,67 +361,34 @@ bool HandleFileSetMode(cmExecutionStatus& status, std::string const& name,
bool HandleSourceMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName,
cmMakefile& directory_makefile,
bool const source_file_paths_should_be_absolute)
bool sourceFileDirectoryOptionEnabled,
bool sourceFileTargetOptionEnabled,
std::vector<std::string>& sourceFileDirectories,
std::vector<std::string>& sourceFileTargetDirectories)
{
if (name.empty()) {
status.SetError("not given name for SOURCE scope.");
cmValue prop;
if (!GetPropertyCommand::LookupSourceProperty(
status, name, propertyName, sourceFileDirectoryOptionEnabled,
sourceFileTargetOptionEnabled, sourceFileDirectories,
sourceFileTargetDirectories, prop)) {
return false;
}
// Special handling for GENERATED property.
// Note: Only, if CMP0163 is set to NEW!
if (propertyName == "GENERATED"_s) {
auto& mf = status.GetMakefile();
auto cmp0163 = directory_makefile.GetPolicyStatus(cmPolicies::CMP0163);
bool const cmp0163new =
cmp0163 != cmPolicies::OLD && cmp0163 != cmPolicies::WARN;
if (cmp0163new) {
return GetPropertyCommand::GetSourceFilePropertyGENERATED(
name, mf, [infoType, &variable, &mf](bool isGenerated) -> bool {
// Set the value on the original Makefile scope, not the scope of the
// requested directory.
return StoreResult(infoType, mf, variable,
(isGenerated) ? cmValue("1") : cmValue("0"));
});
}
}
// Get the source file.
std::string const source_file_absolute_path =
SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded(
status, name, source_file_paths_should_be_absolute);
if (cmSourceFile* sf =
directory_makefile.GetOrCreateSource(source_file_absolute_path)) {
// Set the value on the original Makefile scope, not the scope of the
// requested directory.
return StoreResult(infoType, status.GetMakefile(), variable,
sf->GetPropertyForUser(propertyName));
}
status.SetError(
cmStrCat("given SOURCE name that could not be found or created: ",
source_file_absolute_path));
return false;
return StoreResult(infoType, status.GetMakefile(), variable, prop);
}
bool HandleTestMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName, cmMakefile& test_makefile)
std::string const& propertyName,
bool testDirectoryOptionEnabled,
std::string& testDirectory)
{
if (name.empty()) {
status.SetError("not given name for TEST scope.");
cmValue prop;
if (!GetPropertyCommand::LookupTestProperty(status, name, propertyName,
testDirectoryOptionEnabled,
testDirectory, prop)) {
return false;
}
// Loop over all tests looking for matching names.
if (cmTest* test = test_makefile.GetTest(name)) {
return StoreResult(infoType, status.GetMakefile(), variable,
test->GetProperty(propertyName));
}
// If not found it is an error.
status.SetError(cmStrCat("given TEST name that does not exist: ", name));
return false;
return StoreResult(infoType, status.GetMakefile(), variable, prop);
}
bool HandleVariableMode(cmExecutionStatus& status, std::string const& name,
@@ -542,16 +408,11 @@ bool HandleCacheMode(cmExecutionStatus& status, std::string const& name,
OutType infoType, std::string const& variable,
std::string const& propertyName)
{
if (name.empty()) {
status.SetError("not given name for CACHE scope.");
cmValue value;
if (!GetPropertyCommand::LookupCacheProperty(status, name, propertyName,
value)) {
return false;
}
cmValue value = nullptr;
if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) {
value = status.GetMakefile().GetState()->GetCacheEntryProperty(
name, propertyName);
}
StoreResult(infoType, status.GetMakefile(), variable, value);
return true;
}
@@ -581,3 +442,110 @@ bool HandleInstallMode(cmExecutionStatus& status, std::string const& name,
return false;
}
}
namespace GetPropertyCommand {
bool LookupTargetProperty(cmExecutionStatus& status, std::string const& name,
std::string const& propertyName, cmValue& out)
{
if (name.empty()) {
status.SetError("not given name for TARGET scope.");
return false;
}
auto result =
cmGetTargetProperty(name, propertyName, status.GetMakefile(), out);
if (result == cmGetTargetPropertyResult::Success) {
return true;
}
if (result == cmGetTargetPropertyResult::TargetNotFound) {
status.SetError(cmStrCat("could not find TARGET ", name,
". Perhaps it has not yet been created."));
}
return false;
}
bool LookupDirectoryProperty(cmExecutionStatus& status,
std::string const& name,
std::string const& propertyName, cmValue& out)
{
auto result =
cmGetDirectoryProperty(name, propertyName, status.GetMakefile(), out);
if (result == cmGetDirectoryPropertyResult::Success) {
return true;
}
if (result == cmGetDirectoryPropertyResult::DirectoryNotFound) {
status.SetError(
"DIRECTORY scope provided but requested directory was not found. "
"This could be because the directory argument was invalid or, "
"it is valid but has not been processed yet.");
}
return false;
}
bool LookupSourceProperty(
cmExecutionStatus& status, std::string const& name,
std::string const& propertyName, bool sourceFileDirectoryOptionEnabled,
bool sourceFileTargetOptionEnabled,
std::vector<std::string>& sourceFileDirectories,
std::vector<std::string>& sourceFileTargetDirectories, cmValue& out)
{
if (name.empty()) {
status.SetError("not given name for SOURCE scope.");
return false;
}
auto result = cmGetSourceFileProperty(
name, propertyName, status, sourceFileDirectoryOptionEnabled,
sourceFileTargetOptionEnabled, sourceFileDirectories,
sourceFileTargetDirectories, out, /*alwaysCreateSource=*/true);
if (result == cmGetSourceFilePropertyResult::Success) {
return true;
}
if (result == cmGetSourceFilePropertyResult::Error ||
result == cmGetSourceFilePropertyResult::SourceNotFound) {
status.SetError(cmStrCat(
"given SOURCE name that could not be found or created: ", name));
}
return false;
}
bool LookupTestProperty(cmExecutionStatus& status, std::string const& name,
std::string const& propertyName,
bool testDirectoryOptionEnabled,
std::string& testDirectory, cmValue& out)
{
if (name.empty()) {
status.SetError("not given name for TEST scope.");
return false;
}
auto result =
cmGetTestProperty(name, propertyName, status, testDirectoryOptionEnabled,
testDirectory, out);
if (result == cmGetTestPropertyResult::Success) {
return true;
}
if (result == cmGetTestPropertyResult::TestNotFound) {
status.SetError(cmStrCat("given TEST name that does not exist: ", name));
}
return false;
}
bool LookupCacheProperty(cmExecutionStatus& status, std::string const& name,
std::string const& propertyName, cmValue& out)
{
if (name.empty()) {
status.SetError("not given name for CACHE scope.");
return false;
}
out = nullptr;
if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) {
out = status.GetMakefile().GetState()->GetCacheEntryProperty(name,
propertyName);
}
return true;
}
}
+34
View File
@@ -7,7 +7,41 @@
#include <string>
#include <vector>
#include "cmValue.h"
class cmExecutionStatus;
namespace GetPropertyCommand {
// Per-entity property lookups used by the get_property command. Each preserves
// the script command's error semantics for its scope (status.SetError on
// missing entity / empty name where applicable). On success, returns true and
// fills `out`; `out` is null iff the property is unset. On hard error returns
// false with status.SetError already set.
bool LookupTargetProperty(cmExecutionStatus& status, std::string const& name,
std::string const& propertyName, cmValue& out);
bool LookupDirectoryProperty(cmExecutionStatus& status,
std::string const& name,
std::string const& propertyName, cmValue& out);
bool LookupSourceProperty(
cmExecutionStatus& status, std::string const& name,
std::string const& propertyName, bool sourceFileDirectoryOptionEnabled,
bool sourceFileTargetOptionEnabled,
std::vector<std::string>& sourceFileDirectories,
std::vector<std::string>& sourceFileTargetDirectories, cmValue& out);
bool LookupTestProperty(cmExecutionStatus& status, std::string const& name,
std::string const& propertyName,
bool testDirectoryOptionEnabled,
std::string& testDirectory, cmValue& out);
bool LookupCacheProperty(cmExecutionStatus& status, std::string const& name,
std::string const& propertyName, cmValue& out);
}
bool cmGetPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status);
+16 -64
View File
@@ -2,24 +2,14 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmGetSourceFilePropertyCommand.h"
#include <functional>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
#include "cmSourceFilePropertyHelper.h"
#include "cmValue.h"
namespace GetPropertyCommand {
bool GetSourceFilePropertyGENERATED(
std::string const& name, cmMakefile& mf,
std::function<bool(bool)> const& storeResult);
}
bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -45,66 +35,28 @@ bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
source_file_target_directories.push_back(args[3]);
}
std::vector<cmMakefile*> source_file_directory_makefiles;
bool file_scopes_handled =
SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
status, source_file_directory_option_enabled,
source_file_target_option_enabled, source_file_directories,
source_file_target_directories, source_file_directory_makefiles);
if (!file_scopes_handled) {
return false;
}
std::string const& var = args[0];
std::string const& sourceName = args[1];
std::string const& propName = args[property_arg_index];
bool source_file_paths_should_be_absolute =
source_file_directory_option_enabled || source_file_target_option_enabled;
cmMakefile& directory_makefile = *source_file_directory_makefiles[0];
// Special handling for GENERATED property.
// Note: Only, if CMP0163 is set to NEW!
if (propName == "GENERATED"_s) {
auto& mf = status.GetMakefile();
auto cmp0163 = directory_makefile.GetPolicyStatus(cmPolicies::CMP0163);
bool const cmp0163new =
cmp0163 != cmPolicies::OLD && cmp0163 != cmPolicies::WARN;
if (cmp0163new) {
return GetPropertyCommand::GetSourceFilePropertyGENERATED(
args[1], mf, [&var, &mf](bool isGenerated) -> bool {
// Set the value on the original Makefile scope, not the scope of the
// requested directory.
mf.AddDefinition(var, (isGenerated) ? cmValue("1") : cmValue("0"));
return true;
});
}
}
cmValue prop;
auto result = cmGetSourceFileProperty(
sourceName, propName, status, source_file_directory_option_enabled,
source_file_target_option_enabled, source_file_directories,
source_file_target_directories, prop);
// Get the source file.
std::string const file =
SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded(
status, args[1], source_file_paths_should_be_absolute);
cmSourceFile* sf = directory_makefile.GetSource(file);
// for the location we must create a source file first
if (!sf && propName == "LOCATION"_s) {
sf = directory_makefile.CreateSource(file);
}
if (sf) {
cmValue prop = nullptr;
if (!propName.empty()) {
prop = sf->GetPropertyForUser(propName);
}
if (result == cmGetSourceFilePropertyResult::Success) {
if (prop) {
// Set the value on the original Makefile scope, not the scope of the
// requested directory.
status.GetMakefile().AddDefinition(var, *prop);
return true;
}
status.GetMakefile().AddDefinition(var, "NOTFOUND");
return true;
}
// Set the value on the original Makefile scope, not the scope of the
// requested directory.
status.GetMakefile().AddDefinition(var, "NOTFOUND");
return true;
if (result == cmGetSourceFilePropertyResult::SourceNotFound ||
result == cmGetSourceFilePropertyResult::Error) {
status.GetMakefile().AddDefinition(var, "NOTFOUND");
return true;
}
return false;
}
+13 -35
View File
@@ -3,11 +3,10 @@
#include "cmGetTargetPropertyCommand.h"
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTargetPropertyHelper.h"
#include "cmValue.h"
bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
@@ -19,45 +18,24 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
}
std::string const& var = args[0];
std::string const& targetName = args[1];
std::string prop;
bool prop_exists = false;
std::string const& propertyName = args[2];
cmMakefile& mf = status.GetMakefile();
if (cmTarget* tgt = mf.FindTargetToUse(targetName)) {
if (args[2] == "ALIASED_TARGET" || args[2] == "ALIAS_GLOBAL") {
if (mf.IsAlias(targetName)) {
prop_exists = true;
if (args[2] == "ALIASED_TARGET") {
prop = tgt->GetName();
}
if (args[2] == "ALIAS_GLOBAL") {
prop =
mf.GetGlobalGenerator()->IsAlias(targetName) ? "TRUE" : "FALSE";
}
}
} else if (!args[2].empty()) {
cmValue prop_cstr = nullptr;
prop_cstr = tgt->GetComputedProperty(args[2], mf);
if (!prop_cstr) {
prop_cstr = tgt->GetProperty(args[2]);
}
if (prop_cstr) {
prop = *prop_cstr;
prop_exists = true;
}
cmValue propValue;
auto result = cmGetTargetProperty(targetName, propertyName, mf, propValue);
if (result == cmGetTargetPropertyResult::Success) {
if (propValue) {
mf.AddDefinition(var, *propValue);
return true;
}
} else {
mf.AddDefinition(var, var + "-NOTFOUND");
return true;
}
if (result == cmGetTargetPropertyResult::TargetNotFound) {
mf.IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("get_target_property() called with non-existent target \"",
targetName, "\"."));
return false;
}
if (prop_exists) {
mf.AddDefinition(var, prop);
return true;
}
mf.AddDefinition(var, var + "-NOTFOUND");
return true;
return false;
}
+20 -25
View File
@@ -4,8 +4,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSetPropertyCommand.h"
#include "cmTest.h"
#include "cmTestPropertyHelper.h"
#include "cmValue.h"
bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
@@ -17,39 +16,35 @@ bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
return false;
}
std::string test_directory;
bool test_directory_option_enabled = false;
std::string testDirectory;
bool testDirectoryOptionEnabled = false;
int var_arg_index = 2;
if (args[2] == "DIRECTORY" && args_size == 5) {
var_arg_index = 4;
test_directory_option_enabled = true;
test_directory = args[3];
}
cmMakefile* test_directory_makefile = &status.GetMakefile();
bool file_scopes_handled =
SetPropertyCommand::HandleAndValidateTestDirectoryScopes(
status, test_directory_option_enabled, test_directory,
test_directory_makefile);
if (!file_scopes_handled) {
return false;
testDirectoryOptionEnabled = true;
testDirectory = args[3];
}
std::string const& testName = args[0];
std::string const& propertyName = args[1];
std::string const& var = args[var_arg_index];
cmMakefile& mf = status.GetMakefile();
cmTest* test = test_directory_makefile->GetTest(testName);
if (test) {
cmValue prop;
if (!args[1].empty()) {
prop = test->GetProperty(args[1]);
}
cmValue prop;
auto result =
cmGetTestProperty(testName, propertyName, status,
testDirectoryOptionEnabled, testDirectory, prop);
if (result == cmGetTestPropertyResult::Success) {
if (prop) {
mf.AddDefinition(var, prop);
status.GetMakefile().AddDefinition(var, prop);
return true;
}
status.GetMakefile().AddDefinition(var, "NOTFOUND");
return true;
}
mf.AddDefinition(var, "NOTFOUND");
return true;
if (result == cmGetTestPropertyResult::TestNotFound) {
status.GetMakefile().AddDefinition(var, "NOTFOUND");
return true;
}
return false;
}
+105
View File
@@ -0,0 +1,105 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmSourceFilePropertyHelper.h"
#include <cm/string_view>
#include <cmext/string_view>
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
#include "cmValue.h"
static bool GetSourceFilePropertyGENERATED(std::string const& name,
cmMakefile& mf,
cmValue& propertyValue)
{
// Globally set as generated?
// Note: If the given "name" only contains a filename or a relative path
// the file's location is ambiguous. In general, one would expect
// it in the source-directory, because that is where source files
// are located normally. However, generated files are normally
// generated in the build-directory. Therefore, we first check for
// a generated file in the build-directory before we check for a
// generated file in the source-directory.
static std::string const sOne = "1";
static std::string const sZero = "0";
{
auto file =
cmSystemTools::CollapseFullPath(name, mf.GetCurrentBinaryDirectory());
if (mf.GetGlobalGenerator()->IsGeneratedFile(file)) {
propertyValue = cmValue(sOne);
return true;
}
}
{
auto file =
cmSystemTools::CollapseFullPath(name, mf.GetCurrentSourceDirectory());
if (mf.GetGlobalGenerator()->IsGeneratedFile(file)) {
propertyValue = cmValue(sOne);
return true;
}
}
propertyValue = cmValue(sZero);
return true;
}
cmGetSourceFilePropertyResult cmGetSourceFileProperty(
std::string const& sourceName, std::string const& propertyName,
cmExecutionStatus& status, bool sourceFileDirectoryOptionEnabled,
bool sourceFileTargetOptionEnabled,
std::vector<std::string>& sourceFileDirectories,
std::vector<std::string>& sourceFileTargetDirectories,
cmValue& propertyValue, bool alwaysCreateSource)
{
std::vector<cmMakefile*> sourceFileDirectoryMakefiles;
if (!SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
status, sourceFileDirectoryOptionEnabled,
sourceFileTargetOptionEnabled, sourceFileDirectories,
sourceFileTargetDirectories, sourceFileDirectoryMakefiles)) {
return cmGetSourceFilePropertyResult::ScopeError;
}
bool const sourceFilePathsShouldBeAbsolute =
sourceFileDirectoryOptionEnabled || sourceFileTargetOptionEnabled;
cmMakefile& directoryMakefile = *sourceFileDirectoryMakefiles[0];
// Special handling for GENERATED property.
// Note: Only if CMP0163 is set to NEW.
if (propertyName == "GENERATED"_s) {
auto cmp0163 = directoryMakefile.GetPolicyStatus(cmPolicies::CMP0163);
bool const cmp0163new =
cmp0163 != cmPolicies::OLD && cmp0163 != cmPolicies::WARN;
if (cmp0163new) {
if (!GetSourceFilePropertyGENERATED(sourceName, status.GetMakefile(),
propertyValue)) {
return cmGetSourceFilePropertyResult::Error;
}
return cmGetSourceFilePropertyResult::Success;
}
}
std::string const absolutePath =
SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded(
status, sourceName, sourceFilePathsShouldBeAbsolute);
cmSourceFile* sf = nullptr;
if (alwaysCreateSource || propertyName == "LOCATION"_s) {
sf = directoryMakefile.GetOrCreateSource(absolutePath);
if (!sf) {
return cmGetSourceFilePropertyResult::Error;
}
} else {
sf = directoryMakefile.GetSource(absolutePath);
if (!sf) {
return cmGetSourceFilePropertyResult::SourceNotFound;
}
}
propertyValue = sf->GetPropertyForUser(propertyName);
return cmGetSourceFilePropertyResult::Success;
}
+26
View File
@@ -0,0 +1,26 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include <string>
#include <vector>
#include "cmValue.h"
class cmExecutionStatus;
enum class cmGetSourceFilePropertyResult
{
Success,
ScopeError, // directory scope validation failed
SourceNotFound, // source file does not exist in this directory scope
Error, // unexpected internal failure (e.g. source could not be created)
};
cmGetSourceFilePropertyResult cmGetSourceFileProperty(
std::string const& sourceName, std::string const& propertyName,
cmExecutionStatus& status, bool sourceFileDirectoryOptionEnabled,
bool sourceFileTargetOptionEnabled,
std::vector<std::string>& sourceFileDirectories,
std::vector<std::string>& sourceFileTargetDirectories,
cmValue& propertyValue, bool alwaysCreateSource = false);
+1 -1
View File
@@ -2862,7 +2862,7 @@ bool cmTarget::GetPropertyAsBool(std::string const& prop) const
return this->GetProperty(prop).IsOn();
}
cmPropertyMap const& cmTarget::GetProperties() const
cmPropertyMap const& cmTarget::GetDirectProperties() const
{
return this->impl->Properties;
}
+2 -2
View File
@@ -233,8 +233,8 @@ public:
bool GetPropertyAsBool(std::string const& prop) const;
void CheckProperty(std::string const& prop, cmMakefile* context) const;
cmValue GetComputedProperty(std::string const& prop, cmMakefile& mf) const;
//! Get all properties
cmPropertyMap const& GetProperties() const;
//! Get properties set directly on this target (no special/computed/chained)
cmPropertyMap const& GetDirectProperties() const;
//! Return whether or not the target is for a DLL platform.
bool IsDLLPlatform() const;
+52
View File
@@ -0,0 +1,52 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmTargetPropertyHelper.h"
#include <utility>
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmTarget.h"
#include "cmValue.h"
cmGetTargetPropertyResult cmGetTargetProperty(std::string const& targetName,
std::string const& propertyName,
cmMakefile& mf,
cmValue& propertyValue)
{
cmTarget* target = mf.FindTargetToUse(targetName);
if (!target) {
return cmGetTargetPropertyResult::TargetNotFound;
}
return cmGetTargetProperty(targetName, target, propertyName, mf,
propertyValue);
}
cmGetTargetPropertyResult cmGetTargetProperty(std::string const& targetName,
cmTarget const* target,
std::string const& propertyName,
cmMakefile& mf,
cmValue& propertyValue)
{
if (propertyName == "ALIASED_TARGET" || propertyName == "ALIAS_GLOBAL") {
if (mf.IsAlias(targetName)) {
if (propertyName == "ALIASED_TARGET") {
propertyValue = cmValue(target->GetName());
} else {
static std::string const sTrue = "TRUE";
static std::string const sFalse = "FALSE";
propertyValue = cmValue(
mf.GetGlobalGenerator()->IsAlias(targetName) ? sTrue : sFalse);
}
} else {
propertyValue = cmValue(nullptr);
}
return cmGetTargetPropertyResult::Success;
}
propertyValue = target->GetComputedProperty(propertyName, mf);
if (!propertyValue) {
propertyValue = target->GetProperty(propertyName);
}
return cmGetTargetPropertyResult::Success;
}
+32
View File
@@ -0,0 +1,32 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include <string>
#include "cmValue.h"
class cmMakefile;
class cmTarget;
class cmValue;
enum class cmGetTargetPropertyResult
{
Success,
TargetNotFound,
};
cmGetTargetPropertyResult cmGetTargetProperty(std::string const& targetName,
std::string const& propertyName,
cmMakefile& mf,
cmValue& propertyValue);
// Overload for callers that have already resolved the target. The
// targetName is still required for ALIASED_TARGET / ALIAS_GLOBAL,
// which dispatch on whether the *lookup* name is an alias (not whether
// the resolved target is one).
cmGetTargetPropertyResult cmGetTargetProperty(std::string const& targetName,
cmTarget const* target,
std::string const& propertyName,
cmMakefile& mf,
cmValue& propertyValue);
+32
View File
@@ -0,0 +1,32 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmTestPropertyHelper.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSetPropertyCommand.h"
#include "cmTest.h"
#include "cmValue.h"
cmGetTestPropertyResult cmGetTestProperty(std::string const& testName,
std::string const& propertyName,
cmExecutionStatus& status,
bool testDirectoryOptionEnabled,
std::string& testDirectory,
cmValue& propertyValue)
{
cmMakefile* testDirectoryMakefile = &status.GetMakefile();
if (!SetPropertyCommand::HandleAndValidateTestDirectoryScopes(
status, testDirectoryOptionEnabled, testDirectory,
testDirectoryMakefile)) {
return cmGetTestPropertyResult::ScopeError;
}
cmTest* test = testDirectoryMakefile->GetTest(testName);
if (!test) {
return cmGetTestPropertyResult::TestNotFound;
}
propertyValue = test->GetProperty(propertyName);
return cmGetTestPropertyResult::Success;
}
+23
View File
@@ -0,0 +1,23 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include <string>
#include "cmValue.h"
class cmExecutionStatus;
enum class cmGetTestPropertyResult
{
Success,
ScopeError, // test directory scope validation failed
TestNotFound, // test does not exist
};
cmGetTestPropertyResult cmGetTestProperty(std::string const& testName,
std::string const& propertyName,
cmExecutionStatus& status,
bool testDirectoryOptionEnabled,
std::string& testDirectory,
cmValue& propertyValue);
+4 -2
View File
@@ -1117,7 +1117,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0)
this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) {
references.assign(*vsDotNetReferences);
}
cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
cmPropertyMap const& props =
this->GeneratorTarget->Target->GetDirectProperties();
for (auto const& i : props.GetList()) {
static cm::string_view const vsDnRef = "VS_DOTNET_REFERENCE_";
if (cmHasPrefix(i.first, vsDnRef)) {
@@ -1228,7 +1229,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
cmStrCat(refpropPrefix, ref, refpropInfix);
using CustomTags = std::map<std::string, std::string>;
CustomTags tags;
cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
cmPropertyMap const& props =
this->GeneratorTarget->Target->GetDirectProperties();
for (auto const& i : props.GetList()) {
if (cmHasPrefix(i.first, refPropFullPrefix) && !i.second.empty()) {
tags[i.first.substr(refPropFullPrefix.length())] = i.second;
@@ -213,7 +213,7 @@ static bool testCreateFromTarget()
ASSERT_VARIABLE(variables[12], "PolicyMap", "", "collection");
ASSERT_VARIABLE(variables[13], "Properties",
std::to_string(dummies.Makefile->GetOrderedTargets()[0]
->GetProperties()
->GetDirectProperties()
.GetList()
.size()),
"collection");
+4
View File
@@ -317,6 +317,7 @@ CMAKE_CXX_SOURCES="\
cmDefinitions \
cmDiagnostics \
cmDiagnosticContext \
cmDirectoryPropertyHelper \
cmDiscoverTestsCommand \
cmDocumentationFormatter \
cmELF \
@@ -471,6 +472,7 @@ CMAKE_CXX_SOURCES="\
cmSiteNameCommand \
cmSourceFile \
cmSourceFileLocation \
cmSourceFilePropertyHelper \
cmStandardLevelResolver \
cmState \
cmStateDirectory \
@@ -496,10 +498,12 @@ CMAKE_CXX_SOURCES="\
cmTargetPropCommandBase \
cmTargetPropertyComputer \
cmTargetPropertyEntry \
cmTargetPropertyHelper \
cmTargetSourcesCommand \
cmTargetTraceDependencies \
cmTest \
cmTestGenerator \
cmTestPropertyHelper \
cmTimestamp \
cmTransformDepfile \
cmTryCompileCommand \