Commits

mkur committed cec07d5

OS X build fixes

Comments (0)

Files changed (7)

 # OASIS_START
-# DO NOT EDIT (digest: bc1e05bfc8b39b664f29dae8dbd3ebbb)
+# DO NOT EDIT (digest: a3c674b4239234cbbe53afe090018954)
 
 SETUP = ocaml setup.ml
 
 test: setup.data build
 	$(SETUP) -test $(TESTFLAGS)
 
-all: 
+all:
 	$(SETUP) -all $(ALLFLAGS)
 
 install: setup.data
 reinstall: setup.data
 	$(SETUP) -reinstall $(REINSTALLFLAGS)
 
-clean: 
+clean:
 	$(SETUP) -clean $(CLEANFLAGS)
 
-distclean: 
+distclean:
 	$(SETUP) -distclean $(DISTCLEANFLAGS)
 
 setup.data:
 	$(SETUP) -configure $(CONFIGUREFLAGS)
 
+configure:
+	$(SETUP) -configure $(CONFIGUREFLAGS)
+
 .PHONY: build doc test all install uninstall reinstall clean distclean configure
 
 # OASIS_STOP
 OASISFormat:		0.3
 Name:			nlopt
-Version:		0.4
+Version:		0.5.1
 Synopsis:		nlopt-ocaml implements OCaml bindings to the NLOpt optimization library.
 Authors:		Michał Kurcewicz <michal.kurcewicz@gmail.com>
 Maintainers:		Michał Kurcewicz <michal.kurcewicz@gmail.com>
         Modules:	Nlopt
         Csources:	nlopt_wrapper.c
         CCopt:		-std=c99 -O3 -Wall
-        CCLib:		-lnlopt
+        if system(macosx)
+               CCLib:   -lnlopt_cxx
+        else
+               CCLib:   -lnlopt
 
 Executable rosenbrock
         Path:		examples
 # OASIS_START
-# DO NOT EDIT (digest: 0d7b9a85340e2281d55a467b023e0b4d)
-# Ignore VCS directories, you can use the same kind of rule outside 
-# OASIS_START/STOP if you want to exclude directories that contains 
+# DO NOT EDIT (digest: c87d5117b19b660e3eb476fd14631ea5)
+# Ignore VCS directories, you can use the same kind of rule outside
+# OASIS_START/STOP if you want to exclude directories that contains
 # useless stuff for the build process
 <**/.svn>: -traverse
 <**/.svn>: not_hygienic
 #!/bin/sh
 
 # OASIS_START
-# DO NOT EDIT (digest: 425187ed8bfdbdd207fd76392dd243a7)
+# DO NOT EDIT (digest: dc86c2ad450f91ca10c931b6045d0499)
 set -e
 
 FST=true
-for i in "$@"; do 
+for i in "$@"; do
   if $FST; then
     set --
     FST=false
 (* OASIS_START *)
-(* DO NOT EDIT (digest: 37532d2111e1d9943fcec4577bd453b3) *)
+(* DO NOT EDIT (digest: f7bb04c291582e9a501bfb09c59677a8) *)
 module OASISGettext = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISGettext.ml" *)
+(* # 22 "src/oasis/OASISGettext.ml" *)
+
 
   let ns_ str =
     str
 
+
   let s_ str =
     str
 
-  let f_ (str : ('a, 'b, 'c, 'd) format4) =
+
+  let f_ (str: ('a, 'b, 'c, 'd) format4) =
     str
 
+
   let fn_ fmt1 fmt2 n =
     if n = 1 then
       fmt1^^""
     else
       fmt2^^""
 
+
   let init =
     []
 
+
 end
 
 module OASISExpr = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISExpr.ml" *)
+(* # 22 "src/oasis/OASISExpr.ml" *)
+
+
 
 
 
   open OASISGettext
 
-  type test = string 
 
-  type flag = string 
+  type test = string
+
+
+  type flag = string
+
 
   type t =
     | EBool of bool
     | EOr of t * t
     | EFlag of flag
     | ETest of test * string
-    
 
-  type 'a choices = (t * 'a) list 
+
+
+  type 'a choices = (t * 'a) list
+
 
   let eval var_get t =
     let rec eval' =
     in
       eval' t
 
+
   let choose ?printer ?name var_get lst =
     let rec choose_aux =
       function
     in
       choose_aux (List.rev lst)
 
+
 end
 
 
-# 117 "myocamlbuild.ml"
+# 132 "myocamlbuild.ml"
 module BaseEnvLight = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/base/BaseEnvLight.ml" *)
+(* # 22 "src/base/BaseEnvLight.ml" *)
+
 
   module MapString = Map.Make(String)
 
+
   type t = string MapString.t
 
+
   let default_filename =
     Filename.concat
       (Sys.getcwd ())
       "setup.data"
 
+
   let load ?(allow_empty=false) ?(filename=default_filename) () =
     if Sys.file_exists filename then
       begin
              filename)
       end
 
+
+  let rec var_expand str env =
+    let buff =
+      Buffer.create ((String.length str) * 2)
+    in
+      Buffer.add_substitute
+        buff
+        (fun var ->
+           try
+             var_expand (MapString.find var env) env
+           with Not_found ->
+             failwith
+               (Printf.sprintf
+                  "No variable %s defined when trying to expand %S."
+                  var
+                  str))
+        str;
+      Buffer.contents buff
+
+
   let var_get name env =
-    let rec var_expand str =
-      let buff =
-        Buffer.create ((String.length str) * 2)
-      in
-        Buffer.add_substitute
-          buff
-          (fun var ->
-             try
-               var_expand (MapString.find var env)
-             with Not_found ->
-               failwith
-                 (Printf.sprintf
-                    "No variable %s defined when trying to expand %S."
-                    var
-                    str))
-          str;
-        Buffer.contents buff
-    in
-      var_expand (MapString.find name env)
+    var_expand (MapString.find name env) env
+
 
   let var_choose lst env =
     OASISExpr.choose
 end
 
 
-# 215 "myocamlbuild.ml"
+# 237 "myocamlbuild.ml"
 module MyOCamlbuildFindlib = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
