@@ -67,6 +67,12 @@ class CustomPathStrategy(
6767 // We trust that the user knows the distinction if they purposefully override the framework path
6868 override fun resolvePaths (architectures : Set <String >): FrameworkPaths {
6969 return linker.frameworkPath.orNull?.takeIf { it.isNotEmpty() }?.let { basePath ->
70+ project.logger.lifecycle(
71+ " Resolving Sentry Cocoa framework paths using custom path: {} and looking for Sentry architectures: {} within the custom path" ,
72+ basePath,
73+ architectures
74+ )
75+
7076 when {
7177 basePath.endsWith(" Sentry.xcframework" ) -> FrameworkPaths .createValidated(
7278 staticBasePath = basePath,
@@ -78,7 +84,7 @@ class CustomPathStrategy(
7884 architectures = architectures
7985 )
8086
81- else -> null
87+ else -> FrameworkPaths . NONE
8288 }
8389 } ? : FrameworkPaths .NONE
8490 }
@@ -90,12 +96,19 @@ class DerivedDataStrategy(
9096 private val linker: LinkerExtension = project.extensions.getByType(LinkerExtension ::class .java)
9197
9298 override fun resolvePaths (architectures : Set <String >): FrameworkPaths {
93- val xcodeprojPath = linker.xcodeprojPath.orNull
94- val derivedDataPath = xcodeprojPath?.let { path ->
99+ project.logger.lifecycle(" Resolving Sentry Cocoa framework paths using derived data path" )
100+
101+ // First priority: User-specified xcodeproj path
102+ val xcodeprojSetByUser = linker.xcodeprojPath.orNull?.takeIf { it.isNotEmpty() }
103+ // Second priority: Auto-discovered xcodeproj in project root
104+ val foundXcodeproj = xcodeprojSetByUser ? : findXcodeprojFile2(project.rootDir)?.absolutePath
105+
106+ val derivedDataPath = foundXcodeproj?.let { path ->
95107 project.providers.of(DerivedDataPathValueSource ::class .java) {
96108 it.parameters.xcodeprojPath.set(path)
97- }.get()
98- } ? : return FrameworkPaths .NONE
109+ }.orNull
110+ } ? : FrameworkPaths .NONE
111+
99112 val dynamicBasePath =
100113 " ${derivedDataPath} /SourcePackages/artifacts/sentry-cocoa/Sentry-Dynamic/Sentry-Dynamic.xcframework"
101114 val staticBasePath =
@@ -107,6 +120,30 @@ class DerivedDataStrategy(
107120 architectures = architectures
108121 )
109122 }
123+
124+ /* *
125+ * Searches for a xcodeproj starting from the root directory. This function will only work for
126+ * monorepos and if it is not, the user needs to provide the custom path through the
127+ * [LinkerExtension] configuration.
128+ */
129+ internal fun findXcodeprojFile2 (dir : File ): File ? {
130+ val ignoredDirectories = listOf (" build" , " DerivedData" )
131+
132+ fun searchDirectory (directory : File ): File ? {
133+ val files = directory.listFiles() ? : return null
134+
135+ return files.firstNotNullOfOrNull { file ->
136+ when {
137+ file.name in ignoredDirectories -> null
138+ file.extension == " xcodeproj" -> file
139+ file.isDirectory -> searchDirectory(file)
140+ else -> null
141+ }
142+ }
143+ }
144+
145+ return searchDirectory(dir)
146+ }
110147}
111148
112149class ManualSearchStrategy (
@@ -139,18 +176,34 @@ class FrameworkPathResolver(
139176 fun resolvePaths (
140177 architectures : Set <String >
141178 ): FrameworkPaths {
142- return strategies.firstNotNullOfOrNull { strategy ->
143- try {
144- strategy.resolvePaths(architectures)
145- } catch (e: Exception ) {
146- project.logger.debug(
147- " Path resolution strategy ${strategy::class .simpleName} failed" ,
148- e
149- )
150- null
179+ return strategies.asSequence()
180+ .mapNotNull { strategy ->
181+ try {
182+ val result = strategy.resolvePaths(architectures)
183+ when {
184+ result == FrameworkPaths .NONE -> {
185+ project.logger.debug(" Strategy ${strategy::class .simpleName} returned no paths" )
186+ null
187+ }
188+
189+ else -> {
190+ project.logger.lifecycle(" ✅ Found Sentry Cocoa framework paths using ${strategy::class .simpleName} " )
191+ result
192+ }
193+ }
194+ } catch (e: Exception ) {
195+ project.logger.debug(
196+ " Strategy ${strategy::class .simpleName} failed: ${e.message} "
197+ )
198+ null
199+ }
151200 }
152- }
153- ? : throw FrameworkLinkingException (" All framework resolution strategies failed. Could not find Sentry Cocoa framework path" )
201+ .firstOrNull()
202+ ? : throw FrameworkLinkingException (
203+ " No valid framework paths found. Attempted strategies: ${
204+ strategies.joinToString { it::class .simpleName!! }
205+ } "
206+ )
154207 }
155208
156209 companion object {
@@ -164,7 +217,9 @@ class FrameworkPathResolver(
164217 return listOf (
165218 CustomPathStrategy (project),
166219 DerivedDataStrategy (project),
167- ManualSearchStrategy (project)
220+ ManualSearchStrategy (project),
221+ // TODO: add DownloadStrategy -> downloads the framework and stores it in build dir
222+ // this is especially useful for users who dont have a monorepo setup
168223 )
169224 }
170225 }
0 commit comments