From 882b18d9af6e58e2c9489df61ea35197a32bfece Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Thu, 16 Apr 2026 19:28:00 +0200 Subject: [PATCH 1/8] chore: tweak skylabs-deps.opam to be closer to lockfile --- dev/opam-deps/skylabs-deps.opam | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/opam-deps/skylabs-deps.opam b/dev/opam-deps/skylabs-deps.opam index 7bf61941..bdfcb657 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 " @@ -200,4 +202,3 @@ depends: [ "zarith" {= "1.14"} "zarith_stubs_js" {= "v0.17.0"} ] -build: [] From 941a220afed20f53eaa1da872ab11b1ef230e594 Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Thu, 16 Apr 2026 16:50:36 +0200 Subject: [PATCH 2/8] chore skylabs-deps.opam: Remove all "simple" version constraints Goal: let opam pick new versions. Implementation: `s/ \{[^|&]*$//` regexp. --- dev/opam-deps/skylabs-deps.opam | 370 ++++++++++++++++---------------- 1 file changed, 185 insertions(+), 185 deletions(-) diff --git a/dev/opam-deps/skylabs-deps.opam b/dev/opam-deps/skylabs-deps.opam index bdfcb657..06c00338 100644 --- a/dev/opam-deps/skylabs-deps.opam +++ b/dev/opam-deps/skylabs-deps.opam @@ -14,191 +14,191 @@ license: "LGPL-2.1-only" homepage: "https://github.com/SkylabsAI/fm-ci" 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"} - "base" {= "v0.17.3"} - "base-bigarray" {= "base"} - "base-bytes" {= "base"} - "base-domains" {= "base"} - "base-effects" {= "base"} - "base-nnp" {= "base"} - "base-threads" {= "base"} - "base-unix" {= "base"} - "base_bigstring" {= "v0.17.0"} - "base_quickcheck" {= "v0.17.1"} - "bheap" {= "2.0.0"} - "bigstringaf" {= "0.10.0"} - "bin_prot" {= "v0.17.0-1"} - "biniou" {= "1.2.2"} - "bos" {= "0.2.1"} - "camlp-streams" {= "5.0.1"} - "camlzip" {= "1.13"} - "capitalization" {= "v0.17.0"} - "chrome-trace" {= "3.21.0"} - "cmdliner" {= "2.1.0"} - "conf-gmp" {= "5"} - "conf-libffi" {= "2.0.0"} + "angstrom" + "astring" + "atd" + "atdgen" + "atdgen-runtime" + "atdts" + "base" + "base-bigarray" + "base-bytes" + "base-domains" + "base-effects" + "base-nnp" + "base-threads" + "base-unix" + "base_bigstring" + "base_quickcheck" + "bheap" + "bigstringaf" + "bin_prot" + "biniou" + "bos" + "camlp-streams" + "camlzip" + "capitalization" + "chrome-trace" + "cmdliner" + "conf-gmp" + "conf-libffi" "conf-linux-libc-dev" {= "0" & os = "linux"} - "conf-pkg-config" {= "4"} - "conf-zlib" {= "1"} - "core" {= "v0.17.1"} - "core_kernel" {= "v0.17.0"} - "core_unix" {= "v0.17.1"} - "cppo" {= "1.8.0"} - "crunch" {= "4.0.0"} - "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"} - "easy-format" {= "1.3.4"} - "either" {= "1.0.0"} - "expect_test_helpers_core" {= "v0.17.0"} - "fiber" {= "3.7.0"} - "fieldslib" {= "v0.17.0"} - "fileutils" {= "0.6.6"} - "fix" {= "20250919"} - "fmt" {= "0.11.0"} - "fpath" {= "0.7.3"} - "fs-io" {= "3.21.0"} - "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"} - "jst-config" {= "v0.17.0"} - "logs" {= "0.10.0"} - "lsp" {= "1.25.0"} - "lwt" {= "6.1.0"} - "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"} - "mtime" {= "2.1.0"} - "num" {= "1.6"} - "ocaml" {= "5.4.0"} - "ocaml-compiler" {= "5.4.0"} - "ocaml-compiler-libs" {= "v0.17.0"} - "ocaml-config" {= "3"} - "ocaml-index" {= "5.6.1-504"} - "ocaml-lsp-server" {= "1.25.0"} - "ocaml-option-flambda" {= "1"} + "conf-pkg-config" + "conf-zlib" + "core" + "core_kernel" + "core_unix" + "cppo" + "crunch" + "csexp" + "ctypes" + "ctypes-foreign" + "dot-merlin-reader" + "dune" + "dune-build-info" + "dune-configurator" + "dune-rpc" + "dyn" + "easy-format" + "either" + "expect_test_helpers_core" + "fiber" + "fieldslib" + "fileutils" + "fix" + "fmt" + "fpath" + "fs-io" + "gel" + "gen" + "ISO8601" + "int_repr" + "integers" + "jane-street-headers" + "js_of_ocaml" + "js_of_ocaml-compiler" + "js_of_ocaml-ppx" + "jsonrpc" + "jst-config" + "logs" + "lsp" + "lwt" + "memprof-limits" + "memtrace" + "menhir" + "menhirCST" + "menhirGLR" + "menhirLib" + "menhirSdk" + "merlin" + "merlin-lib" + "mtime" + "num" + "ocaml" + "ocaml-compiler" + "ocaml-compiler-libs" + "ocaml-config" + "ocaml-index" + "ocaml-lsp-server" + "ocaml-option-flambda" "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_intrinsics_kernel" {= "v0.17.1"} - "ocamlbuild" {= "0.16.1"} - "ocamlc-loc" {= "3.21.0"} - "ocamlfind" {= "1.9.8"} - "ocamlformat" {= "0.28.1"} - "ocamlformat-lib" {= "0.28.1"} - "ocamlformat-rpc-lib" {= "0.28.1"} - "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"} - "parsexp" {= "v0.17.0"} - "patdiff" {= "v0.17.0"} - "patience_diff" {= "v0.17.0"} - "pp" {= "2.0.0"} - "ppx_assert" {= "v0.17.0"} - "ppx_base" {= "v0.17.0"} - "ppx_bench" {= "v0.17.1"} - "ppx_bin_prot" {= "v0.17.1"} - "ppx_cold" {= "v0.17.0"} - "ppx_compare" {= "v0.17.0"} - "ppx_custom_printf" {= "v0.17.0"} - "ppx_derivers" {= "1.2.1"} - "ppx_deriving" {= "6.1.1"} - "ppx_deriving_yojson" {= "3.10.0"} - "ppx_diff" {= "v0.17.1"} - "ppx_disable_unused_warnings" {= "v0.17.0"} - "ppx_enumerate" {= "v0.17.0"} - "ppx_expect" {= "v0.17.3"} - "ppx_fields_conv" {= "v0.17.0"} - "ppx_fixed_literal" {= "v0.17.0"} - "ppx_globalize" {= "v0.17.2"} - "ppx_hash" {= "v0.17.0"} - "ppx_here" {= "v0.17.0"} - "ppx_ignore_instrumentation" {= "v0.17.0"} - "ppx_import" {= "1.12.0"} - "ppx_inline_test" {= "v0.17.1"} - "ppx_jane" {= "v0.17.0"} - "ppx_js_style" {= "v0.17.1"} - "ppx_let" {= "v0.17.1"} - "ppx_log" {= "v0.17.0"} - "ppx_module_timer" {= "v0.17.0"} - "ppx_optcomp" {= "v0.17.1"} - "ppx_optional" {= "v0.17.0"} - "ppx_pipebang" {= "v0.17.0"} - "ppx_sexp_conv" {= "v0.17.1"} - "ppx_sexp_message" {= "v0.17.0"} - "ppx_sexp_value" {= "v0.17.0"} - "ppx_stable" {= "v0.17.1"} - "ppx_stable_witness" {= "v0.17.0"} - "ppx_string" {= "v0.17.0"} - "ppx_string_conv" {= "v0.17.0"} - "ppx_tydi" {= "v0.17.1"} - "ppx_typerep_conv" {= "v0.17.1"} - "ppx_variants_conv" {= "v0.17.1"} - "ppx_yojson_conv" {= "v0.17.1"} - "ppx_yojson_conv_lib" {= "v0.17.0"} - "ppxlib" {= "0.37.0"} - "ppxlib_jane" {= "v0.17.4"} - "ptime" {= "1.2.0"} - "ptmap" {= "2.0.5"} - "ptset" {= "1.0.1"} - "re" {= "1.14.0"} - "rresult" {= "0.7.0"} - "sedlex" {= "3.7"} - "sel" {= "0.8.0"} - "seq" {= "base"} - "sexp_pretty" {= "v0.17.0"} - "sexplib" {= "v0.17.0"} - "sexplib0" {= "v0.17.0"} - "spawn" {= "v0.17.0"} - "splittable_random" {= "v0.17.0"} - "stdio" {= "v0.17.0"} - "stdlib-shims" {= "0.3.0"} - "stdune" {= "3.21.0"} - "stringext" {= "1.6.0"} - "time_now" {= "v0.17.0"} - "timezone" {= "v0.17.0"} - "toml" {= "7.1.0"} - "top-closure" {= "3.21.0"} - "topkg" {= "1.1.1"} - "typerep" {= "v0.17.1"} - "tyxml" {= "4.6.0"} - "uopt" {= "v0.17.0"} - "uri" {= "4.4.0"} - "uucp" {= "17.0.0"} - "uuseg" {= "17.0.0"} - "uutf" {= "1.0.4"} - "variantslib" {= "v0.17.0"} - "xdg" {= "3.21.0"} - "yaml" {= "3.2.0"} - "yojson" {= "3.0.0"} - "zarith" {= "1.14"} - "zarith_stubs_js" {= "v0.17.0"} + "ocaml-syntax-shims" + "ocaml-variants" + "ocaml-version" + "ocaml_intrinsics_kernel" + "ocamlbuild" + "ocamlc-loc" + "ocamlfind" + "ocamlformat" + "ocamlformat-lib" + "ocamlformat-rpc-lib" + "ocp-indent" + "ocplib-endian" + "octavius" + "odoc" + "odoc-parser" + "ordering" + "parsexp" + "patdiff" + "patience_diff" + "pp" + "ppx_assert" + "ppx_base" + "ppx_bench" + "ppx_bin_prot" + "ppx_cold" + "ppx_compare" + "ppx_custom_printf" + "ppx_derivers" + "ppx_deriving" + "ppx_deriving_yojson" + "ppx_diff" + "ppx_disable_unused_warnings" + "ppx_enumerate" + "ppx_expect" + "ppx_fields_conv" + "ppx_fixed_literal" + "ppx_globalize" + "ppx_hash" + "ppx_here" + "ppx_ignore_instrumentation" + "ppx_import" + "ppx_inline_test" + "ppx_jane" + "ppx_js_style" + "ppx_let" + "ppx_log" + "ppx_module_timer" + "ppx_optcomp" + "ppx_optional" + "ppx_pipebang" + "ppx_sexp_conv" + "ppx_sexp_message" + "ppx_sexp_value" + "ppx_stable" + "ppx_stable_witness" + "ppx_string" + "ppx_string_conv" + "ppx_tydi" + "ppx_typerep_conv" + "ppx_variants_conv" + "ppx_yojson_conv" + "ppx_yojson_conv_lib" + "ppxlib" + "ppxlib_jane" + "ptime" + "ptmap" + "ptset" + "re" + "rresult" + "sedlex" + "sel" + "seq" + "sexp_pretty" + "sexplib" + "sexplib0" + "spawn" + "splittable_random" + "stdio" + "stdlib-shims" + "stdune" + "stringext" + "time_now" + "timezone" + "toml" + "top-closure" + "topkg" + "typerep" + "tyxml" + "uopt" + "uri" + "uucp" + "uuseg" + "uutf" + "variantslib" + "xdg" + "yaml" + "yojson" + "zarith" + "zarith_stubs_js" ] From 0c75d5718a709af0daa291f3453daee0cf928551 Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Thu, 16 Apr 2026 18:05:00 +0200 Subject: [PATCH 3/8] chore skylabs-deps.opam: Pin ocaml compiler Because `opam install ../skylabs-deps.opam` doesn't pick the latest compiler. --- dev/opam-deps/skylabs-deps.opam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/opam-deps/skylabs-deps.opam b/dev/opam-deps/skylabs-deps.opam index 06c00338..cdce242e 100644 --- a/dev/opam-deps/skylabs-deps.opam +++ b/dev/opam-deps/skylabs-deps.opam @@ -94,7 +94,7 @@ depends: [ "merlin-lib" "mtime" "num" - "ocaml" + "ocaml" {= "5.4.1"} "ocaml-compiler" "ocaml-compiler-libs" "ocaml-config" From bcc4cacad9291d75490b18baddabbf56f753466a Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Thu, 16 Apr 2026 19:35:40 +0200 Subject: [PATCH 4/8] chore: pin deps in skylabs-deps.opam again based on lockfile This is based on the output of ``` opam install -y dev/opam-deps/skylabs-deps.opam -j5 && opam lock skylabs-deps ``` I readded conf-linux-libc-dev and ocaml-option-fp by hand. --- dev/opam-deps/skylabs-deps.opam | 368 ++++++++++++++++---------------- 1 file changed, 184 insertions(+), 184 deletions(-) diff --git a/dev/opam-deps/skylabs-deps.opam b/dev/opam-deps/skylabs-deps.opam index cdce242e..b20bbdc4 100644 --- a/dev/opam-deps/skylabs-deps.opam +++ b/dev/opam-deps/skylabs-deps.opam @@ -14,191 +14,191 @@ license: "LGPL-2.1-only" homepage: "https://github.com/SkylabsAI/fm-ci" bug-reports: "https://github.com/SkylabsAI/fm-ci/issues" depends: [ - "angstrom" - "astring" - "atd" - "atdgen" - "atdgen-runtime" - "atdts" - "base" - "base-bigarray" - "base-bytes" - "base-domains" - "base-effects" - "base-nnp" - "base-threads" - "base-unix" - "base_bigstring" - "base_quickcheck" - "bheap" - "bigstringaf" - "bin_prot" - "biniou" - "bos" - "camlp-streams" - "camlzip" - "capitalization" - "chrome-trace" - "cmdliner" - "conf-gmp" - "conf-libffi" + "angstrom" {= "0.16.1"} + "astring" {= "0.8.5"} + "atd" {= "4.1.0"} + "atdgen" {= "4.1.0"} + "atdgen-runtime" {= "4.1.0"} + "atdts" {= "4.1.0"} + "base" {= "v0.17.3"} + "base-bigarray" {= "base"} + "base-bytes" {= "base"} + "base-domains" {= "base"} + "base-effects" {= "base"} + "base-nnp" {= "base"} + "base-threads" {= "base"} + "base-unix" {= "base"} + "base_bigstring" {= "v0.17.0"} + "base_quickcheck" {= "v0.17.1"} + "bheap" {= "2.0.0"} + "bigstringaf" {= "0.10.0"} + "bin_prot" {= "v0.17.0-1"} + "biniou" {= "1.2.2"} + "bos" {= "0.2.1"} + "camlp-streams" {= "5.0.1"} + "camlzip" {= "1.14"} + "capitalization" {= "v0.17.0"} + "chrome-trace" {= "3.22.2"} + "cmdliner" {= "2.1.0"} + "conf-gmp" {= "5"} + "conf-libffi" {= "2.0.0"} "conf-linux-libc-dev" {= "0" & os = "linux"} - "conf-pkg-config" - "conf-zlib" - "core" - "core_kernel" - "core_unix" - "cppo" - "crunch" - "csexp" - "ctypes" - "ctypes-foreign" - "dot-merlin-reader" - "dune" - "dune-build-info" - "dune-configurator" - "dune-rpc" - "dyn" - "easy-format" - "either" - "expect_test_helpers_core" - "fiber" - "fieldslib" - "fileutils" - "fix" - "fmt" - "fpath" - "fs-io" - "gel" - "gen" - "ISO8601" - "int_repr" - "integers" - "jane-street-headers" - "js_of_ocaml" - "js_of_ocaml-compiler" - "js_of_ocaml-ppx" - "jsonrpc" - "jst-config" - "logs" - "lsp" - "lwt" - "memprof-limits" - "memtrace" - "menhir" - "menhirCST" - "menhirGLR" - "menhirLib" - "menhirSdk" - "merlin" - "merlin-lib" - "mtime" - "num" + "conf-pkg-config" {= "4"} + "conf-zlib" {= "1"} + "core" {= "v0.17.2"} + "core_kernel" {= "v0.17.0"} + "core_unix" {= "v0.17.1"} + "cppo" {= "1.8.0"} + "crunch" {= "4.0.0"} + "csexp" {= "1.5.2"} + "ctypes" {= "0.24.0"} + "ctypes-foreign" {= "0.24.0"} + "dot-merlin-reader" {= "5.7.0-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"} + "fiber" {= "3.7.0"} + "fieldslib" {= "v0.17.0"} + "fileutils" {= "0.6.6"} + "fix" {= "20250919"} + "fmt" {= "0.11.0"} + "fpath" {= "0.7.3"} + "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.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.26.0"} + "lwt" {= "6.1.1"} + "memprof-limits" {= "0.3.0"} + "memtrace" {= "0.2.3"} + "menhir" {= "20260209"} + "menhirCST" {= "20260209"} + "menhirGLR" {= "20260209"} + "menhirLib" {= "20260209"} + "menhirSdk" {= "20260209"} + "merlin" {= "5.7.0-504"} + "merlin-lib" {= "5.7.0-504"} + "mtime" {= "2.1.0"} + "num" {= "1.6"} "ocaml" {= "5.4.1"} - "ocaml-compiler" - "ocaml-compiler-libs" - "ocaml-config" - "ocaml-index" - "ocaml-lsp-server" - "ocaml-option-flambda" + "ocaml-compiler" {= "5.4.1"} + "ocaml-compiler-libs" {= "v0.17.0"} + "ocaml-config" {= "3"} + "ocaml-index" {= "5.7.0-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" - "ocaml-variants" - "ocaml-version" - "ocaml_intrinsics_kernel" - "ocamlbuild" - "ocamlc-loc" - "ocamlfind" - "ocamlformat" - "ocamlformat-lib" - "ocamlformat-rpc-lib" - "ocp-indent" - "ocplib-endian" - "octavius" - "odoc" - "odoc-parser" - "ordering" - "parsexp" - "patdiff" - "patience_diff" - "pp" - "ppx_assert" - "ppx_base" - "ppx_bench" - "ppx_bin_prot" - "ppx_cold" - "ppx_compare" - "ppx_custom_printf" - "ppx_derivers" - "ppx_deriving" - "ppx_deriving_yojson" - "ppx_diff" - "ppx_disable_unused_warnings" - "ppx_enumerate" - "ppx_expect" - "ppx_fields_conv" - "ppx_fixed_literal" - "ppx_globalize" - "ppx_hash" - "ppx_here" - "ppx_ignore_instrumentation" - "ppx_import" - "ppx_inline_test" - "ppx_jane" - "ppx_js_style" - "ppx_let" - "ppx_log" - "ppx_module_timer" - "ppx_optcomp" - "ppx_optional" - "ppx_pipebang" - "ppx_sexp_conv" - "ppx_sexp_message" - "ppx_sexp_value" - "ppx_stable" - "ppx_stable_witness" - "ppx_string" - "ppx_string_conv" - "ppx_tydi" - "ppx_typerep_conv" - "ppx_variants_conv" - "ppx_yojson_conv" - "ppx_yojson_conv_lib" - "ppxlib" - "ppxlib_jane" - "ptime" - "ptmap" - "ptset" - "re" - "rresult" - "sedlex" - "sel" - "seq" - "sexp_pretty" - "sexplib" - "sexplib0" - "spawn" - "splittable_random" - "stdio" - "stdlib-shims" - "stdune" - "stringext" - "time_now" - "timezone" - "toml" - "top-closure" - "topkg" - "typerep" - "tyxml" - "uopt" - "uri" - "uucp" - "uuseg" - "uutf" - "variantslib" - "xdg" - "yaml" - "yojson" - "zarith" - "zarith_stubs_js" + "ocaml-syntax-shims" {= "1.0.0"} + "ocaml-variants" {= "5.4.1+options"} + "ocaml-version" {= "4.0.4"} + "ocaml_intrinsics_kernel" {= "v0.17.1"} + "ocamlbuild" {= "0.16.1"} + "ocamlc-loc" {= "3.22.2"} + "ocamlfind" {= "1.9.8"} + "ocamlformat" {= "0.29.0"} + "ocamlformat-lib" {= "0.29.0"} + "ocamlformat-rpc-lib" {= "0.29.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.22.2"} + "parsexp" {= "v0.17.0"} + "patdiff" {= "v0.17.0"} + "patience_diff" {= "v0.17.0"} + "pp" {= "2.0.0"} + "ppx_assert" {= "v0.17.0"} + "ppx_base" {= "v0.17.0"} + "ppx_bench" {= "v0.17.1"} + "ppx_bin_prot" {= "v0.17.1"} + "ppx_cold" {= "v0.17.0"} + "ppx_compare" {= "v0.17.0"} + "ppx_custom_printf" {= "v0.17.0"} + "ppx_derivers" {= "1.2.1"} + "ppx_deriving" {= "6.1.1"} + "ppx_deriving_yojson" {= "3.10.0"} + "ppx_diff" {= "v0.17.1"} + "ppx_disable_unused_warnings" {= "v0.17.0"} + "ppx_enumerate" {= "v0.17.0"} + "ppx_expect" {= "v0.17.3"} + "ppx_fields_conv" {= "v0.17.0"} + "ppx_fixed_literal" {= "v0.17.0"} + "ppx_globalize" {= "v0.17.2"} + "ppx_hash" {= "v0.17.0"} + "ppx_here" {= "v0.17.0"} + "ppx_ignore_instrumentation" {= "v0.17.0"} + "ppx_import" {= "1.12.0"} + "ppx_inline_test" {= "v0.17.1"} + "ppx_jane" {= "v0.17.0"} + "ppx_js_style" {= "v0.17.1"} + "ppx_let" {= "v0.17.1"} + "ppx_log" {= "v0.17.0"} + "ppx_module_timer" {= "v0.17.0"} + "ppx_optcomp" {= "v0.17.1"} + "ppx_optional" {= "v0.17.0"} + "ppx_pipebang" {= "v0.17.0"} + "ppx_sexp_conv" {= "v0.17.1"} + "ppx_sexp_message" {= "v0.17.0"} + "ppx_sexp_value" {= "v0.17.0"} + "ppx_stable" {= "v0.17.1"} + "ppx_stable_witness" {= "v0.17.0"} + "ppx_string" {= "v0.17.0"} + "ppx_string_conv" {= "v0.17.0"} + "ppx_tydi" {= "v0.17.1"} + "ppx_typerep_conv" {= "v0.17.1"} + "ppx_variants_conv" {= "v0.17.1"} + "ppx_yojson_conv" {= "v0.17.1"} + "ppx_yojson_conv_lib" {= "v0.17.0"} + "ppxlib" {= "0.38.0"} + "ppxlib_jane" {= "v0.17.4"} + "ptime" {= "1.2.0"} + "ptmap" {= "2.0.5"} + "ptset" {= "1.0.1"} + "re" {= "1.14.0"} + "rresult" {= "0.7.0"} + "sedlex" {= "3.7"} + "sel" {= "0.8.0"} + "seq" {= "base"} + "sexp_pretty" {= "v0.17.0"} + "sexplib" {= "v0.17.0"} + "sexplib0" {= "v0.17.0"} + "spawn" {= "v0.17.0"} + "splittable_random" {= "v0.17.0"} + "stdio" {= "v0.17.0"} + "stdlib-shims" {= "0.3.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.22.2"} + "topkg" {= "1.1.1"} + "typerep" {= "v0.17.1"} + "tyxml" {= "4.6.0"} + "uopt" {= "v0.17.0"} + "uri" {= "4.4.0"} + "uucp" {= "17.0.0"} + "uuseg" {= "17.0.0"} + "uutf" {= "1.0.4"} + "variantslib" {= "v0.17.0"} + "xdg" {= "3.22.2"} + "yaml" {= "3.2.0"} + "yojson" {= "3.0.0"} + "zarith" {= "1.14"} + "zarith_stubs_js" {= "v0.17.0"} ] From 2bada96bc1634655705deba1382f187dfd5ff9dd Mon Sep 17 00:00:00 2001 From: Rodolphe Lepigre Date: Mon, 4 May 2026 10:12:39 +0200 Subject: [PATCH 5/8] Bump a little bit more. --- dev/opam-deps/skylabs-deps.opam | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/dev/opam-deps/skylabs-deps.opam b/dev/opam-deps/skylabs-deps.opam index b20bbdc4..7e695796 100644 --- a/dev/opam-deps/skylabs-deps.opam +++ b/dev/opam-deps/skylabs-deps.opam @@ -16,10 +16,10 @@ bug-reports: "https://github.com/SkylabsAI/fm-ci/issues" depends: [ "angstrom" {= "0.16.1"} "astring" {= "0.8.5"} - "atd" {= "4.1.0"} - "atdgen" {= "4.1.0"} - "atdgen-runtime" {= "4.1.0"} - "atdts" {= "4.1.0"} + "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"} @@ -34,12 +34,12 @@ 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.14"} "capitalization" {= "v0.17.0"} "chrome-trace" {= "3.22.2"} - "cmdliner" {= "2.1.0"} + "cmdliner" {= "2.1.1"} "conf-gmp" {= "5"} "conf-libffi" {= "2.0.0"} "conf-linux-libc-dev" {= "0" & os = "linux"} @@ -53,7 +53,7 @@ depends: [ "csexp" {= "1.5.2"} "ctypes" {= "0.24.0"} "ctypes-foreign" {= "0.24.0"} - "dot-merlin-reader" {= "5.7.0-504"} + "dot-merlin-reader" {= "5.7.1-504"} "dune" {= "3.22.2"} "dune-build-info" {= "3.22.2"} "dune-configurator" {= "3.22.2"} @@ -82,7 +82,7 @@ depends: [ "jst-config" {= "v0.17.0"} "logs" {= "0.10.0"} "lsp" {= "1.26.0"} - "lwt" {= "6.1.1"} + "lwt" {= "6.1.2"} "memprof-limits" {= "0.3.0"} "memtrace" {= "0.2.3"} "menhir" {= "20260209"} @@ -90,21 +90,21 @@ depends: [ "menhirGLR" {= "20260209"} "menhirLib" {= "20260209"} "menhirSdk" {= "20260209"} - "merlin" {= "5.7.0-504"} - "merlin-lib" {= "5.7.0-504"} + "merlin" {= "5.7.1-504"} + "merlin-lib" {= "5.7.1-504"} "mtime" {= "2.1.0"} "num" {= "1.6"} "ocaml" {= "5.4.1"} "ocaml-compiler" {= "5.4.1"} "ocaml-compiler-libs" {= "v0.17.0"} "ocaml-config" {= "3"} - "ocaml-index" {= "5.7.0-504"} + "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.1+options"} - "ocaml-version" {= "4.0.4"} + "ocaml-version" {= "4.1.0"} "ocaml_intrinsics_kernel" {= "v0.17.1"} "ocamlbuild" {= "0.16.1"} "ocamlc-loc" {= "3.22.2"} From b8a8a121c3041ec9886e8c96f9672bb7d02d5c16 Mon Sep 17 00:00:00 2001 From: Rodolphe Lepigre Date: Tue, 5 May 2026 14:52:20 +0200 Subject: [PATCH 6/8] Add ocamlgraph dependency. --- dev/opam-deps/skylabs-deps.opam | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/opam-deps/skylabs-deps.opam b/dev/opam-deps/skylabs-deps.opam index 7e695796..56f79675 100644 --- a/dev/opam-deps/skylabs-deps.opam +++ b/dev/opam-deps/skylabs-deps.opam @@ -112,6 +112,7 @@ depends: [ "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"} From b36c8367b5895ddf52ef8b3a476f5ddc0bc00d0b Mon Sep 17 00:00:00 2001 From: Rodolphe Lepigre Date: Mon, 4 May 2026 18:07:04 +0200 Subject: [PATCH 7/8] Adapt [dune-named-logfile] to [trace.csexp]. The script now additionally extracts data to jsonl format, using the provided [dune trace cat] command. This contains strictly more data than what we used to collect with [dune-report]. --- .../dune-named-logfile/dune-named-logfile | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) 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 From d78be0697bb82aab4b9f19d1894681ed45c502ef Mon Sep 17 00:00:00 2001 From: Rodolphe Lepigre Date: Tue, 5 May 2026 14:43:35 +0200 Subject: [PATCH 8/8] Turn [dune-report] into [dune-commands]. --- dev/dune-tools/dune-commands/README.md | 13 ++ .../{dune-report => dune-commands}/dune | 0 .../dune-commands.opam} | 2 +- .../dune-project | 6 +- dev/dune-tools/dune-commands/src/dune | 6 + dev/dune-tools/dune-commands/src/dune_log.ml | 99 ++++++++++++++++ dev/dune-tools/dune-commands/src/dune_log.mli | 21 ++++ .../bin => dune-commands/src}/main.ml | 34 +++--- dev/dune-tools/dune-report/README.md | 6 - dev/dune-tools/dune-report/bin/dune | 5 - dev/dune-tools/dune-report/lib/dune | 6 - dev/dune-tools/dune-report/lib/dune_log.ml | 111 ------------------ dev/dune-tools/dune-report/lib/dune_log.mli | 25 ---- 13 files changed, 158 insertions(+), 176 deletions(-) create mode 100644 dev/dune-tools/dune-commands/README.md rename dev/dune-tools/{dune-report => dune-commands}/dune (100%) rename dev/dune-tools/{dune-report/dune-report.opam => dune-commands/dune-commands.opam} (91%) rename dev/dune-tools/{dune-report => dune-commands}/dune-project (73%) create mode 100644 dev/dune-tools/dune-commands/src/dune create mode 100644 dev/dune-tools/dune-commands/src/dune_log.ml create mode 100644 dev/dune-tools/dune-commands/src/dune_log.mli rename dev/dune-tools/{dune-report/bin => dune-commands/src}/main.ml (71%) delete mode 100644 dev/dune-tools/dune-report/README.md delete mode 100644 dev/dune-tools/dune-report/bin/dune delete mode 100644 dev/dune-tools/dune-report/lib/dune delete mode 100644 dev/dune-tools/dune-report/lib/dune_log.ml delete mode 100644 dev/dune-tools/dune-report/lib/dune_log.mli 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-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