Unverified Commit be67f665 authored by Arne Keller's avatar Arne Keller Committed by GitHub
Browse files

racket: separate recipes, fix bugs (#375992)

parents b026686b 3a8ef07d
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
#lang racket/base
(require
 racket/function
 racket/list
 racket/pretty
 racket/string
 setup/dirs
 )

(define config-file (build-path (find-config-dir) "config.rktd"))

(define lib-paths
  ((compose remove-duplicates
            (curry map (curryr string-trim "-L" #:right? #f))
            (curry filter (curryr string-prefix? "-L"))
            string-split)
   (getenv "NIX_LDFLAGS")))

(define config
  (let* ([prev-config (read-installation-configuration-table)]
         [prev-lib-search-dirs (hash-ref prev-config 'lib-search-dirs '(#f))]
         [lib-search-dirs (remove-duplicates (append lib-paths prev-lib-search-dirs))])
    (hash-set prev-config 'lib-search-dirs lib-search-dirs)))

(call-with-output-file config-file
  #:exists 'replace
  (curry pretty-write config))
+60 −192
Original line number Diff line number Diff line
@@ -2,14 +2,7 @@
  lib,
  stdenv,
  fetchurl,

  libiconvReal,
  libz,
  lz4,
  ncurses,
  openssl,

  isMinimal ? false,
  racket-minimal,

  cairo,
  fontconfig,
@@ -22,17 +15,17 @@
  libpng,
  makeFontsConf,
  pango,
  sqlite,
  unixODBC,
  wrapGAppsHook3,

  disableDocs ? false,

  callPackage,
  writers,
}:

let
  minimal = racket-minimal.override { inherit disableDocs; };

  makeLibPaths = lib.concatMapStringsSep " " (
    lib.flip lib.pipe [
      lib.getLib
@@ -41,100 +34,46 @@ let
  );

  manifest = lib.importJSON ./manifest.json;
  inherit (stdenv.hostPlatform) isDarwin isStatic;
  inherit (stdenv.hostPlatform) isDarwin;
in

  runtimeDeps = [ openssl ];
  mainDistDeps = [
minimal.overrideAttrs (
  finalAttrs: prevAttrs: {
    src = fetchurl {
      url = "https://mirror.racket-lang.org/installers/${manifest.version}/${manifest.full.filename}";
      inherit (manifest.full) sha256;
    };

    buildInputs = prevAttrs.buildInputs ++ [
      (if isDarwin then libiodbc else unixODBC)
      cairo
    fontconfig
      fontconfig.lib
      glib
      gtk3
      libGL
      libjpeg
      libpng
      pango
    sqlite
    ];
in

stdenv.mkDerivation (finalAttrs: {
  pname = "racket";
  inherit (manifest) version;

  src =
    let
      info = manifest.${if isMinimal then "minimal" else "full"};
    in
    fetchurl {
      url = "https://mirror.racket-lang.org/installers/${manifest.version}/${info.filename}";
      inherit (info) sha256;
    };

  nativeBuildInputs = lib.optionals (!isMinimal) [
    nativeBuildInputs = [
      wrapGAppsHook3
    ];

  buildInputs = [
    libiconvReal
    libz
    lz4
    ncurses
  ];

  patches = lib.optionals isDarwin [
    patches = prevAttrs.patches or [ ] ++ [
      /*
      The entry point binary $out/bin/racket is codesigned at least once. The
      following error is triggered as a result.
      (error 'add-ad-hoc-signature "file already has a signature")
      We always remove the existing signature then call add-ad-hoc-signature to
      circumvent this error.
        Hardcode variant detection because nixpkgs wraps the Racket binary making it
        fail to detect its variant at runtime.
        https://github.com/NixOS/nixpkgs/issues/114993#issuecomment-812951247
      */
    ./patches/force-remove-codesign-then-add.patch
  ];

  preConfigure =
    /*
      The configure script forces using `libtool -o` as AR on Darwin. But, the
      `-o` option is only available from Apple libtool. GNU ar works here.
    */
    lib.optionalString isDarwin ''
      substituteInPlace src/ChezScheme/zlib/configure \
          --replace-fail 'ARFLAGS="-o"' 'AR=ar; ARFLAGS="rc"'
    ''
    + ''
      mkdir src/build
      cd src/build
    '';

  configureScript = "../configure";

  configureFlags =
    [
      "--enable-check"
      "--enable-csonly"
      "--enable-liblz4"
      "--enable-libz"
    ]
    ++ lib.optional disableDocs "--disable-docs"
    ++ lib.optionals (!isStatic) [
      # instead of `--disable-static` that `stdenv` assumes
      "--disable-libs"
      # "not currently supported" in `configure --help-cs` but still emphasized in README
      "--enable-shared"
    ]
    ++ lib.optionals isDarwin [
      "--disable-strip"
      # "use Unix style (e.g., use Gtk) for Mac OS", which eliminates many problems
      "--enable-xonx"
      ./patches/force-cs-variant.patch
    ];

    preBuild =
      let
      libPaths = makeLibPaths mainDistDeps;
        libPaths = makeLibPaths finalAttrs.buildInputs;
        libPathsVar = if isDarwin then "DYLD_FALLBACK_LIBRARY_PATH" else "LD_LIBRARY_PATH";
      in
    lib.optionalString (!isMinimal) (
      /*
        Makes FFIs available for setting up `main-distribution` and its
        dependencies, which is integrated into the build process of Racket
@@ -148,81 +87,29 @@ stdenv.mkDerivation (finalAttrs: {
      + ''
        export FONTCONFIG_FILE=${makeFontsConf { fontDirectories = [ ]; }}
        export XDG_CACHE_HOME=$(mktemp -d)
      ''
    );

  dontStrip = isDarwin;
      '';

  preFixup = lib.optionalString (!isMinimal && !isDarwin) ''
    preFixup = lib.optionalString (!isDarwin) ''
      gappsWrapperArgs+=("--set" "LOCALE_ARCHIVE" "${glibcLocales}/lib/locale/locale-archive")
    '';

  postFixup =
    passthru =
      let
      libPaths = makeLibPaths (runtimeDeps ++ lib.optionals (!isMinimal) mainDistDeps);
        notUpdated = x: !builtins.isAttrs x || lib.isDerivation x;
        stopPred =
          _: lhs: rhs:
          notUpdated lhs || notUpdated rhs;
      in
    ''
      $out/bin/racket -f - <<EOF
      (require setup/dirs)

      (define config-path (build-path (find-config-dir) "config.rktd"))

      (define prev-config (with-input-from-file config-path read))
      (define prev-lib-search-dirs (hash-ref prev-config 'lib-search-dirs '(#f)))

      (define lib-search-dirs (append '(${libPaths}) prev-lib-search-dirs))
      (define config (hash-set prev-config 'lib-search-dirs lib-search-dirs))

      (with-output-to-file config-path (thunk (pretty-write config))
        #:exists 'replace)
      EOF
    '';

  passthru = {
    # Functionalities #
    updateScript = {
      command = ./update.py;
      attrPath = "racket";
      supportedFeatures = [ "commit" ];
    };
    writeScript =
      nameOrPath:
      {
        libraries ? [ ],
        ...
      }@config:
      assert lib.assertMsg (libraries == [ ]) "library integration for Racket has not been implemented";
      writers.makeScriptWriter (
        builtins.removeAttrs config [ "libraries" ]
        // {
          interpreter = "${lib.getExe finalAttrs.finalPackage}";
        }
      ) nameOrPath;
    writeScriptBin = name: finalAttrs.passthru.writeScript "/bin/${name}";

    # Tests #
    tests = builtins.mapAttrs (name: path: callPackage path { racket = finalAttrs.finalPackage; }) (
      {
        ## Basic ##
        write-greeting = ./tests/write-greeting.nix;
        get-version-and-variant = ./tests/get-version-and-variant.nix;
        load-openssl = ./tests/load-openssl.nix;

        ## Nixpkgs supports ##
        nix-write-script = ./tests/nix-write-script.nix;
      }
      // lib.optionalAttrs (!isMinimal) {
      lib.recursiveUpdateUntil stopPred prevAttrs.passthru {
        tests = builtins.mapAttrs (name: path: callPackage path { racket = finalAttrs.finalPackage; }) {
          ## `main-distribution` ##
          draw-crossing = ./tests/draw-crossing.nix;
      }
    );
        };
      };

  meta = {
    description =
      "Programmable programming language" + lib.optionalString isMinimal " (minimal distribution)";
    longDescription =
      ''
    meta = prevAttrs.meta // {
      description = "Programmable programming language";
      longDescription = ''
        Racket is a full-spectrum programming language. It goes beyond
        Lisp and Scheme with dialects that support objects, types,
        laziness, and more. Racket enables programmers to link
@@ -230,28 +117,9 @@ stdenv.mkDerivation (finalAttrs: {
        programmers to create new, project-specific dialects. Racket's
        libraries support applications from web servers and databases to
        GUIs and charts.
      ''
      + lib.optionalString isMinimal ''

        This minimal distribution includes just enough of Racket that you can
        use `raco pkg` to install more.
      '';
    homepage = "https://racket-lang.org/";
    changelog = "https://github.com/racket/racket/releases/tag/v${finalAttrs.version}";
    /*
      > Racket is distributed under the MIT license and the Apache version 2.0
      > license, at your option.

      > The Racket runtime system embeds Chez Scheme, which is distributed
      > under the Apache version 2.0 license.
    */
    license = with lib.licenses; [
      asl20
      mit
    ];
    maintainers = with lib.maintainers; [ rc-zb ];
    mainProgram = "racket";
    platforms = lib.platforms.${if isMinimal then "all" else "unix"};
      platforms = lib.platforms.unix;
      badPlatforms = lib.platforms.darwin;
    };
})
  }
)
+169 −0
Original line number Diff line number Diff line
{
  lib,
  stdenv,
  fetchurl,

  libiconvReal,
  libz,
  lz4,
  ncurses,
  openssl,
  sqlite,

  disableDocs ? false,

  callPackage,
  writers,
}:

let
  manifest = lib.importJSON ./manifest.json;

  inherit (stdenv.hostPlatform) isDarwin isStatic;
in

stdenv.mkDerivation (finalAttrs: {
  pname = "racket";
  inherit (manifest) version;

  src = fetchurl {
    url = "https://mirror.racket-lang.org/installers/${manifest.version}/${manifest.minimal.filename}";
    inherit (manifest.minimal) sha256;
  };

  buildInputs = [
    libiconvReal
    libz
    lz4
    ncurses
    openssl
    sqlite.out
  ];

  patches = lib.optionals isDarwin [
    /*
      The entry point binary $out/bin/racket is codesigned at least once. The
      following error is triggered as a result.
      (error 'add-ad-hoc-signature "file already has a signature")
      We always remove the existing signature then call add-ad-hoc-signature to
      circumvent this error.
    */
    ./patches/force-remove-codesign-then-add.patch
  ];

  preConfigure =
    /*
      The configure script forces using `libtool -o` as AR on Darwin. But, the
      `-o` option is only available from Apple libtool. GNU ar works here.
    */
    lib.optionalString isDarwin ''
      substituteInPlace src/ChezScheme/zlib/configure \
          --replace-fail 'ARFLAGS="-o"' 'AR=ar; ARFLAGS="rc"'
    ''
    + ''
      mkdir src/build
      cd src/build
    '';

  configureScript = "../configure";

  configureFlags =
    [
      "--enable-check"
      "--enable-csonly"
      "--enable-liblz4"
      "--enable-libz"
    ]
    ++ lib.optional disableDocs "--disable-docs"
    ++ lib.optionals (!isStatic) [
      # instead of `--disable-static` that `stdenv` assumes
      "--disable-libs"
      # "not currently supported" in `configure --help-cs` but still emphasized in README
      "--enable-shared"
    ]
    ++ lib.optionals isDarwin [
      "--disable-strip"
      # "use Unix style (e.g., use Gtk) for Mac OS", which eliminates many problems
      "--enable-xonx"
    ];

  dontStrip = isDarwin;

  postFixup =
    let
      configureInstallation = builtins.path {
        name = "configure-installation.rkt";
        path = ./configure-installation.rkt;
      };
    in
    ''
      $out/bin/racket -U -u ${configureInstallation}
    '';

  passthru = {
    # Functionalities #
    updateScript = {
      command = ./update.py;
      attrPath = "racket";
      supportedFeatures = [ "commit" ];
    };
    writeScript =
      nameOrPath:
      {
        libraries ? [ ],
        ...
      }@config:
      assert lib.assertMsg (libraries == [ ]) "library integration for Racket has not been implemented";
      writers.makeScriptWriter (
        builtins.removeAttrs config [ "libraries" ]
        // {
          interpreter = "${lib.getExe finalAttrs.finalPackage}";
        }
      ) nameOrPath;
    writeScriptBin = name: finalAttrs.passthru.writeScript "/bin/${name}";

    # Tests #
    tests = builtins.mapAttrs (name: path: callPackage path { racket = finalAttrs.finalPackage; }) {
      ## Basic ##
      write-greeting = ./tests/write-greeting.nix;
      get-version-and-variant = ./tests/get-version-and-variant.nix;
      load-openssl = ./tests/load-openssl.nix;

      ## Nixpkgs supports ##
      nix-write-script = ./tests/nix-write-script.nix;
    };
  };

  meta = {
    description = "Programmable programming language (minimal distribution)";
    longDescription = ''
      Racket is a full-spectrum programming language. It goes beyond
      Lisp and Scheme with dialects that support objects, types,
      laziness, and more. Racket enables programmers to link
      components written in different dialects, and it empowers
      programmers to create new, project-specific dialects. Racket's
      libraries support applications from web servers and databases to
      GUIs and charts.

      This minimal distribution includes just enough of Racket that you can
      use `raco pkg` to install more.
    '';
    homepage = "https://racket-lang.org/";
    changelog = "https://github.com/racket/racket/releases/tag/v${finalAttrs.version}";
    /*
      > Racket is distributed under the MIT license and the Apache version 2.0
      > license, at your option.

      > The Racket runtime system embeds Chez Scheme, which is distributed
      > under the Apache version 2.0 license.
    */
    license = with lib.licenses; [
      asl20
      mit
    ];
    maintainers = with lib.maintainers; [ rc-zb ];
    mainProgram = "racket";
    platforms = lib.platforms.all;
    badPlatforms = lib.platforms.darwin;
  };
})
+12 −0
Original line number Diff line number Diff line
--- old/collects/setup/variant.rkt
+++ new/collects/setup/variant.rkt
@@ -7,7 +7,8 @@
 (provide variant-suffix
          script-variant?)

-(define plain-variant
+(define plain-variant 'cs)
+#;(define plain-variant
   (delay/sync
    (cond
      [(cross-installation?)
+38 −20
Original line number Diff line number Diff line
{ runCommandLocal, racket }:
{
  lib,
  runCommandLocal,
  racket,
}:

runCommandLocal "racket-test-get-version-and-variant"
  {
    nativeBuildInputs = [ racket ];
  }
  (
    lib.concatLines (
      builtins.map
        (
          { expectation, output }:
          ''
    expectation="${racket.version}"

    output="$(racket -e '(display (version))')"

    if test "$output" != "$expectation"; then
        echo "output mismatch: expected ''${expectation}, but got ''${output}"
        exit 1
    fi

    expectation="cs"
            expectation="${expectation}"

    output="$(racket -e '(require launcher/launcher) (display (current-launcher-variant))')"
            output="${output}"

            if test "$output" != "$expectation"; then
                echo "output mismatch: expected ''${expectation}, but got ''${output}"
                exit 1
            fi

          ''
        )
        [
          {
            expectation = racket.version;
            output = "$(racket -e '(display (version))')";
          }
          {
            expectation = "cs";
            output = "$(racket -e '(require launcher/launcher) (display (current-launcher-variant))')";
          }
          {
            expectation = "${lib.getExe racket}";
            output = "$(racket -e '(require compiler/find-exe) (display (find-exe))')";
          }
        ]
    )
    + ''
      touch $out
    ''
  )
Loading