From 0e3621df5ff55718add9b6a07cce1c9419704ef2 Mon Sep 17 00:00:00 2001 From: Kharkunov Eugene Date: Mon, 27 Oct 2025 21:22:39 +0200 Subject: [PATCH 1/2] Fix PodBuildSpec creation when PodSpec has more than 2 level of subspecs --- .../services/cocoapods/CocoaPodsService.java | 6 +- .../services/cocoapods/PodBuildSpecTest.java | 26 +++++ .../pod_specs/YandexMobileMetrica.json | 105 ++++++++++++++++++ .../xcconfigs/YandexMobileMetrica.xcconfig | 14 +++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 server/test-data/pod_specs/YandexMobileMetrica.json create mode 100644 server/test-data/xcconfigs/YandexMobileMetrica.xcconfig diff --git a/server/src/main/java/com/defold/extender/services/cocoapods/CocoaPodsService.java b/server/src/main/java/com/defold/extender/services/cocoapods/CocoaPodsService.java index 21959088..74378cba 100644 --- a/server/src/main/java/com/defold/extender/services/cocoapods/CocoaPodsService.java +++ b/server/src/main/java/com/defold/extender/services/cocoapods/CocoaPodsService.java @@ -421,7 +421,11 @@ public ResolvedPods resolveDependencies(PlatformConfig config, ExtenderBuildStat PodBuildSpec buildSpec = null; if (!tmpRegistry.containsKey(podName)) { - buildSpec = new PodBuildSpec(args, podSpec.parentSpec != null ? podSpec.parentSpec : podSpec); + PodSpec mainSpec = podSpec; + while (mainSpec.parentSpec != null) { + mainSpec = mainSpec.parentSpec; + } + buildSpec = new PodBuildSpec(args, mainSpec); tmpRegistry.put(podName, buildSpec); pods.add(buildSpec); } else { diff --git a/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java b/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java index 63284ac5..163ed787 100644 --- a/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java +++ b/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java @@ -1,5 +1,6 @@ package com.defold.extender.services.cocoapods; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; @@ -102,4 +103,29 @@ public void testCompilationFlags() throws IOException, ExtenderException { assertTrue(buildSpec.flags.swift.contains(String.format("-I%s/Sentry/Sources/Sentry/include", this.podsDir.toString()))); } + @Test + public void testNesptedPodSpecName() throws IOException, ExtenderException { + String jsonSpec = Files.readString(Path.of("test-data/pod_specs/YandexMobileMetrica.json")); + XCConfigParser parser = new XCConfigParser(this.buildDir, this.podsDir, PodUtils.Platform.IPHONEOS, "Debug", "arm64"); + File sentryTargetFolder = Path.of(this.podsDir.toString(), "Target Support Files", "YandexMobileMetrica").toFile(); + sentryTargetFolder.mkdirs(); + Files.copy(Path.of("test-data/xcconfigs/YandexMobileMetrica.xcconfig"), Path.of(sentryTargetFolder.toString(), "YandexMobileMetrica.debug.xcconfig"), StandardCopyOption.REPLACE_EXISTING); + + PodSpec podSpec = PodSpecParser.createPodSpec(PodSpecParser.parseJson(jsonSpec), PodUtils.Platform.IPHONEOS, null); + CocoaPodsServiceBuildState cocoapodsState = new CocoaPodsServiceBuildState(); + cocoapodsState.workingDir = this.workingDir; + cocoapodsState.podsDir = this.podsDir; + cocoapodsState.selectedPlatform = PodUtils.Platform.IPHONEOS; + + CreateBuildSpecArgs args = new CreateBuildSpecArgs.Builder() + .setConfigParser(parser) + .setCocoapodsBuildState(cocoapodsState) + .setJobContext(this.jobContext) + .build(); + args.buildDir = this.buildDir; + args.configuration = "Debug"; + + PodBuildSpec buildSpec = new PodBuildSpec(args, podSpec); + assertEquals(buildSpec.name, "YandexMobileMetrica"); + } } diff --git a/server/test-data/pod_specs/YandexMobileMetrica.json b/server/test-data/pod_specs/YandexMobileMetrica.json new file mode 100644 index 00000000..0f91f1bf --- /dev/null +++ b/server/test-data/pod_specs/YandexMobileMetrica.json @@ -0,0 +1,105 @@ +{ + "name": "YandexMobileMetrica", + "version": "4.5.2", + "summary": "This library is designed to be a part of mobile apps and provide app usage stats to Yandex AppMetrica", + "homepage": "https://appmetrica.yandex.com/", + "license": { + "type": "PROPRIETARY", + "file": "LICENSE.md" + }, + "authors": { + "Yandex LLC": "appmetrica@yandex-team.com" + }, + "source": { + "http": "https://storage.mds.yandex.net/get-appmetrica-mobile-sdk/175948/YandexMobileMetrica-4.5.2-ios-d70f8cb3-2746-4c3d-aa5f-dcd6acaaa5d8.zip", + "sha1": "2b015941841fca10652cc1dc38a4cda3687c6bce" + }, + "platforms": { + "ios": "9.0", + "tvos": "9.0" + }, + "libraries": [ + "c++", + "z", + "sqlite3" + ], + "frameworks": [ + "UIKit", + "Foundation", + "CoreLocation", + "CoreGraphics", + "AdSupport", + "SystemConfiguration" + ], + "ios": { + "frameworks": [ + "CoreTelephony", + "WebKit" + ], + "weak_frameworks": [ + + ] + }, + "requires_arc": true, + "default_subspecs": "Static", + "subspecs": [ + { + "name": "Static", + "subspecs": [ + { + "name": "Core", + "preserve_paths": [ + "static/YandexMobileMetrica.xcframework" + ], + "vendored_frameworks": "static/YandexMobileMetrica.xcframework", + "source_files": "static/YandexMobileMetrica.xcframework/**/YandexMobileMetrica.framework/Versions/A/Headers/*.h", + "public_header_files": "static/YandexMobileMetrica.xcframework/**/YandexMobileMetrica.framework/Versions/A/Headers/*.h" + }, + { + "name": "Crashes", + "preserve_paths": [ + "static/YandexMobileMetricaCrashes.xcframework", + "helper" + ], + "vendored_frameworks": "static/YandexMobileMetricaCrashes.xcframework", + "source_files": "static/YandexMobileMetricaCrashes.xcframework/**/YandexMobileMetricaCrashes.framework/Versions/A/Headers/*.h", + "public_header_files": "static/YandexMobileMetricaCrashes.xcframework/**/YandexMobileMetricaCrashes.framework/Versions/A/Headers/*.h", + "dependencies": { + "YandexMobileMetrica/Static/Core": [ + + ] + } + } + ] + }, + { + "name": "Dynamic", + "subspecs": [ + { + "name": "Core", + "preserve_paths": [ + "dynamic/YandexMobileMetrica.xcframework" + ], + "vendored_frameworks": "dynamic/YandexMobileMetrica.xcframework", + "source_files": "dynamic/YandexMobileMetrica.xcframework/**/YandexMobileMetrica.framework/Headers/*.h", + "public_header_files": "dynamic/YandexMobileMetrica.xcframework/**/YandexMobileMetrica.framework/Headers/*.h" + }, + { + "name": "Crashes", + "preserve_paths": [ + "dynamic/YandexMobileMetricaCrashes.xcframework", + "helper" + ], + "vendored_frameworks": "dynamic/YandexMobileMetricaCrashes.xcframework", + "source_files": "dynamic/YandexMobileMetricaCrashes.xcframework/**/YandexMobileMetricaCrashes.framework/Headers/*.h", + "public_header_files": "dynamic/YandexMobileMetricaCrashes.xcframework/**/YandexMobileMetricaCrashes.framework/Headers/*.h", + "dependencies": { + "YandexMobileMetrica/Dynamic/Core": [ + + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/server/test-data/xcconfigs/YandexMobileMetrica.xcconfig b/server/test-data/xcconfigs/YandexMobileMetrica.xcconfig new file mode 100644 index 00000000..cabbf282 --- /dev/null +++ b/server/test-data/xcconfigs/YandexMobileMetrica.xcconfig @@ -0,0 +1,14 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YandexMobileMetrica +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/YandexMobileMetrica/static" "${PODS_XCFRAMEWORKS_BUILD_DIR}/YandexMobileMetrica/Static/Core" "${PODS_XCFRAMEWORKS_BUILD_DIR}/YandexMobileMetrica/Static/Crashes" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "AdSupport" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "Foundation" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/YandexMobileMetrica +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES From e97cb2fd12e7f38465cc2a67df007aad5e245d0a Mon Sep 17 00:00:00 2001 From: Kharkunov Eugene Date: Tue, 28 Oct 2025 11:27:47 +0200 Subject: [PATCH 2/2] Fix test name --- .../defold/extender/services/cocoapods/PodBuildSpecTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java b/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java index 163ed787..eeb14d13 100644 --- a/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java +++ b/server/src/test/java/com/defold/extender/services/cocoapods/PodBuildSpecTest.java @@ -104,7 +104,7 @@ public void testCompilationFlags() throws IOException, ExtenderException { } @Test - public void testNesptedPodSpecName() throws IOException, ExtenderException { + public void testNestedPodSpecName() throws IOException, ExtenderException { String jsonSpec = Files.readString(Path.of("test-data/pod_specs/YandexMobileMetrica.json")); XCConfigParser parser = new XCConfigParser(this.buildDir, this.podsDir, PodUtils.Platform.IPHONEOS, "Debug", "arm64"); File sentryTargetFolder = Path.of(this.podsDir.toString(), "Target Support Files", "YandexMobileMetrica").toFile();