diff --git a/dev/dune-tools/dune-commands/README.md b/dev/dune-tools/dune-commands/README.md new file mode 100644 index 00000000..ebda3225 --- /dev/null +++ b/dev/dune-tools/dune-commands/README.md @@ -0,0 +1,13 @@ +Dune Commands +============= + +This package provides a program called `dune-commands`, which can extract the +run command from a JSONL dune trace. + +It can be used as follows. +```sh +dune trace cat > trace.jsonl +dune exec -- dune-commands --json --trace-file trace.jsonl > commands.json +``` + +Run `dune-commands --help` for more information. diff --git a/dev/dune-tools/dune-report/dune b/dev/dune-tools/dune-commands/dune similarity index 100% rename from dev/dune-tools/dune-report/dune rename to dev/dune-tools/dune-commands/dune diff --git a/dev/dune-tools/dune-report/dune-report.opam b/dev/dune-tools/dune-commands/dune-commands.opam similarity index 91% rename from dev/dune-tools/dune-report/dune-report.opam rename to dev/dune-tools/dune-commands/dune-commands.opam index 903fbaed..b064fad3 100644 --- a/dev/dune-tools/dune-report/dune-report.opam +++ b/dev/dune-tools/dune-commands/dune-commands.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -synopsis: "Library for interpreting failures from the dune log" +synopsis: "Library for extracting run commands from a dune trace" maintainer: ["Rodolphe Lepigre "] authors: ["Rodolphe Lepigre "] license: "LGPL-2.0-or-later" diff --git a/dev/dune-tools/dune-report/dune-project b/dev/dune-tools/dune-commands/dune-project similarity index 73% rename from dev/dune-tools/dune-report/dune-project rename to dev/dune-tools/dune-commands/dune-project index 823271a1..a3ac4b0e 100644 --- a/dev/dune-tools/dune-report/dune-project +++ b/dev/dune-tools/dune-commands/dune-project @@ -1,5 +1,5 @@ (lang dune 3.21) -(name dune-report) +(name dune-commands) (generate_opam_files true) (source (github SkylabsAI/workspace)) @@ -8,8 +8,8 @@ (license LGPL-2.0-or-later) (package - (name dune-report) - (synopsis "Library for interpreting failures from the dune log") + (name dune-commands) + (synopsis "Library for extracting run commands from a dune trace") (depends cmdliner ppx_deriving_yojson)) diff --git a/dev/dune-tools/dune-commands/src/dune b/dev/dune-tools/dune-commands/src/dune new file mode 100644 index 00000000..23edac19 --- /dev/null +++ b/dev/dune-tools/dune-commands/src/dune @@ -0,0 +1,6 @@ +(executable + (name main) + (public_name dune-commands) + (package dune-commands) + (preprocess (pps ppx_deriving_yojson)) + (libraries cmdliner ppx_deriving_yojson.runtime)) diff --git a/dev/dune-tools/dune-commands/src/dune_log.ml b/dev/dune-tools/dune-commands/src/dune_log.ml new file mode 100644 index 00000000..39cf47c7 --- /dev/null +++ b/dev/dune-tools/dune-commands/src/dune_log.ml @@ -0,0 +1,99 @@ +type command = { + command : string; + output : string list; + status : int; +} +[@@deriving yojson] + +let command_to_json = command_to_yojson + +exception Error of string + +let error : string -> 'a = fun s -> + raise (Error(s)) + +let read : In_channel.t -> fname:string -> command list = fun ic ~fname -> + let lines = In_channel.input_lines ic in + let parse i line = + let lnum = i + 1 in + let error s = + error (Printf.sprintf "File %s, line %i: %s" fname lnum s) + in + let json = + try Yojson.Safe.from_string ~fname ~lnum line with + | Yojson.Json_error(s) -> error ("JSON parse failure.\n" ^ s) + in + let assoc = + match json with + | `Assoc(fields) -> fields + | _ -> error "unexpected JSON value (not an object)" + in + let get field = + try List.assoc field assoc with Not_found -> + error ("no field \"" ^ field ^ "\"") + in + if get "cat" <> `String("process") then None else + if get "name" <> `String("finish") then None else + let args = + match get "args" with + | `Assoc(fields) -> fields + | _ -> error "ill-typed \"args\" field" + in + let get field = + try List.assoc field args with Not_found -> + error ("no field \"" ^ field ^ "\"") + in + let status = + match get "exit" with + | `Int(i) -> i + | _ -> error "ill-typed \"exit\" field" + in + let output = + let lines s = + let parts = String.split_on_char '\n' s in + match List.rev parts with + | "" :: parts -> List.rev parts + | _ -> parts + in + let get s = + match List.assoc_opt s args with + | None -> [] + | Some(`String(s)) -> lines s + | _ -> error ("ill-typed \"" ^ s ^ "\" field") + in + get "stdout" @ get "stderr" + in + let command = + let prog = + match get "prog" with + | `String(p) -> Filename.basename p + | _ -> error ("ill-typed \"prog\" field") + in + let dir = + match List.assoc_opt "dir" args with + | None -> None + | Some(`String(s)) -> Some(s) + | _ -> error ("ill-typed \"dir\" field") + in + let args = + match List.assoc_opt "process_args" args with + | None -> [] + | Some(`List(args)) -> args + | _ -> error ("ill-typed \"process_args\" field") + in + let args = + let get_string json = + match json with + | `String(s) -> s + | _ -> error "expected a string" + in + List.map get_string args + in + let command = String.concat " " (prog :: args) in + match dir with + | None -> command + | Some(d) -> Printf.sprintf "(cd %s && %s)" d command + in + Some({command; output; status}) + in + List.filter_map Fun.id (List.mapi parse lines) diff --git a/dev/dune-tools/dune-commands/src/dune_log.mli b/dev/dune-tools/dune-commands/src/dune_log.mli new file mode 100644 index 00000000..8ccceff1 --- /dev/null +++ b/dev/dune-tools/dune-commands/src/dune_log.mli @@ -0,0 +1,21 @@ +(** Command logged during a dune build. *) +type command = { + command : string; + (** Command that was run. *) + output : string list; + (** Lines of output from the command (including error message). *) + status : int; + (** Return code from the command (non-0 on failure). *) +} + +(** [command_to_json command] turns [command] into its JSON representation. *) +val command_to_json : command -> Yojson.Safe.t + +(** Exception raised by [read]. *) +exception Error of string + +(** [read ic ~fname] extracts a list of run commands from the dune JSONL trace + expected on channel [ic], corresponding to file name [fname]. In case of a + file system error, the [Sys_error] exception is raised. If the channel has + unexpected contents, an [Error] exception is raised. *) +val read : In_channel.t -> fname:string -> command list diff --git a/dev/dune-tools/dune-report/bin/main.ml b/dev/dune-tools/dune-commands/src/main.ml similarity index 71% rename from dev/dune-tools/dune-report/bin/main.ml rename to dev/dune-tools/dune-commands/src/main.ml index 998cfd0f..ebe3e696 100644 --- a/dev/dune-tools/dune-report/bin/main.ml +++ b/dev/dune-tools/dune-commands/src/main.ml @@ -7,20 +7,13 @@ let pp_command : Format.formatter -> Dune_log.command -> unit = fun ff cmd -> List.iter (Format.fprintf ff "%s\n%!") cmd.Dune_log.output; Format.fprintf ff "[%i]\n%!" cmd.Dune_log.status -let run : bool -> bool -> string option -> unit = fun json all log_file -> - let log_file = - match log_file with - | Some(log_file) -> log_file - | None -> - match Dune_log.locate () with - | Some(log_file) -> log_file - | None -> - Printf.eprintf "Could not locate the dune log. "; - Printf.eprintf "Did you run \"dune build\"?\n%!"; - exit 3 - in +let run : bool -> bool -> string option -> unit = fun json all trace_file -> let commands = - try Dune_log.read ~log_file with + try + match trace_file with + | Some(fname) -> In_channel.with_open_text fname (Dune_log.read ~fname) + | None -> Dune_log.read ~fname:"-" stdin + with | Sys_error(s) -> Printf.eprintf "File system error: %s.\n%!" s; exit 2 @@ -53,17 +46,20 @@ let all = in Arg.(value & flag & info ["all"] ~doc) -let log_file = +let trace_file = let doc = - "Specify a path to the dune log to process. When not specified, the log \ - from the current dune workspace is located." + "Specify a path to a file containing a JSONL file holding a dune log. \ + When not specified, the log is read on the standard input." in - let i = Arg.(info ["log-file"] ~docv:"LOGFILE" ~doc) in + let i = Arg.(info ["trace-file"] ~docv:"TRACEFILE" ~doc) in Arg.(value & opt (some non_dir_file) None & i) let cmd = - let doc = "Builds a report form the dune build log." in - let term = Term.(const run $ json $ all $ log_file) in + let doc = + "Builds a report from a JSONL dune build trace. Such a trace can be \ + obtained using $(b,dune trace cat)." + in + let term = Term.(const run $ json $ all $ trace_file) in let exits = let open Cmd.Exit in info ~doc:"On success." ok :: diff --git a/dev/dune-tools/dune-named-logfile/dune-named-logfile b/dev/dune-tools/dune-named-logfile/dune-named-logfile index b48197e2..092e3a87 100755 --- a/dev/dune-tools/dune-named-logfile/dune-named-logfile +++ b/dev/dune-tools/dune-named-logfile/dune-named-logfile @@ -2,10 +2,10 @@ set -o errexit set -o pipefail -# "dune-named-logfile ARGS ..." invokes "dune ARGS ...", and then copies the -# resulting dune "_build/log" to the path specified by SL_DUNE_LOG_FILE. If -# SL_LOG_APPEND is set and non-empty, the log contents is added to the end of -# the file instead of overwriting it. +# "dune-named-logfile ARGS ..." invokes "dune ARGS ...", and then extracts the +# data from "_build/trace.csexp" to the path specified by environment variable +# SL_DUNE_LOG_FILE using "dune trace cat ...". If SL_DUNE_LOG_APPEND is set +# and non-empty, the data is added to the end of the file. # # This script is meant to be put in the PATH under name "dune". This is useful # when "dune" invocations cannot easily be replaced by "dune-named-logfile". @@ -14,8 +14,9 @@ set -o pipefail # # Options (all passed via environment variables): # - SL_DUNE_ORIGINAL: absolute path to the original "dune" binary. -# - SL_DUNE_LOG_FILE: target log file. -# - SL_DUNE_LOG_APPEND: if non-empty, the log is appended and not overwritten. +# - SL_DUNE_LOG_FILE: target data file (in jsonl format). +# - SL_DUNE_LOG_APPEND: if non-empty, append data at the end of the file that +# is specified by SL_DUNE_LOG_FILE instead of overwriting it. SELF=$(realpath $0) DUNE=$(realpath "${SL_DUNE_ORIGINAL:=$(which dune)}") @@ -56,16 +57,16 @@ else fi BUILD_PATH=$(realpath "${DUNE_PATH}/..") - DUNE_LOG="${BUILD_PATH}/log" - rm "${DUNE_LOG}" + DUNE_TRACE="${BUILD_PATH}/trace.csexp" + rm -f "${DUNE_TRACE}" ${DUNE} "$@" && EXIT=$? || EXIT=$? - if [ -f "${DUNE_LOG}" ]; then + if [ -f "${DUNE_TRACE}" ]; then if [ -z "${SL_DUNE_LOG_APPEND}" ]; then - cp "${DUNE_LOG}" "${LOG}" + ${DUNE} trace cat --trace-file "${DUNE_TRACE}" > "${LOG}" else - cat "${DUNE_LOG}" >> "${LOG}" + ${DUNE} trace cat --trace-file "${DUNE_TRACE}" >> "${LOG}" fi else if [ -z "${SL_DUNE_LOG_APPEND}" ]; then diff --git a/dev/dune-tools/dune-report/README.md b/dev/dune-tools/dune-report/README.md deleted file mode 100644 index 691e8d60..00000000 --- a/dev/dune-tools/dune-report/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Dune Report -=========== - -This package provides a program called `dune-report`, which can parse the dune -logs and turn them into program-friendly JSON output. Run `dune-report --help` -for more details. diff --git a/dev/dune-tools/dune-report/bin/dune b/dev/dune-tools/dune-report/bin/dune deleted file mode 100644 index 51ca8680..00000000 --- a/dev/dune-tools/dune-report/bin/dune +++ /dev/null @@ -1,5 +0,0 @@ -(executable - (name main) - (public_name dune-report) - (package dune-report) - (libraries dune_log cmdliner)) diff --git a/dev/dune-tools/dune-report/lib/dune b/dev/dune-tools/dune-report/lib/dune deleted file mode 100644 index 57dea207..00000000 --- a/dev/dune-tools/dune-report/lib/dune +++ /dev/null @@ -1,6 +0,0 @@ -(library - (name dune_log) - (public_name dune-report) - (wrapped false) - (preprocess (pps ppx_deriving_yojson)) - (libraries ppx_deriving_yojson.runtime)) diff --git a/dev/dune-tools/dune-report/lib/dune_log.ml b/dev/dune-tools/dune-report/lib/dune_log.ml deleted file mode 100644 index 238a3e77..00000000 --- a/dev/dune-tools/dune-report/lib/dune_log.ml +++ /dev/null @@ -1,111 +0,0 @@ -type command = { - command : string; - output : string list; - status : int; -} -[@@deriving yojson] - -let command_to_json = command_to_yojson - -exception Error of string - -let error : string -> 'a = fun s -> - raise (Error(s)) - -type item = - | Command of string - | Output of string - | Status of int - -let rec next_item : int -> In_channel.t -> (int * item) option = fun n ic -> - let skip_space ic = - match In_channel.input_char ic with - | Some(' ') -> () - | _ -> error (Printf.sprintf "space expected on line %i" n) - in - let get_line ic = - match In_channel.input_line ic with - | Some(line) -> line - | None -> - error (Printf.sprintf "unexpected end of input on line %i" n) - in - let get_output_line ic = - let remove_space line = - match String.get line 0 with - | ' ' -> String.sub line 1 (String.length line - 1) - | _ -> error (Printf.sprintf "space expected on line %i" n) - in - match In_channel.input_line ic with - | Some(line) -> if line = "" then line else remove_space line - | None -> - error (Printf.sprintf "unexpected end of input on line %i" n) - in - let read_status ic = - let line = get_line ic in - try Scanf.sscanf line "%d]" Fun.id with - | Failure(_) | Scanf.Scan_failure(_) | End_of_file -> - error (Printf.sprintf "invalid status on line %i" n) - in - match In_channel.input_char ic with - | None -> None - | Some('#') -> ignore (get_line ic); next_item (n + 1) ic - | Some('$') -> skip_space ic; Some(n + 1, Command(get_line ic)) - | Some('>') -> Some(n + 1, Output(get_output_line ic)) - | Some('[') -> Some(n + 1, Status(read_status ic)) - | Some(c ) -> - error (Printf.sprintf "unexpected start of line (%C) on line %i" c n) - -let rev_items : In_channel.t -> item list = fun ic -> - let rec loop n acc = - match next_item n ic with - | None -> acc - | Some(n, item) -> loop n (item :: acc) - in - loop 1 [] - -let read : log_file:string -> command list = fun ~log_file -> - let rev_items = In_channel.with_open_text log_file rev_items in - let rec loop acc output status rev_items = - match (rev_items, output, status) with - | (Status(i) :: rev_items, [], None ) -> - loop acc [] (Some(i)) rev_items - | (Status(_) :: _ , _ , Some(_)) -> - error "duplicated status line" - | (Status(_) :: _ , _ , None ) -> - error "leftover output" - | (Output(s) :: rev_items, [], None ) -> - loop acc [s] (Some(0)) rev_items - | (Output(_) :: _ , _ , None ) -> - error "leftover output" - | (Output(s) :: rev_items, _ , Some(_)) -> - loop acc (s :: output) status rev_items - | (Command(s) :: rev_items, _ , None ) -> - loop ({command = s; output; status = 0} :: acc) [] None rev_items - | (Command(s) :: rev_items, _ , Some(i)) -> - loop ({command = s; output; status = i} :: acc) [] None rev_items - | ([] , [], None ) -> - acc - | ([] , [] , _ ) -> - error "hanging status line" - | ([] , _ , _ ) -> - error "leftover output" - in - loop [] [] None rev_items - -let locate : unit -> string option = fun () -> - let rec locate_build dir = - let candidate = Filename.concat dir "_build" in - let found = try Sys.is_directory candidate with Sys_error(_) -> false in - match found with - | true -> Some(candidate) - | false -> - let parent_dir = Filename.dirname dir in - match parent_dir = dir with - | true -> None - | false -> locate_build parent_dir - in - match locate_build (Sys.getcwd ()) with - | None -> None - | Some(build) -> - let log_file = Filename.concat build "log" in - if Sys.file_exists log_file then Some(log_file) else None diff --git a/dev/dune-tools/dune-report/lib/dune_log.mli b/dev/dune-tools/dune-report/lib/dune_log.mli deleted file mode 100644 index 734419d9..00000000 --- a/dev/dune-tools/dune-report/lib/dune_log.mli +++ /dev/null @@ -1,25 +0,0 @@ -(** Command logged during a dune build. *) -type command = { - command : string; - (** Command that was run. *) - output : string list; - (** Lines of output from the command (including error message). *) - status : int; - (** Return code from the command (non-0 on failure). *) -} - -(** [command_to_json command] turns [command] into its JSON representation. *) -val command_to_json : command -> Yojson.Safe.t - -(** Exception raised by [read]. *) -exception Error of string - -(** [read ~log_file] collects all the commands logged in file [log_file]. Note - that [log_file] should typically be ["_build/log"]. In case of error while - accessing the file system, the [Sys_error] exception is raised. An [Error] - exception is raised if unexpected contents is found in the file. *) -val read : log_file:string -> command list - -(** [locate ()] attempts to locate the dune log file for the current workspace - (where the current working directory of the program is). *) -val locate : unit -> string option diff --git a/dev/opam-deps/skylabs-deps.opam b/dev/opam-deps/skylabs-deps.opam index 7bf61941..56f79675 100644 --- a/dev/opam-deps/skylabs-deps.opam +++ b/dev/opam-deps/skylabs-deps.opam @@ -1,4 +1,6 @@ opam-version: "2.0" +name: "skylabs-deps" +version: "dev" synopsis: "External deps for the SkyLabs AI toolchain" maintainer: [ "Rodolphe Lepigre " @@ -14,10 +16,10 @@ bug-reports: "https://github.com/SkylabsAI/fm-ci/issues" depends: [ "angstrom" {= "0.16.1"} "astring" {= "0.8.5"} - "atd" {= "3.0.1"} - "atdgen" {= "3.0.1"} - "atdgen-runtime" {= "3.0.1"} - "atdts" {= "3.0.1"} + "atd" {= "4.2.0"} + "atdgen" {= "4.2.0"} + "atdgen-runtime" {= "4.2.0"} + "atdts" {= "4.2.0"} "base" {= "v0.17.3"} "base-bigarray" {= "base"} "base-bytes" {= "base"} @@ -32,18 +34,18 @@ depends: [ "bigstringaf" {= "0.10.0"} "bin_prot" {= "v0.17.0-1"} "biniou" {= "1.2.2"} - "bos" {= "0.2.1"} + "bos" {= "0.3.0"} "camlp-streams" {= "5.0.1"} - "camlzip" {= "1.13"} + "camlzip" {= "1.14"} "capitalization" {= "v0.17.0"} - "chrome-trace" {= "3.21.0"} - "cmdliner" {= "2.1.0"} + "chrome-trace" {= "3.22.2"} + "cmdliner" {= "2.1.1"} "conf-gmp" {= "5"} "conf-libffi" {= "2.0.0"} "conf-linux-libc-dev" {= "0" & os = "linux"} "conf-pkg-config" {= "4"} "conf-zlib" {= "1"} - "core" {= "v0.17.1"} + "core" {= "v0.17.2"} "core_kernel" {= "v0.17.0"} "core_unix" {= "v0.17.1"} "cppo" {= "1.8.0"} @@ -51,12 +53,12 @@ depends: [ "csexp" {= "1.5.2"} "ctypes" {= "0.24.0"} "ctypes-foreign" {= "0.24.0"} - "dot-merlin-reader" {= "5.6.1-504"} - "dune" {= "3.21.0"} - "dune-build-info" {= "3.21.0"} - "dune-configurator" {= "3.21.0"} - "dune-rpc" {= "3.21.0"} - "dyn" {= "3.21.0"} + "dot-merlin-reader" {= "5.7.1-504"} + "dune" {= "3.22.2"} + "dune-build-info" {= "3.22.2"} + "dune-configurator" {= "3.22.2"} + "dune-rpc" {= "3.22.2"} + "dyn" {= "3.22.2"} "easy-format" {= "1.3.4"} "either" {= "1.0.0"} "expect_test_helpers_core" {= "v0.17.0"} @@ -66,56 +68,57 @@ depends: [ "fix" {= "20250919"} "fmt" {= "0.11.0"} "fpath" {= "0.7.3"} - "fs-io" {= "3.21.0"} + "fs-io" {= "3.22.2"} "gel" {= "v0.17.0"} "gen" {= "1.1"} "ISO8601" {= "0.2.6"} "int_repr" {= "v0.17.0"} "integers" {= "0.7.0"} "jane-street-headers" {= "v0.17.0"} - "js_of_ocaml" {= "6.2.0"} - "js_of_ocaml-compiler" {= "6.2.0"} - "js_of_ocaml-ppx" {= "6.2.0"} - "jsonrpc" {= "1.25.0"} + "js_of_ocaml" {= "6.3.2"} + "js_of_ocaml-compiler" {= "6.3.2"} + "js_of_ocaml-ppx" {= "6.3.2"} + "jsonrpc" {= "1.26.0"} "jst-config" {= "v0.17.0"} "logs" {= "0.10.0"} - "lsp" {= "1.25.0"} - "lwt" {= "6.1.0"} + "lsp" {= "1.26.0"} + "lwt" {= "6.1.2"} "memprof-limits" {= "0.3.0"} "memtrace" {= "0.2.3"} - "menhir" {= "20260122"} - "menhirCST" {= "20260122"} - "menhirGLR" {= "20260122"} - "menhirLib" {= "20260122"} - "menhirSdk" {= "20260122"} - "merlin" {= "5.6.1-504"} - "merlin-lib" {= "5.6.1-504"} + "menhir" {= "20260209"} + "menhirCST" {= "20260209"} + "menhirGLR" {= "20260209"} + "menhirLib" {= "20260209"} + "menhirSdk" {= "20260209"} + "merlin" {= "5.7.1-504"} + "merlin-lib" {= "5.7.1-504"} "mtime" {= "2.1.0"} "num" {= "1.6"} - "ocaml" {= "5.4.0"} - "ocaml-compiler" {= "5.4.0"} + "ocaml" {= "5.4.1"} + "ocaml-compiler" {= "5.4.1"} "ocaml-compiler-libs" {= "v0.17.0"} "ocaml-config" {= "3"} - "ocaml-index" {= "5.6.1-504"} - "ocaml-lsp-server" {= "1.25.0"} + "ocaml-index" {= "5.7.1-504"} + "ocaml-lsp-server" {= "1.26.0"} "ocaml-option-flambda" {= "1"} "ocaml-option-fp" {= "1" & (os = "linux" | os = "macos") & arch = "x86_64"} "ocaml-syntax-shims" {= "1.0.0"} - "ocaml-variants" {= "5.4.0+options"} - "ocaml-version" {= "4.0.3"} + "ocaml-variants" {= "5.4.1+options"} + "ocaml-version" {= "4.1.0"} "ocaml_intrinsics_kernel" {= "v0.17.1"} "ocamlbuild" {= "0.16.1"} - "ocamlc-loc" {= "3.21.0"} + "ocamlc-loc" {= "3.22.2"} "ocamlfind" {= "1.9.8"} - "ocamlformat" {= "0.28.1"} - "ocamlformat-lib" {= "0.28.1"} - "ocamlformat-rpc-lib" {= "0.28.1"} + "ocamlformat" {= "0.29.0"} + "ocamlformat-lib" {= "0.29.0"} + "ocamlformat-rpc-lib" {= "0.29.0"} + "ocamlgraph" {= "2.2.0"} "ocp-indent" {= "1.9.0"} "ocplib-endian" {= "1.2"} "octavius" {= "1.2.2"} "odoc" {= "3.1.0"} "odoc-parser" {= "3.1.0"} - "ordering" {= "3.21.0"} + "ordering" {= "3.22.2"} "parsexp" {= "v0.17.0"} "patdiff" {= "v0.17.0"} "patience_diff" {= "v0.17.0"} @@ -162,7 +165,7 @@ depends: [ "ppx_variants_conv" {= "v0.17.1"} "ppx_yojson_conv" {= "v0.17.1"} "ppx_yojson_conv_lib" {= "v0.17.0"} - "ppxlib" {= "0.37.0"} + "ppxlib" {= "0.38.0"} "ppxlib_jane" {= "v0.17.4"} "ptime" {= "1.2.0"} "ptmap" {= "2.0.5"} @@ -179,12 +182,12 @@ depends: [ "splittable_random" {= "v0.17.0"} "stdio" {= "v0.17.0"} "stdlib-shims" {= "0.3.0"} - "stdune" {= "3.21.0"} + "stdune" {= "3.22.2"} "stringext" {= "1.6.0"} "time_now" {= "v0.17.0"} "timezone" {= "v0.17.0"} "toml" {= "7.1.0"} - "top-closure" {= "3.21.0"} + "top-closure" {= "3.22.2"} "topkg" {= "1.1.1"} "typerep" {= "v0.17.1"} "tyxml" {= "4.6.0"} @@ -194,10 +197,9 @@ depends: [ "uuseg" {= "17.0.0"} "uutf" {= "1.0.4"} "variantslib" {= "v0.17.0"} - "xdg" {= "3.21.0"} + "xdg" {= "3.22.2"} "yaml" {= "3.2.0"} "yojson" {= "3.0.0"} "zarith" {= "1.14"} "zarith_stubs_js" {= "v0.17.0"} ] -build: []