mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
Xcode: Honor generator expressions in XCODE_EMBED_<type>
Evaluate the XCODE_EMBED_<type> target property through the generator expression evaluator before building the copy-files phase. Xcode shares one copy-files build phase across all configurations, so the embedded set cannot vary by configuration. Reject any expression whose result depends on the configuration, matching the existing per-source diagnostic. Fixes #28082
This commit is contained in:
@@ -65,6 +65,14 @@ at least one of the following:
|
||||
directory and no other :command:`project` calls between themselves and that
|
||||
common :command:`project` call.
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
Contents of ``XCODE_EMBED_<type>`` may use
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
Xcode shares one copy-files build phase across all configurations, so the
|
||||
embedded set cannot vary by configuration. A generator expression whose
|
||||
result depends on the configuration is rejected with an error.
|
||||
|
||||
See also :prop_tgt:`XCODE_EMBED_<type>_PATH`,
|
||||
:prop_tgt:`XCODE_EMBED_<type>_REMOVE_HEADERS_ON_COPY` and
|
||||
:prop_tgt:`XCODE_EMBED_<type>_CODE_SIGN_ON_COPY`.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
xcode-embed-genex
|
||||
-----------------
|
||||
|
||||
* The :prop_tgt:`XCODE_EMBED_<type>` target property now supports
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
Because Xcode shares one copy-files build phase across all configurations,
|
||||
an expression whose result depends on the configuration is rejected with
|
||||
an error.
|
||||
@@ -1037,6 +1037,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
XCodeGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
|
||||
cmGeneratorTarget* headTarget)
|
||||
: cmGeneratorExpressionInterpreter(
|
||||
localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget)
|
||||
, Target(headTarget)
|
||||
{
|
||||
}
|
||||
|
||||
XCodeGeneratorExpressionInterpreter(
|
||||
XCodeGeneratorExpressionInterpreter const&) = delete;
|
||||
XCodeGeneratorExpressionInterpreter& operator=(
|
||||
@@ -1055,13 +1063,23 @@ public:
|
||||
this->cmGeneratorExpressionInterpreter::Evaluate(expression, property);
|
||||
if (this->CompiledGeneratorExpression->GetHadContextSensitiveCondition()) {
|
||||
std::ostringstream e;
|
||||
/* clang-format off */
|
||||
e <<
|
||||
"Xcode does not support per-config per-source " << property << ":\n"
|
||||
" " << expression << "\n"
|
||||
"specified for source:\n"
|
||||
" " << this->SourceFile->ResolveFullPath() << '\n';
|
||||
/* clang-format on */
|
||||
if (this->SourceFile) {
|
||||
/* clang-format off */
|
||||
e <<
|
||||
"Xcode does not support per-config per-source " << property << ":\n"
|
||||
" " << expression << "\n"
|
||||
"specified for source:\n"
|
||||
" " << this->SourceFile->ResolveFullPath() << '\n';
|
||||
/* clang-format on */
|
||||
} else {
|
||||
/* clang-format off */
|
||||
e <<
|
||||
"Xcode does not support per-config " << property << ":\n"
|
||||
" " << expression << "\n"
|
||||
"specified for target:\n"
|
||||
" " << this->Target->GetName() << '\n';
|
||||
/* clang-format on */
|
||||
}
|
||||
this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
||||
}
|
||||
|
||||
@@ -1070,6 +1088,7 @@ public:
|
||||
|
||||
private:
|
||||
cmSourceFile* SourceFile = nullptr;
|
||||
cmGeneratorTarget* Target = nullptr;
|
||||
};
|
||||
|
||||
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
|
||||
@@ -4396,6 +4415,14 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
|
||||
return;
|
||||
}
|
||||
|
||||
// Xcode shares one copy-files build phase across all configurations, so the
|
||||
// embedded set cannot vary by config. Evaluate the property and reject any
|
||||
// generator expression whose result depends on the configuration.
|
||||
XCodeGeneratorExpressionInterpreter genexInterpreter(gt->GetLocalGenerator(),
|
||||
gt);
|
||||
std::string const& evaluatedFiles =
|
||||
genexInterpreter.Evaluate(*files, embedPropertyName);
|
||||
|
||||
// Create an "Embedded Frameworks" build phase
|
||||
auto* copyFilesBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
|
||||
@@ -4418,7 +4445,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
|
||||
this->CreateString("0"));
|
||||
cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
// Collect all embedded frameworks and dylibs and add them to build phase
|
||||
cmList relFiles{ *files };
|
||||
cmList relFiles{ evaluatedFiles };
|
||||
for (std::string const& relFile : relFiles) {
|
||||
cmXCodeObject* buildFile{ nullptr };
|
||||
std::string filePath = relFile;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# The generator expression must resolve to the "embedded" framework target so
|
||||
# that an "Embed Frameworks" copy-files phase is created. Were the expression
|
||||
# left unevaluated, target lookup would fail and no such phase would exist.
|
||||
execute_process(
|
||||
COMMAND grep -c "Embed Frameworks"
|
||||
${RunCMake_TEST_BINARY_DIR}/${test}.xcodeproj/project.pbxproj
|
||||
OUTPUT_VARIABLE actualCount
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT actualCount MATCHES "^[0-9]+$" OR actualCount EQUAL 0)
|
||||
set(RunCMake_TEST_FAILED
|
||||
"no Embed Frameworks phase in project; generator expression was not honored")
|
||||
endif()
|
||||
@@ -0,0 +1,9 @@
|
||||
# A generator expression whose result does not depend on the configuration is
|
||||
# honored. Here it resolves to the name of a framework target to embed.
|
||||
add_library(embedded SHARED func.m)
|
||||
set_target_properties(embedded PROPERTIES FRAMEWORK TRUE)
|
||||
|
||||
add_executable(app MACOSX_BUNDLE main.m)
|
||||
set_target_properties(app PROPERTIES
|
||||
XCODE_EMBED_FRAMEWORKS "$<1:embedded>"
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,10 @@
|
||||
^CMake Error in CMakeLists\.txt:
|
||||
Xcode does not support per-config XCODE_EMBED_FRAMEWORKS:
|
||||
|
||||
\$<\$<CONFIG:Debug>:foo\.framework>
|
||||
|
||||
specified for target:
|
||||
|
||||
app
|
||||
+
|
||||
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
|
||||
@@ -0,0 +1,5 @@
|
||||
add_executable(app MACOSX_BUNDLE main.m)
|
||||
|
||||
set_target_properties(app PROPERTIES
|
||||
XCODE_EMBED_FRAMEWORKS "$<$<CONFIG:Debug>:foo.framework>"
|
||||
)
|
||||
@@ -21,6 +21,13 @@ function(ExternalDependencies)
|
||||
endfunction()
|
||||
ExternalDependencies()
|
||||
|
||||
# A generator expression that does not depend on the configuration is honored.
|
||||
run_cmake(EmbedFrameworksGenex)
|
||||
|
||||
# A generator expression whose result depends on the configuration cannot be
|
||||
# honored, because Xcode shares one copy-files build phase across all configs.
|
||||
run_cmake(EmbedFrameworksPerConfig)
|
||||
|
||||
function(TestFlagsOn testName dependencyName)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-${dependencyName}-build)
|
||||
|
||||
Reference in New Issue
Block a user