Skip to content

Commit 74258e9

Browse files
committed
Use the xcode lock in every Xcode call task
1 parent 6a48cb2 commit 74258e9

File tree

3 files changed

+51
-15
lines changed

3 files changed

+51
-15
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2026 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.jetbrains.androidx.build
18+
19+
import org.gradle.api.Project
20+
import org.gradle.api.provider.Provider
21+
import org.gradle.api.services.BuildService
22+
import org.gradle.api.services.BuildServiceParameters
23+
24+
/**
25+
* A lock to prevent parallel access to Xcode tools, it causes races:
26+
* "error: unable to attach DB: unable to initialize database (database is locked)"
27+
* "external process started 'xcrun --sdk iphoneos --show-sdk-platform-path'"
28+
*
29+
* Works as a service with max usages = 1
30+
*
31+
* Usage inside a task:
32+
* ```
33+
* usesService(XcodeBuildLock.instance(project))
34+
* ```
35+
*/
36+
abstract class XcodeToolsLock : BuildService<BuildServiceParameters.None> {
37+
companion object {
38+
@JvmStatic
39+
fun instance(project: Project): Provider<XcodeToolsLock> =
40+
project.gradle.sharedServices.registerIfAbsent("xcodeBuildLock", XcodeToolsLock::class.java) {
41+
it.maxParallelUsages.set(1)
42+
}
43+
}
44+
}

compose/ui/ui-uikit/build.gradle

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
*/
1616

1717
import androidx.build.KotlinTarget
18-
import androidx.build.ProjectLayoutType
19-
import androidx.build.SoftwareType
20-
import org.gradle.api.services.BuildService
21-
import org.gradle.api.services.BuildServiceParameters
18+
import org.jetbrains.androidx.build.XcodeToolsLock
2219

2320
plugins {
2421
id("AndroidXPlugin")
@@ -44,13 +41,6 @@ kotlin {
4441
}
4542

4643
private def configure(target, isDevice, architecture, testTarget) {
47-
// to prevent "Process 'command 'xcodebuild'' finished with non-zero exit value 65"
48-
// "error: unable to attach DB: unable to initialize database (database is locked)"
49-
def xcodeLock =
50-
project.gradle.sharedServices.registerIfAbsent("xcodeBuildLock", XcodeBuildLock) {
51-
maxParallelUsages.set(1)
52-
}
53-
5444
def frameworkName = "CMPUIKitUtils"
5545
def buildSchemeName = frameworkName
5646
def testSchemeName = "${frameworkName}Tests"
@@ -84,6 +74,7 @@ private def configure(target, isDevice, architecture, testTarget) {
8474
def testFrameworkTaskName = "${target.name}FrameworkTest"
8575

8676
def getTargetDeviceTask = project.tasks.register(getTargetDeviceTaskName, Exec) {
77+
usesService(XcodeToolsLock.instance(project))
8778
ext.device = ""
8879
commandLine "xcrun", "simctl", "list", "devices"
8980
standardOutput = new ByteArrayOutputStream()
@@ -98,6 +89,7 @@ private def configure(target, isDevice, architecture, testTarget) {
9889
def testFrameworkTask = project.tasks.register(testFrameworkTaskName) {
9990
dependsOn getTargetDeviceTask
10091
doLast {
92+
usesService(XcodeToolsLock.instance(project))
10193
project.exec {
10294
workingDir frameworkSourcesDir
10395
commandLine "xcodebuild",
@@ -116,7 +108,7 @@ private def configure(target, isDevice, architecture, testTarget) {
116108
target.compilations.main {
117109
def libTaskName = "${compileTaskProvider.name}ObjCLib"
118110
project.tasks.register(libTaskName, Exec) {
119-
usesService(xcodeLock)
111+
usesService(XcodeToolsLock.instance(project))
120112
inputs.dir(frameworkSourcesDir)
121113
.withPropertyName("${frameworkName}-${sdkName}")
122114
.withPathSensitivity(PathSensitivity.RELATIVE)
@@ -172,6 +164,4 @@ androidx {
172164
inceptionYear = "2023"
173165
description = "Internal iOS UIKit utilities including Objective-C library."
174166
legacyDisableKotlinStrictApiMode = true
175-
}
176-
177-
abstract class XcodeBuildLock implements BuildService<BuildServiceParameters.None> {}
167+
}

testutils/testutils-xctest/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import androidx.build.KotlinTarget
1818
import androidx.build.SoftwareType
19+
import org.jetbrains.androidx.build.XcodeToolsLock
1920
import org.jetbrains.kotlin.konan.target.KonanTarget
2021
import org.jetbrains.kotlin.konan.target.Architecture
2122

@@ -119,6 +120,7 @@ private def configure(target, isDevice) {
119120
target.compilations.main {
120121
def libTaskName = "${compileTaskProvider.name}ObjCLib"
121122
project.tasks.register(libTaskName, Exec) {
123+
usesService(XcodeToolsLock.instance(project))
122124
inputs.dir(frameworkSourcesDir)
123125
.withPropertyName("${frameworkName}-${sdkName}")
124126
.withPathSensitivity(PathSensitivity.RELATIVE)

0 commit comments

Comments
 (0)