-*- mode: org -*-
#+TITLE:       D nix, dev shells with overlays
#+DESCRIPTION: dlang related nixpkgs of interest (dlang compilers & tools)
#+FILETAGS:    :nixos:nixpkgs:dlang:compiler:
#+AUTHOR:      Ralph Amissah
#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
#+COPYRIGHT:   Copyright (C) 2023 Ralph Amissah
#+LICENSE:     Boost Software License 1.0
#+LANGUAGE:    en
#+STARTUP:     show3levels hideblocks hidestars noindent entitiespretty
#+PROPERTY:    header-args  :exports code
#+PROPERTY:    header-args+ :noweb yes
#+PROPERTY:    header-args+ :results no
#+PROPERTY:    header-args+ :cache no
#+PROPERTY:    header-args+ :padline no
#+PROPERTY:    header-args+ :mkdirp yes
#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t

* nix ( written to ../ )
** check updates CHECK

- https://github.com/nix-community/nix-direnv/releases
- https://github.com/dlang/dmd/tags
  https://code.dlang.org/packages/dmd
- https://github.com/ldc-developers/ldc/releases
- https://github.com/dlang/dub/releases
  https://code.dlang.org/packages/dub
- https://github.com/dlang/tools/tags
  https://code.dlang.org/packages/dtools

** README

#+HEADER: :tangle "../README"
#+BEGIN_SRC org
-*- mode: org -*-
,#+TITLE:       D related overlays
,#+DESCRIPTION: ldc, dub, dtools: dlang compiler build tool and tools
,#+FILETAGS:    :dlang:build:tools:
,#+AUTHOR:      Ralph Amissah
,#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
,#+COPYRIGHT:   Copyright (C) 2022 - 2025 Ralph Amissah
,#+LANGUAGE:    en
,#+STARTUP:     content hideblocks hidestars noindent entitiespretty

,* README for D related dev shells with overlays
,** in emacs write (tangle) this (org) file for its output

This org file: "dlang-nix-flakes.org" when using emacs and saved (tangling output)
it creates and writes output to the subdirectory path:

  ..

and writes output there, this is to prevent accidentally writing over anything
in the directory in which the dlang-nix-flakes.org file happens to be saved.

.. becomes your nix flake work directory.

,** dlang-nix-flakes.org

the file dlang-nix-flakes.org contains nix related files for producing more
recent versions of the dlang compiler and build tools: ldc, dub and dtools, than
exist in nixpkgs at the time of publishing, in some cases with additional fixes.

.envrc files

nix control files
  - default.nix
  - shell.nix
  - flake.nix

nix overlays for (updates nixpkgs, more recent versions of):
  - ldc     ( 1.30.0 -> <<ldc_version>> )
  - dub     ( 1.23.0 -> <<dub_version>> ) [for nix versions 1.31.0 ... 1.33.0 broken]
  - dtools  ( 2.095.1 -> <<dtools_version>> )

  - dmd     ( 2.100.2 -> <<dmd_version>> )
  - gdc     [not yet available]

(updates nixpkgs circa 2023-05-12)

dlang-nix-flakes.org --❯
  .
  └── dlang-nix-flakes
      ├── #default.nix
      ├── flake.lock
      ├── flake.nix
      ├── README
      ├── shell.nix
      └── nix-overlays
          ├── dmd [not working]
          │   ├── binary.nix
          │   ├── bootstrap.nix
          │   ├── default.nix
          │   └── generic.nix
          ├── dtools
          │   └── default.nix
          ├── dub
          │   └── default.nix
          └── ldc
              ├── binary.nix
              ├── bootstrap.nix
              ├── default.nix
              └── generic.nix

search nixpkgs here:

- https://search.nixos.org/packages?channel=unstable&from=0&size=100&sort=relevance&query=

,** compilers
,*** ldc OK ✓ ( 1.30.0 -> <<ldc_version>> )

- https://wiki.dlang.org/LDC

- https://github.com/ldc-developers/ldc
  - https://github.com/ldc-developers/ldc/releases
    nix-prefetch-url --unpack https://github.com/ldc-developers/ldc/archive/refs/tags/v<<ldc_version>>.tar.gz
  - https://github.com/ldc-developers/ldc/issues

- version in nixpkgs:
  - https://search.nixos.org/packages?channel=unstable&show=ldc&from=0&size=100&sort=relevance&type=packages&query=ldc

,*** dmd OK ✓ ( 2.100.2 -> <<dmd_version>> )

- https://dlang.org/
  - https://wiki.dlang.org/LDC

- https://github.com/dlang/dmd
  - https://github.com/dlang/dmd/tags
    nix-prefetch-url --unpack https://github.com/dlang/dmd/archive/refs/tags/v<<dmd_version>>.tar.gz
  - https://github.com/dlang/dmd/pulls

- version in nixpkgs:
  - https://search.nixos.org/packages?channel=unstable&show=dmd&from=0&size=100&sort=relevance&type=packages&query=dmd

- dmd nixpkg modified and appears to build ok, but it appears my overlay does
  not get things right REVIEW

- dmd on nixos FAILS to build (my working projects), appears not to find parts
  of itself

,*** gdc ( not provided yet with gcc12 in nixpkgs )

not yet provided in nixpkgs with gcc12, no attempt made

- https://wiki.dlang.org/GDC
  - https://wiki.dlang.org/GDC_Development

- https://github.com/D-Programming-GDC/gdc

,** build tool
,*** dub ( 1.23.0 -> <<dub_version>> )

- https://code.dlang.org/packages/dub

- https://github.com/dlang/dub
  - https://github.com/dlang/dub/releases
    nix-prefetch-url --unpack https://github.com/dlang/dub/archive/refs/tags/v<<dub_version>>.tar.gz
  - https://github.com/dlang/dub/issues

- version in nixpkgs:
  - https://search.nixos.org/packages?channel=unstable&show=dub&from=0&size=100&sort=relevance&type=packages&query=dub

- dub nixpkg overlay is updated and runs most dub tests correctly

- dub OK ✓ ( 1.30.0 -> <<dub_version>> )

  from v1.31.0 requires seeting of pwd in buildPhase else fails to build
  packages with nix tools that previous version of dub built;

,** tools
,*** dtools OK ✓ ( 2.095.1 -> <<dtools_version>> )

- https://code.dlang.org/packages/dtools

- https://github.com/dlang/tools
  - https://github.com/dlang/tools/tags
    nix-prefetch --unpack https://github.com/dlang/tools/archive/refs/tags/v<<dtools_version>>.tar.gz
  - https://github.com/dlang/tools/issues

- version in nixpkgs
  - https://search.nixos.org/packages?channel=unstable&show=dtools&from=0&size=100&sort=relevance&type=packages&query=dtools

,** nixpkgs

It is possible to work directly against a local copy of nixpkgs. To do so you
would clone nixpkgs and point to the local nixpkgs as your build source.

git clone --depth=1 --branch master https://github.com/nixos/nixpkgs nixpkgs

