(****************************************************************************)
(*  Copyright © 2012-2015 Mehdi Dogguy <mehdi@debian.org>                   *)
(*                                                                          *)
(*  This file is part of Dochelp.                                           *)
(*                                                                          *)
(*  Dochelp is free software: you can redistribute it and/or modify it      *)
(*  under the terms of the GNU General Public License as published by the   *)
(*  Free Software Foundation, either version 3 of the License, or (at your  *)
(*  option) any later version.                                              *)
(*                                                                          *)
(*  Dochelp is distributed in the hope that it will be useful, but WITHOUT  *)
(*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   *)
(*  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *)
(*  for more details.                                                       *)
(*                                                                          *)
(*  You should have received a copy of the GNU General Public License       *)
(*  along with Dochelp.  If not, see <http://www.gnu.org/licenses/>.        *)
(****************************************************************************)

open Printf
open Ocamlbuild_plugin

let packages = [
  "unix";
  "pcre";
  "tyxml";
  "cmdliner";
]

exception Require_findlib
exception Missing_findlib_package of string
exception Subprocess_died_unexpectedly of Unix.process_status

let try_exec cmd =
  Sys.command (sprintf "%s >/dev/null 2>&1" cmd) = 0

let try_run cmd = (* reads one single line *)
  let in_c = Unix.open_process_in cmd in
  let line = input_line in_c in
  let _ = Unix.close_process_in in_c in
  line

let version = try_run "dpkg-parsechangelog -S Version"

let require pkg =
  if not (try_exec (sprintf "ocamlfind query %s" pkg)) then
    raise (Missing_findlib_package pkg)

let ocamlfind x = S[A"ocamlfind"; A x]
let has_ocamlopt = try_exec "which ocamlopt"
let best =
  try Sys.getenv "OCAMLBEST"
  with Not_found -> if has_ocamlopt then "native" else "byte"
let () = if not (try_exec "ocamlfind printconf") then raise Require_findlib
let () = List.iter require packages

let () =
  dispatch begin function

    | Before_options ->
        Options.ocamlc := ocamlfind "ocamlc";
        Options.ocamlopt := ocamlfind "ocamlopt";
        Options.ocamldep := ocamlfind "ocamldep";
        Options.ocamldoc := ocamlfind "ocamldoc";
        Options.use_menhir := true;
        Options.ocaml_yaccflags := ["--explain"]

    | After_rules ->
        flag ["ocaml"; "link"; "program"] & A"-linkpkg";
        List.iter
          (fun pkg ->
             let flag x = flag (x::["ocaml"]) & S[A"-package"; A pkg] in
             List.iter flag ["ocamldep"; "compile"; "link"; "doc"])
          packages;

        (* C stubs *)
        flag ["link"; "program"; "ocaml"; "byte"; "use_libdochelp"]
          (S[A"-dllib"; A"-ldochelp"]);
        dep  ["link"; "ocaml"; "use_libdochelp"] ["src/libdochelp.a"];

        (* rule for the main executable that will link all frontends  *)
        rule "src/dochelp.ml" ~deps:["src/dochelp.mlp"] ~prod:"src/dochelp.ml" begin
          fun _ _ ->
            Cmd
              (S [A"sed";
                  A"-e"; A (sprintf "s/@VERSION@/%s/" version);
                  P"src/dochelp.mlp"; Sh">"; P"src/dochelp.ml"])
        end;

    | _ -> ()
  end
