This only runs cargo metadata
for now, but already in a better way than Nix
LQBZJUGCEIU56WBYBLE757W2DHPZWJ4JNG3ILB52RDXMXUYAPZCQC
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