Skip to content

Commit 208c559

Browse files
Non-nix friendly
Use standard Scala Native env vars to configure the build
1 parent 1a49a1c commit 208c559

File tree

4 files changed

+175
-103
lines changed

4 files changed

+175
-103
lines changed

build.sbt

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,11 @@ addCommandsAlias(
3838

3939
addCommandsAlias("massage", List("scalafixAll", "scalafmtSbt", "scalafmtAll", "Test/compile"))
4040

41-
/** @todo Make friendly for non-nix folks. */
42-
lazy val dirs = new {
43-
val bin = file(sys.env("DEVSHELL_DIR")) / "bin"
44-
val includes = file(sys.env("C_INCLUDE_PATH"))
45-
val lib = file(sys.env("LIBRARY_PATH"))
46-
}
47-
4841
lazy val `unikernel-scala` = project
4942
.in(file("."))
5043
.enablePlugins(ScalaNativePlugin, BindgenPlugin)
5144
.settings(
52-
version := "0.0.1",
45+
version := java.nio.file.Files.readString(file("version").toPath()),
5346
organization := "tech.igorramazanov.unikernel.scala",
5447
scalacOptions :=
5548
List("-deprecation", "-feature", "-new-syntax", "-rewrite", "-unchecked", "-Wall", "-Wunused:imports"),
@@ -60,24 +53,14 @@ lazy val `unikernel-scala` = project
6053
Compile / fork := true,
6154
logLevel := Level.Info,
6255
nativeConfig ~=
63-
(config =>
64-
config
65-
.withBuildTarget(BuildTarget.application)
56+
(c =>
57+
// The rest is managed through env vars, check flake.nix
58+
c.withBuildTarget(BuildTarget.application)
6659
.withCheckFatalWarnings(true)
6760
.withCheck(true)
68-
.withClang((dirs.bin / "clang").toPath())
69-
.withClangPP((dirs.bin / "clang++").toPath())
70-
// TODO: Make friendly for non-nix folks.
71-
.withCompileOptions(config.compileOptions :+ s"-I${dirs.includes}")
7261
.withEmbedResources(false)
73-
.withGC(GC.immix)
7462
.withIncrementalCompilation(true)
75-
// TODO: Make friendly for non-nix folks.
76-
.withLinkingOptions(config.linkingOptions :+ s"${dirs.lib}/liburing.a" :+ s"${dirs.lib}/libcrypto.a")
7763
.withLinkStubs(true)
78-
.withLTO(LTO.full)
79-
.withMode(Mode.releaseFast)
80-
.withOptimize(true)
8164
),
8265
libraryDependencies ++= List(
8366
"co.fs2" %%% "fs2-core" % versions.fs2,

flake.lock

Lines changed: 25 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 145 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,16 @@
22
inputs = {
33
devshell = {
44
url = "github:numtide/devshell";
5-
inputs = {
6-
flake-utils.follows = "flake-utils";
7-
nixpkgs.follows = "nixpkgs";
8-
};
5+
inputs.nixpkgs.follows = "nixpkgs";
96
};
107

11-
nixpkgs = {
12-
url = "github:NixOS/nixpkgs";
13-
};
14-
15-
flake-utils = {
16-
url = "github:numtide/flake-utils";
17-
inputs.systems.follows = "systems";
18-
};
8+
flake-utils.url = "github:numtide/flake-utils";
199

20-
systems.url = "github:nix-systems/default";
10+
nixpkgs.url = "github:NixOS/nixpkgs";
2111

22-
typelevel-nix = {
23-
url = "github:typelevel/typelevel-nix";
12+
sbt-derivation = {
13+
url = "github:zaninime/sbt-derivation";
2414
inputs = {
25-
devshell.follows = "devshell";
2615
flake-utils.follows = "flake-utils";
2716
nixpkgs.follows = "nixpkgs";
2817
};
@@ -33,53 +22,158 @@
3322
devshell,
3423
flake-utils,
3524
nixpkgs,
36-
typelevel-nix,
37-
...
25+
sbt-derivation,
26+
self,
3827
}:
39-
flake-utils.lib.eachSystem ["x86_64-linux"] (system: let
28+
flake-utils.lib.eachDefaultSystem (system: let
4029
pkgs = import nixpkgs {
4130
inherit system;
42-
overlays = [devshell.overlays.default];
31+
32+
overlays = [
33+
devshell.overlays.default
34+
sbt-derivation.overlays.default
35+
36+
# Reusing the same JDK for all tools
37+
(final: prev: let
38+
jre = prev.graalvm-ce;
39+
in {
40+
bloop = prev.bloop.override {inherit jre;};
41+
coursier = prev.coursier.override {inherit jre;};
42+
metals = prev.metals.override {inherit jre;};
43+
sbt = prev.sbt.override {inherit jre;};
44+
scala-cli = prev.scala-cli.override {inherit jre;};
45+
scalafix = prev.scalafix.override {inherit jre;};
46+
scalafmt = prev.scalafmt.override {inherit jre;};
47+
})
48+
];
4349
};
44-
in {
45-
formatter = pkgs.alejandra;
4650

47-
devShell = pkgs.devshell.mkShell rec {
48-
name = "unikernel-scala";
49-
imports = [typelevel-nix.typelevelShell];
51+
# Utility imports
52+
inherit
53+
(pkgs.lib)
54+
attrsToList
55+
concatStringsSep
56+
getDev
57+
getLib
58+
map
59+
readFile
60+
;
5061

51-
packages = let
52-
static = pkgs.pkgsStatic;
53-
in [
54-
(pkgs.scalafix.override {jre = typelevelShell.jdk.package;})
62+
pname = "unikernel-scala";
5563

56-
# I didn't succeed dynamically linking Scala Native with these packages,
57-
# hence using static variants.
58-
static.liburing.dev
59-
static.liburing.out
60-
static.openssl.dev
61-
static.openssl.out
64+
# Reading from file to synchronize with sbt to avoid double-hardcoding
65+
# TODO: Use https://github.com/sbt/sbt-git
66+
version = readFile ./version;
6267

63-
# For packaging as unikernel
64-
pkgs.ops
68+
llvm = pkgs.llvmPackages_19;
6569

66-
# For running a unikernel image
67-
pkgs.qemu
68-
];
70+
scalaTools = [
71+
pkgs.bloop
72+
pkgs.coursier
73+
pkgs.metals
74+
pkgs.sbt
75+
pkgs.scala-cli
76+
pkgs.scalafix
77+
pkgs.scalafmt
78+
];
79+
80+
unikernelDevTools = [
81+
# For packaging as unikernel
82+
pkgs.ops
83+
# For running a unikernel image
84+
pkgs.qemu
85+
];
6986

70-
typelevelShell = {
71-
jdk.package = pkgs.graalvm-ce;
87+
# Native libraries for linking with the Scala Native app
88+
nativeLibraries = [
89+
pkgs.liburing
90+
pkgs.openssl
91+
pkgs.zlib
92+
];
7293

73-
native = {
74-
enable = true;
75-
libraries = [
76-
pkgs.zlib
77-
];
78-
};
94+
# Environment variables expected and parsed by Scala Native sbt plugin:
95+
# https://github.com/scala-native/scala-native/blob/691cf35751de7edf9dc7d183dd87a83b23558360/tools/src/main/scala/scala/scalanative/build/Discover.scala#L14
96+
scalaNativeEnvVars = {
97+
# A path to the `/bin` dir of `clang` installation
98+
LLVM_BIN = "${llvm.clang}/bin";
99+
100+
# NanoVM didn't work with `immix`
101+
SCALANATIVE_GC = "commix";
102+
103+
# `:`-joined `/include/` dirs for each native library
104+
SCALANATIVE_INCLUDE_DIRS = concatStringsSep ":" (
105+
map (dep: "${getDev dep}/include") nativeLibraries
106+
);
107+
108+
# `:`-joined `/lib/` dirs for each native library
109+
SCALANATIVE_LIB_DIRS = concatStringsSep ":" (
110+
map (dep: "${getLib dep}/lib") nativeLibraries
111+
);
112+
113+
# NanoVM didn't work with `thin`
114+
SCALANATIVE_LTO = "full";
115+
116+
# The most convenient mode, `release-full` is slow, but doesn't give much advantage
117+
SCALANATIVE_MODE = "release-fast";
118+
119+
# No idea what is this, but sounds nice to have
120+
SCALANATIVE_OPTIMIZE = "true";
121+
};
122+
123+
server =
124+
sbt-derivation.mkSbtDerivation.${system}.withOverrides {
125+
# Using `clang` instead of default `gcc`
126+
inherit (llvm) stdenv;
127+
} (
128+
scalaNativeEnvVars
129+
// {
130+
inherit pname version;
131+
# Needed by Scala Native sbt plugin:
132+
# https://github.com/scala-native/scala-native/blob/691cf35751de7edf9dc7d183dd87a83b23558360/tools/src/main/scala/scala/scalanative/build/Discover.scala#L204
133+
nativeBuildInputs = [pkgs.which];
134+
src = self;
135+
depsSha256 = "sha256-zkW+XX/uWGlnMh4swDy7FQlntQ14PL51C6P0IfCGjXY=";
136+
buildPhase = ''
137+
sbt nativeLink
138+
'';
139+
installPhase = ''
140+
mkdir -p $out/bin
141+
# Synchronize with sbt
142+
SCALA_VERSION="$(sbt --color=never --supershell=never scalaVersion | tail -n 1 | cut -d' ' -f2)"
143+
cp "./target/scala-$SCALA_VERSION/${pname}-out" $out/bin/${pname}
144+
'';
145+
}
146+
);
147+
148+
# TODO: Broken at the moment, see:
149+
qemu = pkgs.callPackage (pkgs.stdenv.mkDerivation {
150+
inherit version;
151+
pname = "${pname}-qemu";
152+
dontUnpack = true;
153+
dontPatch = true;
154+
dontConfigure = true;
155+
dontFixup = true;
156+
nativeBuildInputs = unikernelDevTools;
157+
buildPhase = ''
158+
ops build ${server}/bin/${pname}
159+
'';
160+
installPhase = ''
161+
mkdir -p $out/share
162+
cp $HOME/.ops/images/${pname}.img $out/share/
163+
'';
164+
}) {};
165+
in {
166+
formatter = pkgs.alejandra;
167+
168+
devShell = pkgs.devshell.mkShell {
169+
name = pname;
170+
packages = scalaTools ++ unikernelDevTools ++ nativeLibraries;
171+
env = attrsToList scalaNativeEnvVars;
172+
};
79173

80-
nodejs.enable = false;
81-
sbtMicrosites.enable = false;
82-
};
174+
packages = {
175+
inherit server qemu;
176+
default = server;
83177
};
84178
});
85179
}

version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.0.1

0 commit comments

Comments
 (0)