Unverified Commit e6b154b0 authored by david-perez's avatar david-perez Committed by GitHub
Browse files

Generate MSRV in Kotlin file (#3869)

Currently, when generating Rust crates, the MSRV is read from
`gradle.properties` by determining the project root using `git
rev-parse`. However, some build environments smithy-rs needs to build on
don't have `git` available.

This commit uses Gradle's `rootDir` to determine the project root, and
generates a Kotlin file exposing the MSRV as part of a Gradle build task
that is then published as part of `codegen-core.jar`. This also has the
benefit that consumers of smithy-rs can read the MSRV from there.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent 24703417
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@

import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import java.io.ByteArrayOutputStream
import java.util.Properties

plugins {
    kotlin("jvm")
@@ -53,6 +54,44 @@ fun gitCommitHash(): String {
    }
}

// Define the directory where the generated Kotlin file will be placed
val generatedSrcDir = layout.buildDirectory.dir("generated/src/main/kotlin")

sourceSets {
    main {
        kotlin {
            srcDir(generatedSrcDir)
        }
    }
}

val generateBuildEnvironmentConstants = tasks.register("generateBuildEnvironmentConstants") {
    // Specify that the task generates sources.
    val outputDir = generatedSrcDir.get().asFile
    outputs.dir(outputDir)

    doLast {
        // Load properties from `gradle.properties`.
        val properties = Properties()
        val gradlePropertiesFile = file("${rootDir}/gradle.properties")
        properties.load(gradlePropertiesFile.inputStream())

        val rustMsrv = properties.getProperty("rust.msrv")

        // Generate the Kotlin file.
        val generatedFile = file("$outputDir/BuildEnvironment.kt")
        generatedFile.writeText("""
            // This file is automatically generated. Do not modify manually.
            package software.amazon.smithy.rust.codegen.core.generated

            object BuildEnvironment {
                const val MSRV: String = "$rustMsrv"
                const val PROJECT_DIR: String = "$rootDir"
            }
        """.trimIndent())
    }
}

val generateSmithyRuntimeCrateVersion by tasks.registering {
    // Generate the version of the runtime to use as a resource.
    // This keeps us from having to manually change version numbers in multiple places.
@@ -125,6 +164,7 @@ java {
tasks.compileKotlin {
    kotlinOptions.jvmTarget = "11"
    dependsOn(generateSmithyRuntimeCrateVersion)
    dependsOn(generateBuildEnvironmentConstants)
}

// Reusable license copySpec
+6 −17
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ import software.amazon.smithy.model.loader.ModelAssembler
import software.amazon.smithy.model.node.Node
import software.amazon.smithy.model.node.ObjectNode
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.rust.codegen.core.generated.BuildEnvironment
import software.amazon.smithy.rust.codegen.core.rustlang.Attribute
import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.core.rustlang.DependencyScope
@@ -40,11 +41,10 @@ import software.amazon.smithy.rust.codegen.core.util.letIf
import software.amazon.smithy.rust.codegen.core.util.orNullIfEmpty
import software.amazon.smithy.rust.codegen.core.util.runCommand
import java.io.File
import java.io.FileInputStream
import java.nio.file.Files
import java.nio.file.Files.createTempDirectory
import java.nio.file.Path
import java.util.Properties
import kotlin.io.path.Path
import kotlin.io.path.absolutePathString
import kotlin.io.path.writeText

@@ -56,8 +56,6 @@ val TestModuleDocProvider =
            }
    }

val projectRootDir by lazy { File("git rev-parse --show-toplevel".runCommand().replace("\n", "")) }

/**
 * Waiting for Kotlin to stabilize their temp directory functionality
 */
@@ -73,23 +71,14 @@ private fun tempDir(directory: File? = null): File {
 * This function returns the minimum supported Rust version, as specified in the `gradle.properties` file
 * located at the root of the project.
 */
fun msrv(): String {
    val properties = Properties()
    val propertiesFilePath = projectRootDir.resolve("gradle.properties")

    FileInputStream(propertiesFilePath).use { inputStream ->
        properties.load(inputStream)
    }

    return properties.getProperty("rust.msrv")
}
fun msrv(): String = BuildEnvironment.MSRV

/**
 * Generates the `rust-toolchain.toml` file in the specified directory.
 *
 * The compiler version is set in `gradle.properties` under the `rust.msrv` property.
 * The Gradle task `GenerateMsrvTask` generates the Kotlin class
 * `software.amazon.smithy.rust.codegen.core.Msrv` and writes the value of `rust.msrv` into it.
 * The Gradle task `generateRustMsrvFile` generates the Kotlin class
 * `software.amazon.smithy.rust.codegen.core.generated.RustMsrv.kt` and writes the value of `rust.msrv` into it.
 */
private fun File.generateRustToolchainToml() {
    resolve("rust-toolchain.toml").writeText(
@@ -123,7 +112,7 @@ object TestWorkspace {
    private val subprojects = mutableListOf<String>()

    private val cargoLock: File by lazy {
        projectRootDir.resolve("aws/sdk/Cargo.lock")
        File(BuildEnvironment.PROJECT_DIR).resolve("aws/sdk/Cargo.lock")
    }

    init {
+7 −7
Original line number Diff line number Diff line
@@ -9,9 +9,10 @@ import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.paths.shouldExist
import io.kotest.matchers.shouldNotBe
import org.junit.jupiter.api.Test
import software.amazon.smithy.rust.codegen.core.generated.BuildEnvironment
import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel
import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext
import software.amazon.smithy.rust.codegen.core.testutil.projectRootDir
import java.io.File
import java.nio.file.Files.createTempDirectory
import java.util.regex.Pattern

@@ -48,7 +49,7 @@ internal class RustToolChainTomlTest {

        // Read the MSRV written in `gradle.properties` file.
        val msrvPattern = Pattern.compile("rust\\.msrv=(.+)")
        val gradlePropertiesPath = projectRootDir.resolve("gradle.properties")
        val gradlePropertiesPath = File(BuildEnvironment.PROJECT_DIR).resolve("gradle.properties")
        val msrv =
            gradlePropertiesPath.useLines { lines ->
                lines.firstNotNullOfOrNull { line ->
@@ -75,7 +76,6 @@ internal class RustToolChainTomlTest {

                // There should be a [toolchain] table, and it must have a key called 'channel' whose value must
                // match the `rust.msrv` specified in gradle.properties.
                toolchainSection != null &&
                toolchainSection.any { line ->
                    channelPattern.matcher(line).let { matcher ->
                        matcher.find() && matcher.group(1) == msrv