+(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
 
-  (** OCamlbuild extension, copied from 
+
+  (** OCamlbuild extension, copied from
     * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
     * by N. Pouillard and others
     *
     * Updated on 2009/02/28
     *
-    * Modified by Sylvain Le Gall 
+    * Modified by Sylvain Le Gall
     *)
   open Ocamlbuild_plugin
 
+
   (* these functions are not really officially exported *)
-  let run_and_read = 
+  let run_and_read =
     Ocamlbuild_pack.My_unix.run_and_read
 
-  let blank_sep_strings = 
+
+  let blank_sep_strings =
     Ocamlbuild_pack.Lexers.blank_sep_strings
 
+
+  let exec_from_conf exec =
+    let exec =
+      let env_filename = Pathname.basename BaseEnvLight.default_filename in
+      let env = BaseEnvLight.load ~filename:env_filename ~allow_empty:true () in
+      try
+        BaseEnvLight.var_get exec env
+      with Not_found ->
+        Printf.eprintf "W: Cannot get variable %s\n" exec;
+        exec
+    in
+    let fix_win32 str =
+      if Sys.os_type = "Win32" then begin
+        let buff = Buffer.create (String.length str) in
+        (* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
+         *)
+        String.iter
+          (fun c -> Buffer.add_char buff (if c = '\\' then '/' else c))
+          str;
+        Buffer.contents buff
+      end else begin
+        str
+      end
+    in
+      fix_win32 exec
+
   let split s ch =
-    let x = 
-      ref [] 
+    let buf = Buffer.create 13 in
+    let x = ref [] in
+    let flush () =
+      x := (Buffer.contents buf) :: !x;
+      Buffer.clear buf
     in
-    let rec go s =
-      let pos = 
-        String.index s ch 
-      in
-        x := (String.before s pos)::!x;
-        go (String.after s (pos + 1))
-    in
-      try
-        go s
-      with Not_found -> !x
+      String.iter
+        (fun c ->
+           if c = ch then
+             flush ()
+           else
+             Buffer.add_char buf c)
+        s;
+      flush ();
+      List.rev !x
+
 
   let split_nl s = split s '\n'
 
+
   let before_space s =
     try
       String.before s (String.index s ' ')
     with Not_found -> s
 
-  (* this lists all supported packages *)
+  (* ocamlfind command *)
+  let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x]
+
+  (* This lists all supported packages. *)
   let find_packages () =
     List.map before_space (split_nl & run_and_read "ocamlfind list")
 
-  (* this is supposed to list available syntaxes, but I don't know how to do it. *)
+
+  (* Mock to list available syntaxes. *)
   let find_syntaxes () = ["camlp4o"; "camlp4r"]
 
-  (* ocamlfind command *)
-  let ocamlfind x = S[A"ocamlfind"; x]
+
+  let well_known_syntax = [
+    "camlp4.quotations.o";
+    "camlp4.quotations.r";
+    "camlp4.exceptiontracer";
+    "camlp4.extend";
+    "camlp4.foldgenerator";
+    "camlp4.listcomprehension";
+    "camlp4.locationstripper";
+    "camlp4.macro";
+    "camlp4.mapgenerator";
+    "camlp4.metagenerator";
+    "camlp4.profiler";
+    "camlp4.tracer"
+  ]
+
 
   let dispatch =
     function
-      | Before_options ->
-          (* by using Before_options one let command line options have an higher priority *)
-          (* on the contrary using After_options will guarantee to have the higher priority *)
-          (* override default commands by ocamlfind ones *)
+      | After_options ->
+          (* By using Before_options one let command line options have an higher
+           * priority on the contrary using After_options will guarantee to have
+           * the higher priority override default commands by ocamlfind ones *)
           Options.ocamlc     := ocamlfind & A"ocamlc";
           Options.ocamlopt   := ocamlfind & A"ocamlopt";
           Options.ocamldep   := ocamlfind & A"ocamldep";
           Options.ocamldoc   := ocamlfind & A"ocamldoc";
-          Options.ocamlmktop := ocamlfind & A"ocamlmktop"
-                                  
+          Options.ocamlmktop := ocamlfind & A"ocamlmktop";
+          Options.ocamlmklib := ocamlfind & A"ocamlmklib"
+
       | After_rules ->
-          
-          (* When one link an OCaml library/binary/package, one should use -linkpkg *)
+
+          (* When one link an OCaml library/binary/package, one should use
+           * -linkpkg *)
           flag ["ocaml"; "link"; "program"] & A"-linkpkg";
-          
+
           (* For each ocamlfind package one inject the -package option when
            * compiling, computing dependencies, generating documentation and
            * linking. *)
-          List.iter 
+          List.iter
             begin fun pkg ->
-              flag ["ocaml"; "compile";  "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "doc";      "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "link";     "pkg_"^pkg] & S[A"-package"; A pkg];
-              flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S[A"-package"; A pkg];
-            end 
+              let base_args = [A"-package"; A pkg] in
+              (* TODO: consider how to really choose camlp4o or camlp4r. *)
+              let syn_args = [A"-syntax"; A "camlp4o"] in
+              let args =
+              (* Heuristic to identify syntax extensions: whether they end in
+                 ".syntax"; some might not.
+               *)
+                if Filename.check_suffix pkg "syntax" ||
+                   List.mem pkg well_known_syntax then
+                  syn_args @ base_args
+                else
+                  base_args
+              in
+              flag ["ocaml"; "compile";  "pkg_"^pkg] & S args;
+              flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
+              flag ["ocaml"; "doc";      "pkg_"^pkg] & S args;
+              flag ["ocaml"; "link";     "pkg_"^pkg] & S base_args;
+              flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
+            end
             (find_packages ());
 
           (* Like -package but for extensions syntax. Morover -syntax is useless
           flag ["ocaml"; "compile";  "syntax_"^syntax] & S[A"-syntax"; A syntax];
           flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
           flag ["ocaml"; "doc";      "syntax_"^syntax] & S[A"-syntax"; A syntax];
-          flag ["ocaml"; "infer_interface"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
+          flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
+                S[A"-syntax"; A syntax];
           end (find_syntaxes ());
 
           (* The default "thread" tag is not compatible with ocamlfind.
            * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
            * options when using this tag. When using the "-linkpkg" option with
            * ocamlfind, this module will then be added twice on the command line.
-           *                        
+           *
            * To solve this, one approach is to add the "-thread" option when using
            * the "threads" package using the previous plugin.
            *)
           flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
           flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
           flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
-          flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"])
+          flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]);
+          flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]);
+          flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]);
+          flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]);
+          flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]);
 
-      | _ -> 
+      | _ ->
           ()
