1 /*
<lambda>null2  * Copyright 2023 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 androidx.build.clang
18 
19 import com.android.utils.appendCapitalized
20 import org.gradle.api.Project
21 import org.gradle.api.artifacts.Configuration
22 import org.gradle.api.file.RegularFile
23 import org.gradle.api.provider.Provider
24 import org.gradle.api.tasks.TaskProvider
25 import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
26 import org.jetbrains.kotlin.konan.target.HostManager
27 import org.jetbrains.kotlin.konan.target.KonanTarget
28 
29 /**
30  * Configures a CInterop for the given [kotlinNativeCompilation]. The cinterop will be based on the
31  * [cinteropName] in the project sources but will additionally include the references to the library
32  * archive from the [ClangArchiveTask] so that it can be embedded in the generated klib of the
33  * cinterop.
34  */
35 internal fun MultiTargetNativeCompilation.configureCinterop(
36     kotlinNativeCompilation: KotlinNativeCompilation,
37     cinteropName: String = archiveName,
38 ) {
39     val kotlinNativeTarget = kotlinNativeCompilation.target
40     if (!canCompileOnCurrentHost(kotlinNativeTarget.konanTarget)) {
41         return
42     }
43     val konanTarget = kotlinNativeTarget.konanTarget
44     val nativeTargetCompilation = targetProvider(konanTarget)
45     val taskNamePrefix = "androidXCinterop".appendCapitalized(kotlinNativeTarget.name, archiveName)
46     val createDefFileTask =
47         registerCreateDefFileTask(
48             project = project,
49             taskNamePrefix = taskNamePrefix,
50             konanTarget = konanTarget,
51             archiveProvider =
52                 nativeTargetCompilation
53                     .flatMap { it.archiveTask }
54                     .flatMap { it.llvmArchiveParameters.outputFile },
55             cinteropName = cinteropName
56         )
57     registerCInterop(
58         kotlinNativeCompilation,
59         cinteropName,
60         createDefFileTask,
61         nativeTargetCompilation
62     )
63 }
64 
65 /**
66  * Configures a CInterop for the given [kotlinNativeCompilation]. The cinterop will be based on the
67  * [archiveConfiguration] name in the project sources but will additionally include the references
68  * to the library archive from the [ClangArchiveTask] so that it can be embedded in the generated
69  * klib of the cinterop.
70  */
configureCinteropnull71 internal fun configureCinterop(
72     project: Project,
73     kotlinNativeCompilation: KotlinNativeCompilation,
74     archiveConfiguration: Configuration
75 ) {
76     val kotlinNativeTarget = kotlinNativeCompilation.target
77     if (!HostManager().isEnabled(kotlinNativeTarget.konanTarget)) {
78         return
79     }
80     val taskNamePrefix =
81         "androidXCinterop".appendCapitalized(kotlinNativeTarget.name, archiveConfiguration.name)
82     val createDefFileTask =
83         registerCreateDefFileTask(
84             project = project,
85             taskNamePrefix = taskNamePrefix,
86             konanTarget = kotlinNativeCompilation.konanTarget,
87             archiveProvider =
88                 project.layout.file(archiveConfiguration.elements.map { it.single().asFile }),
89             cinteropName = archiveConfiguration.name
90         )
91     registerCInterop(kotlinNativeCompilation, archiveConfiguration.name, createDefFileTask)
92 }
93 
registerCreateDefFileTasknull94 private fun registerCreateDefFileTask(
95     project: Project,
96     taskNamePrefix: String,
97     konanTarget: KonanTarget,
98     archiveProvider: Provider<RegularFile>,
99     cinteropName: String
100 ) =
101     project.tasks.register(
102         taskNamePrefix.appendCapitalized("createDefFileFor", konanTarget.name),
103         CreateDefFileWithLibraryPathTask::class.java
104     ) { task ->
105         task.objectFile.set(archiveProvider)
106         task.target.set(
107             project.layout.buildDirectory.file(
108                 "cinteropDefFiles/$taskNamePrefix/${konanTarget.name}/$cinteropName.def"
109             )
110         )
111         task.original.set(
112             project.layout.projectDirectory.file("src/nativeInterop/cinterop/$cinteropName.def")
113         )
114         task.projectDir.set(project.layout.projectDirectory)
115     }
116 
registerCInteropnull117 private fun registerCInterop(
118     kotlinNativeCompilation: KotlinNativeCompilation,
119     cinteropName: String,
120     createDefFileTask: TaskProvider<CreateDefFileWithLibraryPathTask>,
121     nativeTargetCompilation: Provider<NativeTargetCompilation>? = null
122 ) {
123     kotlinNativeCompilation.cinterops.register(cinteropName) { cInteropSettings ->
124         cInteropSettings.definitionFile.set(createDefFileTask.flatMap { it.target })
125         nativeTargetCompilation?.let { nativeTargetCompilation ->
126             cInteropSettings.includeDirs(
127                 nativeTargetCompilation
128                     .flatMap { it.compileTask }
129                     .map { it.clangParameters.includes }
130             )
131         }
132     }
133 }
134