End of oasisfication
[ocsoap/ocsoap.git] / myocamlbuild.ml
1
2 open Ocamlbuild_plugin
3
4 (***************)
5 (* CDuce rules *)
6 (***************)
7
8 let cduce = A"cduce"
9 let ocamlfind = A"ocamlfind"
10 let ocamlc = A"ocamlc"
11 let ocamlopt = A"ocamlopt"
12
13 let cduce_mkstubs includes = 
14   Quote (S([cduce; 
15             S(List.map 
16                 (fun fn -> S[A"-I"; P fn])
17                 includes);
18             A"--mlstub"]));;
19 (* cduce < 0.3.9:  cdo2ml -static *)
20
21 let cduce_compile_args env = 
22   [
23     A"-c"; A"-package"; A"cduce";
24     A"-pp"; cduce_mkstubs [Filename.dirname (env "%.cmi")];
25     A"-I"; P(Filename.dirname (env "%.cmi"));
26     A"-impl"; P(env "%.cdo")
27   ]
28 ;;
29
30 let cduce_prepare_compile env build =
31   List.iter 
32     (function
33        | Outcome.Bad _ ->
34            (* Fail but it just means that the .cmi will be generated 
35             * during compilation.
36             *)
37            ()
38        | Outcome.Good _ ->
39            ())
40     (build [[env "%.cmi"]])
41 ;;
42
43 rule "cduce: %.cd -> %.cdo"
44   ~prod:"%.cdo"
45   ~dep:"%.cd"
46   begin
47     fun env build ->
48       Cmd(S[cduce;
49             T(tags_of_pathname (env "%.cd")++"cduce"++"compile");
50             A"--compile";
51             A"-I"; P(Filename.dirname (env "%.cd"));
52             P (env "%.cd")])
53   end
54 ;;
55
56 rule "cduce: %.cdo -> %.cmo"
57   ~prod:"%.cmo"
58   ~dep:"%.cdo"
59   begin
60     fun env build ->
61       cduce_prepare_compile env build;
62       Cmd(S(
63         [ocamlfind; ocamlc; 
64          T(tags_of_pathname (env "%.cdo")
65            ++"cduce"++"ocamlc"++"compile"++"byte")]
66         @ (cduce_compile_args env)))
67   end
68 ;;
69
70 rule "cduce: %.cdo -> %.cmx"
71   ~prod:"%.cmx"
72   ~dep:"%.cdo"
73   begin
74     fun env build ->
75       cduce_prepare_compile env build;
76       Cmd(S(
77         [ocamlfind; ocamlopt; 
78          T(tags_of_pathname (env "%.cdo")
79            ++"cduce"++"ocamlopt"++"compile"++"native")]
80         @ (cduce_compile_args env)))
81   end
82 ;;
83
84 (***********************)
85 (* WSDL rules (ocsoap) *)
86 (***********************)
87
88 let ocsoap_dev = ref true;;
89
90 let wsdltointf = ref "src/wsdltointf.byte";;
91 let pa_ocsoapclientstubs = ref "src/pa_ocsoapclientstubs.cma";;
92 let camlp5o = ref "camlp5o";;
93
94 rule "ocsoap: %.wsdl -> %.intf & %_types.ml & %_conv.ml"
95   ~prods:["%.intf"; "%_types.ml"; "%_conv.ml"]
96   ~deps:(if !ocsoap_dev then
97            ["%.wsdl"; !wsdltointf]
98          else
99            ["%.wsdl"])
100   begin
101     fun env build ->
102       Cmd(S([Px !wsdltointf; P(env "%.wsdl")]))
103   end
104 ;;
105
106 rule "ocsoap: %.intf -> %.ml"
107   ~prod:"%.ml"
108   ~deps:(if !ocsoap_dev then 
109            ["%.intf"; !pa_ocsoapclientstubs]
110          else
111            ["%.intf"])
112   begin
113     fun env build ->
114       Cmd(S[Px !camlp5o; P !pa_ocsoapclientstubs; P "pr_o.cmo"; A"-impl"; 
115             P(env "%.intf"); A"-o"; P(env "%.ml")])
116   end
117 ;;
118
119 (* OASIS_START *)
120 (* DO NOT EDIT (digest: ea6f87916d3d3095edf230468afa4ab1) *)
121 module OASISGettext = struct
122 # 21 "/home/gildor/programmation/oasis/src/oasis/OASISGettext.ml"
123
124   let ns_ str =
125     str
126
127   let s_ str =
128     str
129
130   let f_ (str : ('a, 'b, 'c, 'd) format4) =
131     str
132
133   let fn_ fmt1 fmt2 n =
134     if n = 1 then
135       fmt1^^""
136     else
137       fmt2^^""
138
139   let init =
140     []
141
142 end
143
144 module OASISExpr = struct
145 # 21 "/home/gildor/programmation/oasis/src/oasis/OASISExpr.ml"
146
147
148
149   open OASISGettext
150
151   type test = string 
152
153   type flag = string 
154
155   type t =
156     | EBool of bool
157     | ENot of t
158     | EAnd of t * t
159     | EOr of t * t
160     | EFlag of flag
161     | ETest of test * string
162     
163
164   type 'a choices = (t * 'a) list 
165
166   let eval var_get t =
167     let rec eval' =
168       function
169         | EBool b ->
170             b
171
172         | ENot e ->
173             not (eval' e)
174
175         | EAnd (e1, e2) ->
176             (eval' e1) && (eval' e2)
177
178         | EOr (e1, e2) ->
179             (eval' e1) || (eval' e2)
180
181         | EFlag nm ->
182             let v =
183               var_get nm
184             in
185               assert(v = "true" || v = "false");
186               (v = "true")
187
188         | ETest (nm, vl) ->
189             let v =
190               var_get nm
191             in
192               (v = vl)
193     in
194       eval' t
195
196   let choose ?printer ?name var_get lst =
197     let rec choose_aux =
198       function
199         | (cond, vl) :: tl ->
200             if eval var_get cond then
201               vl
202             else
203               choose_aux tl
204         | [] ->
205             let str_lst =
206               if lst = [] then
207                 s_ "<empty>"
208               else
209                 String.concat
210                   (s_ ", ")
211                   (List.map
212                      (fun (cond, vl) ->
213                         match printer with
214                           | Some p -> p vl
215                           | None -> s_ "<no printer>")
216                      lst)
217             in
218               match name with
219                 | Some nm ->
220                     failwith
221                       (Printf.sprintf
222                          (f_ "No result for the choice list '%s': %s")
223                          nm str_lst)
224                 | None ->
225                     failwith
226                       (Printf.sprintf
227                          (f_ "No result for a choice list: %s")
228                          str_lst)
229     in
230       choose_aux (List.rev lst)
231
232 end
233
234
235 # 117 "myocamlbuild.ml"
236 module BaseEnvLight = struct
237 # 21 "/home/gildor/programmation/oasis/src/base/BaseEnvLight.ml"
238
239   module MapString = Map.Make(String)
240
241   type t = string MapString.t
242
243   let default_filename =
244     Filename.concat
245       (Sys.getcwd ())
246       "setup.data"
247
248   let load ?(allow_empty=false) ?(filename=default_filename) () =
249     if Sys.file_exists filename then
250       begin
251         let chn =
252           open_in_bin filename
253         in
254         let st =
255           Stream.of_channel chn
256         in
257         let line =
258           ref 1
259         in
260         let st_line =
261           Stream.from
262             (fun _ ->
263                try
264                  match Stream.next st with
265                    | '\n' -> incr line; Some '\n'
266                    | c -> Some c
267                with Stream.Failure -> None)
268         in
269         let lexer =
270           Genlex.make_lexer ["="] st_line
271         in
272         let rec read_file mp =
273           match Stream.npeek 3 lexer with
274             | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
275                 Stream.junk lexer;
276                 Stream.junk lexer;
277                 Stream.junk lexer;
278                 read_file (MapString.add nm value mp)
279             | [] ->
280                 mp
281             | _ ->
282                 failwith
283                   (Printf.sprintf
284                      "Malformed data file '%s' line %d"
285                      filename !line)
286         in
287         let mp =
288           read_file MapString.empty
289         in
290           close_in chn;
291           mp
292       end
293     else if allow_empty then
294       begin
295         MapString.empty
296       end
297     else
298       begin
299         failwith
300           (Printf.sprintf
301              "Unable to load environment, the file '%s' doesn't exist."
302              filename)
303       end
304
305   let var_get name env =
306     let rec var_expand str =
307       let buff =
308         Buffer.create ((String.length str) * 2)
309       in
310         Buffer.add_substitute
311           buff
312           (fun var ->
313              try
314                var_expand (MapString.find var env)
315              with Not_found ->
316                failwith
317                  (Printf.sprintf
318                     "No variable %s defined when trying to expand %S."
319                     var
320                     str))
321           str;
322         Buffer.contents buff
323     in
324       var_expand (MapString.find name env)
325
326   let var_choose lst env =
327     OASISExpr.choose
328       (fun nm -> var_get nm env)
329       lst
330 end
331
332
333 # 215 "myocamlbuild.ml"
334 module MyOCamlbuildFindlib = struct
335 # 21 "/home/gildor/programmation/oasis/src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml"
336
337   (** OCamlbuild extension, copied from 
338     * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
339     * by N. Pouillard and others
340     *
341     * Updated on 2009/02/28
342     *
343     * Modified by Sylvain Le Gall 
344     *)
345   open Ocamlbuild_plugin
346
347   (* these functions are not really officially exported *)
348   let run_and_read = 
349     Ocamlbuild_pack.My_unix.run_and_read
350
351   let blank_sep_strings = 
352     Ocamlbuild_pack.Lexers.blank_sep_strings
353
354   let split s ch =
355     let x = 
356       ref [] 
357     in
358     let rec go s =
359       let pos = 
360         String.index s ch 
361       in
362         x := (String.before s pos)::!x;
363         go (String.after s (pos + 1))
364     in
365       try
366         go s
367       with Not_found -> !x
368
369   let split_nl s = split s '\n'
370
371   let before_space s =
372     try
373       String.before s (String.index s ' ')
374     with Not_found -> s
375
376   (* this lists all supported packages *)
377   let find_packages () =
378     List.map before_space (split_nl & run_and_read "ocamlfind list")
379
380   (* this is supposed to list available syntaxes, but I don't know how to do it. *)
381   let find_syntaxes () = ["camlp4o"; "camlp4r"]
382
383   (* ocamlfind command *)
384   let ocamlfind x = S[A"ocamlfind"; x]
385
386   let dispatch =
387     function
388       | Before_options ->
389           (* by using Before_options one let command line options have an higher priority *)
390           (* on the contrary using After_options will guarantee to have the higher priority *)
391           (* override default commands by ocamlfind ones *)
392           Options.ocamlc     := ocamlfind & A"ocamlc";
393           Options.ocamlopt   := ocamlfind & A"ocamlopt";
394           Options.ocamldep   := ocamlfind & A"ocamldep";
395           Options.ocamldoc   := ocamlfind & A"ocamldoc";
396           Options.ocamlmktop := ocamlfind & A"ocamlmktop"
397                                   
398       | After_rules ->
399           
400           (* When one link an OCaml library/binary/package, one should use -linkpkg *)
401           flag ["ocaml"; "link"; "program"] & A"-linkpkg";
402           
403           (* For each ocamlfind package one inject the -package option when
404            * compiling, computing dependencies, generating documentation and
405            * linking. *)
406           List.iter 
407             begin fun pkg ->
408               flag ["ocaml"; "compile";  "pkg_"^pkg] & S[A"-package"; A pkg];
409               flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg];
410               flag ["ocaml"; "doc";      "pkg_"^pkg] & S[A"-package"; A pkg];
411               flag ["ocaml"; "link";     "pkg_"^pkg] & S[A"-package"; A pkg];
412               flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S[A"-package"; A pkg];
413             end 
414             (find_packages ());
415
416           (* Like -package but for extensions syntax. Morover -syntax is useless
417            * when linking. *)
418           List.iter begin fun syntax ->
419           flag ["ocaml"; "compile";  "syntax_"^syntax] & S[A"-syntax"; A syntax];
420           flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
421           flag ["ocaml"; "doc";      "syntax_"^syntax] & S[A"-syntax"; A syntax];
422           flag ["ocaml"; "infer_interface"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
423           end (find_syntaxes ());
424
425           (* The default "thread" tag is not compatible with ocamlfind.
426            * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
427            * options when using this tag. When using the "-linkpkg" option with
428            * ocamlfind, this module will then be added twice on the command line.
429            *                        
430            * To solve this, one approach is to add the "-thread" option when using
431            * the "threads" package using the previous plugin.
432            *)
433           flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
434           flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
435           flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
436           flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"])
437
438       | _ -> 
439           ()
440
441 end
442
443 module MyOCamlbuildBase = struct
444 # 21 "/home/gildor/programmation/oasis/src/plugins/ocamlbuild/MyOCamlbuildBase.ml"
445
446   (** Base functions for writing myocamlbuild.ml
447       @author Sylvain Le Gall
448     *)
449
450
451
452   open Ocamlbuild_plugin
453   module OC = Ocamlbuild_pack.Ocaml_compiler
454
455   type dir = string 
456   type file = string 
457   type name = string 
458   type tag = string 
459
460 # 56 "/home/gildor/programmation/oasis/src/plugins/ocamlbuild/MyOCamlbuildBase.ml"
461
462   type t =
463       {
464         lib_ocaml: (name * dir list) list;
465         lib_c:     (name * dir * file list) list; 
466         flags:     (tag list * (spec OASISExpr.choices)) list;
467         (* Replace the 'dir: include' from _tags by a precise interdepends in
468          * directory.
469          *)
470         includes:  (dir * dir list) list; 
471       } 
472
473   let env_filename =
474     Pathname.basename 
475       BaseEnvLight.default_filename
476
477   let dispatch_combine lst =
478     fun e ->
479       List.iter 
480         (fun dispatch -> dispatch e)
481         lst 
482
483   let tag_libstubs nm =
484     "use_lib"^nm^"_stubs"
485
486   let nm_libstubs nm =
487     nm^"_stubs"
488
489   let dispatch t e = 
490     let env = 
491       BaseEnvLight.load 
492         ~filename:env_filename 
493         ~allow_empty:true
494         ()
495     in
496       match e with 
497         | Before_options ->
498             let no_trailing_dot s =
499               if String.length s >= 1 && s.[0] = '.' then
500                 String.sub s 1 ((String.length s) - 1)
501               else
502                 s
503             in
504               List.iter
505                 (fun (opt, var) ->
506                    try 
507                      opt := no_trailing_dot (BaseEnvLight.var_get var env)
508                    with Not_found ->
509                      Printf.eprintf "W: Cannot get variable %s" var)
510                 [
511                   Options.ext_obj, "ext_obj";
512                   Options.ext_lib, "ext_lib";
513                   Options.ext_dll, "ext_dll";
514                 ]
515
516         | After_rules -> 
517             (* Declare OCaml libraries *)
518             List.iter 
519               (function
520                  | nm, [] ->
521                      ocaml_lib nm
522                  | nm, dir :: tl ->
523                      ocaml_lib ~dir:dir (dir^"/"^nm);
524                      List.iter 
525                        (fun dir -> 
526                           List.iter
527                             (fun str ->
528                                flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
529                             ["compile"; "infer_interface"; "doc"])
530                        tl)
531               t.lib_ocaml;
532
533             (* Declare directories dependencies, replace "include" in _tags. *)
534             List.iter 
535               (fun (dir, include_dirs) ->
536                  Pathname.define_context dir include_dirs)
537               t.includes;
538
539             (* Declare C libraries *)
540             List.iter
541               (fun (lib, dir, headers) ->
542                    (* Handle C part of library *)
543                    flag ["link"; "library"; "ocaml"; "byte"; tag_libstubs lib]
544                      (S[A"-dllib"; A("-l"^(nm_libstubs lib)); A"-cclib";
545                         A("-l"^(nm_libstubs lib))]);
546
547                    flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
548                      (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
549                         
550                    flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
551                      (S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
552
553                    (* When ocaml link something that use the C library, then one
554                       need that file to be up to date.
555                     *)
556                    dep ["link"; "ocaml"; "program"; tag_libstubs lib]
557                      [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
558
559                    dep  ["compile"; "ocaml"; "program"; tag_libstubs lib]
560                      [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
561
562                    (* TODO: be more specific about what depends on headers *)
563                    (* Depends on .h files *)
564                    dep ["compile"; "c"] 
565                      headers;
566
567                    (* Setup search path for lib *)
568                    flag ["link"; "ocaml"; "use_"^lib] 
569                      (S[A"-I"; P(dir)]);
570               )
571               t.lib_c;
572
573               (* Add flags *)
574               List.iter
575               (fun (tags, cond_specs) ->
576                  let spec = 
577                    BaseEnvLight.var_choose cond_specs env
578                  in
579                    flag tags & spec)
580               t.flags
581         | _ -> 
582             ()
583
584   let dispatch_default t =
585     dispatch_combine 
586       [
587         dispatch t;
588         MyOCamlbuildFindlib.dispatch;
589       ]
590
591 end
592
593
594 # 476 "myocamlbuild.ml"
595 open Ocamlbuild_plugin;;
596 let package_default =
597   {
598      MyOCamlbuildBase.lib_ocaml =
599        [("ocsoap", ["src"]); ("pa_ocsoapclientstubs", ["src"])];
600      lib_c = [];
601      flags = [];
602      includes = [("examples/adwords", ["src"])];
603      }
604   ;;
605
606 let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;;
607
608 # 491 "myocamlbuild.ml"
609 (* OASIS_STOP *)
610
611 let dispatch_extra = 
612   function
613     | After_rules ->
614         let pp_camlp5 =
615           (S[A"-pp"; 
616              Quote(S[Px !camlp5o; P"pa_extend.cmo"; P"q_MLast.cmo"; 
617                      A"-loc"; A"loc"; A"-impl"])])
618         in
619           flag ["file:src/pa_ocsoapclientstubs.ml"; "ocaml"; "compile"] 
620             pp_camlp5;
621           flag ["file:src/pa_ocsoapclientstubs.ml"; "ocamldep"]
622             pp_camlp5;
623
624           flag ["ocaml"; "doc"] (S[A"-stars"; A"-sort"]);
625
626     | _ ->
627         ()
628 ;;
629
630 Ocamlbuild_plugin.dispatch 
631   (MyOCamlbuildBase.dispatch_combine [dispatch_default; dispatch_extra])
632 ;;