From 8119ca50adbca74feb45047bf7e3bed2d0b6811a Mon Sep 17 00:00:00 2001 From: Lorenzo Gabriele Date: Wed, 8 Jun 2022 11:24:55 +0200 Subject: [PATCH] Support Scala Native `nativeEmbedResources` (#1890) This adds support for `nativeEmbedResources` (available in Scala Native 0.4.4+) Since we support Scala Native 0.4.0+ this uses the same mechanism `scalajslib` uses to execute methods only on versions a certain feature is available. Pull request: https://github.com/com-lihaoyi/mill/pull/1890 --- .../api/ScalaNativeWorkerApi.java | 2 + scalanativelib/src/ScalaNativeModule.scala | 11 ++++- .../0.4/src/ScalaNativeWorkerImpl.scala | 48 +++++++++++-------- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/scalanativelib/api/src/mill/scalanativelib/api/ScalaNativeWorkerApi.java b/scalanativelib/api/src/mill/scalanativelib/api/ScalaNativeWorkerApi.java index 9bbe694667f..cb269ef0bd4 100644 --- a/scalanativelib/api/src/mill/scalanativelib/api/ScalaNativeWorkerApi.java +++ b/scalanativelib/api/src/mill/scalanativelib/api/ScalaNativeWorkerApi.java @@ -1,4 +1,5 @@ package mill.scalanativelib.api; + import sbt.testing.Framework; public interface ScalaNativeWorkerApi { @@ -20,6 +21,7 @@ NativeConfig config(String mainClass, LTO nativeLTO, ReleaseMode releaseMode, boolean optimize, + boolean embedResources, NativeLogLevel logLevel); String defaultGarbageCollector(); diff --git a/scalanativelib/src/ScalaNativeModule.scala b/scalanativelib/src/ScalaNativeModule.scala index 42c8eef1db8..d14f9849d76 100644 --- a/scalanativelib/src/ScalaNativeModule.scala +++ b/scalanativelib/src/ScalaNativeModule.scala @@ -164,6 +164,14 @@ trait ScalaNativeModule extends ScalaModule { outer => // Whether to link `@stub` methods, or ignore them def nativeLinkStubs = T { false } + /** + * Shall the resource files be embedded in the resulting binary file? Allows + * the use of getClass().getResourceAsStream() on the included files. Will + * not embed files with certain extensions, including ".c", ".h", ".scala" + * and ".class". + */ + def nativeEmbedResources = T { false } + // The LTO mode to use used during a release build protected def nativeLTOInput: Target[Option[LTO]] = T.input { readEnvVariable[LTO](T.env, "SCALANATIVE_LTO", LTO.values, _.value) @@ -195,7 +203,8 @@ trait ScalaNativeModule extends ScalaModule { outer => nativeLTO(), releaseMode(), nativeOptimize(), - logLevel() + nativeEmbedResources(), + logLevel(), ) } diff --git a/scalanativelib/worker/0.4/src/ScalaNativeWorkerImpl.scala b/scalanativelib/worker/0.4/src/ScalaNativeWorkerImpl.scala index fdb09b2ad10..8196214a5fe 100644 --- a/scalanativelib/worker/0.4/src/ScalaNativeWorkerImpl.scala +++ b/scalanativelib/worker/0.4/src/ScalaNativeWorkerImpl.scala @@ -3,6 +3,8 @@ package mill.scalanativelib.worker import java.io.File import java.lang.System.{err, out} +import mill.scalanativelib.api.{GetFrameworkResult, LTO, NativeConfig, NativeLogLevel, ReleaseMode} +import sbt.testing.Framework import scala.scalanative.util.Scope import scala.scalanative.build.{ Build, @@ -16,12 +18,19 @@ import scala.scalanative.build.{ NativeConfig => ScalaNativeNativeConfig } import scala.scalanative.nir.Versions -import mill.scalanativelib.api.{GetFrameworkResult, LTO, NativeConfig, NativeLogLevel, ReleaseMode} -import sbt.testing.Framework - import scala.scalanative.testinterface.adapter.TestAdapter +import scala.util.{Success, Try} + class ScalaNativeWorkerImpl extends mill.scalanativelib.api.ScalaNativeWorkerApi { + private def patchIsGreaterThanOrEqual(number: Int) = { + val patch = Versions.current.stripPrefix("0.4.") + Try(patch.toInt) match { + case Success(n) if n < number => false + case _ => true + } + } + def logger(level: NativeLogLevel) = Logger( traceFn = msg => if (level.value >= NativeLogLevel.Trace.value) err.println(s"[trace] $msg"), @@ -51,30 +60,31 @@ class ScalaNativeWorkerImpl extends mill.scalanativelib.api.ScalaNativeWorkerApi nativeLTO: LTO, releaseMode: ReleaseMode, nativeOptimize: Boolean, + nativeEmbedResources: Boolean, logLevel: NativeLogLevel ): NativeConfig = { - val entry = Versions.current match { - case "0.4.0" | "0.4.1" | "0.4.2" => mainClass + "$" - case _ => mainClass + val entry = if (patchIsGreaterThanOrEqual(3)) mainClass else mainClass + "$" + var nativeConfig = + ScalaNativeNativeConfig.empty + .withClang(nativeClang.toPath) + .withClangPP(nativeClangPP.toPath) + .withTargetTriple(if (nativeTarget.isPresent) Some(nativeTarget.get) else None) + .withCompileOptions(nativeCompileOptions) + .withLinkingOptions(nativeLinkingOptions) + .withGC(GC(nativeGC)) + .withLinkStubs(nativeLinkStubs) + .withMode(Mode(releaseMode.value)) + .withOptimize(nativeOptimize) + .withLTO(ScalaNativeLTO(nativeLTO.value)) + if (patchIsGreaterThanOrEqual(4)) { + nativeConfig = nativeConfig.withEmbedResources(nativeEmbedResources) } val config = Config.empty .withMainClass(entry) .withClassPath(classpath.map(_.toPath)) .withWorkdir(nativeWorkdir.toPath) - .withCompilerConfig( - ScalaNativeNativeConfig.empty - .withClang(nativeClang.toPath) - .withClangPP(nativeClangPP.toPath) - .withTargetTriple(if (nativeTarget.isPresent) Some(nativeTarget.get) else None) - .withCompileOptions(nativeCompileOptions) - .withLinkingOptions(nativeLinkingOptions) - .withGC(GC(nativeGC)) - .withLinkStubs(nativeLinkStubs) - .withMode(Mode(releaseMode.value)) - .withOptimize(nativeOptimize) - .withLTO(ScalaNativeLTO(nativeLTO.value)) - ) + .withCompilerConfig(nativeConfig) .withLogger(logger(logLevel)) new NativeConfig(config) }