- ./nixpkgs/pkgs/development/compilers/ldc
- ./nixpkgs/pkgs/development/compilers/dmd
- ./nixpkgs/pkgs/development/tools/build-managers/dub
- ./nixpkgs/pkgs/development/tools/dtools

- ./nixpkgs/pkgs/development/compilers/gcc

Note the overlays if copied to the nixpkgs path locations should work as they do
in the overlay, with a pointer to the cloned nixpkgs as nixpkgs repository
source. In fact the starting point for the overlays was to take verbatim what
was in nixpkgs and then to update and fix where necessary those packages.

It is possible to compare the changes made by the overlays here directly against
what is currently available in nixpkgs.

- https://search.nixos.org/packages?channel=unstable&size=100&sort=relevance&query=

nix flake update && nix flake check --show-trace && nix flake info && echo "" && nix flake show
  │
  ├───devShells
  │   └───x86_64-linux
  │       ├───default: development environment 'nix-shell'
  │       ├───dsh-nixpkgs-ldc-dub: development environment 'nixpkgs---ldc---dub'
  │       ├───dsh-overlay-dmd-dub: development environment 'overlay---dmd-2.104.0---dub-1.30.0---broken'
  │       ├───dsh-overlay-dtest-tilix: development environment 'overlay---ldc-1.32.2---dub-1.30.0---tilix---gtkd'
  │       ├───dsh-overlay-dtools: development environment 'overlay---ldc-1.32.2---dub-1.30.0---dtools-2.103.1'
  │       └───dsh-overlay-ldc-dub: development environment 'overlay---ldc-1.32.2---dub-1.30.0'
  └───packages
      └───x86_64-linux
          ├───check-local-dir-build: package 'dummy-0.1.0'
          ├───check-tilix: package 'tilix-1.9.5'
          └───default: package 'tilix-1.9.5'

#+END_SRC

** .gitignore

