-
Notifications
You must be signed in to change notification settings - Fork 81
/
signatures.mli
892 lines (741 loc) · 34.1 KB
/
signatures.mli
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
(***********************************************************************)
(* *)
(* ocamlbuild *)
(* *)
(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *)
(* *)
(* Copyright 2007 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed *)
(* under the terms of the GNU Library General Public License, with *)
(* the special exception on linking described in file ../LICENSE. *)
(* *)
(***********************************************************************)
(* Original author: Nicolas Pouillard *)
(** This module contains all module signatures that the user
could use to build an ocamlbuild plugin. *)
module type OrderedTypePrintable = sig
type t
val compare : t -> t -> int
val print : Format.formatter -> t -> unit
end
module type SET = sig
include Set.S
val find_elt : (elt -> bool) -> t -> elt
val map : (elt -> elt) -> t -> t
val of_list : elt list -> t
val print : Format.formatter -> t -> unit
end
module type LIST = sig
(* Added functions *)
val print : (Format.formatter -> 'a -> 'b) -> Format.formatter -> 'a list -> unit
val filter_opt : ('a -> 'b option) -> 'a list -> 'b list
val union : 'a list -> 'a list -> 'a list
val ordered_unique : 'a list -> 'a list
val index_of: 'a -> 'a list -> int option
(** give the offset of an element (0 for the first element) *)
val split_at: int -> 'a list -> 'a list * 'a list
(** split the list before the element at the given offset *)
(* Original functions *)
include module type of List
end
module type STRING = sig
val print : Format.formatter -> string -> unit
val chomp : string -> string
(** [before s n] returns the substring of all characters of [s]
that precede position [n] (excluding the character at
position [n]).
This is the same function as {!Str.string_before}. *)
val before : string -> int -> string
(** [after s n] returns the substring of all characters of [s]
that follow position [n] (including the character at
position [n]).
This is the same function as {!Str.string_after}. *)
val after : string -> int -> string
val first_chars : string -> int -> string
(** [first_chars s n] returns the first [n] characters of [s].
This is the same function as {!before} ant {!Str.first_chars}. *)
val last_chars : string -> int -> string
(** [last_chars s n] returns the last [n] characters of [s].
This is the same function as {!Str.last_chars}. *)
val eq_sub_strings : string -> int -> string -> int -> int -> bool
(** [is_prefix u v] is u a prefix of v ? *)
val is_prefix : string -> string -> bool
(** [is_suffix u v] : is v a suffix of u ? *)
val is_suffix : string -> string -> bool
(** [contains_string s1 p2 s2] Search in [s1] starting from [p1] if it
contains the [s2] string. Returns [Some position] where [position]
is the begining of the string [s2] in [s1], [None] otherwise. *)
val contains_string : string -> int -> string -> int option
(** [subst patt repl text] *)
val subst : string -> string -> string -> string
(** [tr patt repl text] *)
val tr : char -> char -> string -> string
val rev : string -> string
(* Convert a character list into a character string *)
val implode : char list -> string
(* Convert a character string into a character list *)
val explode : string -> char list
(** The following are original functions from the [String] module. *)
include module type of String
end
module type TAGS = sig
include Set.S with type elt = string
(** [Tags.elt] represents a tag, which is simply a string, usually
lowercase, for example "ocaml" or "native". The set of tags
attached to a file is computed by applying the tagging rules to
the filename. Tagging rules are defined in _tags files in any
parent directory of a file, up to the main project directory. *)
val of_list : string list -> t
val print : Format.formatter -> t -> unit
val does_match : t -> t -> bool
module Operators : sig
val ( ++ ) : t -> elt -> t
val ( -- ) : t -> elt -> t
val ( +++ ) : t -> elt option -> t
val ( --- ) : t -> elt option -> t
end
end
module type PATHNAME = sig
type t = string
val concat : t -> t -> t
val compare : t -> t -> int
val equal : t -> t -> bool
val exists : t -> bool
val mk : string -> t
val define_context : string -> string list -> unit
val include_dirs_of : string -> string list
val copy : t -> t -> unit
val to_string : t -> string
val print : Format.formatter -> t -> unit
val current_dir_name : t
val parent_dir_name : t
val read : t -> string
val same_contents : t -> t -> bool
val basename : t -> t
val dirname : t -> t
val is_relative : t -> bool
val readlink : t -> t
val readdir : t -> t array
val is_link : t -> bool
val is_directory : t -> bool
val add_extension : string -> t -> t
val check_extension : t -> string -> bool
val get_extension : t -> string
val remove_extension : t -> t
val update_extension : string -> t -> t
val get_extensions : t -> string
val remove_extensions : t -> t
val update_extensions : string -> t -> t
val print_path_list : Format.formatter -> t list -> unit
val pwd : t
val parent : t -> t
(** [is_prefix x y] is [x] a pathname prefix of [y] *)
val is_prefix : t -> t -> bool
val is_implicit : t -> bool
module Operators : sig
val ( / ) : t -> t -> t
val ( -.- ) : t -> string -> t
end
end
(** Provides an abstract type for easily building complex shell
commands without making quotation mistakes. *)
module type COMMAND = sig
type tags
type pathname
(** The type [t] provides some basic combinators and command primitives.
Other commands can be made of command specifications ([spec]). *)
type t =
| Seq of t list (** A sequence of commands (like the `;' in shell) *)
| Cmd of spec (** A command is made of command specifications ([spec]) *)
| Echo of string list * pathname
(** Write the given strings as is (newlines are not added) to the given file *)
| Nop (** The command that does nothing *)
(** The type for command specifications. That is pieces of command. *)
and spec =
| N (** No operation. *)
| S of spec list (** A sequence. This gets flattened in the last stages *)
| A of string (** An atom. *)
| P of pathname (** A pathname. *)
| Px of pathname (** A pathname, that will also be given to the
call_with_target hook. *)
| Sh of string (** A bit of raw shell code, that will not be escaped. *)
| T of tags (** A set of tags, that describe properties and
some semantics information about the
command, afterward these tags will be
replaced by command [spec]s (flags for
instance). *)
| V of string (** A virtual command, that will be resolved at
execution using [resolve_virtuals] *)
| Quote of spec (** A string that should be quoted like a
filename but isn't really one. *)
(*type v = [ `Seq of v list | `Cmd of vspec | `Nop ]
and vspec =
[ `N
| `S of vspec list
| `A of string
| `P of pathname
| `Px of pathname
| `Sh of string
| `Quote of vspec ]
val spec_of_vspec : vspec -> spec
val vspec_of_spec : spec -> vspec
val t_of_v : v -> t
val v_of_t : t -> v*)
(** Will convert a string list to a list of atoms by adding [A] constructors. *)
val atomize : string list -> spec
(** Will convert a string list to a list of paths by adding [P] constructors. *)
val atomize_paths : string list -> spec
(** Run the command. *)
val execute : ?quiet:bool -> ?pretend:bool -> t -> unit
(** Run the commands in the given list, if possible in parallel.
See the module [Ocamlbuild_executor]. *)
val execute_many : ?quiet:bool -> ?pretend:bool -> t list -> (bool list * exn) option
(** [setup_virtual_command_solver virtual_command solver]
the given solver can raise Not_found if it fails to find a valid
command for this virtual command. *)
val setup_virtual_command_solver : string -> (unit -> spec) -> unit
(** Search the given command in the command path and return its absolute
pathname. *)
val search_in_path : string -> string
(** Simplify a command by flattening the sequences and resolving the tags
into command-line options. *)
val reduce : spec -> spec
(** Print a command (the format is not suitable to running the command). *)
val print : Format.formatter -> t -> unit
(** Convert a command to a string (same format as print). *)
val to_string : t -> string
(** Build a string representation of a command that can be passed to the
system calls. *)
val string_of_command_spec : spec -> string
end
(** A self-contained module implementing extended shell glob patterns who have an expressive power
equal to boolean combinations of regular expressions. *)
module type GLOB = sig
(** A globber is a boolean combination of basic expressions indented to work on
pathnames. Known operators
are [or], [and] and [not], which may also be written [|], [&] and [~]. There are
also constants [true] and [false] (or [1] and [0]). Expression can be grouped
using parentheses.
- [true] matches anything,
- [false] matches nothing,
- {i basic} [or] {i basic} matches strings matching either one of the basic expressions,
- {i basic} [and] {i basic} matches strings matching both basic expressions,
- not {i basic} matches string that don't match the basic expression,
- {i basic} matches strings that match the basic expression.
A basic expression can be a constant string enclosed in double quotes, in which
double quotes must be preceded by backslashes, or a glob pattern enclosed between a [<] and a [>],
- ["]{i string}["] matches the literal string {i string},
- [<]{i glob}[>] matches the glob pattern {i glob}.
A glob pattern is an anchored regular expression in a shell-like syntax. Most characters stand for themselves.
Character ranges are given in usual shell syntax between brackets. The star [*] stands for any sequence of
characters. The joker '?' stands for exactly one, unspecified character. Alternation is achieved using braces [{].
- {i glob1}{i glob2} matches strings who have a prefix matching {i glob1} and the corresponding suffix
matching {i glob2}.
- [a] matches the string consisting of the single letter [a].
- [{]{i glob1},{i glob2}[}] matches strings matching {i glob1} or {i glob2}.
- [?] any one-letter string, excluding the slash.
- [*] matches all strings not containing a slash, including the empty one.
- [**/] the empty string, or any string ending with a slash.
- [/**] any string starting with a slash, or the empty string.
- [/**/] any string starting and ending with a slash.
- [\[]{i c1}-{i c2}{i c3}-{i c4}...[\]] matches characters in the range {i c1} to {i c2} inclusive,
or in the range {i c3} to {i c4} inclusive. For instance [\[a-fA-F0-9\]] matches hexadecimal digits.
To match the dash, put it at the end.
*)
(** The type representing globbers. Do not attempt to compare them, as they get on-the-fly optimizations. *)
type globber
(** [parse ~dir pattern] will parse the globber pattern [pattern], optionally prefixing its patterns with [dir]. *)
val parse : ?dir:string -> string -> globber
(** A descriptive exception raised when an invalid glob pattern description is given. *)
exception Parse_error of string
(** [eval g u] returns [true] if and only if the string [u] matches the given glob expression. Avoid reparsing
the same pattern, since the automaton implementing the pattern is optimized on the fly. The first few evaluations
are done using a time-inefficient but memory-efficient algorithm. It then compiles the pattern into an efficient
but more memory-hungry data structure. *)
val eval : globber -> string -> bool
end
(** Module for modulating the logging output with the logging level. *)
module type LOG = sig
(** Current logging (debugging) level. *)
val level : int ref
(** [dprintf level fmt args...] formats the logging information [fmt]
with the arguments [args...] on the logging output if the logging
level is greater than or equal to [level]. The default level is 1.
More obscure debugging information should have a higher logging
level. Youre formats are wrapped inside these two formats
["@\[<2>"] and ["@\]@."]. *)
val dprintf : int -> ('a, Format.formatter, unit) format -> 'a
(** @return whether logging at this level will print anything *)
val is_logging : int -> bool
(** Equivalent to calling [dprintf] with a level [< 0]. *)
val eprintf : ('a, Format.formatter, unit) format -> 'a
(** Same as dprintf but without the format wrapping. *)
val raw_dprintf : int -> ('a, Format.formatter, unit) format -> 'a
end
module type OUTCOME = sig
type ('a,'b) t =
| Good of 'a
| Bad of 'b
val wrap : ('a -> 'b) -> 'a -> ('b, exn) t
val ignore_good : ('a, exn) t -> unit
val good : ('a, exn) t -> 'a
end
module type MISC = sig
val opt_print :
(Format.formatter -> 'a -> unit) -> Format.formatter -> 'a option -> unit
val the : 'a option -> 'a
val getenv : ?default:string -> string -> string
val with_input_file : ?bin:bool -> string -> (in_channel -> 'a) -> 'a
val with_output_file : ?bin:bool -> string -> (out_channel -> 'a) -> 'a
val with_temp_file : string -> string -> (string -> 'a) -> 'a
val read_file : string -> string
val copy_chan : in_channel -> out_channel -> unit
val copy_file : string -> string -> unit
val print_string_list : Format.formatter -> string list -> unit
(** A shortcut to force lazy value (See {Lazy.force}). *)
val ( !* ) : 'a Lazy.t -> 'a
(** The right associative application.
Useful when writing to much parentheses:
<< f (g x ... t) >> becomes << f& g x ... t >>
<< f (g (h x)) >> becomes << f& g& h x >> *)
val ( & ) : ('a -> 'b) -> 'a -> 'b
(** The reversed application combinator.
Useful to describe some operations chaining.
<< f x (g y (h z)) >> becomes << z |> h |> g y |> f x >> *)
val ( |> ) : 'a -> ('a -> 'b) -> 'b
(** [r @:= l] is equivalent to [r := !r @ l] *)
val ( @:= ) : 'a list ref -> 'a list -> unit
val memo : ('a -> 'b) -> ('a -> 'b)
val memo2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'c)
val memo3 : ('a -> 'b -> 'c -> 'd) -> ('a -> 'b -> 'c -> 'd)
end
module type OPTIONS = sig
type command_spec
val build_dir : string ref
val include_dirs : string list ref
val exclude_dirs : string list ref
val nothing_should_be_rebuilt : bool ref
val ocamlc : command_spec ref
val ocamlopt : command_spec ref
val ocamldep : command_spec ref
val ocamldoc : command_spec ref
val ocamlyacc : command_spec ref
val ocamllex : command_spec ref
val ocamlrun : command_spec ref
val ocamlmklib : command_spec ref
val ocamlmktop : command_spec ref
val hygiene : bool ref
val sanitize : bool ref
val sanitization_script : string ref
val ignore_auto : bool ref
val plugin : bool ref
val just_plugin : bool ref
val native_plugin : bool ref
val make_links : bool ref
val nostdlib : bool ref
val program_to_execute : bool ref
val must_clean : bool ref
val catch_errors : bool ref
val use_menhir : bool ref
val show_documentation : bool ref
val recursive : bool ref
val use_ocamlfind : bool ref
val targets : string list ref
val ocaml_libs : string list ref
val ocaml_mods : string list ref
val ocaml_pkgs : string list ref
val ocaml_syntax : string option ref
val ocaml_cflags : string list ref
val ocaml_lflags : string list ref
val ocaml_ppflags : string list ref
val ocaml_docflags : string list ref
val ocaml_yaccflags : string list ref
val ocaml_lexflags : string list ref
val program_args : string list ref
val ignore_list : string list ref
val tags : string list ref
val tag_lines : string list ref
val show_tags : string list ref
val ext_obj : string ref
val ext_lib : string ref
val ext_dll : string ref
val exe : string ref
val add : string * Arg.spec * string -> unit
end
module type ARCH = sig
type 'a arch = private
| Arch_dir of string * 'a * 'a arch list
| Arch_dir_pack of string * 'a * 'a arch list
| Arch_file of string * 'a
val dir : string -> unit arch list -> unit arch
val dir_pack : string -> unit arch list -> unit arch
val file : string -> unit arch
type info = private {
current_path : string;
include_dirs : string list;
for_pack : string;
}
val annotate : 'a arch -> info arch
val print : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a arch -> unit
val print_include_dirs : Format.formatter -> string list -> unit
val print_info : Format.formatter -> info -> unit
val iter_info : ('a -> unit) -> 'a arch -> unit
val fold_info : ('a -> 'b -> 'b) -> 'a arch -> 'b -> 'b
val iter_include_dirs : info arch -> (string -> unit) -> unit
val mk_tables :
info arch -> (string, string list) Hashtbl.t * (string, string) Hashtbl.t
val print_table :
(Format.formatter -> 'a -> unit) -> Format.formatter -> (string, 'a) Hashtbl.t -> unit
end
module type FINDLIB = sig
(** Findlib / Ocamlfind tools. *)
type command_spec
type error =
| Cannot_run_ocamlfind
| Dependency_not_found of string * string (* package, dependency *)
| Package_not_found of string
| Cannot_parse_query of string * string (* package, explaination *)
exception Findlib_error of error
val string_of_error: error -> string
(** Return a string message describing an error. *)
val report_error: error -> 'a
(** Report an error on the standard error and exit with code 2. *)
type package = {
name: string;
description: string;
version: string;
archives_byte: string;
(** Archive names, with the .cma extension, but without the directory. *)
archives_native: string;
(** Archive names, with the .cmxa extension, but without the directory. *)
link_options: string;
location: string;
dependencies: package list;
(** Transitive closure, as returned by [ocamlfind query -r]. *)
}
(** Package information. *)
val query: string -> package
(** Query information about a package, given its name. May raise
[Not_found]. *)
val list: unit -> string list
(** Return the names of all known packages. *)
val topological_closure: package list -> package list
(** Computes the transitive closure of a list of
packages and sort them in topological order.
Given any list of package [l], [topological_closure l] returns a list of
packages including [l] and their dependencies, in an order where any element
may only depend on the previous ones. *)
val include_flags: package list -> command_spec
(** Return the list of include directories. *)
val compile_flags_byte: package list -> command_spec
(** Return the flags to add when compiling in byte mode (include
directories). *)
val compile_flags_native: package list -> command_spec
(** Same as [compile_flags_byte] but for native mode. *)
val link_flags_byte: package list -> command_spec
(** Return the flags to add when linking in byte mode. It includes:
include directories, libraries and special link options. *)
val link_flags_native: package list -> command_spec
(** Same as [link_flags_byte] but for native mode. *)
end
(** This module contains the functions and values that can be used by
plugins. *)
module type PLUGIN = sig
module Pathname : PATHNAME
module Tags : TAGS
module Command : COMMAND with type tags = Tags.t and type pathname = Pathname.t
module Outcome : OUTCOME
module String : STRING
module List : LIST
module StringSet : Set.S with type elt = String.t
module Options : OPTIONS with type command_spec = Command.spec
module Arch : ARCH
module Findlib : FINDLIB with type command_spec = Command.spec
include MISC
(** See {!COMMAND.t} for the description of this type. *)
type command = Command.t =
| Seq of command list
| Cmd of spec
| Echo of string list * Pathname.t
| Nop
(** See {!COMMAND.spec} for the description of this type. *)
and spec = Command.spec =
| N | S of spec list | A of string | P of string | Px of string
| Sh of string | T of Tags.t | V of string | Quote of spec
(** [path1/path2] Join the given path names. *)
val ( / ) : Pathname.t -> Pathname.t -> Pathname.t
(** [path-.-extension] Add the given extension to the given pathname. *)
val ( -.- ) : Pathname.t -> string -> Pathname.t
(** [tags++tag] Add the given tag to the given set of tags. *)
val ( ++ ) : Tags.t -> Tags.elt -> Tags.t
(** [tags--tag] Remove the given tag to the given set of tags. *)
val ( -- ) : Tags.t -> Tags.elt -> Tags.t
(** [tags+++optional_tag] Add the given optional tag to the given set of tags
if the given option is Some. *)
val ( +++ ) : Tags.t -> Tags.elt option -> Tags.t
(** [tags---optional_tag] Remove the given optional tag to the given
set of tags if the given option is Some. *)
val ( --- ) : Tags.t -> Tags.elt option -> Tags.t
(** Targets and dependencies in rules are patterns, which are
matched by the actual targets requested by the user. For
example, if a rule explains how to build "%.cmo" from "%.ml", it
will be fired if the user tries to build "foo.cmo".
The environment records the value of the pattern variables
(here "%") in this matching. In the context of our example, the
environment will be a function substituting "%" by "foo";
calling it on "%.cmo" will return "foo.cmo", and calling it on
"%.ml" will return "foo.ml".
For a typical example of use of the environment, see the
[ocamldep_ml_command] example in the documentation of {!action}
below. *)
type env = Pathname.t -> Pathname.t
(** A builder is a function that waits for conjonction of alternative targets.
The alternatives are here to support some choices, for instance for an
OCaml module an alternatives can be foo.cmo, foo.cmi, Foo.cmo, Foo.cmi.
Conjonctions are here to help making parallelism, indeed commands that are
independant will be run concurently.
For an example of use of a builder function, see the [targets]
function given as an example in the documentation of the
{!action} type below.
*)
type builder = Pathname.t list list -> (Pathname.t, exn) Outcome.t list
(** This is the type for rule actions. An action receive as argument, the
environment lookup function (see {!env}), and a function to dynamically
build more targets (see {!builder}). An action should return the command
to run in order to build the rule productions using the rule dependencies.
For example, here is an action to build an [ocamldep] command,
for use in the example of rule given in the documentation of
{!rule} below:
{[
let ocamldep_ml_command env _build =
let arg = env "%.ml" and out = env "%.ml.depends" in
let tags = tags_of_pathname arg ++ "ocaml" ++ "ocamldep" in
Cmd(S[A "ocamldep"; T tags; A "-modules"; P arg; Sh ">"; Px out])
]}
In the example above, the build function is not used, as there
are no dynamic dependencies. There are in the example below: we
build a list of targets dynamically read from a "foo.itarget"
file. The final command returned by the action links each of
them in the current directory.
{[
let target_list env build =
let itarget = env "%.itarget" in
let targets =
let dir = Pathname.dirname itarget in
let files = string_list_of_file itarget in
List.map (fun file -> [Pathname.concat dir file]) files
in
let results = List.map Outcome.good (build targets) in
let link_command result =
Cmd (S [A "ln"; A "-sf";
P (Pathname.concat !Options.build_dir result);
A Pathname.pwd])
in
Seq (List.map link_command results)
]}
*)
type action = env -> builder -> Command.t
(** This is the main function for adding a rule to the ocamlbuild engine.
- The first argument is the name of the rule (should be unique).
- It takes files that the rule produces.
Use [~prod] for one file, [~prods] for list of files.
- It also takes files that the rule uses.
Use [~dep] for one file, [~deps] for list of files.
- It finally takes the action to perform in order to produce the
productions files using the dependencies (see [action]).
There are some more optional parameters:
- The [~insert] argument allows to insert the rules precisely between other
rules.
- The [~stamp] argument specifies the name of a file that will be
automatically produced by ocamlbuild. This file can serve as a virtual
target (or phony target), since it will be filled up by a digest of
it dependencies.
- The [~tags] argument in deprecated, don't use it.
Finally, the optional [~doc] argument allows to give an informal
explanation of the rule purpose and behavior, that will be
displayed by [ocamlbuild -documentation]. For example, it is
a good place to specify the commands that will be called, any
new tags introduced by the rule, and dynamic dependencies.
For example, here is how a rule producing [foo.ml.depends] from
[foo.ml] (calling [ocamldep]) is defined, slightly simplified from
the built-in definition.
{[
rule "ocaml dependencies ml"
~prod:"%.ml.depends"
~dep:"%.ml"
~doc:"call ocamldep to compute a syntactic over-approximation \\
of the dependencies of the corresponding implementation file"
ocamldep_ml_command
]}
The rule that builds a list of targets from a [%.itarget] file is
an example of use of the [?stamp] argument. It uses the
[target_list] action provided in the documentation of {!action}
above. Besides the targets listed in the [%.itarget] file, this
command will also produce a [%.otarget] file (the "stamp") that
contains the digest of all the [%.itarget] dependencies. This stamp
file is the name to use when you want to ask OCamlbuild to build
the targets listed: invoking [ocamlbuild foo.otarget] will build
the the targets listed in [foo.itarget]. Similarly, new rules
that would depend on that list of targets should depend on
[%.otarget] (output), not [%.itarget] (input).
{[
rule "target files"
~dep:"%.itarget"
~stamp:"%.otarget"
~doc:"If foo.itarget contains a list of ocamlbuild targets, \
asking ocamlbuild to produce foo.otarget will \
build each of those targets in turn."
target_list
]}
*)
val rule : string ->
?tags:string list ->
?prods:string list ->
?deps:string list ->
?prod:string ->
?dep:string ->
?stamp:string ->
?insert:[`top | `before of string | `after of string | `bottom] ->
?doc:string ->
action -> unit
(** [copy_rule name ?insert source destination] *)
val copy_rule : string ->
?insert:[`top | `before of string | `after of string | `bottom] ->
string -> string -> unit
(** Empties the list of rules of the ocamlbuild engine. *)
val clear_rules : unit -> unit
(** [dep tags deps] Will build [deps] when all [tags] will be activated.
If you do not know which tags to use, have a look to the file
_build/_log after trying to compile your code. *)
val dep : Tags.elt list -> Pathname.t list -> unit
(** [pdep tags ptag deps] is equivalent to [dep tags deps], with an
additional parameterized tag [ptag]. [deps] is now a function
which takes the parameter of the tag [ptag] as an argument.
Example:
[pdep ["ocaml"; "compile"] "autodep" (fun param -> param)]
says that the tag [autodep(file)] can now be used to automatically
add [file] as a dependency when compiling an OCaml program. *)
val pdep : Tags.elt list -> Tags.elt -> (string -> Pathname.t list) -> unit
(** [flag tags command_spec] Will inject the given piece of command
([command_spec]) when all [tags] will be activated.
If you do not know which tags to use, have a look to the file
_build/_log after trying to compile your code. *)
val flag : Tags.elt list -> Command.spec -> unit
(** Allows to use [flag] with a parametrized tag (as [pdep] for [dep]).
Example:
[pflag ["ocaml"; "compile"] "inline"
(fun count -> S [A "-inline"; A count])]
says that command line option ["-inline 42"] should be added
when compiling OCaml modules tagged with ["inline(42)"]. *)
val pflag : Tags.elt list -> Tags.elt -> (string -> Command.spec) -> unit
(** [flag_and_dep tags command_spec]
Combines [flag] and [dep] function.
Basically it calls [flag tags command_spec], and calls [dep tags files]
where [files] is the list of all pathnames in [command_spec].
Pathnames selected are those in the constructor [P] or [Px], or the
pathname argument of builtins like [Echo]. *)
val flag_and_dep : Tags.elt list -> Command.spec -> unit
(** Allows to use [flag_and_dep] with a parameterized tag
(as [pdep] for [dep]). *)
val pflag_and_dep : Tags.elt list -> Tags.elt ->
(string -> Command.spec) -> unit
(** manually mark the tag as "useful" to silence the warning about
tags that are not part of any flag declaration.
This is useful,
for example, if the tag is used in a flag declaration that is
only perfored in a conditional branch:
[if we_are_on_Windows then flag ["libfoo"] (A "bar");]
When [we_are_on_Windows] is not true, you could get a warning about
"libfoo" not used in any flag declaration.
*)
val mark_tag_used : Tags.elt -> unit
(** [non_dependency module_path module_name]
Example:
[non_dependency "foo/bar/baz" "Goo"]
Says that the module [Baz] in the file [foo/bar/baz.*] does
not depend on [Goo]. *)
val non_dependency : Pathname.t -> string -> unit
(** [use_lib module_path lib_path]*)
val use_lib : Pathname.t -> Pathname.t -> unit
(** [ocaml_lib <options> library_pathname] Declare an ocaml library.
This informs ocamlbuild and produce tags to use the library;
they are named by default use_#{library_name}.
Example: [ocaml_lib "foo/bar"] will setup the tag use_bar.
At link time it will include:
foo/bar.cma or foo/bar.cmxa
@param dir supply the [~dir:"boo"] option to add '-I boo'
at link and compile time.
@param extern use ~extern:true for non-ocamlbuild handled libraries.
Set this to add libraries whose sources are not in your project.
@param byte use ~byte:false to disable byte mode.
@param native use ~native:false to disable native mode.
@param tag_name Use ~tag_name:"usebar" to override the default
tag name. *)
val ocaml_lib :
?extern:bool ->
?byte:bool ->
?native:bool ->
?dir:Pathname.t ->
?tag_name:string ->
Pathname.t -> unit
(** [expand_module include_dirs module_name extensions]
Example:
[expand_module ["a";"b";"c"] "Foo" ["cmo";"cmi"] =
["a/foo.cmo"; "a/Foo.cmo"; "a/foo.cmi"; "a/Foo.cmi";
"b/foo.cmo"; "b/Foo.cmo"; "b/foo.cmi"; "b/Foo.cmi";
"c/foo.cmo"; "c/Foo.cmo"; "c/foo.cmi"; "c/Foo.cmi"]] *)
val expand_module :
Pathname.t list -> Pathname.t -> string list -> Pathname.t list
(** Reads the given file, parse it has list of words separated by blanks.
It ignore lines that begins with a '#' character. *)
val string_list_of_file : Pathname.t -> string list
(** Takes a pathname and returns an OCaml module name. Basically it will
remove directories and extensions, and then capitalize the string. *)
val module_name_of_pathname : Pathname.t -> string
(** The Unix mv command. *)
val mv : Pathname.t -> Pathname.t -> Command.t
(** The Unix cp command. *)
val cp : Pathname.t -> Pathname.t -> Command.t
(** The Unix ln -f command. *)
val ln_f : Pathname.t -> Pathname.t -> Command.t
(** The Unix ln -s command. *)
val ln_s : Pathname.t -> Pathname.t -> Command.t
(** The Unix rm -f command. *)
val rm_f : Pathname.t -> Command.t
(** The Unix chmod command (almost deprecated). *)
val chmod : Command.spec -> Pathname.t -> Command.t
(** The Unix cmp command (almost deprecated). *)
val cmp : Pathname.t -> Pathname.t -> Command.t
(** [hide_package_contents pack_name]
Don't treat the given package as an open package.
So a module will not be replaced during linking by
this package even if it contains that module. *)
val hide_package_contents : string -> unit
(** [tag_file filename tag_list] Tag the given filename with all
given tags. Prefix a tag with the minus sign to remove it.
This is usually used as an [After_rules] hook.
For example [tag_file "bla.ml" ["use_unix"]] tags the file
"bla.ml" with "use_unix" and [tag_file "bla.ml" ["-use_unix"]]
removes the tag "use_unix" from the file "bla.ml". *)
val tag_file : Pathname.t -> Tags.elt list -> unit
(** [tag_any tag_list] Tag anything with all given tags. *)
val tag_any : Tags.elt list -> unit
(** Returns the set of tags that applies to the given pathname. *)
val tags_of_pathname : Pathname.t -> Tags.t
(** Run the given command and returns it's output as a string. *)
val run_and_read : string -> string
(** Here is the list of hooks that the dispatch function have to handle.
Generally one responds to one or two hooks (like After_rules) and do
nothing in the default case. *)
type hook =
| Before_hygiene
| After_hygiene
| Before_options
| After_options
| Before_rules
| After_rules
(** [dispatch hook_handler] Is the entry point for ocamlbuild plugins. Every
plugin must call it with a [hook_handler] where all calls to plugin
functions lives. *)
val dispatch : (hook -> unit) -> unit
end