-
 end
 
 module MyOCamlbuildBase = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+
 
   (** Base functions for writing myocamlbuild.ml
       @author Sylvain Le Gall
 
 
 
+
+
   open Ocamlbuild_plugin
   module OC = Ocamlbuild_pack.Ocaml_compiler
 
-  type dir = string 
-  type file = string 
-  type name = string 
-  type tag = string 
 
-(* # 56 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+  type dir = string
+  type file = string
+  type name = string
+  type tag = string
+
+
+(* # 62 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
+
 
   type t =
       {
-        lib_ocaml: (name * dir list) list;
-        lib_c:     (name * dir * file list) list; 
+        lib_ocaml: (name * dir list * string list) list;
+        lib_c:     (name * dir * file list) list;
         flags:     (tag list * (spec OASISExpr.choices)) list;
         (* Replace the 'dir: include' from _tags by a precise interdepends in
          * directory.
          *)
-        includes:  (dir * dir list) list; 
-      } 
+        includes:  (dir * dir list) list;
+      }
+
 
   let env_filename =
-    Pathname.basename 
+    Pathname.basename
       BaseEnvLight.default_filename
 
+
   let dispatch_combine lst =
     fun e ->
-      List.iter 
+      List.iter
         (fun dispatch -> dispatch e)
-        lst 
+        lst
+
 
   let tag_libstubs nm =
     "use_lib"^nm^"_stubs"
 
+
   let nm_libstubs nm =
     nm^"_stubs"
 
-  let dispatch t e = 
-    let env = 
-      BaseEnvLight.load 
-        ~filename:env_filename 
+
+  let dispatch t e =
+    let env =
+      BaseEnvLight.load
+        ~filename:env_filename
         ~allow_empty:true
         ()
     in
-      match e with 
+      match e with
         | Before_options ->
             let no_trailing_dot s =
               if String.length s >= 1 && s.[0] = '.' then
             in
               List.iter
                 (fun (opt, var) ->
-                   try 
+                   try
                      opt := no_trailing_dot (BaseEnvLight.var_get var env)
                    with Not_found ->
-                     Printf.eprintf "W: Cannot get variable %s" var)
+                     Printf.eprintf "W: Cannot get variable %s\n" var)
                 [
                   Options.ext_obj, "ext_obj";
                   Options.ext_lib, "ext_lib";
                   Options.ext_dll, "ext_dll";
                 ]
 
-        | After_rules -> 
+        | After_rules ->
             (* Declare OCaml libraries *)
-            List.iter 
+            List.iter
               (function
-                 | nm, [] ->
-                     ocaml_lib nm
-                 | nm, dir :: tl ->
+                 | nm, [], intf_modules ->
+                     ocaml_lib nm;
+                     let cmis =
+                       List.map (fun m -> (String.uncapitalize m) ^ ".cmi")
+                                intf_modules in
+                     dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis
+                 | nm, dir :: tl, intf_modules ->
                      ocaml_lib ~dir:dir (dir^"/"^nm);
-                     List.iter 
-                       (fun dir -> 
+                     List.iter
+                       (fun dir ->
                           List.iter
                             (fun str ->
                                flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
                             ["compile"; "infer_interface"; "doc"])
-                       tl)
+                       tl;
+                     let cmis =
+                       List.map (fun m -> dir^"/"^(String.uncapitalize m)^".cmi")
+                                intf_modules in
+                     dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"]
+                         cmis)
               t.lib_ocaml;
 
             (* Declare directories dependencies, replace "include" in _tags. *)
-            List.iter 
+            List.iter
               (fun (dir, include_dirs) ->
                  Pathname.define_context dir include_dirs)
               t.includes;
 
                    flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
                      (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
-                        
+
                    flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
                      (S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
 
 
                    (* TODO: be more specific about what depends on headers *)
                    (* Depends on .h files *)
-                   dep ["compile"; "c"] 
+                   dep ["compile"; "c"]
                      headers;
 
                    (* Setup search path for lib *)
-                   flag ["link"; "ocaml"; "use_"^lib] 
+                   flag ["link"; "ocaml"; "use_"^lib]
                      (S[A"-I"; P(dir)]);
               )
               t.lib_c;
               (* Add flags *)
               List.iter
               (fun (tags, cond_specs) ->
-                 let spec = 
-                   BaseEnvLight.var_choose cond_specs env
+                 let spec = BaseEnvLight.var_choose cond_specs env in
+                 let rec eval_specs =
+                   function
+                     | S lst -> S (List.map eval_specs lst)
+                     | A str -> A (BaseEnvLight.var_expand str env)
+                     | spec -> spec
                  in
-                   flag tags & spec)
+                   flag tags & (eval_specs spec))
               t.flags
-        | _ -> 
+        | _ ->
             ()
 
+
   let dispatch_default t =
-    dispatch_combine 
+    dispatch_combine
       [
         dispatch t;
         MyOCamlbuildFindlib.dispatch;
       ]
 
+
 end
 
 
-# 476 "myocamlbuild.ml"
+# 594 "myocamlbuild.ml"
 open Ocamlbuild_plugin;;
 let package_default =
   {
-     MyOCamlbuildBase.lib_ocaml = [("nlopt", ["src"])];
+     MyOCamlbuildBase.lib_ocaml = [("nlopt", ["src"], [])];
      lib_c = [("nlopt", "src", [])];
      flags =
        [
                    ])
             ]);
           (["oasis_library_nlopt_cclib"; "link"],
-            [(OASISExpr.EBool true, S [A "-cclib"; A "-lnlopt"])]);
+            [
+               (OASISExpr.EBool true, S []);
+               (OASISExpr.ETest ("system", "macosx"),
+                 S [A "-cclib"; A "-lnlopt_cxx"]);
+               (OASISExpr.ENot (OASISExpr.ETest ("system", "macosx")),
+                 S [A "-cclib"; A "-lnlopt"])
+            ]);
           (["oasis_library_nlopt_cclib"; "ocamlmklib"; "c"],
-            [(OASISExpr.EBool true, S [A "-lnlopt"])])
+            [
+               (OASISExpr.EBool true, S []);
+               (OASISExpr.ETest ("system", "macosx"), S [A "-lnlopt_cxx"]);
+               (OASISExpr.ENot (OASISExpr.ETest ("system", "macosx")),
+                 S [A "-lnlopt"])
+            ])
        ];
-     includes = [("examples", ["src"])];
-     }
+     includes = [("examples", ["src"])]
+  }
   ;;
 
 let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;;
 
-# 509 "myocamlbuild.ml"
+# 638 "myocamlbuild.ml"
 (* OASIS_STOP *)
 Ocamlbuild_plugin.dispatch dispatch_default;;
 (* setup.ml generated for the first time by OASIS v0.3.0 *)
 
 (* OASIS_START *)
-(* DO NOT EDIT (digest: b285737fc18d49faa4b58b953e186fdc) *)
+(* DO NOT EDIT (digest: 82dcf4f8cbedf051c6be671fbb62842a) *)
 (*
-   Regenerated by OASIS v0.3.0
+   Regenerated by OASIS v0.4.4
    Visit http://oasis.forge.ocamlcore.org for more information and
    documentation about functions used in this file.
 *)
 module OASISGettext = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISGettext.ml" *)
