Packaging dart/flutter for GNU Guix

Recently I have been wanting to learn the flutter toolkit, so I decided to write package definitions for dart and flutter. But I soon learned that its a bit more complex than I thought.

Here is what I have so far,

(define-module (nebula packages dart)
  #:use-module (gnu packages)
  #:use-module (gnu packages base)
  #:use-module (gnu packages compression)
  #:use-module (gnu packages curl)
  #:use-module (gnu packages elf)
  #:use-module (guix git-download)
  #:use-module (guix packages)
  #:use-module (guix build utils)
  #:use-module (guix build-system python)
  #:use-module (guix utils)
  #:use-module ((guix licenses) #:prefix license:))

(define chromium-depot-tools
  (origin
    (method git-fetch)
    (uri (git-reference
          (url "https://chromium.googlesource.com/chromium/tools/depot_tools")
          (commit "1a61eb625d4b062bb2d6f0902b4979b48def4d33")))
    (sha256
     (base32 "1v38mla41dwy00plhxam8z3xk04m3pj5lsjynq9kzhqhmk6airyz"))))

(define-public dart
  (let ((commit "de84385653631c6283b02f09fb1944f8d8dd3b17")
        (revision "0"))
    (package
      (name "dart")
      (version "3.3.4")
      (source
       (origin
         (method git-fetch)
         (uri (git-reference
               (url "https://github.com/dart-lang/sdk.git")
               (commit commit)))
         (file-name (git-file-name name version))
         (sha256
          (base32 "1v38mla41dwy00plhxam8z3xk04m3pj5lsjynq9kzhqhmk6airyz"))))
      (build-system python-build-system)
      (arguments
       (list #:phases
             #~(modify-phases %standard-phases
                 (add-after 'unpack 'add-depot-tools-to-path
                   (lambda _
                     (let* ((depot-tools-path #$chromium-depot-tools))
                       (setenv "PATH" (string-append (getenv "PATH") ":" depot-tools-path)))))
                 (replace 'build
                   (lambda _
                     (system* "./tools/build.py" "--mode" "release" "--arch" "x64" "create_sdk")))
                 (add-after 'install 'patchelf
                   (lambda* (#:key outputs inputs #:allow-other-keys)
                     (let* ((out (assoc-ref outputs "out")))
                       (system* "find"
                                (string-append out "/bin")
                                "-executable" "-type" "f" "-exec"
                                "patchelf" "--set-interpreter"
                                (string-append #$glibc "/lib/ld-linux.so.2")
                                "{}")
                       ))))))
      (inputs (list curl))
      (native-inputs (list patchelf
                           ;; xz
                           unzip))
      (home-page "https://dart.dev")
      (synopsis "The Dart SDK, including the VM, dart2js, core libraries, and more")
      (description "Dart is a scalable programming language, with robust libraries and runtimes,
for building web, server, and mobile apps.")
      (license license:bsd-3))))

(Yes I am aware the hash for the chromium-depot-tools is wrong)

I was following this guide BTW, Building · dart-lang/sdk Wiki · GitHub, and also the nix package definition.

Currently I get this error,

/home/apoorv/repos/nebula/nebula/packages/dart.scm:62:15: warning: source expression failed to match any pattern
guix build: error: dart: unknown package

In any case, I don’t think I’m even close to making this work.

I also found that someone was trying to package dart for Guix https://issues.guix.gnu.org/44926, but there is no more activity there.

In case anyone is interested, here is the nix package definition for dart,

{ stdenv
, lib
, fetchurl
, unzip
, runCommand
, darwin
, sources ? import ./sources.nix {inherit fetchurl;}
, version ? sources.versionUsed
}:

assert sources != null && (builtins.isAttrs sources);
stdenv.mkDerivation (finalAttrs: {
  pname = "dart";
  inherit version;

  nativeBuildInputs = [ unzip ];

  src = sources."${version}-${stdenv.hostPlatform.system}" or (throw "unsupported version/system: ${version}/${stdenv.hostPlatform.system}");

  installPhase = ''
    mkdir -p $out
    cp -R * $out/
    echo $libPath
  '' + lib.optionalString (stdenv.isLinux) ''
    find $out/bin -executable -type f -exec patchelf --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) {} \;
  '';

  libPath = lib.makeLibraryPath [ stdenv.cc.cc ];
  dontStrip = true;
  passthru = {
    updateScript = ./update.sh;
    tests = {
      testCreate = runCommand "dart-test-create" { nativeBuildInputs = [ finalAttrs.finalPackage ]; } ''
        PROJECTNAME="dart_test_project"
        dart create --no-pub $PROJECTNAME

        [[ -d $PROJECTNAME ]]
        [[ -f $PROJECTNAME/bin/$PROJECTNAME.dart ]]
        touch $out
      '';

      testCompile = runCommand "dart-test-compile" {
        nativeBuildInputs = [ finalAttrs.finalPackage ]
          ++ lib.optionals stdenv.isDarwin [ darwin.cctools darwin.sigtool ];
      } ''
        HELLO_MESSAGE="Hello, world!"
        echo "void main() => print('$HELLO_MESSAGE');" > hello.dart
        dart compile exe hello.dart
        PROGRAM_OUT=$(./hello.exe)

        [[ "$PROGRAM_OUT" == "$HELLO_MESSAGE" ]]
        touch $out
      '';
    };
  };

  meta = with lib; {
    homepage = "https://dart.dev";
    maintainers = with maintainers; [ grburst ];
    description = "Scalable programming language, with robust libraries and runtimes, for building web, server, and mobile apps";
    longDescription = ''
      Dart is a class-based, single inheritance, object-oriented language
      with C-style syntax. It offers compilation to JavaScript, interfaces,
      mixins, abstract classes, reified generics, and optional typing.
    '';
    platforms = [ "x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
    sourceProvenance = with sourceTypes; [ binaryNativeCode ];
    license = licenses.bsd3;
  };
})
1 Like

This particular error seems to go away if #use-module (guix gexp) is added to the module definition.

I haven’t tried building it, so I don’t know if anything else will show up (aside from the wrong hash).

This particular error seems to go away if #use-module (guix gexp) is added to the module definition.

Yup I was missing this.

But I don’t think I am even remotely close to building it. Apparently I might also have to package Android Studio which I think will require a fhs container, of which I have no idea how to package.

For now I am using Android Studio installed via Nix package manager with a locally installed flutter sdk under ~/.local/share/flutter.

It works, but I wanted to use emacs, as I’m so used to it, the keybinds and all.

The issue with Emacs ATM is that it couldn’t read the flutter and dart bin/scripts I just get this error when I run dart binary from shell,

  dart
/home/apoorv/.local/share/flutter/bin/internal/shared.sh: line 263: /home/apoorv/.local/share/flutter/bin/cache/dart-sdk/bin/dart: No such file or directory

same with flutter binary. I’m guessing these also require a fhs container. I actually tried running it inside guix shell fhs container,

 guix shell --container --network --emulate-fhs --preserve=^PATH --preserve=^ANDROID_HOME --verbosity=3 coreutils bash git which inetutils nss-certs pkg-config cmake

But I still couldn’t make it work with emacs so…