app/rust_builder/cargokit/gradle/plugin.gradle
2024-02-06 20:35:52 +08:00

170 lines
5.7 KiB
Groovy

/// This is copied from Cargokit (which is the official way to use it currently)
/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
import java.nio.file.Paths
import org.apache.tools.ant.taskdefs.condition.Os
CargoKitPlugin.file = buildscript.sourceFile
apply plugin: CargoKitPlugin
class CargoKitExtension {
String manifestDir; // Relative path to folder containing Cargo.toml
String libname; // Library name within Cargo.toml. Must be a cdylib
}
abstract class CargoKitBuildTask extends DefaultTask {
@Input
String buildMode
@Input
String buildDir
@Input
String outputDir
@Input
String ndkVersion
@Input
String sdkDirectory
@Input
int compileSdkVersion;
@Input
int minSdkVersion;
@Input
String pluginFile
@Input
List<String> targetPlatforms
@TaskAction
def build() {
if (project.cargokit.manifestDir == null) {
throw new GradleException("Property 'manifestDir' must be set on cargokit extension");
}
if (project.cargokit.libname == null) {
throw new GradleException("Property 'libname' must be set on cargokit extension");
}
def executableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "run_build_tool.cmd" : "run_build_tool.sh"
def path = Paths.get(new File(pluginFile).parent, "..", executableName);
def manifestDir = Paths.get(project.buildscript.sourceFile.parent, project.cargokit.manifestDir)
def rootProjectDir = project.rootProject.projectDir
project.exec {
executable path
args "build-gradle"
environment "CARGOKIT_ROOT_PROJECT_DIR", rootProjectDir
environment "CARGOKIT_TOOL_TEMP_DIR", "${buildDir}/build_tool"
environment "CARGOKIT_MANIFEST_DIR", manifestDir
environment "CARGOKIT_CONFIGURATION", buildMode
environment "CARGOKIT_TARGET_TEMP_DIR", buildDir
environment "CARGOKIT_OUTPUT_DIR", outputDir
environment "CARGOKIT_NDK_VERSION", ndkVersion
environment "CARGOKIT_SDK_DIR", sdkDirectory
environment "CARGOKIT_COMPILE_SDK_VERSION", compileSdkVersion
environment "CARGOKIT_MIN_SDK_VERSION", minSdkVersion
environment "CARGOKIT_TARGET_PLATFORMS", targetPlatforms.join(",")
environment "CARGOKIT_JAVA_HOME", System.properties['java.home']
}
}
}
class CargoKitPlugin implements Plugin<Project> {
static String file;
private Plugin findFlutterPlugin(Project rootProject) {
_findFlutterPlugin(rootProject.childProjects)
}
private Plugin _findFlutterPlugin(Map projects) {
for (project in projects) {
for (plugin in project.value.getPlugins()) {
if (plugin.class.name == "FlutterPlugin") {
return plugin;
}
}
def plugin = _findFlutterPlugin(project.value.childProjects);
if (plugin != null) {
return plugin;
}
}
return null;
}
@Override
void apply(Project project) {
def plugin = findFlutterPlugin(project.rootProject);
project.extensions.create("cargokit", CargoKitExtension)
if (plugin == null) {
print("Flutter plugin not found, CargoKit plugin will not be applied.")
return;
}
def cargoBuildDir = "${project.buildDir}/build"
plugin.project.android.applicationVariants.all { variant ->
final buildType = variant.buildType.name
def cargoOutputDir = "${project.buildDir}/jniLibs/${buildType}";
def jniLibs = project.android.sourceSets.maybeCreate(buildType).jniLibs;
jniLibs.srcDir(new File(cargoOutputDir))
def platforms = plugin.getTargetPlatforms().collect()
// Same thing addFlutterDependencies does in flutter.gradle
if (buildType == "debug") {
platforms.add("android-x86")
platforms.add("android-x64")
}
// The task name depends on plugin properties, which are not available
// at this point
project.getGradle().afterProject {
def taskName = "cargokitCargoBuild${project.cargokit.libname.capitalize()}${buildType.capitalize()}";
if (project.tasks.findByName(taskName)) {
return
}
if (plugin.project.android.ndkVersion == null) {
throw new GradleException("Please set 'android.ndkVersion' in 'app/build.gradle'.")
}
def task = project.tasks.create(taskName, CargoKitBuildTask.class) {
buildMode = variant.buildType.name
buildDir = cargoBuildDir
outputDir = cargoOutputDir
ndkVersion = plugin.project.android.ndkVersion
sdkDirectory = plugin.project.android.sdkDirectory
minSdkVersion = plugin.project.android.defaultConfig.minSdkVersion.apiLevel as int
compileSdkVersion = plugin.project.android.compileSdkVersion.substring(8) as int
targetPlatforms = platforms
pluginFile = CargoKitPlugin.file
}
def onTask = { newTask ->
if (newTask.name == "merge${buildType.capitalize()}NativeLibs") {
newTask.dependsOn task
// Fix gradle 7.4.2 not picking up JNI library changes
newTask.outputs.upToDateWhen { false }
}
}
project.tasks.each onTask
project.tasks.whenTaskAdded onTask
}
}
}
}