diff options
Diffstat (limited to 'nixpkgs/pkgs/build-support/dlang')
5 files changed, 256 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/build-support/dlang/README.md b/nixpkgs/pkgs/build-support/dlang/README.md new file mode 100644 index 000000000000..bdd5fd2b6046 --- /dev/null +++ b/nixpkgs/pkgs/build-support/dlang/README.md @@ -0,0 +1,7 @@ +# Build support for D + +Build utilities for the D language can be found in this directory. + +### Current maintainers +- @TomaSajt +- @jtbx diff --git a/nixpkgs/pkgs/build-support/dlang/builddubpackage/default.nix b/nixpkgs/pkgs/build-support/dlang/builddubpackage/default.nix new file mode 100644 index 000000000000..31454d5cd69b --- /dev/null +++ b/nixpkgs/pkgs/build-support/dlang/builddubpackage/default.nix @@ -0,0 +1,147 @@ +{ + lib, + stdenv, + fetchurl, + fetchgit, + linkFarm, + dub, + ldc, + removeReferencesTo, +}: + +# See https://nixos.org/manual/nixpkgs/unstable#dlang for more detailed usage information + +{ + # A lockfile generated by `dub-to-nix` from the source of the package. + # Can be either a path to the file, or an attrset already parsed with `lib.importJSON`. + dubLock, + # The build type to pass to `dub build` as a value for the `--build=` flag. + dubBuildType ? "release", + # The flags to pass to `dub build` and `dub test`. + dubFlags ? [ ], + # The flags to pass to `dub build`. + dubBuildFlags ? [ ], + # The flags to pass to `dub test`. + dubTestFlags ? [ ], + # The D compiler to be used by `dub`. + compiler ? ldc, + ... +}@args: + +let + makeDubDep = + { + pname, + version, + sha256, + }: + { + inherit pname version; + src = fetchurl { + name = "dub-${pname}-${version}.zip"; + url = "mirror://dub/${pname}/${version}.zip"; + inherit sha256; + }; + }; + + makeGitDep = + { + pname, + version, + repository, + sha256, + }: + { + inherit pname version; + src = fetchgit { + url = repository; + rev = version; + inherit sha256; + }; + }; + + lockJson = if lib.isPath dubLock then lib.importJSON dubLock else dubLock; + depsRaw = lib.mapAttrsToList (pname: args: { inherit pname; } // args) lockJson.dependencies; + + dubDeps = map makeDubDep (lib.filter (args: !(args ? repository)) depsRaw); + gitDeps = map makeGitDep (lib.filter (args: args ? repository) depsRaw); + + # a directory with multiple single element registries + # one big directory with all .zip files leads to version parsing errors + # when the name of a package is a prefix of the name of another package + dubRegistryBase = linkFarm "dub-registry-base" ( + map (dep: { + name = "${dep.pname}/${dep.pname}-${dep.version}.zip"; + path = dep.src; + }) dubDeps + ); + + combinedFlags = "--skip-registry=all --compiler=${lib.getExe compiler} ${toString dubFlags}"; + combinedBuildFlags = "${combinedFlags} --build=${dubBuildType} ${toString dubBuildFlags}"; + combinedTestFlags = "${combinedFlags} ${toString dubTestFlags}"; +in +stdenv.mkDerivation ( + builtins.removeAttrs args [ "dubLock" ] + // { + strictDeps = args.strictDeps or true; + + nativeBuildInputs = args.nativeBuildInputs or [ ] ++ [ + dub + compiler + removeReferencesTo + ]; + + configurePhase = + args.configurePhase or '' + runHook preConfigure + + export DUB_HOME="$NIX_BUILD_TOP/.dub" + mkdir -p "$DUB_HOME" + + # register dub dependencies + ${lib.concatMapStringsSep "\n" (dep: '' + dub fetch ${dep.pname}@${dep.version} --cache=user --skip-registry=standard --registry=file://${dubRegistryBase}/${dep.pname} + '') dubDeps} + + # register git dependencies + ${lib.concatMapStringsSep "\n" (dep: '' + mkdir -p "$DUB_HOME/packages/${dep.pname}/${dep.version}" + cp -r --no-preserve=all ${dep.src} "$DUB_HOME/packages/${dep.pname}/${dep.version}/${dep.pname}" + '') gitDeps} + + runHook postConfigure + ''; + + buildPhase = + args.buildPhase or '' + runHook preBuild + + dub build ${combinedBuildFlags} + + runHook postBuild + ''; + + doCheck = args.doCheck or false; + + checkPhase = + args.checkPhase or '' + runHook preCheck + + dub test ${combinedTestFlags} + + runHook postCheck + ''; + + preFixup = '' + ${args.preFixup or ""} + + find "$out" -type f -exec remove-references-to -t ${compiler} '{}' + + ''; + + disallowedReferences = [ compiler ]; + + meta = { + platforms = dub.meta.platforms; + } // args.meta or { }; + } +) diff --git a/nixpkgs/pkgs/build-support/dlang/dub-support.nix b/nixpkgs/pkgs/build-support/dlang/dub-support.nix new file mode 100644 index 000000000000..879d59357d11 --- /dev/null +++ b/nixpkgs/pkgs/build-support/dlang/dub-support.nix @@ -0,0 +1,5 @@ +{ callPackage }: +{ + buildDubPackage = callPackage ./builddubpackage { }; + dub-to-nix = callPackage ./dub-to-nix { }; +} diff --git a/nixpkgs/pkgs/build-support/dlang/dub-to-nix/default.nix b/nixpkgs/pkgs/build-support/dlang/dub-to-nix/default.nix new file mode 100644 index 000000000000..87db7eed0933 --- /dev/null +++ b/nixpkgs/pkgs/build-support/dlang/dub-to-nix/default.nix @@ -0,0 +1,26 @@ +{ + lib, + runCommand, + makeWrapper, + python3, + nix, + nix-prefetch-git, +}: + +let + binPath = lib.makeBinPath [ + nix + nix-prefetch-git + ]; +in +runCommand "dub-to-nix" + { + nativeBuildInputs = [ makeWrapper ]; + buildInputs = [ python3 ]; + } + '' + install -Dm755 ${./dub-to-nix.py} "$out/bin/dub-to-nix" + patchShebangs "$out/bin/dub-to-nix" + wrapProgram "$out/bin/dub-to-nix" \ + --prefix PATH : ${binPath} + '' diff --git a/nixpkgs/pkgs/build-support/dlang/dub-to-nix/dub-to-nix.py b/nixpkgs/pkgs/build-support/dlang/dub-to-nix/dub-to-nix.py new file mode 100644 index 000000000000..fbb51960ad7b --- /dev/null +++ b/nixpkgs/pkgs/build-support/dlang/dub-to-nix/dub-to-nix.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import sys +import json +import os +import subprocess +import string + + +def eprint(text: str): + print(text, file=sys.stderr) + + +if not os.path.exists("dub.selections.json"): + eprint("The file `dub.selections.json` does not exist in the current working directory") + eprint("run `dub upgrade --annotate` to generate it") + sys.exit(1) + +with open("dub.selections.json") as f: + selectionsJson = json.load(f) + +depsDict: dict = selectionsJson["versions"] + +# For each dependency expand non-expanded version into a dict with a "version" key +depsDict = {pname: (versionOrDepDict if isinstance(versionOrDepDict, dict) else {"version": versionOrDepDict}) for (pname, versionOrDepDict) in depsDict.items()} + +# Don't process path-type selections +depsDict = {pname: depDict for (pname, depDict) in depsDict.items() if "path" not in depDict} + +# Pre-validate selections before trying to fetch +for pname in depsDict: + depDict = depsDict[pname] + version = depDict["version"] + if version.startswith("~"): + eprint(f'Expected version of "{pname}" to be non-branch type') + eprint(f'Found: "{version}"') + eprint("Please specify a non-branch version inside `dub.selections.json`") + eprint("When packaging, you might also need to patch the version value in the appropriate places (`dub.selections.json`, dub.sdl`, `dub.json`)") + sys.exit(1) + if "repository" in depDict: + repository = depDict["repository"] + if not repository.startswith("git+"): + eprint(f'Expected repository field of "{pname}" to begin with "git+"') + eprint(f'Found: "{repository}"') + sys.exit(1) + if (len(version) < 7 or len(version) > 40 or not all(c in string.hexdigits for c in version)): + eprint(f'Expected version field of "{pname}" to begin be a valid git revision') + eprint(f'Found: "{version}"') + sys.exit(1) + +lockedDepsDict: dict[str, dict[str, str]] = {} + +for pname in depsDict: + depDict = depsDict[pname] + version = depDict["version"] + if "repository" in depDict: + repository = depDict["repository"] + strippedRepo = repository[4:] + eprint(f"Fetching {pname}@{version} ({strippedRepo})") + command = ["nix-prefetch-git", strippedRepo, version] + rawRes = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout + sha256 = json.loads(rawRes)["sha256"] + lockedDepsDict[pname] = {"version": version, "repository": repository, "sha256": sha256} + else: + eprint(f"Fetching {pname}@{version}") + url = f"https://code.dlang.org/packages/{pname}/{version}.zip" + command = ["nix-prefetch-url", "--type", "sha256", url] + sha256 = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.rstrip() + lockedDepsDict[pname] = {"version": version, "sha256": sha256} + +print(json.dumps({"dependencies": lockedDepsDict}, indent=2)) |