core/pkgs/build-support/dart/build-dart-application/default.nix
2024-06-30 09:12:46 +01:00

187 lines
5.2 KiB
Nix

{
lib,
stdenv,
callPackage,
runCommand,
writeText,
pub2nix,
dartHooks,
makeWrapper,
dart,
nodejs,
darwin,
jq,
yq,
}:
{
src,
sourceRoot ? "source",
packageRoot ? (lib.removePrefix "/" (lib.removePrefix "source" sourceRoot)),
gitHashes ? { },
sdkSourceBuilders ? { },
customSourceBuilders ? { },
sdkSetupScript ? "",
extraPackageConfigSetup ? "",
# Output type to produce. Can be any kind supported by dart
# https://dart.dev/tools/dart-compile#types-of-output
# If using jit, you might want to pass some arguments to `dartJitFlags`
dartOutputType ? "exe",
dartCompileCommand ? "dart compile",
dartCompileFlags ? [ ],
# These come at the end of the command, useful to pass flags to the jit run
dartJitFlags ? [ ],
# Attrset of entry point files to build and install.
# Where key is the final binary path and value is the source file path
# e.g. { "bin/foo" = "bin/main.dart"; }
# Set to null to read executables from pubspec.yaml
dartEntryPoints ? null,
# Used when wrapping aot, jit, kernel, and js builds.
# Set to null to disable wrapping.
dartRuntimeCommand ?
if dartOutputType == "aot-snapshot" then
"${dart}/bin/dartaotruntime"
else if (dartOutputType == "jit-snapshot" || dartOutputType == "kernel") then
"${dart}/bin/dart"
else if dartOutputType == "js" then
"${nodejs}/bin/node"
else
null,
runtimeDependencies ? [ ],
extraWrapProgramArgs ? "",
autoPubspecLock ? null,
pubspecLock ?
if autoPubspecLock == null then
throw "The pubspecLock argument is required. If import-from-derivation is allowed (it isn't in Nixpkgs), you can set autoPubspecLock to the path to a pubspec.lock instead."
else
assert lib.assertMsg (builtins.pathExists autoPubspecLock)
"The pubspec.lock file could not be found!";
lib.importJSON (
runCommand "${lib.getName args}-pubspec-lock-json" {
nativeBuildInputs = [ yq ];
} ''yq . '${autoPubspecLock}' > "$out"''
),
...
}@args:
let
generators = callPackage ./generators.nix { inherit dart; } { buildDrvArgs = args; };
pubspecLockFile = builtins.toJSON pubspecLock;
pubspecLockData = pub2nix.readPubspecLock {
inherit
src
packageRoot
pubspecLock
gitHashes
sdkSourceBuilders
customSourceBuilders
;
};
packageConfig = generators.linkPackageConfig {
packageConfig = pub2nix.generatePackageConfig {
pname = if args.pname != null then "${args.pname}-${args.version}" else null;
dependencies =
# Ideally, we'd only include the main dependencies and their transitive
# dependencies.
#
# The pubspec.lock file does not contain information about where
# transitive dependencies come from, though, and it would be weird to
# include the transitive dependencies of dev and override dependencies
# without including the dev and override dependencies themselves.
builtins.concatLists (builtins.attrValues pubspecLockData.dependencies);
inherit (pubspecLockData) dependencySources;
};
extraSetupCommands = extraPackageConfigSetup;
};
inherit (dartHooks.override { inherit dart; })
dartConfigHook
dartBuildHook
dartInstallHook
dartFixupHook
;
baseDerivation = stdenv.mkDerivation (
finalAttrs:
(builtins.removeAttrs args [
"gitHashes"
"sdkSourceBuilders"
"pubspecLock"
"customSourceBuilders"
])
// {
inherit
pubspecLockFile
packageConfig
sdkSetupScript
dartCompileCommand
dartOutputType
dartRuntimeCommand
dartCompileFlags
dartJitFlags
;
outputs = [
"out"
"pubcache"
] ++ args.outputs or [ ];
dartEntryPoints =
if (dartEntryPoints != null) then
writeText "entrypoints.json" (builtins.toJSON dartEntryPoints)
else
null;
runtimeDependencies = map lib.getLib runtimeDependencies;
nativeBuildInputs =
(args.nativeBuildInputs or [ ])
++ [
dart
dartConfigHook
dartBuildHook
dartInstallHook
dartFixupHook
makeWrapper
jq
]
++ lib.optionals stdenv.isDarwin [ darwin.sigtool ]
++
# Ensure that we inherit the propagated build inputs from the dependencies.
builtins.attrValues pubspecLockData.dependencySources;
preConfigure =
args.preConfigure or ""
+ ''
ln -sf "$pubspecLockFilePath" pubspec.lock
'';
# When stripping, it seems some ELF information is lost and the dart VM cli
# runs instead of the expected program. Don't strip if it's an exe output.
dontStrip = args.dontStrip or (dartOutputType == "exe");
passAsFile = [ "pubspecLockFile" ];
passthru = {
pubspecLock = pubspecLockData;
} // (args.passthru or { });
meta = (args.meta or { }) // {
platforms = args.meta.platforms or dart.meta.platforms;
};
}
);
in
assert
!(builtins.isString dartOutputType && dartOutputType != "")
-> throw "dartOutputType must be a non-empty string";
baseDerivation