pijul nest
guest [sign in]

Adding a basic Rust builder

pmeunier
Jun 27, 2025, 10:33 PM
LQBZJUGCEIU56WBYBLE757W2DHPZWJ4JNG3ILB52RDXMXUYAPZCQC

Dependencies

  • [2] UWQB743K First working shell (with ocaml code)

Change contents

  • file addition: rust.ml (----------)
    [2.55449]
    open Derivation
    open Lwt.Syntax
    let fetch_crate source checksum crate version =
    let registry_dl =
    if source = "registry+https://github.com/rust-lang/crates.io-index" then
    "https://crates.io/api/v1/crates"
    else failwith "Not implemented"
    in
    http
    ~url:(registry_dl ^ "/" ^ crate ^ "/" ^ version ^ "/download")
    ~hash_algorithm:Elpegrpc.Elpe.Hash.Sha256
    ~hash:(Hex.to_bytes (`Hex checksum))
    let str_from_toml_table k toml =
    match Toml.Types.Table.find (Toml.Types.Table.Key.of_string k) toml with
    | Toml.Types.TString s -> s
    | _ -> raise Not_found
    let unzip pkg =
    object (self)
    inherit std_derivation
    method name = "rust"
    method! unpack_phase = Lwt.return ""
    method! build_inputs =
    Lwt.return
    [
    (ubuntu "libc6-dev" :> derivation);
    (ubuntu "coreutils" :> derivation);
    (ubuntu "tar" :> derivation);
    (ubuntu "gzip" :> derivation);
    ]
    method! build_phase =
    let* zipped = self#derivation pkg in
    Lwt.return
    ("mkdir -p $DESTDIR; tar -xf " ^ List.hd zipped.destdir ^ " -C $DESTDIR")
    end
    let rust ?(version = "1.84") src =
    object (self)
    inherit std_derivation
    method name = "rust"
    method! src = Lwt.return src
    method! build_inputs = Lwt.return [ (ubuntu "coreutils" :> derivation) ]
    method packages toml =
    let packages =
    match
    Toml.Types.Table.find (Toml.Types.Table.Key.of_string "package") toml
    with
    | Toml.Types.TArray (Toml.Types.NodeTable arr) -> arr
    | _ -> failwith "Unexpected type"
    in
    let* packages =
    Lwt.all
    (List.map
    (fun pkg ->
    try
    let source = str_from_toml_table "source" pkg in
    let checksum = str_from_toml_table "checksum" pkg in
    let name = str_from_toml_table "name" pkg in
    let version = str_from_toml_table "version" pkg in
    let h = fetch_crate source checksum name version in
    let* drv = self#derivation (unzip h :> derivation) in
    Lwt.return (Some (name, version, h, drv))
    with Not_found -> Lwt.return None)
    packages)
    in
    let h = Hashtbl.create 16 in
    Lwt.return
    (List.fold_left
    (fun acc x ->
    match x with
    | Some (crate_name, version, _, drv) ->
    let target =
    if Hashtbl.find_opt h crate_name = None then
    let _ = Hashtbl.add h crate_name () in
    crate_name ^ "-" ^ version
    else crate_name
    in
    acc ^ "ln -s " ^ List.hd drv.destdir ^ "/" ^ crate_name ^ "-"
    ^ version ^ " vendor/" ^ target ^ "\n"
    | None -> acc)
    "" packages)
    method! build_phase =
    let* src = self#src in
    let* src_built = src#build in
    let lock =
    Stdlib.open_in
    (Filename.concat (List.hd src_built.destdir) "Cargo.lock")
    in
    let parsed =
    match Toml.Parser.from_channel lock with
    | `Ok toml -> toml
    | `Error (err, _) -> failwith ("Error: " ^ err)
    in
    let* packages = self#packages parsed in
    let metadata =
    object (self)
    inherit std_derivation
    method name = "test"
    method! src = Lwt.return src
    method! build_phase =
    let* rustc = self#derivation (ubuntu ("rustc-" ^ version)) in
    let rustc = List.hd rustc.destdir in
    let* cargo = self#derivation (ubuntu ("cargo-" ^ version)) in
    let cargo = List.hd cargo.destdir in
    let setup =
    "export HOME=/home/me\nmkdir -p $HOME\nexport PATH=" ^ rustc
    ^ "/usr/lib/rust-" ^ version ^ "/bin:" ^ cargo ^ "/usr/lib/rust-"
    ^ version ^ "/bin:$PATH\nmkdir -p vendor .cargo\n" ^ packages
    ^ "\n\
    cat <<EOF >> .cargo/config.toml\n\
    [source.crates-io]\n\
    replace-with = \"vendored-sources\"\n\n\
    [source.vendored-sources]\n\
    directory = \"vendor\"\n\
    EOF\n\
    cargo metadata --offline --format-version 1"
    in
    Lwt.return setup
    method! build_inputs =
    Lwt.return [ (ubuntu "coreutils" :> derivation) ]
    end
    in
    let buf = metadata#set_stdout in
    let* _ = metadata#build in
    let meta_json = Yojson.Basic.from_string (Buffer.contents buf) in
    let open Yojson.Basic.Util in
    let members =
    meta_json |> member "workspace_members" |> to_list |> filter_string
    in
    let _ = List.map (fun x -> print_endline x) members in
    Lwt.return ""
    end