[Pkg-ocaml-maint-commits] [SCM] dh-ocaml packaging branch, master, updated. ff17e15a60961f1e1c7047e8728f44b4a022dcb7
Stefano Zacchiroli
zack at upsilon.cc
Thu Aug 7 18:55:47 UTC 2008
The following commit has been merged in the master branch:
commit ff17e15a60961f1e1c7047e8728f44b4a022dcb7
Author: Stefano Zacchiroli <zack at upsilon.cc>
Date: Thu Aug 7 15:55:03 2008 -0300
inject ocaml-md5sums code
... but currently refrain from shipping it, see TODO
diff --git a/debian/README.Debian b/debian/README.Debian
index 5bb7a7c..f40d0d3 100644
--- a/debian/README.Debian
+++ b/debian/README.Debian
@@ -14,3 +14,25 @@ If you need the CDBS class to build your OCaml-related packages you will
now need to Build-Depends on dh-ocaml.
-- Stefano Zacchiroli <zack at debian.org> Thu, 07 Aug 2008 12:57:36 -0300
+
+ocaml-md5sums: the dependency hell
+----------------------------------
+
+ocaml-md5sums relationships with ocaml itself are kinda tricky.
+
+ocaml-md5sums needs _at runtime_ on ocaml-nox as the latter ships
+`ocamlobjinfo` (note that other parts of dh-ocaml does not require
+ocaml-nox at all, that's way the relationship is just a Recommends).
+
+ocaml needs _at build-time_ ocaml-md5sums to compute md5sums for the
+standard library. That's way ocaml Build-Depends on dh-ocaml, though in
+order to use ocaml-md5sums it overrides the default location of
+`ocamlobjinfo` in order to use the one just built. This also means that
+ocaml-md5sums can not be written in OCaml itself otherwise it would need
+to depend on some ocaml binary package creating a circular build or
+runtime dependency chain.
+
+At the time of writing, ocaml-md5sums is TEMPORARILY DISABLED, as it
+needs to be reimplemented in something else than OCaml.
+
+ -- Stefano Zacchiroli <zack at debian.org> Thu, 07 Aug 2008 15:42:24 -0300
diff --git a/debian/TODO b/debian/TODO
new file mode 100644
index 0000000..1f58701
--- /dev/null
+++ b/debian/TODO
@@ -0,0 +1,4 @@
+
+- migrate ocaml-md5sums to OCaml to some scripting language, so as to
+ not induce circular dependencies in the OCaml build process
+
diff --git a/debian/control b/debian/control
index 8e55153..c789578 100644
--- a/debian/control
+++ b/debian/control
@@ -12,6 +12,7 @@ Vcs-Browser: http://git.debian.org/?p=pkg-ocaml-maint/packages/dh-ocaml.git
Package: dh-ocaml
Architecture: all
Depends: ${misc:Depends}
+Recommends: ocaml-nox
Replaces: ocaml-base-nox (<= 3.10.2-3),
ocaml (<= 3.10.2-3),
ocaml-nox (<= 3.10.2-3),
diff --git a/debian/manpages b/debian/manpages
index 6eb1f4d..a2231ae 100644
--- a/debian/manpages
+++ b/debian/manpages
@@ -1 +1,2 @@
debhelper/dh_ocaml.1
+ocaml-md5sums/ocaml-md5sums.1
diff --git a/ocaml-md5sums/Makefile b/ocaml-md5sums/Makefile
new file mode 100644
index 0000000..3749c18
--- /dev/null
+++ b/ocaml-md5sums/Makefile
@@ -0,0 +1,30 @@
+
+DESTDIR = /usr/local/bin
+OFLAGS = -nostdlib -I ../../stdlib -I ../../otherlibs/unix -I ../../otherlibs/str
+OCAMLC = ../../boot/ocamlrun ../../ocamlc $(OFLAGS)
+OCAMLOPT = ../../boot/ocamlrun ../../ocamlopt $(OFLAGS)
+OCAML_LIBS = unix str
+NAME = ocaml-md5sums
+BYTE = $(NAME)
+OPT = $(NAME).opt
+
+all: $(BYTE)
+opt: $(OPT)
+install:
+ if [ -x "$(OPT)" ]; then \
+ cp -a "$(OPT)" $(DESTDIR)/$(NAME); \
+ elif [ -x "$(BYTE)" ]; then \
+ cp -a "$(BYTE)" $(DESTDIR)/$(NAME); \
+ else \
+ echo "Nothing to be installed, aborting."; \
+ exit 2; \
+ fi
+
+$(BYTE): $(NAME).ml
+ $(OCAMLC) $(patsubst %,%.cma,$(OCAML_LIBS)) -o $@ $<
+$(OPT): $(NAME).ml
+ $(OCAMLOPT) $(patsubst %,%.cmxa,$(OCAML_LIBS)) -o $@ $<
+
+clean:
+ rm -f ocaml-md5sums ocaml-md5sums.opt *.cm[aiox] *.cmxa *.[ao]
+
diff --git a/ocaml-md5sums/configure.in b/ocaml-md5sums/configure.in
new file mode 100644
index 0000000..bf760c8
--- /dev/null
+++ b/ocaml-md5sums/configure.in
@@ -0,0 +1,15 @@
+#!/bin/sh
+VERSION="#OcamlABI#"
+DEFAULT="/var/lib/ocaml/#OcamlABI#/md5sums"
+if [ -z "$1" ]; then
+ echo "No dir provided, using default: $DEFAULT"
+ echo "You can override it with: ./configure [ md5sums_dir ]"
+ MD5SUMS_DIR="$DEFAULT"
+else
+ MD5SUMS_DIR="$1"
+fi
+echo -n "Creating ocaml-md5sums.ml ... "
+sed -e "s:@MD5SUMS_DIR@:$MD5SUMS_DIR:" \
+ -e "s:@VERSION@:$VERSION:" \
+ < ocaml-md5sums.ml.in > ocaml-md5sums.ml
+echo "done."
diff --git a/ocaml-md5sums/feeding.sh b/ocaml-md5sums/feeding.sh
new file mode 100755
index 0000000..80cc854
--- /dev/null
+++ b/ocaml-md5sums/feeding.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# Copyright (C) 2005, Stefano Zacchiroli <zack at debian.org>
+#
+# This is free software, you can redistribute it and/or modify it under the
+# terms of the GNU General Public License version 2 as published by the Free
+# Software Foundation.
+
+pkg="$1"
+stdlibdir="$2"
+version="$3"
+rootdir="$4"
+SORT="sort -k 2"
+if [ -x ./ocaml-md5sums.opt ]; then
+ OCAML_MD5SUMS="./ocaml-md5sums.opt"
+elif [ -x ./ocaml-md5sums ]; then
+ OCAML_MD5SUMS="./ocaml-md5sums"
+else
+ echo "Can't find ocaml-md5sums{.opt,}, aborting."
+ exit 2
+fi
+export OCAMLOBJINFO="../../boot/ocamlrun ../../tools/objinfo"
+COMPUTE="$OCAML_MD5SUMS compute --package $pkg-$version"
+if [ -z "$pkg" ] || [ -z "$stdlibdir" ] || [ -z "$version" ] || [ -z "$rootdir" ]; then
+ echo "Usage: feeding.sh <pkg_name> <stdlib_dir> <ocaml_version> <root_dir>"
+ exit 1
+fi
+case "$pkg" in
+ ocaml-compiler-libs)
+ find $rootdir -name "*.cm[ao]" | $COMPUTE | $SORT
+ ;;
+ *)
+ RUNTIME="`echo $pkg | sed 's/ocaml/ocaml-base/'`-$version"
+ find $rootdir -name "*.cm[ao]" |
+ grep -v $stdlibdir/ocamldoc/ |
+ grep -v $stdlibdir/camlp4/ |
+ $COMPUTE --runtime $RUNTIME |
+ $SORT
+ ;;
+esac
+
diff --git a/ocaml-md5sums/ocaml-md5sums.1 b/ocaml-md5sums/ocaml-md5sums.1
new file mode 100644
index 0000000..3174eb5
--- /dev/null
+++ b/ocaml-md5sums/ocaml-md5sums.1
@@ -0,0 +1,48 @@
+.TH OCAML-MD5SUMS "1" "June 2007" "ocaml-md5sums 3.10.0" "User Commands"
+.SH NAME
+ocaml-md5sums \- use and maintain system-wide OCaml md5sums registry
+.SH SYNOPSIS
+.B ocaml-md5sums compute
+\fB\-\-package\fR <name>
+[\fIoption\ ...\fR] \fIfile ...\fR
+.br
+.B ocaml-md5sums dep
+[\fIoption\ ...\fR] \fIfile ...\fR
+.br
+.B ocaml-md5sums update
+[\fIoption\ ...\fR]
+.SH DESCRIPTION
+ocaml-md5sums is an administrative tool for maintaining the system-wide
+registry of md5sums of OCaml modules. For each OCaml object registered, the
+registry contains information about which modules (compilation unit) are
+contained and their md5sums.
+.SH OPTIONS
+.HP
+\fB\-\-package\fR set package name for development dependency
+.HP
+\fB\-\-runtime\fR set package name for runtime dependency
+.HP
+\fB\-\-version\fR set package version for dependencies
+.HP
+\fB\-\-dump\-info\fR dump ocamlobjinfo to file
+.HP
+\fB\-\-load\-info\fR restore ocamlobjinfo from file
+.HP
+\fB\-v\fR increase verbosity
+.HP
+\fB\-\-my\-version\fR print ocaml\-md5sum version and exit
+.TP
+\fB\-help\fR
+Display this list of options
+.TP
+\fB\-\-help\fR
+Display this list of options
+.SH "SEE ALSO"
+.BR ocamlc(1),
+.BR ocaml(1).
+.SH AUTHOR
+ocaml-md5sums is Copyright Stefano Zacchiroli and is distributed under the
+terms of the GNU General Public License.
+.PP
+This manual page was written by Stefano Zacchiroli <zack at debian.org>,
+for the Debian project (but may be used by others).
diff --git a/ocaml-md5sums/ocaml-md5sums.ml.in b/ocaml-md5sums/ocaml-md5sums.ml.in
new file mode 100644
index 0000000..b10a7ca
--- /dev/null
+++ b/ocaml-md5sums/ocaml-md5sums.ml.in
@@ -0,0 +1,317 @@
+(*
+ * ocaml-md5sums - use and maintain debian registry of ocaml md5sums
+ *
+ * Copyright (C) 2005, Stefano Zacchiroli <zack at debian.org>
+ *
+ * Created: Wed, 06 Apr 2005 16:55:39 +0200 zack
+ * Last-Modified: Fri, 12 Aug 2005 10:28:10 +0200 zack
+ *
+ * This is free software, you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *)
+
+open Printf
+
+(** {2 Constants} *)
+
+let my_version = "@VERSION@"
+let md5sums_dir = "@MD5SUMS_DIR@"
+let md5sums_index = "MD5SUMS"
+let md5sums_ext = ".md5sums"
+let registry_file = sprintf "%s/%s" md5sums_dir md5sums_index
+
+(** {2 System requirements} *)
+
+let ocamlobjinfo =
+ try (* needed at ocaml package build time, when *)
+ Sys.getenv "OCAMLOBJINFO" (* ocamlobjinfo is not yet installed *)
+ with Not_found -> "/usr/bin/ocamlobjinfo"
+
+(** {2 Regular expressions, for parsing purposes} *)
+
+let unit_name_line_RE =
+ Str.regexp "^[ \t]*Unit[ \t]+name[ \t]*:[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*$"
+let md5sum_line_RE =
+ Str.regexp "^[ \t]*\\([a-f0-9]+\\)[ \t]+\\([a-zA-Z0-9_]+\\)[ \t]*$"
+let blanks_RE = Str.regexp "[ \t]+"
+let ignorable_line_RE = Str.regexp "^[ \t]*\\(#.*\\)?"
+let md5sums_ext_RE = Str.regexp (sprintf "^.*%s$" (Str.quote md5sums_ext))
+
+(** {2 Argument parsing} *)
+
+let objects = ref []
+let dev_dep = ref ""
+let runtime_dep = ref "-"
+let dep_version = ref "-"
+let verbosity = ref 0
+let dump_info_to = ref ""
+let load_info_from = ref ""
+let action = ref None
+
+let usage_msg =
+ "Use and maintain system-wide ocaml md5sums registry\n"
+ ^ "Usage:\n"
+ ^ " ocaml-md5sum compute --package <name> [option ...] file ...\n"
+ ^ " ocaml-md5sum dep [option ...] file ...\n"
+ ^ " ocaml-md5sum update [option ...]\n"
+ ^ "Options:"
+let cmdline_spec = [
+ "--package", Arg.Set_string dev_dep,
+ "set package name for development dependency";
+ "--runtime", Arg.Set_string runtime_dep,
+ "set package name for runtime dependency";
+ "--version", Arg.Set_string dep_version,
+ "set package version for dependencies";
+ "--dump-info", Arg.Set_string dump_info_to,
+ "dump ocamlobjinfo to file";
+ "--load-info", Arg.Set_string load_info_from,
+ "restore ocamlobjinfo from file";
+ "-v", Arg.Unit (fun () -> incr verbosity), "increase verbosity";
+ "--my-version", Arg.Unit (fun () -> print_endline my_version ; exit 0),
+ "print ocaml-md5sum version and exit";
+]
+let die_usage () =
+ Arg.usage cmdline_spec usage_msg;
+ exit 1
+
+(** {2 Helpers} *)
+
+let error msg = prerr_endline ("Error: " ^ msg); exit 2
+let warning msg = prerr_endline ("Warning: " ^ msg)
+let info ?(level = 1) msg =
+ if !verbosity >= level then prerr_endline ("Info: " ^ msg)
+let iter_in f ic =
+ try while true do f (input_line ic) done with End_of_file -> ()
+let iter_file f fname =
+ let ic = open_in fname in
+ iter_in f ic;
+ close_in ic
+let iter_table f = iter_file (fun line -> f (Str.split blanks_RE line))
+
+module Strings = Set.Make (String)
+
+(** read until the end of standard input
+ * @return the list of lines read from stdin, without trailing "\n" *)
+let read_stdin () =
+ let lines = ref [] in
+ iter_in (fun s -> lines := s :: !lines) stdin;
+ List.rev !lines
+
+let is_empty fname = (Unix.stat fname).Unix.st_size = 0
+let is_regular fname = (Unix.stat fname).Unix.st_kind = Unix.S_REG
+let is_dir fname = (Unix.stat fname).Unix.st_kind = Unix.S_DIR
+
+(** {2 Auxiliary functions} *)
+
+(** loads info previously stored in a file using --dump-info and stores them in
+ * two hashtables
+ * @param defined hashtable for md5sums of defined units
+ * @param imported hashtable for md5sums of imported units
+ * @param fname file where the dump has been saved *)
+let load_info ~defined ~imported fname =
+ info ("loading ocamlobjinfo information from " ^ fname);
+ let lineno = ref 0 in
+ iter_table
+ (fun fields ->
+ incr lineno;
+ match fields with
+ | [ "defined"; md5; unit_name ] ->
+ info ~level:2 (String.concat " " fields);
+ Hashtbl.replace defined unit_name md5
+ | [ "imported"; md5; unit_name ] ->
+ info ~level:2 (String.concat " " fields);
+ Hashtbl.replace imported unit_name md5
+ | _ ->
+ warning (sprintf "ignoring dump entry (%s, line %d)" fname !lineno))
+ fname
+
+(** dumps ocamlobjinfo to file
+ * @param defined hashtable containing md5sums of defined units
+ * @param imported hashtable containing md5sums of imported units
+ * @param fname file where to dump ocamlobjinfo *)
+let dump_info ~defined ~imported fname =
+ info ("dumping ocamlobjinfo information to " ^ fname);
+ let oc = open_out fname in
+ Hashtbl.iter
+ (fun unit_name md5sum -> fprintf oc "defined %s %s\n" md5sum unit_name)
+ defined;
+ Hashtbl.iter
+ (fun unit_name md5sum -> fprintf oc "imported %s %s\n" md5sum unit_name)
+ imported;
+ close_out oc
+
+(** @param fnames list of *.cm[ao] file names
+ * @return a pair of hash tables <defined_units, imported_units>. Both tables
+ * contains mappings <unit_name, md5sum>. defined_units lists units defined in
+ * given files while imported_units imported ones *)
+let unit_info fnames =
+ let (defined, imported) = (Hashtbl.create 1024, Hashtbl.create 1024) in
+ if !load_info_from <> "" then
+ load_info ~defined ~imported !load_info_from;
+ List.iter
+ (fun fname ->
+ info ("getting unit info from " ^ fname);
+ let current_unit = ref "" in
+ let ic = Unix.open_process_in (sprintf "%s %s" ocamlobjinfo fname) in
+ iter_in
+ (fun line ->
+ if Str.string_match unit_name_line_RE line 0 then
+ current_unit := Str.matched_group 1 line
+ else if Str.string_match md5sum_line_RE line 0 then
+ let md5sum = Str.matched_group 1 line in
+ let unit_name = Str.matched_group 2 line in
+ if unit_name = !current_unit then begin (* defined unit *)
+ let dump_entry = sprintf "defined %s %s" md5sum unit_name in
+ info ~level:2 dump_entry;
+ Hashtbl.replace defined unit_name md5sum
+ end else begin (* imported unit *)
+ let dump_entry = sprintf "imported %s %s" md5sum unit_name in
+ info ~level:2 dump_entry;
+ Hashtbl.replace imported unit_name md5sum
+ end)
+ ic;
+ close_in ic)
+ fnames;
+ Hashtbl.iter (* imported := imported - defined *)
+ (fun unit_name _ -> Hashtbl.remove imported unit_name)
+ defined;
+ if !dump_info_to <> "" then
+ dump_info ~defined ~imported !dump_info_to;
+ (defined, imported)
+
+(** pretty print a registry entry sending output to an output channel *)
+let pp_entry outchan ~md5sum ~unit_name ~dev_dep ~runtime_dep ~dep_version =
+ fprintf outchan "%s %s %s %s %s\n"
+ md5sum unit_name dev_dep runtime_dep dep_version
+
+(** iter a function over the entries of a registry file
+ * @param f function to be executed for each entries, it takes 4 labeled
+ * arguments: ~md5sum ~unit_name ~package ?version
+ * @param fname file containining the registry *)
+let iter_registry f fname =
+ info ("processing registry " ^ fname);
+ let lineno = ref 0 in
+ iter_file
+ (fun line ->
+ incr lineno;
+ (match Str.split blanks_RE line with
+ | [ md5sum; unit_name; dev_dep; runtime_dep; dep_version ] ->
+ f ~md5sum ~unit_name ~dev_dep ~runtime_dep ~dep_version
+ | _ when Str.string_match ignorable_line_RE line 0 -> ()
+ | _ ->
+ warning (sprintf "ignoring registry entry (%s, line %d)"
+ fname !lineno)))
+ fname
+
+(** @param fname file name of the registry file, if fname does not exists an
+ * empty registry will be returned
+ * @return an hashtbl mapping pairs <unit_name, md5sum> to pairs <package_name,
+ * version_info>. E.g. ("Foo_bar", "74be7fa4320ebd9415f1c7cfc04c2d7b") ->
+ * ("libfoo-ocaml-dev", ">= 1.2.3-4") *)
+let parse_registry fname =
+ let registry = Hashtbl.create 1024 in
+ if Sys.file_exists fname then
+ iter_registry
+ (fun ~md5sum ~unit_name ~dev_dep ~runtime_dep ~dep_version ->
+ Hashtbl.replace registry (unit_name, md5sum)
+ (dev_dep, runtime_dep, dep_version))
+ fname;
+ registry
+
+(** {2 Main functions, one for each command line action} *)
+
+(** compute registry entry for a set of ocaml objects *)
+let compute dev_dep runtime_dep dep_version objects () =
+ let defined, _ = unit_info objects in
+ Hashtbl.iter
+ (fun unit_name md5sum ->
+ pp_entry stdout ~md5sum ~unit_name ~dev_dep ~runtime_dep ~dep_version)
+ defined
+
+(** compute package dependencies for a set of ocaml objects *)
+let dep objects () =
+ let _, imported = unit_info objects in
+ let registry = parse_registry registry_file in
+ let deps =
+ Hashtbl.fold
+ (fun unit_name md5sum deps ->
+ try
+ let (dev_dep, runtime_dep, dep_version) =
+ Hashtbl.find registry (unit_name, md5sum)
+ in
+ Strings.add (sprintf "%s %s %s" dev_dep runtime_dep dep_version) deps
+ with Not_found -> deps)
+ imported
+ Strings.empty
+ in
+ Strings.iter print_endline deps
+
+(** update debian registry of ocaml md5sums *)
+let update () =
+ info (sprintf "updating registry %s using info from %s/"
+ registry_file md5sums_dir);
+ let keys = Hashtbl.create 1024 in (* history of seen registry keys *)
+ if Sys.file_exists md5sums_dir && is_dir md5sums_dir then begin
+ let dir = Unix.opendir md5sums_dir in
+ let registry = open_out registry_file in
+ try
+ while true do
+ let fname = sprintf "%s/%s" md5sums_dir (Unix.readdir dir) in
+ if (Str.string_match md5sums_ext_RE fname 0) && is_regular fname then
+ iter_registry
+ (fun ~md5sum ~unit_name ~dev_dep ~runtime_dep ~dep_version ->
+ if Hashtbl.mem keys (unit_name, md5sum) then
+ error (sprintf "duplicate entry %s %s in registry" unit_name
+ md5sum);
+ Hashtbl.replace keys (unit_name, md5sum) ();
+ pp_entry registry ~md5sum ~unit_name ~dev_dep ~runtime_dep
+ ~dep_version)
+ fname
+ done
+ with End_of_file ->
+ Unix.closedir dir;
+ close_out registry;
+ if is_empty registry_file then Sys.remove registry_file
+ end else
+ warning (sprintf "%s/ does not exist or is not a directory, not updating"
+ md5sums_dir)
+
+(** {2 Main} *)
+
+(** main *)
+let main () =
+ Arg.parse cmdline_spec
+ (fun s ->
+ if !action = None then
+ action := Some s
+ else
+ objects := s :: !objects)
+ usage_msg;
+ match !action with
+ | Some "update" -> update ()
+ | Some action ->
+ let objects =
+ match !objects with
+ | [] when !load_info_from = "" -> read_stdin ()
+ | objects -> List.rev objects
+ in
+ (match action with
+ | "compute" ->
+ if !dev_dep = "" then die_usage ();
+ compute !dev_dep !runtime_dep !dep_version objects ()
+ | "dep" -> dep objects ()
+ | _ -> die_usage ())
+ | None -> die_usage ()
+
+let _ = Unix.handle_unix_error main ()
+
--
dh-ocaml packaging
More information about the Pkg-ocaml-maint-commits
mailing list