133 lines
4.7 KiB
Nix
133 lines
4.7 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
|