+(* # 22 "src/oasis/OASISGettext.ml" *)
+
 
   let ns_ str =
     str
 
+
   let s_ str =
     str
 
-  let f_ (str : ('a, 'b, 'c, 'd) format4) =
+
+  let f_ (str: ('a, 'b, 'c, 'd) format4) =
     str
 
+
   let fn_ fmt1 fmt2 n =
     if n = 1 then
       fmt1^^""
     else
       fmt2^^""
 
+
   let init =
     []
 
+
 end
 
 module OASISContext = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISContext.ml" *)
+(* # 22 "src/oasis/OASISContext.ml" *)
+
 
   open OASISGettext
 
+
   type level =
     [ `Debug
     | `Info
     | `Warning
     | `Error]
 
+
   type t =
     {
+      (* TODO: replace this by a proplist. *)
       quiet:                 bool;
       info:                  bool;
       debug:                 bool;
       printf:                level -> string -> unit;
     }
 
+
   let printf lvl str =
     let beg =
       match lvl with
     in
       prerr_endline (beg^str)
 
+
   let default =
     ref
       {
         printf                = printf;
       }
 
+
   let quiet =
     {!default with quiet = true}
 
 
-  let args () =
+  let fspecs () =
+    (* TODO: don't act on default. *)
+    let ignore_plugins = ref false in
     ["-quiet",
      Arg.Unit (fun () -> default := {!default with quiet = true}),
-     (s_ " Run quietly");
+     s_ " Run quietly";
 
      "-info",
      Arg.Unit (fun () -> default := {!default with info = true}),
-     (s_ " Display information message");
+     s_ " Display information message";
 
 
      "-debug",
      Arg.Unit (fun () -> default := {!default with debug = true}),
-     (s_ " Output debug message")]
+     s_ " Output debug message";
+
+     "-ignore-plugins",
+     Arg.Set ignore_plugins,
+     s_ " Ignore plugin's field.";
+
+     "-C",
+     (* TODO: remove this chdir. *)
+     Arg.String (fun str -> Sys.chdir str),
+     s_ "dir Change directory before running."],
+    fun () -> {!default with ignore_plugins = !ignore_plugins}
 end
 
 module OASISString = struct
-(* # 1 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISString.ml" *)
-
+(* # 22 "src/oasis/OASISString.ml" *)
 
 
   (** Various string utilities.
-     
+
       Mostly inspired by extlib and batteries ExtString and BatString libraries.
 
       @author Sylvain Le Gall
     *)
 
+
   let nsplitf str f =
     if str = "" then
       []
         push ();
         List.rev !lst
 
+
   (** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
       separator.
     *)
   let nsplit str c =
     nsplitf str ((=) c)
 
+
   let find ~what ?(offset=0) str =
     let what_idx = ref 0 in
-    let str_idx = ref offset in 
-      while !str_idx < String.length str && 
+    let str_idx = ref offset in
+      while !str_idx < String.length str &&
             !what_idx < String.length what do
         if str.[!str_idx] = what.[!what_idx] then
           incr what_idx
       done;
       if !what_idx <> String.length what then
         raise Not_found
-      else 
+      else
         !str_idx - !what_idx
 
-  let sub_start str len = 
+
+  let sub_start str len =
     let str_len = String.length str in
     if len >= str_len then
       ""
     else
       String.sub str len (str_len - len)
 
+
   let sub_end ?(offset=0) str len =
     let str_len = String.length str in
     if len >= str_len then
     else
       String.sub str 0 (str_len - len)
 
+
   let starts_with ~what ?(offset=0) str =
     let what_idx = ref 0 in
     let str_idx = ref offset in
     let ok = ref true in
       while !ok &&
-            !str_idx < String.length str && 
+            !str_idx < String.length str &&
             !what_idx < String.length what do
         if str.[!str_idx] = what.[!what_idx] then
           incr what_idx
       done;
       if !what_idx = String.length what then
         true
-      else 
+      else
         false
 
+
   let strip_starts_with ~what str =
     if starts_with ~what str then
       sub_start str (String.length what)
     else
       raise Not_found
 
+
   let ends_with ~what ?(offset=0) str =
     let what_idx = ref ((String.length what) - 1) in
     let str_idx = ref ((String.length str) - 1) in
     let ok = ref true in
       while !ok &&
-            offset <= !str_idx && 
+            offset <= !str_idx &&
             0 <= !what_idx do
         if str.[!str_idx] = what.[!what_idx] then
           decr what_idx
       done;
       if !what_idx = -1 then
         true
-      else 
+      else
         false
 
+
   let strip_ends_with ~what str =
     if ends_with ~what str then
       sub_end str (String.length what)
     else
       raise Not_found
 
+
   let replace_chars f s =
     let buf = String.make (String.length s) 'X' in
       for i = 0 to String.length s - 1 do
       done;
       buf
 
+
 end
 
 module OASISUtils = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISUtils.ml" *)
+(* # 22 "src/oasis/OASISUtils.ml" *)
+
 
   open OASISGettext
 
-  module MapString = Map.Make(String)
-
-  let map_string_of_assoc assoc =
-    List.fold_left
-      (fun acc (k, v) -> MapString.add k v acc)
-      MapString.empty
-      assoc
-
-  module SetString = Set.Make(String)
-
-  let set_string_add_list st lst =
-    List.fold_left
-      (fun acc e -> SetString.add e acc)
-      st
-      lst
-
-  let set_string_of_list =
-    set_string_add_list
-      SetString.empty
+
+  module MapExt =
+  struct
+    module type S =
+    sig
+      include Map.S
+      val add_list: 'a t -> (key * 'a) list -> 'a t
+      val of_list: (key * 'a) list -> 'a t
+      val to_list: 'a t -> (key * 'a) list
+    end
+
+    module Make (Ord: Map.OrderedType) =
+    struct
+      include Map.Make(Ord)
+
+      let rec add_list t =
+        function
+          | (k, v) :: tl -> add_list (add k v t) tl
+          | [] -> t
+
+      let of_list lst = add_list empty lst
+
+      let to_list t = fold (fun k v acc -> (k, v) :: acc) t []
+    end
+  end
+
+
+  module MapString = MapExt.Make(String)
+
+
+  module SetExt  =
+  struct
+    module type S =
+    sig
+      include Set.S
+      val add_list: t -> elt list -> t
+      val of_list: elt list -> t
+      val to_list: t -> elt list
+    end
+
+    module Make (Ord: Set.OrderedType) =
+    struct
+      include Set.Make(Ord)
+
+      let rec add_list t =
+        function
+          | e :: tl -> add_list (add e t) tl
+          | [] -> t
+
+      let of_list lst = add_list empty lst
+
+      let to_list = elements
+    end
+  end
+
+
+  module SetString = SetExt.Make(String)
 
 
   let compare_csl s1 s2 =
     String.compare (String.lowercase s1) (String.lowercase s2)
 
+
   module HashStringCsl =
     Hashtbl.Make
       (struct
            Hashtbl.hash (String.lowercase s)
        end)
 
+  module SetStringCsl =
+    SetExt.Make
+      (struct
+         type t = string
+         let compare = compare_csl
+       end)
+
+
   let varname_of_string ?(hyphen='_') s =
     if String.length s = 0 then
       begin
           String.lowercase buf
       end
 
+
   let varname_concat ?(hyphen='_') p s =
     let what = String.make 1 hyphen in
     let p =
   let is_varname str =
     str = varname_of_string str
 
+
   let failwithf fmt = Printf.ksprintf failwith fmt
 
+
 end
 
 module PropList = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/PropList.ml" *)
+(* # 22 "src/oasis/PropList.ml" *)
+
 
   open OASISGettext
 
+
   type name = string
 
+
   exception Not_set of name * string option
   exception No_printer of name
   exception Unknown_field of name * name
 
+
   let () =
     Printexc.register_printer
       (function
          | Not_set (nm, Some rsn) ->
-             Some 
+             Some
                (Printf.sprintf (f_ "Field '%s' is not set: %s") nm rsn)
          | Not_set (nm, None) ->
-             Some 
+             Some
                (Printf.sprintf (f_ "Field '%s' is not set") nm)
          | No_printer nm ->
              Some
                (Printf.sprintf (f_ "No default printer for value %s") nm)
          | Unknown_field (nm, schm) ->
-             Some 
-               (Printf.sprintf (f_ "Field %s is not defined in schema %s") nm schm)
+             Some
+               (Printf.sprintf
+                  (f_ "Field %s is not defined in schema %s") nm schm)
          | _ ->
              None)
 
+
   module Data =
   struct
-
     type t =
         (name, unit -> unit) Hashtbl.t
 
     let clear t =
       Hashtbl.clear t
 
-(* # 71 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/PropList.ml" *)
+
+(* # 78 "src/oasis/PropList.ml" *)
   end
 
+
   module Schema =
   struct
-
     type ('ctxt, 'extra) value =
         {
           get:   Data.t -> string;
       t.name
   end
 
+
   module Field =
   struct
-
     type ('ctxt, 'value, 'extra) t =
         {
           set:    Data.t -> ?context:'ctxt -> 'value -> unit;
 
     let fgets data t =
       t.gets data
-
   end
 
+
   module FieldRO =
   struct
-
     let create ?schema ?name ?parse ?print ?default ?update ?help extra =
       let fld =
         Field.create ?schema ?name ?parse ?print ?default ?update ?help extra
       in
         fun data -> Field.fget data fld
-
   end
 end
 
 module OASISMessage = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISMessage.ml" *)
+(* # 22 "src/oasis/OASISMessage.ml" *)
 
 
   open OASISGettext
   open OASISContext
 
+
   let generic_message ~ctxt lvl fmt =
     let cond =
       if ctxt.quiet then
              end)
         fmt
 
+
   let debug ~ctxt fmt =
     generic_message ~ctxt `Debug fmt
 
+
   let info ~ctxt fmt =
     generic_message ~ctxt `Info fmt
 
+
   let warning ~ctxt fmt =
     generic_message ~ctxt `Warning fmt
 
+
   let error ~ctxt fmt =
     generic_message ~ctxt `Error fmt
 
 end
 
 module OASISVersion = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISVersion.ml" *)
+(* # 22 "src/oasis/OASISVersion.ml" *)
+
 
   open OASISGettext
 
 
 
+
+
   type s = string
 
-  type t = string 
+
+  type t = string
+
 
   type comparator =
     | VGreater of t
     | VLesserEqual of t
     | VOr of  comparator * comparator
     | VAnd of comparator * comparator
-    
+
+
 
   (* Range of allowed characters *)
   let is_digit c =
     '0' <= c && c <= '9'
 
+
   let is_alpha c =
     ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
 
+
   let is_special =
     function
       | '.' | '+' | '-' | '~' -> true
       | _ -> false
 
+
   let rec version_compare v1 v2 =
     if v1 <> "" || v2 <> "" then
       begin
               while !p < String.length v && is_digit v.[!p] do
                 incr p
               done;
-              let substr = 
+              let substr =
                 String.sub v !p ((String.length v) - !p)
-              in 
-              let res = 
-                match String.sub v start_p (!p - start_p) with 
+              in
+              let res =
+                match String.sub v start_p (!p - start_p) with
                   | "" -> 0
                   | s -> int_of_string s
               in
 
   let version_of_string str = str
 
+
   let string_of_version t = t
 
+
+  let version_compare_string s1 s2 =
+    version_compare (version_of_string s1) (version_of_string s2)
+
+
   let chop t =
     try
       let pos =
     with Not_found ->
       t
 
+
   let rec comparator_apply v op =
     match op with
       | VGreater cv ->
       | VAnd (op1, op2) ->
           (comparator_apply v op1) && (comparator_apply v op2)
 
+
   let rec string_of_comparator =
     function
       | VGreater v  -> "> "^(string_of_version v)
       | VAnd (c1, c2) ->
           (string_of_comparator c1)^" && "^(string_of_comparator c2)
 
+
   let rec varname_of_comparator =
     let concat p v =
       OASISUtils.varname_concat
         | VAnd (c1, c2) ->
             (varname_of_comparator c1)^"_and_"^(varname_of_comparator c2)
 
-  let version_0_3_or_after t =
-    comparator_apply t (VGreaterEqual (string_of_version "0.3"))
+
+  let rec comparator_ge v' =
+    let cmp v = version_compare v v' >= 0 in
+    function
+      | VEqual v
+      | VGreaterEqual v
+      | VGreater v -> cmp v
+      | VLesserEqual _
+      | VLesser _ -> false
+      | VOr (c1, c2) -> comparator_ge v' c1 || comparator_ge v' c2
+      | VAnd (c1, c2) -> comparator_ge v' c1 && comparator_ge v' c2
+
 
 end
 
 module OASISLicense = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISLicense.ml" *)
+(* # 22 "src/oasis/OASISLicense.ml" *)
+
 
   (** License for _oasis fields
       @author Sylvain Le Gall
 
 
 
-  type license = string 
-
-  type license_exception = string 
+
+
+  type license = string
+
+
+  type license_exception = string
+
 
   type license_version =
     | Version of OASISVersion.t
     | VersionOrLater of OASISVersion.t
     | NoVersion
-    
+
+
 
   type license_dep_5_unit =
     {
       excption:  license_exception option;
       version:   license_version;
     }
-    
+
+
 
   type license_dep_5 =
     | DEP5Unit of license_dep_5_unit
     | DEP5Or of license_dep_5 list
     | DEP5And of license_dep_5 list
-    
+
 
   type t =
     | DEP5License of license_dep_5
     | OtherLicense of string (* URL *)
-    
+
+
 
 end
 
 module OASISExpr = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISExpr.ml" *)
+(* # 22 "src/oasis/OASISExpr.ml" *)
+
+
 
 
 
   open OASISGettext
 
-  type test = string 
-
-  type flag = string 
+
+  type test = string
+
+
+  type flag = string
+
 
   type t =
     | EBool of bool
     | EOr of t * t
     | EFlag of flag
     | ETest of test * string
-    
-
-  type 'a choices = (t * 'a) list 
+
+
+
+  type 'a choices = (t * 'a) list
+
 
   let eval var_get t =
     let rec eval' =
     in
       eval' t
 
+
   let choose ?printer ?name var_get lst =
     let rec choose_aux =
       function
     in
       choose_aux (List.rev lst)
 
+
 end
 
+module OASISText = struct
+(* # 22 "src/oasis/OASISText.ml" *)
+
+
+
+  type elt =
+    | Para of string
+    | Verbatim of string
+    | BlankLine
+
+
+  type t = elt list
+
+end
+
 module OASISTypes = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISTypes.ml" *)
-
-
-
-
-  type name          = string 
-  type package_name  = string 
-  type url           = string 
-  type unix_dirname  = string 
-  type unix_filename = string 
-  type host_dirname  = string 
-  type host_filename = string 
-  type prog          = string 
-  type arg           = string 
-  type args          = string list 
-  type command_line  = (prog * arg list) 
-
-  type findlib_name = string 
-  type findlib_full = string 
+(* # 22 "src/oasis/OASISTypes.ml" *)
+
+
+
+
+
+  type name          = string
+  type package_name  = string
+  type url           = string
+  type unix_dirname  = string
+  type unix_filename = string
+  type host_dirname  = string
+  type host_filename = string
+  type prog          = string
+  type arg           = string
+  type args          = string list
+  type command_line  = (prog * arg list)
+
+
+  type findlib_name = string
+  type findlib_full = string
+
 
   type compiled_object =
     | Byte
     | Native
     | Best
-    
+
+
 
   type dependency =
     | FindlibPackage of findlib_full * OASISVersion.comparator option
     | InternalLibrary of name
-    
+
+
 
   type tool =
     | ExternalTool of name
     | InternalExecutable of name
-    
+
+
 
   type vcs =
     | Darcs
     | Arch
     | Monotone
     | OtherVCS of url
-    
+
+
 
   type plugin_kind =
       [  `Configure
        | `Extra
       ]
 
+
   type plugin_data_purpose =
       [  `Configure
        | `Build
        | `Other of string
       ]
 
-  type 'a plugin = 'a * name * OASISVersion.t option 
+
+  type 'a plugin = 'a * name * OASISVersion.t option
+
 
   type all_plugin = plugin_kind plugin
 
+
   type plugin_data = (all_plugin * plugin_data_purpose * (unit -> unit)) list
 
-(* # 102 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISTypes.ml" *)
-
-  type 'a conditional = 'a OASISExpr.choices 
+
+(* # 115 "src/oasis/OASISTypes.ml" *)
+
+
+  type 'a conditional = 'a OASISExpr.choices
+
 
   type custom =
       {
         pre_command:  (command_line option) conditional;
         post_command: (command_line option) conditional;
       }
-      
+
+
 
   type common_section =
       {
         cs_data: PropList.Data.t;
         cs_plugin_data: plugin_data;
       }
-      
+
+
 
   type build_section =
       {
         bs_byteopt:         args conditional;
         bs_nativeopt:       args conditional;
       }
-      
+
+
 
   type library =
       {
         lib_findlib_parent:     findlib_name option;
         lib_findlib_name:       findlib_name option;
         lib_findlib_containers: findlib_name list;
-      } 
+      }
+
+
+  type object_ =
+      {
+        obj_modules:            string list;
+        obj_findlib_fullname:   findlib_name list option;
+      }
+
 
   type executable =
       {
         exec_custom:          bool;
         exec_main_is:         unix_filename;
-      } 
+      }
+
 
   type flag =
       {
         flag_description:  string option;
         flag_default:      bool conditional;
-      } 
+      }
+
 
   type source_repository =
       {
         src_repo_branch:      string option;
         src_repo_tag:         string option;
         src_repo_subdir:      unix_filename option;
-      } 
+      }
+
 
   type test =
       {
         test_working_directory:  unix_filename option;
         test_run:                bool conditional;
         test_tools:              tool list;
-      } 
+      }
+
 
   type doc_format =
     | HTML of unix_filename
     | Info of unix_filename
     | DVI
     | OtherDoc
-    
+
+
 
   type doc =
       {
         doc_format:      doc_format;
         doc_data_files:  (unix_filename * unix_filename option) list;
         doc_build_tools: tool list;
-      } 
+      }
+
 
   type section =
     | Library    of common_section * build_section * library
+    | Object     of common_section * build_section * object_
     | Executable of common_section * build_section * executable
     | Flag       of common_section * flag
     | SrcRepo    of common_section * source_repository
     | Test       of common_section * test
     | Doc        of common_section * doc
-    
+
+
 
   type section_kind =
-      [ `Library | `Executable | `Flag | `SrcRepo | `Test | `Doc ]
-
-  type package = 
+      [ `Library | `Object | `Executable | `Flag | `SrcRepo | `Test | `Doc ]
+
+
+  type package =
       {
-        oasis_version:    OASISVersion.t;
-        ocaml_version:    OASISVersion.comparator option;
-        findlib_version:  OASISVersion.comparator option;
-        name:             package_name;
-        version:          OASISVersion.t;
-        license:          OASISLicense.t;
-        license_file:     unix_filename option;
-        copyrights:       string list;
-        maintainers:      string list;
-        authors:          string list;
-        homepage:         url option;
-        synopsis:         string;
-        description:      string option;
-        categories:       url list;
-
-        conf_type:        [`Configure] plugin;
-        conf_custom:      custom;
-
-        build_type:       [`Build] plugin;
-        build_custom:     custom;
-
-        install_type:     [`Install] plugin;
-        install_custom:   custom;
-        uninstall_custom: custom;
-
-        clean_custom:     custom;
-        distclean_custom: custom;
-
-        files_ab:         unix_filename list;
-        sections:         section list;
-        plugins:          [`Extra] plugin list;
-        schema_data:      PropList.Data.t;
-        plugin_data:      plugin_data;
-      } 
+        oasis_version:          OASISVersion.t;
+        ocaml_version:          OASISVersion.comparator option;
+        findlib_version:        OASISVersion.comparator option;
+        alpha_features:         string list;
+        beta_features:          string list;
+        name:                   package_name;
+        version:                OASISVersion.t;
+        license:                OASISLicense.t;
+        license_file:           unix_filename option;
+        copyrights:             string list;
+        maintainers:            string list;
+        authors:                string list;
+        homepage:               url option;
+        synopsis:               string;
+        description:            OASISText.t option;
+        categories:             url list;
+
+        conf_type:              [`Configure] plugin;
+        conf_custom:            custom;
+
+        build_type:             [`Build] plugin;
+        build_custom:           custom;
+
+        install_type:           [`Install] plugin;
+        install_custom:         custom;
+        uninstall_custom:       custom;
+
+        clean_custom:           custom;
+        distclean_custom:       custom;
+
+        files_ab:               unix_filename list;
+        sections:               section list;
+        plugins:                [`Extra] plugin list;
+        disable_oasis_section:  unix_filename list;
+        schema_data:            PropList.Data.t;
+        plugin_data:            plugin_data;
+      }
+
 
 end
 
+module OASISFeatures = struct
+(* # 22 "src/oasis/OASISFeatures.ml" *)
+
+  open OASISTypes
+  open OASISUtils
+  open OASISGettext
+  open OASISVersion
+
+  module MapPlugin =
+    Map.Make
+      (struct
+         type t = plugin_kind * name
+         let compare = Pervasives.compare
+       end)
+
+  module Data =
+  struct
+    type t =
+        {
+          oasis_version: OASISVersion.t;
+          plugin_versions: OASISVersion.t option MapPlugin.t;
+          alpha_features: string list;
+          beta_features: string list;
+        }
+
+    let create oasis_version alpha_features beta_features =
+      {
+        oasis_version = oasis_version;
+        plugin_versions = MapPlugin.empty;
+        alpha_features = alpha_features;
+        beta_features = beta_features
+      }
+
+    let of_package pkg =
+      create
+        pkg.OASISTypes.oasis_version
+        pkg.OASISTypes.alpha_features
+        pkg.OASISTypes.beta_features
+
+    let add_plugin (plugin_kind, plugin_name, plugin_version) t =
+      {t with
+           plugin_versions = MapPlugin.add
+                               (plugin_kind, plugin_name)
+                               plugin_version
+                               t.plugin_versions}
+
+    let plugin_version plugin_kind plugin_name t =
+      MapPlugin.find (plugin_kind, plugin_name) t.plugin_versions
+
+    let to_string t =
+      Printf.sprintf
+        "oasis_version: %s; alpha_features: %s; beta_features: %s; \
+         plugins_version: %s"
+        (OASISVersion.string_of_version t.oasis_version)
+        (String.concat ", " t.alpha_features)
+        (String.concat ", " t.beta_features)
+        (String.concat ", "
+           (MapPlugin.fold
+              (fun (_, plg) ver_opt acc ->
+                 (plg^
+                  (match ver_opt with
+                     | Some v ->
+                         " "^(OASISVersion.string_of_version v)
+                     | None -> ""))
+                 :: acc)
+              t.plugin_versions []))
+  end
+
+  type origin =
+    | Field of string * string
+    | Section of string
+    | NoOrigin
+
+  type stage = Alpha | Beta
+
+
+  let string_of_stage =
+    function
+      | Alpha -> "alpha"
+      | Beta -> "beta"
+
+
+  let field_of_stage =
+    function
+      | Alpha -> "AlphaFeatures"
+      | Beta -> "BetaFeatures"
+
+  type publication = InDev of stage | SinceVersion of OASISVersion.t
+
+  type t =
+      {
+        name: string;
+        plugin: all_plugin option;
+        publication: publication;
+        description: unit -> string;
+      }
+
+  (* TODO: mutex protect this. *)
+  let all_features = Hashtbl.create 13
+
+
+  let since_version ver_str = SinceVersion (version_of_string ver_str)
+  let alpha = InDev Alpha
+  let beta = InDev Beta
+
+
+  let to_string t =
+    Printf.sprintf
+      "feature: %s; plugin: %s; publication: %s"
+      t.name
+      (match t.plugin with
+         | None -> "<none>"
+         | Some (_, nm, _) -> nm)
+      (match t.publication with
+         | InDev stage -> string_of_stage stage
+         | SinceVersion ver -> ">= "^(OASISVersion.string_of_version ver))
+
+  let data_check t data origin =
+    let no_message = "no message" in
+
+    let check_feature features stage =
+      let has_feature = List.mem t.name features in
+      if not has_feature then
+        match origin with
+          | Field (fld, where) ->
+              Some
+                (Printf.sprintf
+                   (f_ "Field %s in %s is only available when feature %s \
+                        is in field %s.")
+                   fld where t.name (field_of_stage stage))
+          | Section sct ->
+              Some
+                (Printf.sprintf
+                   (f_ "Section %s is only available when features %s \
+                        is in field %s.")
+                   sct t.name (field_of_stage stage))
+          | NoOrigin ->
+              Some no_message
+      else
+        None
+    in
+
+    let version_is_good ~min_version version fmt =
+      let version_is_good =
+        OASISVersion.comparator_apply
+          version (OASISVersion.VGreaterEqual min_version)
+      in
+        Printf.ksprintf
+          (fun str ->
+             if version_is_good then
+               None
+             else
+               Some str)
+          fmt
+    in
+
+    match origin, t.plugin, t.publication with
+      | _, _, InDev Alpha -> check_feature data.Data.alpha_features Alpha
+      | _, _, InDev Beta -> check_feature data.Data.beta_features Beta
+      | Field(fld, where), None, SinceVersion min_version ->
+          version_is_good ~min_version data.Data.oasis_version
+            (f_ "Field %s in %s is only valid since OASIS v%s, update \
+                 OASISFormat field from '%s' to '%s' after checking \
+                 OASIS changelog.")
+            fld where (string_of_version min_version)
+            (string_of_version data.Data.oasis_version)
+            (string_of_version min_version)
+
+      | Field(fld, where), Some(plugin_knd, plugin_name, _),
+        SinceVersion min_version ->
+          begin
+            try
+              let plugin_version_current =
+                try
+                  match Data.plugin_version plugin_knd plugin_name data with
+                    | Some ver -> ver
+                    | None ->
+                        failwithf
+                          (f_ "Field %s in %s is only valid for the OASIS \
+                               plugin %s since v%s, but no plugin version is \
+                               defined in the _oasis file, change '%s' to \
+                               '%s (%s)' in your _oasis file.")
+                          fld where plugin_name (string_of_version min_version)
+                          plugin_name
+                          plugin_name (string_of_version min_version)
+                with Not_found ->
+                  failwithf
+                    (f_ "Field %s in %s is only valid when the OASIS plugin %s \
+                         is defined.")
+                    fld where plugin_name
+              in
+              version_is_good ~min_version plugin_version_current
+                (f_ "Field %s in %s is only valid for the OASIS plugin %s \
+                     since v%s, update your plugin from '%s (%s)' to \
+                     '%s (%s)' after checking the plugin's changelog.")
+                fld where plugin_name (string_of_version min_version)
+                plugin_name (string_of_version plugin_version_current)
+                plugin_name (string_of_version min_version)
+            with Failure msg ->
+              Some msg
+          end
+
+      | Section sct, None, SinceVersion min_version ->
+          version_is_good ~min_version data.Data.oasis_version
+            (f_ "Section %s is only valid for since OASIS v%s, update \
+                 OASISFormat field from '%s' to '%s' after checking OASIS \
+                 changelog.")
+            sct (string_of_version min_version)
+            (string_of_version data.Data.oasis_version)
+            (string_of_version min_version)
+
+      | Section sct, Some(plugin_knd, plugin_name, _),
+        SinceVersion min_version ->
+          begin
+            try
+              let plugin_version_current =
+                try
+                  match Data.plugin_version plugin_knd plugin_name data with
+                    | Some ver -> ver
+                    | None ->
+                        failwithf
+                          (f_ "Section %s is only valid for the OASIS \
+                               plugin %s since v%s, but no plugin version is \
+                               defined in the _oasis file, change '%s' to \
+                               '%s (%s)' in your _oasis file.")
+                          sct plugin_name (string_of_version min_version)
+                          plugin_name
+                          plugin_name (string_of_version min_version)
+                with Not_found ->
+                  failwithf
+                    (f_ "Section %s is only valid when the OASIS plugin %s \
+                         is defined.")
+                    sct plugin_name
+              in
+              version_is_good ~min_version plugin_version_current
+                (f_ "Section %s is only valid for the OASIS plugin %s \
+                     since v%s, update your plugin from '%s (%s)' to \
+                     '%s (%s)' after checking the plugin's changelog.")
+                sct plugin_name (string_of_version min_version)
+                plugin_name (string_of_version plugin_version_current)
+                plugin_name (string_of_version min_version)
+            with Failure msg ->
+              Some msg
+          end
+
+      | NoOrigin, None, SinceVersion min_version ->
+          version_is_good ~min_version data.Data.oasis_version "%s" no_message
+
+      | NoOrigin, Some(plugin_knd, plugin_name, _), SinceVersion min_version ->
+          begin
+            try
+              let plugin_version_current =
+                match Data.plugin_version plugin_knd plugin_name data with
+                  | Some ver -> ver
+                  | None -> raise Not_found
+              in
+              version_is_good ~min_version plugin_version_current
+                "%s" no_message
+            with Not_found ->
+              Some no_message
+          end
+
+
+  let data_assert t data origin =
+    match data_check t data origin with
+      | None -> ()
+      | Some str -> failwith str
+
+
+  let data_test t data =
+    match data_check t data NoOrigin with
+      | None -> true
+      | Some str -> false
+
+
+  let package_test t pkg =
+    data_test t (Data.of_package pkg)
+
+
+  let create ?plugin name publication description =
+    let () =
+      if Hashtbl.mem all_features name then
+        failwithf "Feature '%s' is already declared." name
+    in
+    let t =
+      {
+        name = name;
+        plugin = plugin;
+        publication = publication;
+        description = description;
+      }
+    in
+      Hashtbl.add all_features name t;
+      t
+
+
+  let get_stage name =
+    try
+      (Hashtbl.find all_features name).publication
+    with Not_found ->
+      failwithf (f_ "Feature %s doesn't exist.") name
+
+
+  let list () =
+    Hashtbl.fold (fun _ v acc -> v :: acc) all_features []
+
+  (*
+   * Real flags.
+   *)
+
+
+  let features =
+    create "features_fields"
+      (since_version "0.4")
+      (fun () ->
+         s_ "Enable to experiment not yet official features.")
+
+
+  let flag_docs =
+    create "flag_docs"
+      (since_version "0.3")
+      (fun () ->
+         s_ "Building docs require '-docs' flag at configure.")
+
+
+  let flag_tests =
+    create "flag_tests"
+      (since_version "0.3")
+      (fun () ->
+         s_ "Running tests require '-tests' flag at configure.")
+
+
+  let pack =
+    create "pack"
+      (since_version "0.3")
+      (fun () ->
+         s_ "Allow to create packed library.")
+
+
+  let section_object =
+    create "section_object" beta
+      (fun () ->
+         s_ "Implement an object section.")
+
+
+  let dynrun_for_release =
+    create "dynrun_for_release" alpha
+      (fun () ->
+         s_ "Make '-setup-update dynamic' suitable for releasing project.")
+
+
+  let compiled_setup_ml =
+    create "compiled_setup_ml" alpha
+      (fun () ->
+         s_ "It compiles the setup.ml and speed-up actions done with it.")
+
+  let disable_oasis_section =
+    create "disable_oasis_section" alpha
+      (fun () ->
+        s_ "Allows the OASIS section comments and digest to be omitted in \
+            generated files.")
+end
+
 module OASISUnixPath = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISUnixPath.ml" *)
+(* # 22 "src/oasis/OASISUnixPath.ml" *)
+
 
   type unix_filename = string
   type unix_dirname = string
 
+
   type host_filename = string
   type host_dirname = string
 
+
   let current_dir_name = "."
 
+
   let parent_dir_name = ".."
 
+
   let is_current_dir fn =
     fn = current_dir_name || fn = ""
 
+
   let concat f1 f2 =
     if is_current_dir f1 then
       f2
       in
         f1'^"/"^f2
 
+
   let make =
     function
       | hd :: tl ->
       | [] ->
           invalid_arg "OASISUnixPath.make"
 
+
   let dirname f =
     try
       String.sub f 0 (String.rindex f '/')
     with Not_found ->
       current_dir_name
 
+
   let basename f =
     try
       let pos_start =
     with Not_found ->
       f
 
+
   let chop_extension f =
     try
       let last_dot =
     with Not_found ->
       f
 
+
   let capitalize_file f =
     let dir = dirname f in
     let base = basename f in
     concat dir (String.capitalize base)
 
+
   let uncapitalize_file f =
     let dir = dirname f in
     let base = basename f in
     concat dir (String.uncapitalize base)
 
+
 end
 
 module OASISHostPath = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISHostPath.ml" *)
+(* # 22 "src/oasis/OASISHostPath.ml" *)
 
 
   open Filename
 
+
   module Unix = OASISUnixPath
 
+
   let make =
     function
       | [] ->
       | hd :: tl ->
           List.fold_left Filename.concat hd tl
 
+
   let of_unix ufn =
     if Sys.os_type = "Unix" then
       ufn
 end
 
 module OASISSection = struct
-(* # 21 "/Users/mkur/.opam/4.00.1/build/oasis.0.3.0/src/oasis/OASISSection.ml" *)
+(* # 22 "src/oasis/OASISSection.ml" *)
+
 
   open OASISTypes
 
-  let section_kind_common = 
+
+  let section_kind_common =
     function
-      | Library (cs, _, _) -> 
+      | Library (cs, _, _) ->
           `Library, cs
+      | Object (cs, _, _) ->
+          `Object, cs
       | Executable (cs, _, _) ->
           `Executable, cs
       | Flag (cs, _) ->
       | Doc (cs, _) ->
           `Doc, cs
 
+
   let section_common sct =
     snd (section_kind_common sct)
 
+
   let section_common_set cs =
     function
       | Library (_, bs, lib)     -> Library (cs, bs, lib)
+      | Object (_, bs, obj)      -> Object (cs, bs, obj)
       | Executable (_, bs, exec) -> Executable (cs, bs, exec)
       | Flag (_, flg)            -> Flag (cs, flg)
       | SrcRepo (_, src_repo)    -> SrcRepo (cs, src_repo)
       | Test (_, tst)            -> Test (cs, tst)
       | Doc (_, doc)             -> Doc (cs, doc)
 
+
   (** Key used to identify section
     *)
-  let section_id sct = 
-    let k, cs = 
+  let section_id sct =
+    let k, cs =
       section_kind_common sct
     in
       k, cs.cs_name
 
+
   let string_of_section sct =
     let k, nm =
       section_id sct
     in
       (match k with
-         | `Library    -> "library" 
+         | `Library    -> "library"