#+HEADER: :tangle "../.gitignore"
#+BEGIN_SRC shell
# git ls-files --others --exclude-from=.git/info/exclude
# git check-ignore -v flake.lock
# git clean -ix
# find . -name "*_" | xargs rm -rf
# find . -name "*.o" | xargs rm -rf
,*
!.gitignore
!nixDevEnv.sh
!.envrc
!.envrc-local
!.envrc-nix
!flake.nix
!flake.lock
!nix-overlays
!nix-overlays/**
!shell.nix
!makefile
!justfile
!README
!*.nix
!*.json
!*.org
!org/
!org/*.org
!*.sh
!*.d
!*.txt
!src
!src/**
!views

# EXCLUDED Files & directories - ensure excluded
.dub/**
tmp/**
,*_.org
,*_.nix
,*_.d
,*_.txt
,*_
,*.swp
,*~
,*.\#*
\#*
#+END_SRC

** .env*
*** nixDevEnv.sh (.envrc)

#+HEADER: :tangle "../nixDevEnv.sh"
#+BEGIN_SRC shell
if [ -f .envrc ]; then
  source_env_if_exists .envrc || source .envrc
fi
#+END_SRC

#+HEADER: :tangle "../.envrc"
#+BEGIN_SRC shell
if [ -f .envrc-local ]; then
  source_env_if_exists .envrc-local || source .envrc-local
fi
if [ -f .envrc-nix ]; then
  source_env_if_exists .envrc-nix || source .envrc-nix
fi
#+END_SRC

*** .envrc-local

#+HEADER: :tangle "../.envrc-local"
#+BEGIN_SRC shell
#if [[ !( -f ./nix-flakes.org) && -f ../dlang-nix-flakes.org ]]; then
#  # for editing purpose link to the .org file that creates ./dlang-nix-flakes/ content
#  ln -s ../dlang-nix-flakes.org ./nix-flakes.org
#fi
if [[ ! -d ./.git ]]; then
  git init
  git add .
fi
#eval "$(nix print-dev-env)"
#+END_SRC

*** .envrc-nix

- https://github.com/nix-community/nix-direnv
- https://github.com/nix-community/nix-direnv/releases
  - source_url
    - direnv fetchurl "https://raw.githubusercontent.com/nix-community/nix-direnv/<<direnv-version>>/direnvrc" "<<direnv-sha>>"
    - ${NixDirEnvVersion}

#+HEADER: :tangle "../.envrc-nix"
#+BEGIN_SRC shell
NIX_ENFORCE_PURITY=1
# - https://github.com/nix-community/nix-direnv
NixDirEnvVersion="<<direnv_version>>"
NixDirEnvSHA="<<direnv_hash>>"
if ! has nix_direnv_version || ! nix_direnv_version ${NixDirEnvVersion}; then
  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/${NixDirEnvVersion}/direnvrc" "${NixDirEnvSHA}"
fi
watch_file flake.lock
watch_file flake.nix
watch_file shell.nix
watch_file makefile
watch_file nixDevEnv.sh
watch_file .envrc-local
watch_file .envrc-nix
nix flake update
nix flake check
nix flake show
echo ""
PATH_add result/bin
use flake .
#use flake .#default
#+END_SRC

** .nix
*** flake.nix

#+HEADER: :tangle "../flake.nix"
#+BEGIN_SRC nix
{
  description = "build dummy D package using dub build tool";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  #inputs.flake-utils.url = "github:numtide/flake-utils";
  outputs = {
    self,
    nixpkgs,
    #flake-utils,
    ...
  }@inputs: let
    pname = "dummy";
    version = "0.1.0";
    shell = ./shell.nix;
    devEnv = ./nixDevEnv.sh; # ./.envrc;
    supportedSystems = ["x86_64-linux"]; # [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
    forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
    nixpkgsFor = forAllSystems (system: import nixpkgs {inherit system;});
    checkPhase = ''
      runHook preCheck
      #dub test --combined --skip-registry=all
      runHook postCheck
    '';
    localOverlay = (final: prev: {
      ldc = prev.callPackage ./nix-overlays/ldc {  };       # -> ok <<ldc_version>>
      dmd = prev.callPackage ./nix-overlays/dmd {  };       # -> ok <<dmd_version>>
      dub = prev.callPackage ./nix-overlays/dub {  };       # -> ? <<dub_version>>
      dtools = prev.callPackage ./nix-overlays/dtools {  }; # -> ok <<dtools_version>>
      #gdc = prev.callPackage ./nix-overlays/gdc {  };      # empty
    });
    pkgsForSystem = system: import nixpkgs {
      overlays = [
        localOverlay
      ];
      inherit system;
    };
    installPhase = ''
      runHook preInstall
      mkdir -p $out/bin
      install -m755 ./bin/dummy $out/bin/dummy
      runHook postInstall
    '';
    postInstall = ''
      echo `ls -la $out/bin/dummy`
      $out/bin/dummy -v
    '';
  in {
    packages = forAllSystems (system: let
      pkgs-ovl = pkgsForSystem system;
      pkgs-nix = nixpkgsFor.${system};
    in
      with pkgs-ovl; {
        default = tilix;
        check-tilix = tilix;
        check-local-dir-build = stdenv.mkDerivation {
          inherit pname;
          inherit version;
          meta.mainProgram = "dummy";
          executable = true;
          src = self;
          inherit shell;
          inherit devEnv;
          buildInputs = [sqlite];
          nativeBuildInputs = [gnumake dub ldc];
          preBuild = ''
            export DCn=ldmd2
            export DC=$(type -P $DCn || echo "")
            if [ "$DC" == "" ]; then exit "Error: could not find D compiler"; fi
          '';
          buildPhase = ''
            runHook preBuild
            echo "$DCn used as D compiler to build $pname"
            dub build --cache=local --compiler=$DC --build=$DCn --combined --skip-registry=all
            runHook postBuild
          '';
          inherit checkPhase;
          inherit installPhase;
          inherit postInstall;
        };
      });
    devShells = forAllSystems (system: let
      pkgs-ovl = pkgsForSystem system;
      pkgs-nix = nixpkgsFor.${system};
      shellHook = ''
      '';
    in
      with pkgs-ovl; {
        dsh-overlay-dtools = mkShell {
          name = "overlay - ldc-<<ldc_version>> - dub-<<dub_version>> - dtools-<<dtools_version>>";
          inherit shell;
          inherit devEnv;
          packages = [
            ldc
            dub
            dtools
            gnumake
          ];
          inherit shellHook;
        };
        dsh-overlay-ldc-dub = mkShell {
          name = "overlay - ldc-<<ldc_version>> - dub-<<dub_version>> - dtools-<<dtools_version>>";
          inherit shell;
          inherit devEnv;
          packages = [
            ldc
            dub
            dtools
            gnumake
          ];
          inherit shellHook;
        };
        dsh-overlay-dmd-dub = mkShell {
          name = "overlay - dmd-<<dmd_version>> - dub-<<dub_version>> - dtools-<<dtools_version>>";
          inherit shell;
          inherit devEnv;
          packages = [
            dmd
            dub
            dtools
            gnumake
          ];
          inherit shellHook;
        };
        dsh-overlay-dtest-tilix = mkShell {
          name = "overlay - ldc-<<ldc_version>> - dub-<<dub_version>> - tilix - gtkd";
          inherit shell;
          inherit devEnv;
          packages = [
            ldc
            gtkd
            tilix
            dub
            dtools
            gnumake
          ];
          inherit shellHook;
        };
        #dsh-overlay-gdc = mkShell {
        #  name = "dub + gdc dev shell";
        #  inherit shell;
        #  inherit devEnv;
        #  packages = [
        #    gdc
        #    dub
        #    dtools
        #    gnumake
        #  ];
        #  inherit shellHook;
        #};
        dsh-nixpkgs-ldc-dub = mkShell {
          name = "nixpkgs - ldc - dub";
          inherit shell;
          inherit devEnv;
          packages = with pkgs-nix; [
            ldc
            dub
            dtools
            gnumake
          ];
          inherit shellHook;
        };
        dsh-nixpkgs-dmd-dub = mkShell {
          name = "nixpkgs - ldc - dub";
          inherit shell;
          inherit devEnv;
          packages = with pkgs-nix; [
            dmd
            dub
            dtools
            gnumake
          ];
          inherit shellHook;
        };
        default = import ./shell.nix {inherit pkgs-nix;};
      });
  };
}
#+END_SRC

*** shell.nix

#+HEADER: :tangle "../shell.nix"
#+HEADER: :tangle-mode (identity #o755)
#+HEADER: :shebang "#!/usr/bin/env -S nix-shell --pure\n#!nix-shell -i bash"
#+BEGIN_SRC nix
{pkgs-nix ? import <nixpkgs> {}}:
with pkgs-nix;
  mkShell {
    buildInputs = [
      # ❯❯❯ nix_related
      #nix
      direnv
      nixVersions.latest #nixVersions.latest #nixVersions.git
      nix-prefetch-git
      validatePkgConfig
      nix-output-monitor
      #nix-tree
      #nvd
      jq #gx
      #nixfmt-rfc-style
      git
      # ❯❯❯ dev
      gnumake
      ps
      # ❯❯❯ d_build_related
      # ❯❯ package manager
      #dub
      # ❯❯ compiler
      #dmd
      #ldc
      #rund
      # ❯❯ linker
      #lld
      #mold
      # ❯❯ builder
      #ninja
      #meson
      # ❯❯ tools
      #dub
      #dtools
      # ❯❯❯ test
      #tilix
      #gtkd
    ];
    shellHook = ''
      #echo '
      #  shell.nix echo ❯❯
      #  ❯❯ nix flake update && nix flake check --show-trace && nix flake show && nix develop ".#devShell" -c $SHELL
      #'
    '';
  }
#+END_SRC

*** default.nix

will automatically build the default development shell, perhaps unecessary

#+HEADER: :tangle-NO "../default.nix"
#+HEADER: :tangle-mode (identity #o755)
#+HEADER: :shebang "#!/usr/bin/env -S nix-build"
#+BEGIN_SRC nix
{pkgs ? import <nixpkgs> {}}:
pkgs.callPackage ./shell.nix {}
#+END_SRC

* nixpkgs overlays ( written to ../nix-overlays/ )
** ldc OK ✓
*** info
**** links

- https://wiki.dlang.org/LDC

- https://github.com/ldc-developers/ldc
  - https://github.com/ldc-developers/ldc/releases
  - https://github.com/ldc-developers/ldc/issues

- version in nixpkgs:
  - https://search.nixos.org/packages?channel=unstable&show=ldc&from=0&size=100&sort=relevance&type=packages&query=ldc

**** notes

- OK ldc 1.32.2 tested

*** overlays OK ✓
**** default.nix

#+HEADER: :tangle "../nix-overlays/ldc/default.nix"
#+BEGIN_SRC nix
import ./package.nix
#+END_SRC

**** package.nix OK ✓

#+HEADER: :tangle "../nix-overlays/ldc/package.nix"
#+BEGIN_SRC nix
{
  lib,
  stdenv,
  fetchFromGitHub,
  cmake,
  ninja,
  <<ldc_llvm_set>>,
  curl,
  tzdata,
  lit,
  gdb,
  unzip,
  darwin,
  callPackage,
  makeWrapper,
  runCommand,
  writeText,
  targetPackages,

  ldcBootstrap ? callPackage ./bootstrap.nix { },
}:

let
  pathConfig = runCommand "ldc-lib-paths" { } ''
    mkdir $out
    echo ${tzdata}/share/zoneinfo/ > $out/TZDatabaseDirFile
    echo ${curl.out}/lib/libcurl${stdenv.hostPlatform.extensions.sharedLibrary} > $out/LibcurlPathFile
  '';

in

stdenv.mkDerivation (finalAttrs: {
  pname = "ldc";
  version = "<<ldc_version>>";

  src = fetchFromGitHub {
    owner = "ldc-developers";
    repo = "ldc";
    rev = "v${finalAttrs.version}";
    hash = "<<ldc_hash>>";
    fetchSubmodules = true;
  };

  # https://issues.dlang.org/show_bug.cgi?id=19553
  hardeningDisable = [ "fortify" ];

  postPatch = ''
    patchShebangs runtime tools tests

    rm tests/dmd/fail_compilation/mixin_gc.d
    rm tests/dmd/runnable/xtest46_gc.d
    rm tests/dmd/runnable/testptrref_gc.d

    # test depends on current year
    rm tests/dmd/compilable/ddocYear.d
  '' + lib.optionalString stdenv.hostPlatform.isLinux ''
    substituteInPlace runtime/phobos/std/socket.d --replace-fail "assert(ih.addrList[0] == 0x7F_00_00_01);" ""
  '' + lib.optionalString stdenv.hostPlatform.isDarwin ''
    substituteInPlace runtime/phobos/std/socket.d --replace-fail "foreach (name; names)" "names = []; foreach (name; names)"

    # https://github.com/NixOS/nixpkgs/issues/34817
    rm -r tests/plugins/addFuncEntryCall
  '';

  nativeBuildInputs = [
    cmake ldcBootstrap lit lit.python <<ldc_llvm_set>>.dev makeWrapper ninja unzip
  ] ++ lib.optionals stdenv.hostPlatform.isDarwin [
    darwin.apple_sdk.frameworks.Foundation
  ] ++ lib.optionals (!stdenv.hostPlatform.isDarwin) [
    # https://github.com/NixOS/nixpkgs/pull/36378#issuecomment-385034818
    gdb
  ];

  buildInputs = [ curl tzdata ];

  outputs = [ "out" "include" ];
  outputInclude = "include";

  cmakeFlags = [
    "-DD_FLAGS=-d-version=TZDatabaseDir;-d-version=LibcurlPath;-J${pathConfig}"
    "-DINCLUDE_INSTALL_DIR=${placeholder "include"}/include/d"
  ];

  postConfigure = ''
    export DMD=$PWD/bin/ldmd2
  '';

  makeFlags = [ "DMD=$DMD" ];

  fixNames = lib.optionalString stdenv.hostPlatform.isDarwin ''
    fixDarwinDylibNames() {
      local flags=()

      for fn in "$@"; do
        flags+=(-change "$(basename "$fn")" "$fn")
      done

      for fn in "$@"; do
        if [ -L "$fn" ]; then continue; fi
        echo "$fn: fixing dylib"
        install_name_tool -id "$fn" "''${flags[@]}" "$fn"
      done
    }

    fixDarwinDylibNames $(find "$(pwd)/lib" -name "*.dylib")
    export DYLD_LIBRARY_PATH=$(pwd)/lib
  '';

  # https://github.com/ldc-developers/ldc/issues/2497#issuecomment-459633746
  additionalExceptions = lib.optionalString stdenv.hostPlatform.isDarwin "|druntime-test-shared";

  checkPhase = ''
    # Build default lib test runners
    ninja -j$NIX_BUILD_CORES all-test-runners

    ${finalAttrs.fixNames}

    # Run dmd testsuite
    export DMD_TESTSUITE_MAKE_ARGS="-j$NIX_BUILD_CORES DMD=$DMD"
    ctest -V -R "dmd-testsuite"

    # Build and run LDC D unittests.
    ctest --output-on-failure -R "ldc2-unittest"

    # Run LIT testsuite.
    ctest -V -R "lit-tests"

    # Run default lib unittests
    ctest -j$NIX_BUILD_CORES --output-on-failure -E "ldc2-unittest|lit-tests|dmd-testsuite${finalAttrs.additionalExceptions}"
  '';

  postInstall = ''
    wrapProgram $out/bin/ldc2 \
      --prefix PATH : ${targetPackages.stdenv.cc}/bin \
      --set-default CC ${targetPackages.stdenv.cc}/bin/cc
  '';

  meta = with lib; {
    description = "LLVM-based D compiler";
    homepage = "https://github.com/ldc-developers/ldc";
    changelog = "https://github.com/ldc-developers/ldc/releases/tag/v${finalAttrs.version}";
    # from https://github.com/ldc-developers/ldc/blob/master/LICENSE
    license = with licenses; [ bsd3 boost mit ncsa gpl2Plus ];
    mainProgram = "ldc2";
    maintainers = with maintainers; [ lionello jtbx ];
    platforms = [ "x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
  };

  passthru.ldcBootstrap = ldcBootstrap;
  passthru.tests =
    let
      ldc = finalAttrs.finalPackage;
      helloWorld = stdenv.mkDerivation (finalAttrs: {
        name = "ldc-hello-world";
        src = writeText "hello_world.d" ''
          module hello_world;
          import std.stdio;
          void main() {
            writeln("Hello, world!");
          }
        '';
        dontUnpack = true;
        buildInputs = [ ldc ];
        dFlags = [ ];
        buildPhase = ''
          ldc2 ${lib.escapeShellArgs finalAttrs.dFlags} -of=test $src
        '';
        installPhase = ''
          mkdir -p $out/bin
          mv test $out/bin
        '';
      });
    in {
      # Without -shared, built binaries should not contain
      # references to the compiler binaries.
      no-references-to-compiler = helloWorld.overrideAttrs {
        disallowedReferences = [ ldc ];
        dFlags = ["-g"];
    };
  };
})
#+END_SRC

**** bootstrap.nix

- this is the ldc bootstrap in current use, nixpkgs:

#+HEADER: :tangle "../nix-overlays/ldc/bootstrap.nix"
#+BEGIN_SRC nix
{
  lib,
  stdenv,
  fetchurl,
  curl,
  tzdata,
  autoPatchelfHook,
  fixDarwinDylibNames,
  libxml2,
}:

let
  inherit (stdenv) hostPlatform;
  OS = if hostPlatform.isDarwin then "osx" else hostPlatform.parsed.kernel.name;
  ARCH = if hostPlatform.isDarwin && hostPlatform.isAarch64 then "arm64" else hostPlatform.parsed.cpu.name;
  <<ldc_bootstrap_1-25-0_hashes>>
in stdenv.mkDerivation {
  pname = "ldc-bootstrap";
  inherit version;

  src = fetchurl rec {
    name = "ldc2-${version}-${OS}-${ARCH}.tar.xz";
    url = "https://github.com/ldc-developers/ldc/releases/download/v${version}/${name}";
    hash = hashes."${OS}-${ARCH}" or (throw "missing bootstrap hash for ${OS}-${ARCH}");
  };

  dontConfigure = true;
  dontBuild = true;

  nativeBuildInputs = lib.optionals hostPlatform.isLinux [
    autoPatchelfHook
  ] ++ lib.optional hostPlatform.isDarwin fixDarwinDylibNames;

  buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ libxml2 stdenv.cc.cc ];

  propagatedBuildInputs = [ curl tzdata ];

  installPhase = ''
    mkdir -p $out

    mv bin etc import lib LICENSE README $out/
  '';

  meta = with lib; {
    description = "LLVM-based D Compiler";
    homepage = "https://github.com/ldc-developers/ldc";
    # from https://github.com/ldc-developers/ldc/blob/master/LICENSE
    license = with licenses; [ bsd3 boost mit ncsa gpl2Plus ];
    maintainers = with maintainers; [ lionello ];
    platforms = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
  };
}
#+END_SRC

***** bootstrap.nix version SELECT
****** bootstrap.nix ldc2-1.25.0

#+NAME: ldc_bootstrap_1-25-0_hashes
#+BEGIN_SRC nix
version = "1.25.0";
hashes = {
  # Get these from `nix store prefetch-file https://github.com/ldc-developers/ldc/releases/download/v1.25.0/ldc2-1.25.0-osx-x86_64.tar.xz` etc..
  osx-x86_64 = "sha256-6iKnbS+oalLKmyS8qYD/wS21b7+O+VgsWG2iT4PrWPU=";
  linux-x86_64 = "sha256-sfg47RdlsIpryc3iZvE17OtLweh3Zw6DeuNJYgpuH+o=";
  linux-aarch64  = "sha256-UDZ43x4flSo+SfsPeE8juZO2Wtk2ZzwySk0ADHnvJBI=";
  osx-arm64  = "sha256-O/x0vy0wwQFaDc4uWSeMhx+chJKqbQb6e5QNYf+7DCw=";
};
#+END_SRC

****** bootstrap.nix ldc2-1.30.0

#+NAME: ldc_bootstrap_1-30-0_hashes
#+BEGIN_SRC nix
version = "1.30.0";
hashes = {
  # Get these from `nix store prefetch-file https://github.com/ldc-developers/ldc/releases/download/v1.30.0/ldc2-1.30.0-osx-x86_64.tar.xz` etc..
  osx-x86_64 = "sha256-AAWZvxuZC82xvrW6fpYm783TY+H8k3DvqE94ZF1yjmk=";
  linux-x86_64 = "sha256-V4TUzEfQhFrwiX07dHOgjdAoGkzausCkhnQIQNAU/eE=";
  linux-aarch64 = "sha256-kTeglub75iv/jWWNPCn15aCGAbmck0RQl6L7bFOUu7Y=";
  osx-arm64 = "sha256-Nb/owBdIeroB9jLMDvwjo8bvsTC9vFyJPLMTOMsSAd4=";
};
#+END_SRC

** dmd OK ✓
*** info
**** links

- https://dlang.org/
  - https://wiki.dlang.org/DMD

- https://github.com/dlang/dmd
  - https://github.com/dlang/dmd/tags
  - https://github.com/dlang/dmd/pulls

- version in nixpkgs:
  - https://search.nixos.org/packages?channel=unstable&show=dmd&from=0&size=100&sort=relevance&type=packages&query=dmd

**** notes KO ✗

- dmd nixpkg modified and appears to build ok

- ISSUES dmd on nixos FAILS to build (my working projects), appears not to find parts of itself

*** overlays
**** default.nix

#+HEADER: :tangle "../nix-overlays/dmd/default.nix"
#+BEGIN_SRC nix
import ./package.nix
#+END_SRC

**** package.nix OK ✓
***** package.nix  >=2.108.0)

#+HEADER: :tangle "../nix-overlays/dmd/package.nix"
#+BEGIN_SRC nix
import ./generic.nix {
  version = "<<dmd_version>>";
  dmdHash = "<<dmd_hash>>";
  phobosHash = "<<phobos_hash>>";
}
#+END_SRC

***** package.nix  < 2.108.0)

#+HEADER: :tangle-NO "../nix-overlays/dmd/package.nix"
#+BEGIN_SRC nix
import ./generic.nix {
  version = "<<dmd_version>>";
  dmdSha256 = "<<dmd_hash>>";
  phobosSha256 = "<<phobos_hash>>";
}
#+END_SRC

**** generic.nix

#+HEADER: :tangle "../nix-overlays/dmd/generic.nix"
#+BEGIN_SRC nix
{
  version,
  dmdHash,
  phobosHash,
}:

{
  stdenv,
  lib,
  fetchFromGitHub,
  removeReferencesTo,
  makeWrapper,
  which,
  writeTextFile,
  curl,
  tzdata,
  gdb,
  # Foundation,
  callPackage,
  targetPackages,
  fetchpatch,
  bash,
  installShellFiles,
  git,
  unzip,
  dmdBootstrap ? callPackage ./bootstrap.nix { },
  dmdBin ? "${dmdBootstrap}/bin",
}:

let
  dmdConfFile = writeTextFile {
    name = "dmd.conf";
    text = (lib.generators.toINI { } {
      Environment = {
        DFLAGS = ''-I@out@/include/dmd -L-L@out@/lib -fPIC ${lib.optionalString (!targetPackages.stdenv.cc.isClang) "-L--export-dynamic"}'';
      };
    });
  };

  bits = builtins.toString stdenv.hostPlatform.parsed.cpu.bits;
  osname = if stdenv.hostPlatform.isDarwin then "osx"
    else stdenv.hostPlatform.parsed.kernel.name;

  pathToDmd = "\${NIX_BUILD_TOP}/dmd/generated/${osname}/release/${bits}/dmd";
in

stdenv.mkDerivation (finalAttrs: {
  pname = "dmd";
  inherit version;

  enableParallelBuilding = true;

  srcs = [
    (fetchFromGitHub {
      owner = "dlang";
      repo = "dmd";
      rev = "v${finalAttrs.version}";
      hash = dmdHash;
      name = "dmd";
    })
    (fetchFromGitHub {
      owner = "dlang";
      repo = "phobos";
      rev = "v${finalAttrs.version}";
      hash = phobosHash;
      name = "phobos";
    })
  ];

  sourceRoot = ".";

  # https://issues.dlang.org/show_bug.cgi?id=19553
  hardeningDisable = [ "fortify" ];

  patches = lib.optionals (lib.versionOlder version "2.088.0") [
    # Migrates D1-style operator overloads in DMD source, to allow building with
    # a newer DMD
    (fetchpatch {
      url = "https://github.com/dlang/dmd/commit/c4d33e5eb46c123761ac501e8c52f33850483a8a.patch";
      stripLen = 1;
      extraPrefix = "dmd/";
      hash = "sha256-N21mAPfaTo+zGCip4njejasraV5IsWVqlGR5eOdFZZE=";
    })
  ];

  postPatch = ''
    patchShebangs dmd/compiler/test/{runnable,fail_compilation,compilable,tools}{,/extra-files}/*.sh

    rm dmd/compiler/test/runnable/gdb1.d
    rm dmd/compiler/test/runnable/gdb10311.d
    rm dmd/compiler/test/runnable/gdb14225.d
    rm dmd/compiler/test/runnable/gdb14276.d
    rm dmd/compiler/test/runnable/gdb14313.d
    rm dmd/compiler/test/runnable/gdb14330.d
    rm dmd/compiler/test/runnable/gdb15729.sh
    rm dmd/compiler/test/runnable/gdb4149.d
    rm dmd/compiler/test/runnable/gdb4181.d
    rm dmd/compiler/test/compilable/ddocYear.d
    rm dmd/compiler/test/compilable/sarif_success_test.d
    rm dmd/compiler/test/fail_compilation/sarif_test.d
    rm dmd/compiler/test/fail_compilation/sarifmultiple_test.d

    # Disable tests that rely on objdump whitespace until fixed upstream:
    #   https://issues.dlang.org/show_bug.cgi?id=23317
    rm dmd/compiler/test/runnable/cdvecfill.sh
    rm dmd/compiler/test/compilable/cdcmp.d
  '' + lib.optionalString (lib.versionAtLeast version "2.089.0" && lib.versionOlder version "2.092.2") ''
    rm dmd/compiler/test/dshell/test6952.d
  '' + lib.optionalString (lib.versionAtLeast version "2.092.2") ''
    substituteInPlace dmd/compiler/test/dshell/test6952.d --replace-fail "/usr/bin/env bash" "${bash}/bin/bash"
  '' + lib.optionalString stdenv.hostPlatform.isLinux ''
    substituteInPlace phobos/std/socket.d --replace-fail "assert(ih.addrList[0] == 0x7F_00_00_01);" ""
  ''; # + lib.optionalString stdenv.hostPlatform.isDarwin ''
  #  substituteInPlace phobos/std/socket.d --replace-fail "foreach (name; names)" "names = []; foreach (name; names)"
  #'';

  nativeBuildInputs = [
    makeWrapper
    which
    installShellFiles
  ] ++ lib.optionals (lib.versionOlder version "2.088.0") [
    git
  ];

  buildInputs = [
    curl
    tzdata
  # ] ++ lib.optionals stdenv.hostPlatform.isDarwin []
  #   Foundation
  ];

  nativeCheckInputs = [
    gdb
  ] ++ lib.optionals (lib.versionOlder version "2.089.0") [
    unzip
  ];

  buildFlags = [
    "BUILD=release"
    "ENABLE_RELEASE=1"
    "PIC=1"
  ];

  # Build and install are based on http://wiki.dlang.org/Building_DMD
  buildPhase = ''
    runHook preBuild

    export buildJobs=$NIX_BUILD_CORES
    [ -z "$enableParallelBuilding" ] && buildJobs=1

    ${dmdBin}/rdmd dmd/compiler/src/build.d -j$buildJobs $buildFlags \
      HOST_DMD=${dmdBin}/dmd
    make -C dmd/druntime -j$buildJobs DMD=${pathToDmd} $buildFlags
    echo ${tzdata}/share/zoneinfo/ > TZDatabaseDirFile
    echo ${lib.getLib curl}/lib/libcurl${stdenv.hostPlatform.extensions.sharedLibrary} \
      > LibcurlPathFile
    make -C phobos -j$buildJobs $buildFlags \
      DMD=${pathToDmd} DFLAGS="-version=TZDatabaseDir -version=LibcurlPath -J$PWD"

    runHook postBuild
  '';

  doCheck = true;

  # many tests are disabled because they are failing

  # NOTE: Purity check is disabled for checkPhase because it doesn't fare well
  # with the DMD linker. See https://github.com/NixOS/nixpkgs/issues/97420
  checkPhase = ''
    runHook preCheck

    export checkJobs=$NIX_BUILD_CORES
    [ -z "$enableParallelChecking" ] && checkJobs=1

    CC=$CXX HOST_DMD=${pathToDmd} NIX_ENFORCE_PURITY= \
      ${dmdBin}/rdmd dmd/compiler/test/run.d -j$checkJobs

    NIX_ENFORCE_PURITY= \
      make -C phobos unittest -j$checkJobs $checkFlags \
        DFLAGS="-version=TZDatabaseDir -version=LibcurlPath -J$PWD"

    runHook postCheck
  '';

  installPhase = ''
    runHook preInstall

    install -Dm755 ${pathToDmd} $out/bin/dmd

    installManPage dmd/docs/man/man*/*

    mkdir -p $out/include/dmd
    cp -r {dmd/druntime/import/*,phobos/{std,etc}} $out/include/dmd/

    mkdir $out/lib
    cp phobos/generated/${osname}/release/${bits}/libphobos2.* $out/lib/

    wrapProgram $out/bin/dmd \
      --prefix PATH : "${targetPackages.stdenv.cc}/bin" \
      --set-default CC "${targetPackages.stdenv.cc}/bin/cc"

    substitute ${dmdConfFile} "$out/bin/dmd.conf" --subst-var out

    runHook postInstall
  '';

  preFixup = ''
    find $out/bin -type f -exec ${removeReferencesTo}/bin/remove-references-to -t ${dmdBin}/dmd '{}' +
  '';

  disallowedReferences = [ dmdBootstrap ];

  passthru = {
    inherit dmdBootstrap;
  };

  meta = with lib; {
    description = "Official reference compiler for the D language";
    homepage = "https://dlang.org/";
    changelog = "https://dlang.org/changelog/${finalAttrs.version}.html";
    # Everything is now Boost licensed, even the backend.
    # https://github.com/dlang/dmd/pull/6680
    license = licenses.boost;
    mainProgram = "dmd";
    maintainers = with maintainers; [ lionello dukc jtbx ];
    platforms = [ "x86_64-linux" "i686-linux" "x86_64-darwin" ];
    # ld: section __DATA/__thread_bss has type zero-fill but non-zero file offset file '/private/tmp/nix-build-dmd-2.109.1.drv-0/.rdmd-301/rdmd-build.d-A1CF043A7D87C5E88A58F3C0EF5A0DF7/objs/build.o' for architecture x86_64
    # clang-16: error: linker command failed with exit code 1 (use -v to see invocation)
    broken = stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64;
  };
})
#+END_SRC

**** bootstrap.nix

#+HEADER: :tangle "../nix-overlays/dmd/bootstrap.nix"
#+BEGIN_SRC nix
{ callPackage }:
callPackage ./binary.nix {
  version = "2.090.1";
  hashes = {
    # Get these from `nix-prefetch-url http://downloads.dlang.org/releases/2.x/2.090.1/dmd.2.090.1.linux.tar.xz` etc..
    osx = "sha256-9HwGVO/8jfZ6aTiDIUi8w4C4Ukry0uUS8ACP3Ig8dmU=";
    linux = "sha256-ByCrIA4Nt7i9YT0L19VXIL1IqIp+iObcZux407amZu4=";
  };
}
#+END_SRC

**** binary.nix

#+HEADER: :tangle "../nix-overlays/dmd/binary.nix"
#+BEGIN_SRC nix
{ lib, stdenv, fetchurl, curl, tzdata, autoPatchelfHook, fixDarwinDylibNames, glibc
, version, hashes }:

let
  inherit (stdenv) hostPlatform;
  OS = if hostPlatform.isDarwin then "osx" else hostPlatform.parsed.kernel.name;
  MODEL = toString hostPlatform.parsed.cpu.bits;
in

# On linux pargets like `pkgsLLVM.dmd` `cc` does not expose `libgcc`
# and can't build `dmd`.
assert hostPlatform.isLinux -> (stdenv.cc.cc ? libgcc);
stdenv.mkDerivation {
  pname = "dmd-bootstrap";
  inherit version;

  src = fetchurl rec {
    name = "dmd.${version}.${OS}.tar.xz";
    url = "http://downloads.dlang.org/releases/2.x/${version}/${name}";
    sha256 = hashes.${OS} or (throw "missing bootstrap sha256 for OS ${OS}");
  };

  dontConfigure = true;
  dontBuild = true;

  nativeBuildInputs = lib.optionals hostPlatform.isLinux [
    autoPatchelfHook
  ] ++ lib.optionals hostPlatform.isDarwin [
    fixDarwinDylibNames
  ];
  propagatedBuildInputs = [
    curl
    tzdata
  ] ++ lib.optionals hostPlatform.isLinux [
    glibc
    stdenv.cc.cc.libgcc
  ];

  installPhase = ''
    runHook preInstall

    mkdir -p $out

    # try to copy model-specific binaries into bin first
    mv ${OS}/bin${MODEL} $out/bin || true

    mv src license.txt ${OS}/* $out/

    # move man into place
    mkdir -p $out/share
    mv man $out/share/

    # move docs into place
    mkdir -p $out/share/doc
    mv html/d $out/share/doc/

    # fix paths in dmd.conf (one level less)
    substituteInPlace $out/bin/dmd.conf --replace "/../../" "/../"

    runHook postInstall
  '';

  # Stripping on Darwin started to break libphobos2.a
  # Undefined symbols for architecture x86_64:
  #   "_rt_envvars_enabled", referenced from:
  #       __D2rt6config16rt_envvarsOptionFNbNiAyaMDFNbNiQkZQnZQq in libphobos2.a(config_99a_6c3.o)
  dontStrip = hostPlatform.isDarwin;

  meta = with lib; {
    description = "Digital Mars D Compiler Package";
    # As of 2.075 all sources and binaries use the boost license
    license = licenses.boost;
    maintainers = [ maintainers.lionello ];
    homepage = "https://dlang.org/";
    platforms = [ "x86_64-darwin" "i686-linux" "x86_64-linux" ];
  };
}
#+END_SRC

** dub OK
*** info
**** links

- https://code.dlang.org/packages/dub

- https://github.com/dlang/dub
  - https://github.com/dlang/dub/releases
  - https://github.com/dlang/dub/issues

- version in nixpkgs:
  - https://search.nixos.org/packages?channel=unstable&show=dub&from=0&size=100&sort=relevance&type=packages&query=dub

**** notes

- OK dub == current OK ✓

- NOTES for dub 1.33.0 >= 1.31.0 KO ✗
  - dub builds test tilix which calls in gtkd
  - ISSUES dub FAILS to build project from local disk that has built without issue
    since dub v1.23.0
    - BROKEN breaks on subproject ends up in nix: Error /homeless-shelter:
      Permission denied

- OK dub == 1.30.0 OK ✓

*** overlays
**** default.nix

#+HEADER: :tangle "../nix-overlays/dub/default.nix"
#+BEGIN_SRC nix
import ./package.nix
#+END_SRC

**** package.nix OK ✓

#+HEADER: :tangle "../nix-overlays/dub/package.nix"
#+BEGIN_SRC nix
{
  lib,
  stdenv,
  fetchFromGitHub,
  curl,
  <<dcompiler>>,
  dcompiler ? <<dcompiler>>,
  libevent,
  rsync,
}:

assert dcompiler != null;

stdenv.mkDerivation (finalAttrs: {
  pname = "dub";
  version = "<<dub_version>>";

  enableParallelBuilding = true;

  src = fetchFromGitHub {
    owner = "dlang";
    repo = "dub";
    rev = "v${finalAttrs.version}";
    hash = "<<dub_hash>>";
  };

  postPatch = ''
    patchShebangs test
  '';

  nativeBuildInputs = [ dcompiler libevent rsync ];
  buildInputs = [ curl ];

  preBuild = ''
    for DCn in dmd ldmd2 gdmd; do
      echo "... check for D compiler $DCn ..."
      export DC=$(type -P $DCn || echo "")
      if [ ! "$DC" == "" ]; then
        break
      fi
    done
    #export DMD=${ldc}/bin/ldmd2
    if [ "$DC" == "" ]; then
      exit "Error: could not find D compiler"
    fi
    echo "$DCn found and used as D compiler in buildPhase for $pname"
  '';

  buildPhase = ''
    runHook preBuild
    $DC -run ./build.d
    runHook postBuild
  '';

  doCheck = !stdenv.hostPlatform.isDarwin;

  checkPhase = ''
    runHook preCheck
    export DUB=$NIX_BUILD_TOP/source/bin/dub
    export PATH=$PATH:$NIX_BUILD_TOP/source/bin/
    if [ "$DC" == "" ]; then
      exit "Error: could not find D compiler"
    fi
    echo "DC out --> $DC"
    export HOME=$TMP

    rm -rf test/issue502-root-import
    rm -r test/dpath-variable # requires execution of dpath-variable.sh
    rm -rf test/git-dependency
    rm -rf test/use-c-sources # added to build v1.33.0
    rm -rf test/pr2642-cache-db # added to build v1.34.0
    rm -rf test/pr2644-describe-artifact-path # added to build v1.36.0
    rm -rf test/pr2647-build-deep # added to build v1.36.0

    ./test/run-unittest.sh
    runHook postCheck
  '';

  installPhase = ''
    runHook preInstall
    install -Dm755 bin/dub $out/bin/dub
    runHook postInstall
  '';

  meta = with lib; {
    description = "Package and build manager for D programs and libraries";
    homepage = "https://code.dlang.org/";
    license = licenses.mit;
    mainProgram = "dub";
    maintainers = with maintainers; [ jtbx ];
    platforms = [ "x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
  };
})
#+END_SRC

*** dcompiler

#+NAME: dcompiler
#+BEGIN_SRC nix
ldc
#+END_SRC

#+BEGIN_SRC nix
dmd
#+END_SRC

** dtools OK ✓
*** info
**** links

- https://code.dlang.org/packages/dtools

- https://github.com/dlang/tools
  - https://github.com/dlang/tools/tags
    nix-prefetch --unpack https://github.com/dlang/tools/archive/refs/tags/v<<dtools_version>>.tar.gz
  - https://github.com/dlang/tools/issues

- version in nixpkgs
  - https://search.nixos.org/packages?channel=unstable&show=dtools&from=0&size=100&sort=relevance&type=packages&query=dtools

**** notes

- OK dtools 2.103.1

*** overlays
**** default.nix

#+HEADER: :tangle "../nix-overlays/dtools/default.nix"
#+BEGIN_SRC nix
import ./package.nix
#+END_SRC

**** package.nix

#+HEADER: :tangle "../nix-overlays/dtools/package.nix"
#+BEGIN_SRC nix
{
  lib,
  stdenv,
  fetchFromGitHub,
  ldc,
  curl,
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "dtools";
  version = "<<dtools_version>>";

  src = fetchFromGitHub {
    owner = "dlang";
    repo = "tools";
    rev = "v${finalAttrs.version}";
    hash = "<<dtools_hash>>";
    name = "dtools";
  };

  patches = [
    # Disable failing tests
    ./disabled-tests.diff
    # Fix LDC arm64 build
    ./fix-ldc-arm64.diff
  ];

  nativeBuildInputs = [ ldc ];
  buildInputs = [ curl ];

  makeFlags = [
    "CC=${stdenv.cc}/bin/cc"
    "DMD=${ldc.out}/bin/ldmd2"
    "INSTALL_DIR=$(out)"
  ];

  enableParallelBuilding = true;

  doCheck = true;
  checkTarget = "test_rdmd";

  meta = with lib; {
    description = "Ancillary tools for the D programming language";
    homepage = "https://github.com/dlang/tools";
    license = licenses.boost;
    maintainers = with maintainers; [ jtbx ];
    platforms = platforms.unix;
  };
})
#+END_SRC

#+HEADER: :tangle "../nix-overlays/dtools/disabled-tests.diff"
#+BEGIN_SRC diff
--- a/rdmd_test.d
+++ b/rdmd_test.d
@@ -616,7 +616,7 @@ void runTests(string rdmdApp, string compiler, string model)
         enforce(res.status == 1, res.output);
     }
 
-    version (Posix)
+    version (none)
     {
         import std.conv : to;
         auto makeVersion = execute(["make", "--version"]).output.splitLines()[0];
#+END_SRC

#+HEADER: :tangle "../nix-overlays/dtools/fix-ldc-arm64.diff"
#+BEGIN_SRC diff
Adapted from https://github.com/dlang/tools/commit/6c6a042d1b08e3ec1790bd07a7f69424625ee866.patch
--- /dev/null
+++ b/osmodel.mak
@@ -0,0 +1,75 @@
+#   osmodel.mak
+#
+# Detects and sets the macros:
+#
+#   OS         = one of {osx,linux,freebsd,openbsd,netbsd,dragonflybsd,solaris}
+#   MODEL      = one of { 32, 64 }
+#   MODEL_FLAG = one of { -m32, -m64 }
+#   ARCH       = one of { x86, x86_64, aarch64 }
+#
+# Note:
+#   Keep this file in sync between druntime, phobos, and dmd repositories!
+# Source: https://github.com/dlang/dmd/blob/master/src/osmodel.mak
+
+
+ifeq (,$(OS))
+  uname_S:=$(shell uname -s)
+  ifeq (Darwin,$(uname_S))
+    OS:=osx
+  endif
+  ifeq (Linux,$(uname_S))
+    OS:=linux
+  endif
+  ifeq (FreeBSD,$(uname_S))
+    OS:=freebsd
+  endif
+  ifeq (OpenBSD,$(uname_S))
+    OS:=openbsd
+  endif
+  ifeq (NetBSD,$(uname_S))
+    OS:=netbsd
+  endif
+  ifeq (DragonFly,$(uname_S))
+    OS:=dragonflybsd
+  endif
+  ifeq (Solaris,$(uname_S))
+    OS:=solaris
+  endif
+  ifeq (SunOS,$(uname_S))
+    OS:=solaris
+  endif
+  ifeq (,$(OS))
+    $(error Unrecognized or unsupported OS for uname: $(uname_S))
+  endif
+endif
+
+# When running make from XCode it may set environment var OS=MACOS.
+# Adjust it here:
+ifeq (MACOS,$(OS))
+  OS:=osx
+endif
+
+ifeq (,$(MODEL))
+  ifeq ($(OS), solaris)
+    uname_M:=$(shell isainfo -n)
+  else
+    uname_M:=$(shell uname -m)
+  endif
+  ifneq (,$(findstring $(uname_M),x86_64 amd64))
+    MODEL:=64
+    ARCH:=x86_64
+  endif
+  ifneq (,$(findstring $(uname_M),aarch64 arm64))
+    MODEL:=64
+    ARCH:=aarch64
+  endif
+  ifneq (,$(findstring $(uname_M),i386 i586 i686))
+    MODEL:=32
+    ARCH:=x86
+  endif
+  ifeq (,$(MODEL))
+    $(error Cannot figure 32/64 model and arch from uname -m: $(uname_M))
+  endif
+endif
+
+MODEL_FLAG:=-m$(MODEL)
--- a/Makefile
+++ b/Makefile
@@ -9,9 +9,8 @@ DUB=dub
 WITH_DOC = no
 DOC = ../dlang.org
 
-# Load operating system $(OS) (e.g. linux, osx, ...) and $(MODEL) (e.g. 32, 64) detection Makefile from dmd
-$(shell [ ! -d $(DMD_DIR) ] && git clone --depth=1 https://github.com/dlang/dmd $(DMD_DIR))
-include $(DMD_DIR)/compiler/src/osmodel.mak
+# Load operating system $(OS) (e.g. linux, osx, ...) and $(MODEL) (e.g. 32, 64) detection Makefile
+include osmodel.mak
 
 ifeq (windows,$(OS))
     DOTEXE:=.exe
@@ -30,7 +29,7 @@ DFLAGS = $(MODEL_FLAG) $(if $(findstring windows,$(OS)),,-fPIC) -preview=dip1000
 DFLAGS += $(WARNINGS)
 
 # Default DUB flags (DUB uses a different architecture format)
-DUBFLAGS = --arch=$(subst 32,x86,$(subst 64,x86_64,$(MODEL)))
+DUBFLAGS = --arch=$(ARCH)
 
 TOOLS = \
     $(ROOT)/catdoc$(DOTEXE) \
#+END_SRC

** versions GET
*** direnv
***** select version

#+NAME: direnv_version
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:direnv-version()>>
#+END_SRC

#+NAME: direnv_hash
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:direnv-hash()>>
#+END_SRC

*** ldc
***** version & sha256 nix composite

#+NAME: ldc_version_info
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:ldc-version-info()>>
#+END_SRC

***** selected version

#+NAME: ldc_version
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:ldc-version()>>
#+END_SRC

#+NAME: ldc_hash
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:ldc-hash()>>
#+END_SRC

#+NAME: ldc_llvm_set
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:ldc-llvm-set()>>
#+END_SRC

*** dmd
**** selected version

#+NAME: dmd_version
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:dmd-version()>>
#+END_SRC

#+NAME: dmd_hash
#+BEGIN_SRC org
<<./nix-develop-dlang-shared.org:dmd-hash()>>
#+END_SRC

#+NAME: phobos_hash
#+BEGIN_SRC org
<<./nix-develop-dlang-shared.org:phobos-hash()>>
#+END_SRC

*** dub
**** selected version

#+NAME: dub_version
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:dub-version()>>
#+END_SRC

#+NAME: dub_hash
#+BEGIN_SRC nix
<<./nix-develop-dlang-shared.org:dub-hash()>>
#+END_SRC

*** dtools
**** selected version

#+NAME: dtools_version
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:dtools-version()>>
#+END_SRC

#+NAME: dtools_hash
#+BEGIN_SRC emacs-lisp
<<./nix-develop-dlang-shared.org:dtools-hash()>>
#+END_SRC

** sha256 blank_hash

#+NAME: sha256-blank
#+BEGIN_SRC nix
<<./nix-develop-dlang-shared.org:sha256-blank()>>
#+END_SRC

#+NAME: blank_hash
#+BEGIN_SRC nix
<<./nix-develop-dlang-shared.org:sha256-blank()>>
#+END_SRC

* __END__