-
Notifications
You must be signed in to change notification settings - Fork 77
Add per build type cargoBuild${buildType}
tasks
#68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,15 +53,17 @@ rustup target add x86_64-pc-windows-msvc # for win32-x86-64-msvc | |
... | ||
``` | ||
|
||
Finally, run the `cargoBuild` task to cross compile: | ||
Finally, run a `cargoBuild${buildType}` task (see `buildTypeToProfile`) to cross compile: | ||
```sh | ||
./gradlew cargoBuild | ||
./gradlew cargoBuildDebug | ||
``` | ||
Or add it as a dependency to one of your other build tasks, to build your rust code when you normally build your project: | ||
```gradle | ||
tasks.whenTaskAdded { task -> | ||
if ((task.name == 'javaPreCompileDebug' || task.name == 'javaPreCompileRelease')) { | ||
task.dependsOn 'cargoBuild' | ||
if (task.name == 'javaPreCompileDebug') { | ||
task.dependsOn 'cargoBuildDebug' | ||
} else if (task.name == 'javaPreCompileRelease') { | ||
task.dependsOn 'cargoBuildRelease' | ||
} | ||
} | ||
``` | ||
|
@@ -99,11 +101,6 @@ which can be specified using the `apiLevel` option. This option defaults to the | |
level. As of API level 21, 64-bit builds are possible; and conversely, the `arm64` and `x86_64` | ||
targets require `apiLevel >= 21`. | ||
|
||
### Cargo release profile | ||
|
||
The `profile` option selects between the `--debug` and `--release` profiles in `cargo`. *Defaults | ||
to `debug`!* | ||
|
||
### Extension reference | ||
|
||
### module | ||
|
@@ -190,18 +187,24 @@ cargo { | |
} | ||
``` | ||
|
||
### profile | ||
|
||
The Cargo [release profile](https://doc.rust-lang.org/book/second-edition/ch14-01-release-profiles.html#customizing-builds-with-release-profiles) to build. | ||
### buildTypeToProfile | ||
|
||
Defaults to `"debug"`. | ||
This mandatory option specifies the Cargo [release profile](https://doc.rust-lang.org/book/second-edition/ch14-01-release-profiles.html#customizing-builds-with-release-profiles) to build per [Android build type](https://developer.android.com/studio/build/build-variants#build-types). | ||
Each entry in the map causes a new `cargoBuild${buildType}` task to be created. | ||
|
||
```groovy | ||
cargo { | ||
profile = 'release' | ||
buildTypeToProfile = [ | ||
"debug": "debug", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't it be |
||
"alpha": "debug", | ||
"beta": "release", | ||
"release": "release", | ||
] | ||
} | ||
``` | ||
|
||
The above example creates these targets: `cargoBuildDebug`, `cargoBuildAlpha`, `cargoBuildBeta`, `cargoBuildRelease`. | ||
|
||
### features | ||
|
||
Set the Cargo [features](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,12 +6,16 @@ import org.gradle.api.DefaultTask | |
import org.gradle.api.GradleException | ||
import org.gradle.api.Project | ||
import org.gradle.api.logging.LogLevel | ||
import org.gradle.api.tasks.Input; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: no trailing semi-colon. |
||
import org.gradle.api.tasks.TaskAction | ||
import java.io.ByteArrayOutputStream | ||
import java.io.File | ||
|
||
open class CargoBuildTask : DefaultTask() { | ||
@Input | ||
var toolchain: Toolchain? = null | ||
@Input | ||
var profile: String? = null | ||
|
||
|
||
@Suppress("unused") | ||
|
@@ -24,10 +28,15 @@ open class CargoBuildTask : DefaultTask() { | |
throw GradleException("toolchain cannot be null") | ||
} | ||
|
||
var profile = profile | ||
if (profile == null) { | ||
throw GradleException("profile cannot be null") | ||
} | ||
|
||
project.plugins.all { | ||
when (it) { | ||
is AppPlugin -> buildProjectForTarget<AppExtension>(project, toolchain, this) | ||
is LibraryPlugin -> buildProjectForTarget<LibraryExtension>(project, toolchain, this) | ||
is AppPlugin -> buildProjectForTarget<AppExtension>(project, toolchain, profile, this) | ||
is LibraryPlugin -> buildProjectForTarget<LibraryExtension>(project, toolchain, profile, this) | ||
} | ||
} | ||
// CARGO_TARGET_DIR can be used to force the use of a global, shared target directory | ||
|
@@ -44,10 +53,18 @@ open class CargoBuildTask : DefaultTask() { | |
|
||
val defaultTargetTriple = getDefaultTargetTriple(project, rustcCommand) | ||
|
||
// See https://rust-lang.github.io/rfcs/2678-named-custom-cargo-profiles.html#new-dir-name-attribute | ||
// Right now "dev" maps to "debug", but depending on how RFC 2678 gets merged in the end, we may need to read a property out of `cargo metadata` | ||
var profileDirName = if (profile == "dev") { | ||
"debug" | ||
} else { | ||
profile | ||
} | ||
|
||
val cargoOutputDir = if (toolchain.target == defaultTargetTriple) { | ||
"${targetDirectory}/${profile}" | ||
"${targetDirectory}/${profileDirName}" | ||
} else { | ||
"${targetDirectory}/${toolchain.target}/${profile}" | ||
"${targetDirectory}/${toolchain.target}/${profileDirName}" | ||
} | ||
copy { spec -> | ||
spec.from(File(project.projectDir, cargoOutputDir)) | ||
|
@@ -68,7 +85,7 @@ open class CargoBuildTask : DefaultTask() { | |
} | ||
} | ||
|
||
inline fun <reified T : BaseExtension> buildProjectForTarget(project: Project, toolchain: Toolchain, cargoExtension: CargoExtension) { | ||
inline fun <reified T : BaseExtension> buildProjectForTarget(project: Project, toolchain: Toolchain, profile: String, cargoExtension: CargoExtension) { | ||
val app = project.extensions[T::class] | ||
val apiLevel = cargoExtension.apiLevels[toolchain.platform]!! | ||
val defaultTargetTriple = getDefaultTargetTriple(project, cargoExtension.rustcCommand) | ||
|
@@ -120,12 +137,14 @@ open class CargoBuildTask : DefaultTask() { | |
} | ||
} | ||
|
||
if (cargoExtension.profile != "debug") { | ||
// Cargo is rigid: it accepts "--release" for release (and | ||
// nothing for dev). This is a cheap way of allowing only | ||
// two values. | ||
theCommandLine.add("--${cargoExtension.profile}") | ||
// TODO: When --profile is stabilized use it instead of --release | ||
// https://github.com/rust-lang/cargo/issues/6988 | ||
if (profile == "release") { | ||
theCommandLine.add("--release") | ||
} else if (profile != "dev") { | ||
throw GradleException("Profile may only be 'dev' or 'release', got '${profile}'") | ||
} | ||
|
||
if (toolchain.target != defaultTargetTriple) { | ||
// Only providing --target for the non-default targets means desktop builds | ||
// can share the build cache with `cargo build`/`cargo test`/etc invocations, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -172,6 +172,10 @@ open class RustAndroidPlugin : Plugin<Project> { | |
throw GradleException("libname cannot be null") | ||
} | ||
|
||
if (cargoExtension.buildTypeToProfile.isEmpty()) { | ||
throw GradleException("buildTypeToProfile must have entries") | ||
} | ||
|
||
// Allow to set targets, including per-project, in local.properties. | ||
val localTargets: String? = | ||
cargoExtension.localProperties.getProperty("rust.targets.${project.name}") ?: | ||
|
@@ -256,38 +260,41 @@ open class RustAndroidPlugin : Plugin<Project> { | |
includeEmptyDirs = false | ||
} | ||
|
||
val buildTask = tasks.maybeCreate("cargoBuild", | ||
DefaultTask::class.java).apply { | ||
group = RUST_TASK_GROUP | ||
description = "Build library (all targets)" | ||
} | ||
cargoExtension.buildTypeToProfile.forEach { buildType, theProfile -> | ||
val buildTask = tasks.maybeCreate("cargoBuild${buildType.capitalize()}", | ||
DefaultTask::class.java).apply { | ||
group = RUST_TASK_GROUP | ||
description = "Build library (all targets) for android build type ${buildType}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well include the profile name here. And nit: capitalize Android. |
||
} | ||
|
||
cargoExtension.targets!!.forEach { target -> | ||
val theToolchain = toolchains | ||
.filter { | ||
if (usePrebuilt) { | ||
it.type != ToolchainType.ANDROID_GENERATED | ||
} else { | ||
it.type != ToolchainType.ANDROID_PREBUILT | ||
cargoExtension.targets!!.forEach { target -> | ||
val theToolchain = toolchains | ||
.filter { | ||
if (usePrebuilt) { | ||
it.type != ToolchainType.ANDROID_GENERATED | ||
} else { | ||
it.type != ToolchainType.ANDROID_PREBUILT | ||
} | ||
} | ||
} | ||
.find { it.platform == target } | ||
if (theToolchain == null) { | ||
throw GradleException("Target ${target} is not recognized (recognized targets: ${toolchains.map { it.platform }.sorted()}). Check `local.properties` and `build.gradle`.") | ||
} | ||
.find { it.platform == target } | ||
if (theToolchain == null) { | ||
throw GradleException("Target ${target} is not recognized (recognized targets: ${toolchains.map { it.platform }.sorted()}). Check `local.properties` and `build.gradle`.") | ||
} | ||
|
||
val targetBuildTask = tasks.maybeCreate("cargoBuild${target.capitalize()}", | ||
CargoBuildTask::class.java).apply { | ||
group = RUST_TASK_GROUP | ||
description = "Build library ($target)" | ||
toolchain = theToolchain | ||
} | ||
val targetBuildTask = tasks.maybeCreate("cargoBuild${target.capitalize()}${buildType.capitalize()}", | ||
CargoBuildTask::class.java).apply { | ||
group = RUST_TASK_GROUP | ||
description = "Build library ($target) for android build type ${buildType}" | ||
toolchain = theToolchain | ||
profile = theProfile | ||
} | ||
|
||
if (!usePrebuilt) { | ||
targetBuildTask.dependsOn(generateToolchain!!) | ||
if (!usePrebuilt) { | ||
targetBuildTask.dependsOn(generateToolchain!!) | ||
} | ||
targetBuildTask.dependsOn(generateLinkerWrapper) | ||
buildTask.dependsOn(targetBuildTask) | ||
} | ||
targetBuildTask.dependsOn(generateLinkerWrapper) | ||
buildTask.dependsOn(targetBuildTask) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This link is broken. s/second-edition// to fix it.