Enable native code compilation when ocamlopt is available.
authorRichard W.M. Jones <rjones@redhat.com>
Wed, 21 Mar 2012 15:12:29 +0000 (15:12 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Wed, 21 Mar 2012 15:39:58 +0000 (15:39 +0000)
.gitignore
daemon/Makefile.am
daemon/daemon.ml
daemon/daemon.mli
daemon/whenjobsd.ml
lib/Makefile.am
lib/whenutils.ml
lib/whenutils.mli
tools/Makefile.am
tools/whenjobs.ml

index 9491e0c..e15bd84 100644 (file)
@@ -7,6 +7,7 @@
 *.cma
 *.cmxa
 *.o
+*.a
 Makefile.in
 Makefile
 /aclocal.m4
@@ -19,7 +20,6 @@ Makefile
 /config.status
 /config.sub
 /configure
-/daemon/libdaemon.a
 /daemon/whenjobsd
 /daemon/whenjobsd.8
 /daemon/whenproto.x
@@ -28,7 +28,6 @@ Makefile
 /depcomp
 /install-sh
 /lib/config.ml
-/lib/liblibrary.a
 /lib/whenproto_aux.ml
 /lib/whenproto_aux.mli
 /libtool
index 0599e56..ac76e28 100644 (file)
@@ -41,6 +41,8 @@ OBJECTS = \
        daemon.cmo \
        whenjobsd.cmo
 
+XOBJECTS = $(OBJECTS:.cmo=.cmx)
+
 # Daemon.
 noinst_LIBRARIES = libdaemon.a
 libdaemon_a_SOURCES = exit.c syslog_c.c
@@ -52,11 +54,19 @@ whenproto_srv.ml whenproto_srv.mli: whenproto.x
 whenproto.x: ../lib/whenproto.x
        ln -f $< $@
 
+if HAVE_OCAMLOPT
+whenjobsd: ../lib/whenlib.cmxa $(XOBJECTS) libdaemon.a
+       $(OCAMLFIND) opt $(OCAMLOPTFLAGS) -ccopt -L../lib \
+         -linkpkg whenlib.cmxa \
+         libdaemon_a-exit.o libdaemon_a-syslog_c.o \
+         $(XOBJECTS) -o $@
+else
 whenjobsd: ../lib/whenlib.cma $(OBJECTS) libdaemon.a
        $(OCAMLFIND) c -custom $(OCAMLCFLAGS) -ccopt -L../lib \
          -linkpkg whenlib.cma \
          libdaemon_a-exit.o libdaemon_a-syslog_c.o \
          $(OBJECTS) -o $@
+endif
 
 # Rules for all OCaml files.
 %.cmi: %.mli ../lib/whenlib.cma
index c04bfcb..bc4f51a 100644 (file)
@@ -292,14 +292,11 @@ and proc_whisper_variables vars =
 
 (* Reload the jobs file(s). *)
 and reload_files () =
-  (* Get dir/*.cmo *)
+  (* Get dir/*.cmo (bytecode) or dir/*.cmxs (native code) *)
+  let suffix = if not Dynlink.is_native then ".cmo" else ".cmxs" in
   let dir = !jobsdir in
   let files = Array.to_list (Sys.readdir dir) in
-  let files = List.filter (
-    fun file ->
-      let n = String.length file in
-      n >= 5 && String.sub file (n-4) 4 = ".cmo"
-  ) files in
+  let files = List.filter (fun file -> string_endswith file suffix) files in
   let files = List.map (fun file -> dir // file) files in
   let files = List.sort compare files in
 
index b7f7d57..d351ac2 100644 (file)
@@ -25,7 +25,8 @@ val init : string -> bool -> unit
       The parameters are [jobsdir] and [debug]. *)
 
 val reload_files : unit -> unit
-  (** (Re-)load the file(s) [$jobsdir/*.cmo].
+  (** (Re-)load the file(s) [$jobsdir/*.cmo] (in bytecode)
+      or [$jobsdir/*.cmxs] (in native code).
 
       This can raise [Failure] if the operation fails. *)
 
index 647c7f2..3028503 100644 (file)
@@ -126,9 +126,10 @@ Options:
   Syslog.notice "daemon started: version=%s uid=%d home=%s"
     Config.package_version euid home;
 
-  (* If there is a jobs.cmo file, load it. *)
+  (* If there is a jobs.cmo/jobs.cmxs file, load it. *)
   let () =
-    let file = sprintf "%s/jobs.cmo" jobsdir in
+    let suffix = if not Dynlink.is_native then "cmo" else "cmxs" in
+    let file = sprintf "%s/jobs.%s" jobsdir suffix in
     if Sys.file_exists file then
       try Daemon.reload_files () with Failure _ -> () in
 
index 2a42d1e..747f074 100644 (file)
@@ -20,6 +20,10 @@ EXTRA_DIST = whenproto.x pa_when.ml $(SOURCES)
 libwhenjobsdir = $(libdir)/$(PACKAGE_NAME)
 libwhenjobs_SCRIPTS = whenlib.cma pa_when.cmo $(CMI_FILES)
 
+if HAVE_OCAMLOPT
+libwhenjobs_SCRIPTS += whenlib.cmxa
+endif
+
 OCAMLPACKAGES = -package unix,num,camlp4.lib,calendar,rpc
 
 OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES)
@@ -66,6 +70,8 @@ OBJECTS = \
        whentools.cmo \
        whenlock.cmo
 
+XOBJECTS = $(OBJECTS:.cmo=.cmx)
+
 # Library.
 noinst_LIBRARIES = liblibrary.a
 liblibrary_a_SOURCES = flock.c
@@ -74,6 +80,9 @@ liblibrary_a_CFLAGS = -I$(shell $(OCAMLC) -where)
 whenlib.cma: $(OBJECTS) liblibrary.a
        $(OCAMLFIND) c -a $(OCAMLCFLAGS) $(OBJECTS) -cclib -llibrary -o $@
 
+whenlib.cmxa: $(XOBJECTS) liblibrary.a
+       $(OCAMLFIND) opt -a $(OCAMLOPTFLAGS) $(XOBJECTS) -cclib -llibrary -o $@
+
 whenproto_aux.ml whenproto_aux.mli: whenproto.x
        $(OCAMLRPCGEN) -int int32 -hyper int64 -aux $<
 
index ca26755..5f7c4ee 100644 (file)
@@ -63,3 +63,8 @@ let string_of_time_t ?(localtime = false) t =
     (1900+tm.tm_year) (1+tm.tm_mon) tm.tm_mday
     tm.tm_hour tm.tm_min tm.tm_sec
     (if localtime then "" else " UTC")
+
+let string_endswith str suffix =
+  let len = String.length str in
+  let slen = String.length suffix in
+  len >= slen && String.sub str (len-slen) slen = suffix
index 00b2ff1..da51c70 100644 (file)
@@ -160,3 +160,6 @@ val filter_map : ('a -> 'b option) -> 'a list -> 'b list
 val string_of_time_t : ?localtime:bool -> float -> string
 (** Convert string to time in ISO format.  If [~localtime] is true
     then it uses localtime, else UTC. *)
+
+val string_endswith : string -> string -> bool
+(** [string_endswith str suffix] returns true iff [str] ends with [suffix]. *)
index bbb5fa8..e7e4676 100644 (file)
@@ -39,6 +39,8 @@ OBJECTS = \
        whenproto_clnt.cmo \
        whenjobs.cmo
 
+XOBJECTS = $(OBJECTS:.cmo=.cmx)
+
 libdir.ml: Makefile
        rm -f $@ $@-t
        echo 'let libdir = "$(libdir)/$(PACKAGE_NAME)"' > $@-t
@@ -50,9 +52,15 @@ whenproto_clnt.ml whenproto_clnt.mli: whenproto.x
 whenproto.x: ../lib/whenproto.x
        ln -f $< $@
 
+if HAVE_OCAMLOPT
+whenjobs: ../lib/whenlib.cmxa $(XOBJECTS)
+       $(OCAMLFIND) opt $(OCAMLCFLAGS) -ccopt -L../lib \
+         -linkpkg whenlib.cmxa $(XOBJECTS) -o $@
+else
 whenjobs: ../lib/whenlib.cma $(OBJECTS)
-       $(OCAMLFIND) ocamlc -custom $(OCAMLCFLAGS) -ccopt -L../lib \
+       $(OCAMLFIND) c -custom $(OCAMLCFLAGS) -ccopt -L../lib \
          -linkpkg whenlib.cma $(OBJECTS) -o $@
+endif
 
 # Rules for all OCaml files.
 %.cmi: %.mli ../lib/whenlib.cma
index 49a398d..a9ae7b7 100644 (file)
@@ -311,8 +311,18 @@ and upload_file () =
   let files = get_multijobs_filenames () in
   List.iter (
     fun file ->
-      let cmd = sprintf "%s c -I +camlp4 -I %s -package unix,camlp4.lib -pp 'camlp4o %s/pa_when.cmo' -c %s"
-        Config.ocamlfind !libdir !libdir file in
+      let cmd =
+        if not Config.have_ocamlopt then
+          (* bytecode *)
+          sprintf "%s c -I +camlp4 -I %s -package unix,camlp4.lib -pp 'camlp4o %s/pa_when.cmo' -c %s"
+            Config.ocamlfind !libdir !libdir file
+        else (
+          (* native code *)
+          let base = Filename.chop_extension file in (* without .ml suffix *)
+          sprintf "%s opt -I +camlp4 -I %s -package unix,camlp4.lib -pp 'camlp4o %s/pa_when.cmo' -c %s &&\n%s opt -shared -linkall %s.cmx -o %s.cmxs"
+            Config.ocamlfind !libdir !libdir file
+            Config.ocamlfind base base
+        ) in
       if Sys.command cmd <> 0 then (
         eprintf "whenjobs: %s: could not compile jobs script, see earlier errors\n"
           file;
@@ -321,25 +331,24 @@ and upload_file () =
       )
   ) files;
 
-  let cmo_files = List.map (
+  let suffix = if not Dynlink.is_native then "cmo" else "cmxs" in
+
+  let compiled_files = List.map (
     fun file ->
       let n = String.length file in
       if n < 4 then assert false;
-      String.sub file 0 (n-3) ^ ".cmo"
+      sprintf "%s.%s" (String.sub file 0 (n-3)) suffix
   ) files in
 
   (* Test-load the jobs files to ensure they make sense. *)
   Whenfile.init Whenstate.empty;
   (try
-     List.iter Dynlink.loadfile cmo_files
+     List.iter Dynlink.loadfile compiled_files
    with
      Dynlink.Error err ->
-       eprintf "whenjobs: %s\n" (Dynlink.error_message err);
-       (* Since it failed, unlink the cmo files. *)
-       List.iter (
-         fun cmo_file ->
-           (try unlink cmo_file with Unix_error _ -> ())
-       ) cmo_files;
+       eprintf "whenjobs: dynlink: %s\n" (Dynlink.error_message err);
+       (* Since it failed, unlink the compiled files. *)
+       List.iter (fun f -> try unlink f with Unix_error _ -> ()) compiled_files;
        exit 1
   );
 
@@ -571,11 +580,7 @@ and get_jobs_filename () =
 and get_multijobs_filenames () =
   (* Get dir/*.ml *)
   let files = Array.to_list (Sys.readdir jobsdir) in
-  let files = List.filter (
-    fun file ->
-      let n = String.length file in
-      n >= 4 && String.sub file (n-3) 3 = ".ml"
-  ) files in
+  let files = List.filter (fun file -> string_endswith file ".ml") files in
   let files = List.map (fun file -> jobsdir // file) files in
   List.sort compare files