diff --git a/README.md b/README.md index 10bb07fc..8a45bdb4 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,8 @@ options available. To get the development version of the help, run `make help_cl after `make build`. The `clerk` binary corresponds to the Catala build system, responsible for testing among other things. +To get more information about Clerk, see [the dedicated readme](https://github.com/CatalaLang/catala/tree/master/build_system/README.md) + ## Documentation ### Syntax cheat sheet diff --git a/build_system/README.md b/build_system/README.md index 8b0e395f..13da9fe0 100644 --- a/build_system/README.md +++ b/build_system/README.md @@ -2,14 +2,12 @@ The build system for Catala built on top of [ninja](https://ninja-build.org/). -## Build - -* to build: `dune build` -* to run: `dune exec ./clerk.exe` - ## Usage -See the manpage -- accessible with `clerk --help`. +Use `clerk --help` if you have installed it to get more information about the command line +options available. To get the development version of the help, run `make help_clerk` +after `make build`. The `clerk` binary corresponds to the Catala build system, +responsible for testing among other things. ## Under the hood diff --git a/build_system/clerk.ml b/build_system/clerk.ml index 68ec8d6e..e0d66502 100644 --- a/build_system/clerk.ml +++ b/build_system/clerk.ml @@ -565,6 +565,12 @@ let collect_in_file (ctx : ninja_building_context) (tested_file : string) (ninja all_failed_names = tested_file :: ctx.all_failed_names; } +(** {1 Return code values} *) + +let return_ok = 0 + +let return_err = 1 + let driver (files_or_folders : string list) (command : string) (catala_exe : string option) (catala_opts : string option) (debug : bool) (scope : string option) (reset_test_outputs : bool) : int = @@ -597,7 +603,7 @@ let driver (files_or_folders : string list) (command : string) (catala_exe : str |> Printf.sprintf "No test case found for %s" |> Cli.warning_print) ctx.all_failed_names; - if 0 = List.compare_lengths ctx.all_failed_names files_or_folders then 0 + if 0 = List.compare_lengths ctx.all_failed_names files_or_folders then return_ok else let out = open_out "build.ninja" in Cli.debug_print "writing build.ninja..."; @@ -613,7 +619,7 @@ let driver (files_or_folders : string list) (command : string) (catala_exe : str (fun ret f -> ret + run_file f catala_exe catala_opts scope) 0 files_or_folders in - if 0 <> res then 1 else 0 + if 0 <> res then return_err else return_ok | None -> Cli.error_print "Please provide a scope to run with the -s option"; 1) diff --git a/build_system/dune b/build_system/dune index 561ea92d..4b7c6845 100644 --- a/build_system/dune +++ b/build_system/dune @@ -7,5 +7,6 @@ (library (name ninja_utils) + (public_name ninja_utils) (modules ninja_utils) (libraries re)) diff --git a/build_system/ninja_utils.ml b/build_system/ninja_utils.ml index 1beac38e..35bf5eef 100644 --- a/build_system/ninja_utils.ml +++ b/build_system/ninja_utils.ml @@ -13,7 +13,7 @@ the License. *) module Expr = struct - type t = Seq of t list | Lit of string | Var of string + type t = Lit of string | Var of string | Seq of t list let rec to_string = function | Lit s -> s @@ -54,7 +54,7 @@ module Build = struct let empty = make ~outputs:[ Expr.Lit "empty" ] ~rule:"phony" - let unpath path = Re.Pcre.(substitute ~rex:(regexp "/") ~subst:(fun _ -> "-")) path + let unpath ?(sep = "-") path = Re.Pcre.(substitute ~rex:(regexp "/") ~subst:(fun _ -> sep)) path let to_string build = Printf.sprintf "build %s: %s" (Expr.list_to_string build.outputs) build.rule diff --git a/build_system/ninja_utils.mli b/build_system/ninja_utils.mli index 7bbacd17..643799ca 100644 --- a/build_system/ninja_utils.mli +++ b/build_system/ninja_utils.mli @@ -12,19 +12,41 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** This library contains the implementations of utility functions used to generate {{: + https://ninja-build.org}Ninja} build files in OCaml with almost no dependencies -- it only + depends on {{: https://v3.ocaml.org/p/re/1.10.3/doc/Re/index.html}Re}. It's currently developed + to be used by {{: {https://github.com/CatalaLang/catala/tree/master/build_system}Clerk}, the {{: + https://catala-lang.org}Catala} build system. Therefore, the library {b supports only very basic + features} required by Clerk. *) + +(** {2 What is Ninja?} *) + +(** {{:https://ninja-build.org} Ninja} is a low-level build system. It's designed to have its input + files ({i build.ninja}) generated by a higher-level build system, and to run builds as fast as + possible by supporting native cross-platform (Windows and Unix) parallel builds. + + See the {{:https://ninja-build.org/manual.html} manual} for more details. *) + (** {1 Ninja expressions} *) (** Helper module to build ninja expressions. *) module Expr : sig - (** Represents a ninja expression. Which could be either a literal, a variable references ($_) or - a sequence of sub-expressions. *) + (** Represents a ninja expression. Which could be either a literal, a {{: + https://ninja-build.org/manual.html#_variables}variable references} ($_) or + a sequence of sub-expressions. + + {b Note:} for now, there are no visible differences between an [Expr.Seq] + and a list of {!type: Expr.t}, indeed, in both cases, one space is added + between each expression -- resp. sub-expression. The difference only comes from the semantic: + an [Expr.Seq] is {b a unique} Ninja expression. *) type t = - (* Sequence of sub-expressions. *) - | Seq of t list - (* Literal string. *) | Lit of string - (* Variable reference. *) + (* Literal string. *) | Var of string + (* Variable reference. *) + | Seq of t list + (* Sequence of sub-expressions. *) + val to_string : t -> string (** [to_string exp] returns the string representation of an ninja expression [exp]. *) @@ -36,21 +58,22 @@ end (** {1 Ninja rules} *) -(** Helper module to build ninja rules. *) +(** Helper module to build {{:https://ninja-build.org/manual.html#_rules}ninja rules}. *) module Rule : sig - (* NOTE: is name is really needed despite the use of Map? *) type t = { - (* Name of the rule: `rule `. *) name : string; - (* Command of the rule: ` command = . *) command : Expr.t; - (* Description of the rule: ` description = . *) description : Expr.t option; } - (** Represents the minimal ninja rule representation for clerk. *) + (** Represents the minimal ninja rule representation for Clerk: + {[ +rule + command = + [description = ] + ]} *) val make : string -> command:Expr.t -> description:Expr.t -> t - (** [make name ~command ~description] returns the corresponding ninja rule [Rule.t]. *) + (** [make name ~command ~description] returns the corresponding ninja {!type: Rule.t}. *) val to_string : t -> string (** [to_string rule] returns the string representation of the [rule]. *) @@ -58,33 +81,40 @@ end (** {1 Ninja builds} *) -(** Helper module to build ninja build statements. *) +(** Helper module to build ninja {{: https://ninja-build.org/manual.html#_build_statements}build statements}. *) module Build : sig type t = { outputs : Expr.t list; - (* NOTE: what's the difference between [Expr.t list] and [Expr.Seq]? => [Expr.Seq] is a unique - expression with possible variable references => no space in its string representation. *) rule : string; inputs : Expr.t list option; vars : (string * Expr.t) list; } - (** @note Currently, nothing nothing forces to build valid {!: Expr.t} for the variables. *) + (** Represents the minimal ninja build statement representation for Clerk: + {[ +build : [] + [] + ]}*) val make : outputs:Expr.t list -> rule:string -> t + (** [make ~outputs ~rule] returns the corresponding ninja {!type: Build.t} with no {!field: inputs} + or {!field: vars}. *) val make_with_vars : outputs:Expr.t list -> rule:string -> vars:(string * Expr.t) list -> t + (** [make_with_vars ~outputs ~rule ~vars] returns the corresponding ninja {!type: Build.t} with no {!field: inputs}. *) val make_with_inputs : outputs:Expr.t list -> rule:string -> inputs:Expr.t list -> t + (** [make_with_vars ~outputs ~rule ~inputs] returns the corresponding ninja {!type: Build.t} with no {!field: vars}. *) val make_with_vars_and_inputs : outputs:Expr.t list -> rule:string -> inputs:Expr.t list -> vars:(string * Expr.t) list -> t + (** [make_with_vars ~outputs ~rule ~inputs ~vars] returns the corresponding ninja {!type: Build.t}. *) val empty : t - (** [empty] is the minimal ninja build. *) + (** [empty] is the minimal ninja {!type: Build.t} with ["empty"] as {!field: outputs} and ["phony"] as {!field: rule}. *) - val unpath : string -> string - (** [unpath path] replaces all '/' occurences with '-' in [path] to avoid ninja writing the - corresponding file. *) + val unpath : ?sep:string -> string -> string + (** [unpath ~sep path] replaces all [/] occurences with [sep] in [path] to avoid ninja writing the + corresponding file and use it as sub command. By default, [sep] is set to ["-"]. *) val to_string : t -> string end @@ -98,7 +128,7 @@ module BuildMap : Map.S with type key = String.t (** {1 Ninja} *) type ninja = { rules : Rule.t RuleMap.t; builds : Build.t BuildMap.t } -(** Represents the minimal ninja architectures (list of rule and build statements) needed for clerk. *) +(** Represents the minimal ninja architecture (list of rule and build statements) needed for clerk. *) val empty : ninja (** [empty] returns the empty empty ninja structure. *)