Dune 2.4.0 has a new describe command for extracting various
information about a dune project or workspace in a stable and machine
readable format. The goal is to allow third-party applications such as
the trustworthy refactoring tool rotor to understand the
topology of a dune workspace, locate various compilation artifacts and
other things.
At the time of writing this post, the query language accepted by this
command and its output are not yet stabilised. We plan to stabilise it
once someone wants to release a application that relies on dune
describe.
In the future, we also plan to add a nice human readable output allowing users to quickly understand what a dune project is about and what it has to offer.
Usage
$ dune describe [--lang VERSION] [--format FORMAT] WHAT-TO-DESCRIBE
Passing --lang x.y requests that dune behaves the same way as
version x.y of the dune binary, no matter its current
version. More precisely, the two promises we make are:
- that
WHAT-TO-DESCRIBEwill be parsed in the same way as the versionx.yof thedunebinary - the output of this command will be the same as the version
x.yof thedunebinary
Right now, the only version you can pass to --lang is 0.1. The “0.”
suffix means that the behavior is not yet stabilised and might change
without notice in future minor releases or even bugfix releases of
Dune. Once either rotor or another project is ready to make a stable
release of a tool relying of dune describe, we’ll stabilise this
output. So if you plan on using this feature, please let us know!
If you intend to parse the output of dune describe programmatically,
then you should also pass --format csexp. This will cause dune to
print the result as a S-expression in canonical
form. You can then use the csexp library to
parse the output and use something like ppx_sexp_conv
to parse the result without hassle.
Example
# #require "csexp";;
# #require "ppx_sexp_conv";;
# #require "base";;
# open Base;;
# module Csexp = Csexp.Make(Sexp);;
module Csexp :
sig
val parse_string : string -> (Sexp.t, int * string) result
val parse_string_many : string -> (Sexp.t list, int * string) result
val input : in_channel -> (Sexp.t, string) result
val input_opt : in_channel -> (Sexp.t option, string) result
val input_many : in_channel -> (Sexp.t list, string) result
val serialised_length : Sexp.t -> int
val to_string : Sexp.t -> string
val to_buffer : Buffer.t -> Sexp.t -> unit
val to_channel : out_channel -> Sexp.t -> unit
end
# type item = Library of library
and library =
{ name : string
; uid : uid
; requires : uid list
; source_dir : string
; modules : module_ list
}
and uid = string
and module_ =
{ name : string
; impl : string option
; intf : string option
; cmt : string option
; cmti : string option
}
[@@deriving of_sexp];;
type item = Library of library
and library = {
name : string;
uid : uid;
requires : uid list;
source_dir : string;
modules : module_ list;
}
and uid = string
and module_ = {
name : string;
impl : string option;
intf : string option;
cmt : string option;
cmti : string option;
}
val item_of_sexp : Sexp.t -> item = <fun>
val library_of_sexp : Sexp.t -> library = <fun>
val uid_of_sexp : Sexp.t -> uid = <fun>
val module__of_sexp : Sexp.t -> module_ = <fun>
# Stdlib.Sys.command "dune describe --format csexp > /tmp/x";;
- : int = 0
# match Csexp.input (Stdlib.open_in "/tmp/x") with
| Ok x -> [%of_sexp: item list] x
| Error msg -> failwith msg;;
- : item list =
[Library
{name = "csexp"; uid = "2ac224c04fa61d226241d5394bcfc444"; requires = [];
source_dir = "_build/default/src";
modules =
[{name = "Csexp"; impl = Some "_build/default/src/csexp.ml";
intf = Some "_build/default/src/csexp.mli";
cmt = Some "_build/default/src/.csexp.objs/byte/csexp.cmt";
cmti = Some "_build/default/src/.csexp.objs/byte/csexp.cmti"}]};
Library
{name = "csexp_tests"; uid = "cae2600322b2b8a67c297c353294d54d";
requires =
["2ac224c04fa61d226241d5394bcfc444"; "a09aff04d7aac4201a8d17178505dc41";
"c31eace71b8050d2eaf1b2ac88be5a21"; "0004486e60e09317002ea3fc0f012c04";
"d785d8082259c31f19b0c9350988438d"];
source_dir = "_build/default/test";
modules =
[{name = "Test"; impl = Some "_build/default/test/test.ml";
intf = None;
cmt =
Some
"_build/default/test/.csexp_tests.objs/byte/csexp_tests__Test.cmt";
cmti = None};
{name = "Csexp_tests";
impl = Some "_build/default/test/csexp_tests.ml-gen";
intf = None;
cmt =
Some
"_build/default/test/.csexp_tests.objs/byte/csexp_tests.cmt";
cmti = None}]}]

