ocaml/ocamlbuild/plugin.ml

122 lines
4.9 KiB
OCaml

(***********************************************************************)
(* *)
(* 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 Q Public License version 1.0. *)
(* *)
(***********************************************************************)
(* Original author: Nicolas Pouillard *)
open My_std
open Format
open Log
open Pathname.Operators
open Tags.Operators
open Rule
open Tools
open Command
;;
module Make(U:sig end) =
struct
let plugin = "myocamlbuild"
let plugin_file = plugin^".ml"
let plugin_config_file = plugin^"_config.ml"
let plugin_config_file_interface = plugin^"_config.mli"
let we_have_a_config_file = sys_file_exists plugin_config_file
let we_need_a_plugin = !Options.plugin && sys_file_exists plugin_file
let we_have_a_plugin = sys_file_exists ((!Options.build_dir/plugin)^(!Options.exe))
let we_have_a_config_file_interface = sys_file_exists plugin_config_file_interface
let up_to_date_or_copy fn =
let fn' = !Options.build_dir/fn in
Pathname.exists fn &&
begin
Pathname.exists fn' && Pathname.same_contents fn fn' ||
begin
Shell.cp fn fn';
false
end
end
let profiling = Tags.mem "profile" (tags_of_pathname plugin_file)
let debugging = Tags.mem "debug" (tags_of_pathname plugin_file)
let rebuild_plugin_if_needed () =
let a = up_to_date_or_copy plugin_file in
let b = (not we_have_a_config_file) or up_to_date_or_copy plugin_config_file in
let c = (not we_have_a_config_file_interface) or up_to_date_or_copy plugin_config_file_interface in
if a && b && c && we_have_a_plugin then
() (* Up to date *)
(* FIXME: remove ocamlbuild_config.ml in _build/ if removed in parent *)
else begin
if !Options.native_plugin
&& not (sys_file_exists ((!Ocamlbuild_where.libdir)/"ocamlbuildlib.cmxa")) then
begin
Options.native_plugin := false;
eprintf "Warning: Won't be able to compile a native plugin"
end;
let plugin_config =
if we_have_a_config_file then
if we_have_a_config_file_interface then
S[P plugin_config_file_interface; P plugin_config_file]
else P plugin_config_file
else N in
let cma, cmo, more_options, compiler =
if !Options.native_plugin then
"cmxa", "cmx", (if profiling then A"-p" else N), !Options.ocamlopt
else
"cma", "cmo", (if debugging then A"-g" else N), !Options.ocamlc
in
let ocamlbuildlib, ocamlbuild, libs =
if (not !Options.native_plugin) && !*My_unix.is_degraded then
"ocamlbuildlightlib", "ocamlbuildlight", N
else
"ocamlbuildlib", "ocamlbuild", A("unix"-.-cma)
in
let ocamlbuildlib = ocamlbuildlib-.-cma in
let ocamlbuild = ocamlbuild-.-cmo in
let dir = !Ocamlbuild_where.libdir in
if not (sys_file_exists (dir/ocamlbuildlib)) then
failwith (sprintf "Cannot find %S in ocamlbuild -where directory" ocamlbuildlib);
let dir = if Pathname.is_implicit dir then Pathname.pwd/dir else dir in
let cmd =
Cmd(S[compiler; A"-I"; P dir; libs; more_options;
P(dir/ocamlbuildlib); plugin_config; P plugin_file;
P(dir/ocamlbuild); A"-o"; Px (plugin^(!Options.exe))])
in
Shell.chdir !Options.build_dir;
Shell.rm_f (plugin^(!Options.exe));
Command.execute cmd
end
let execute_plugin_if_needed () =
if we_need_a_plugin then
begin
rebuild_plugin_if_needed ();
Shell.chdir Pathname.pwd;
if not !Options.just_plugin then
let runner = if !Options.native_plugin then N else !Options.ocamlrun in
let argv = List.tl (Array.to_list Sys.argv) in
let spec = S[runner; P(!Options.build_dir/plugin^(!Options.exe));
A"-no-plugin"; atomize (List.filter (fun s -> s <> "-plugin-option") argv)] in
let () = Log.finish () in
raise (Exit_silently_with_code (sys_command (Command.string_of_command_spec spec)))
end
else
()
end
;;
let execute_plugin_if_needed () =
let module P = Make(struct end) in
P.execute_plugin_if_needed ()
;;