[ocaml] 01/01: Support BUILD_PATH_PREFIX_MAP for reproducible builds

Ximin Luo infinity0 at debian.org
Tue Dec 5 13:25:01 UTC 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch pu/reproducible_builds
in repository ocaml.

commit b3e55cce8b01732f92c00e5cbb748a97cc1f920d
Author: Ximin Luo <infinity0 at debian.org>
Date:   Tue Dec 5 13:03:21 2017 +0100

    Support BUILD_PATH_PREFIX_MAP for reproducible builds
---
 debian/changelog                                   |   6 +
 ...tils-import-build_path_prefix_map-library.patch | 151 +++++++++++++++++++++
 ...h_prefix_map-update-.depend-and-Makefiles.patch | 137 +++++++++++++++++++
 ...UILD_PATH_PREFIX_MAP-variable-if-it-exist.patch | 116 ++++++++++++++++
 debian/patches/series                              |   3 +
 5 files changed, 413 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 84aea84..6095e03 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+ocaml (4.05.0-10.0~reproducible1) UNRELEASED; urgency=medium
+
+  * Support BUILD_PATH_PREFIX_MAP for reproducible builds.
+
+ -- Ximin Luo <infinity0 at debian.org>  Tue, 05 Dec 2017 13:01:40 +0100
+
 ocaml (4.05.0-10) unstable; urgency=medium
 
   * Drop support for ocamlopt on armel as suggested by upstream.
diff --git a/debian/patches/0001-utils-import-build_path_prefix_map-library.patch b/debian/patches/0001-utils-import-build_path_prefix_map-library.patch
new file mode 100644
index 0000000..6e9675e
--- /dev/null
+++ b/debian/patches/0001-utils-import-build_path_prefix_map-library.patch
@@ -0,0 +1,151 @@
+From 1dd4f02c280f31d501007a0a603af75252c516ee Mon Sep 17 00:00:00 2001
+From: Gabriel Scherer <gabriel.scherer at gmail.com>
+Date: Mon, 4 Dec 2017 23:30:43 +0000
+Subject: [PATCH 1/3] utils: import build_path_prefix_map library
+
+This library is imported from
+
+  <https://gitlab.com/gasche/build_path_prefix_map/>
+
+commit 811691e479b38c0e6c1c0e5c853c555a63177ee3
+---
+ utils/build_path_prefix_map.ml  | 104 ++++++++++++++++++++++++++++++++++++++++
+ utils/build_path_prefix_map.mli |  24 ++++++++++
+ 2 files changed, 128 insertions(+)
+ create mode 100644 utils/build_path_prefix_map.ml
+ create mode 100644 utils/build_path_prefix_map.mli
+
+--- /dev/null
++++ b/utils/build_path_prefix_map.ml
+@@ -0,0 +1,104 @@
++type path = string
++type path_prefix = string
++type error_message = string
++
++let errorf fmt = Printf.kprintf (fun err -> Error err) fmt
++
++let encode_prefix str =
++  let buf = Buffer.create (String.length str) in
++  let push_char = function
++    | '%' -> Buffer.add_string buf "%#"
++    | '=' -> Buffer.add_string buf "%+"
++    | ':' -> Buffer.add_string buf "%."
++    | c -> Buffer.add_char buf c
++  in
++  String.iter push_char str;
++  Buffer.contents buf
++
++let decode_prefix str =
++  let buf = Buffer.create (String.length str) in
++  let rec loop i =
++    if i >= String.length str
++    then Ok (Buffer.contents buf)
++    else match str.[i] with
++      | '=' ->
++        errorf "invalid character '=' in key or value"
++      | '%' ->
++        let push c = Buffer.add_char buf c; loop (i + 2) in
++        if i + 1 = String.length str then
++          errorf "invalid encoded string %S (trailing '%%')" str
++        else begin match str.[i + 1] with
++            | '#' -> push '%'
++            | '+' -> push '='
++            | '.' -> push ':'
++            | c -> errorf "invalid %%-escaped character '%c'" c
++        end
++      | c ->
++        Buffer.add_char buf c;
++        loop (i + 1)
++  in loop 0
++
++type pair = { target: path_prefix; source : path_prefix }
++
++let encode_pair { target; source } =
++  String.concat "=" [encode_prefix target; encode_prefix source]
++
++let decode_pair str =
++  match String.index str '=' with
++  | exception Not_found ->
++    errorf "invalid key/value pair %S, no '=' separator" str
++  | equal_pos ->
++    let encoded_target = String.sub str 0 equal_pos in
++    let encoded_source =
++      String.sub str (equal_pos + 1) (String.length str - equal_pos - 1) in
++    match decode_prefix encoded_target, decode_prefix encoded_source with
++    | Ok target, Ok source -> Ok { target; source }
++    | ((Error _ as err), _) | (_, (Error _ as err)) -> err
++
++type map = pair option list
++
++let encode_map map =
++  let encode_elem = function
++    | None -> ""
++    | Some pair -> encode_pair pair
++  in
++  List.map encode_elem map
++  |> String.concat ":"
++
++let decode_map str =
++  let exception Shortcut of error_message in
++  let decode_or_empty = function
++    | "" -> None
++    | pair ->
++      begin match decode_pair pair with
++        | Ok str -> Some str
++        | Error err -> raise (Shortcut err)
++      end
++  in
++  let pairs = String.split_on_char ':' str in
++  match List.map decode_or_empty pairs with
++  | exception (Shortcut err) -> Error err
++  | map -> Ok map
++
++let rewrite_opt prefix_map path =
++  let is_prefix = function
++    | None -> false
++    | Some { target = _; source } ->
++      String.length source <= String.length path
++      && String.equal source (String.sub path 0 (String.length source))
++  in
++  match
++    List.find is_prefix
++      (* read key/value pairs from right to left, as the spec demands *)
++      (List.rev prefix_map)
++  with
++  | exception Not_found -> None
++  | None -> None
++  | Some { source; target } ->
++      Some (target ^ (String.sub path (String.length source)
++                       (String.length path - String.length source)))
++
++let rewrite prefix_map path =
++  match rewrite_opt prefix_map path with
++  | None -> path
++  | Some path -> path
+--- /dev/null
++++ b/utils/build_path_prefix_map.mli
+@@ -0,0 +1,24 @@
++type path = string
++type path_prefix = string
++type error_message = string
++
++val encode_prefix : path_prefix -> string
++val decode_prefix : string -> (path_prefix, error_message) result
++
++type pair = { target: path_prefix; source : path_prefix }
++
++val encode_pair : pair -> string
++val decode_pair : string -> (pair, error_message) result
++
++type map = pair option list
++
++val encode_map : map -> string
++val decode_map : string -> (map, error_message) result
++
++val rewrite_opt : map -> path -> path option
++(** [rewrite_opt map path] tries to find a source in [map]
++    that is a prefix of the input [path]. If it succeeds,
++    it replaces this prefix with the corresponding target.
++    If it fails, it just returns [None]. *)
++
++val rewrite : map -> path -> path
diff --git a/debian/patches/0002-build_path_prefix_map-update-.depend-and-Makefiles.patch b/debian/patches/0002-build_path_prefix_map-update-.depend-and-Makefiles.patch
new file mode 100644
index 0000000..4c179ad
--- /dev/null
+++ b/debian/patches/0002-build_path_prefix_map-update-.depend-and-Makefiles.patch
@@ -0,0 +1,137 @@
+From 1679da3479dc5c9ab0186d6442a3b47fb76963eb Mon Sep 17 00:00:00 2001
+From: Gabriel Scherer <gabriel.scherer at gmail.com>
+Date: Mon, 4 Dec 2017 23:33:52 +0000
+Subject: [PATCH 2/3] build_path_prefix_map: update .depend and Makefiles
+
+---
+ .depend                    |  7 +++++--
+ Makefile                   |  1 +
+ debugger/Makefile          |  1 +
+ ocamldoc/.depend           | 14 +++++++-------
+ ocamldoc/Makefile          |  2 +-
+ otherlibs/dynlink/Makefile |  1 +
+ tools/Makefile             |  4 +++-
+ 7 files changed, 19 insertions(+), 11 deletions(-)
+
+--- a/.depend
++++ b/.depend
+@@ -1,6 +1,9 @@
+ utils/arg_helper.cmo : utils/arg_helper.cmi
+ utils/arg_helper.cmx : utils/arg_helper.cmi
+ utils/arg_helper.cmi :
++utils/build_path_prefix_map.cmo : utils/build_path_prefix_map.cmi
++utils/build_path_prefix_map.cmx : utils/build_path_prefix_map.cmi
++utils/build_path_prefix_map.cmi :
+ utils/ccomp.cmo : utils/misc.cmi utils/config.cmi utils/clflags.cmi \
+     utils/ccomp.cmi
+ utils/ccomp.cmx : utils/misc.cmx utils/config.cmx utils/clflags.cmx \
+@@ -108,9 +111,9 @@
+     parsing/location.cmx parsing/docstrings.cmx parsing/lexer.cmi
+ parsing/lexer.cmi : parsing/parser.cmi parsing/location.cmi
+ parsing/location.cmo : utils/warnings.cmi utils/terminfo.cmi utils/misc.cmi \
+-    utils/clflags.cmi parsing/location.cmi
++    utils/clflags.cmi utils/build_path_prefix_map.cmi parsing/location.cmi
+ parsing/location.cmx : utils/warnings.cmx utils/terminfo.cmx utils/misc.cmx \
+-    utils/clflags.cmx parsing/location.cmi
++    utils/clflags.cmx utils/build_path_prefix_map.cmx parsing/location.cmi
+ parsing/location.cmi : utils/warnings.cmi
+ parsing/longident.cmo : utils/misc.cmi parsing/longident.cmi
+ parsing/longident.cmx : utils/misc.cmx parsing/longident.cmi
+--- a/Makefile
++++ b/Makefile
+@@ -88,6 +88,7 @@
+   utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
+   utils/consistbl.cmo \
+   utils/strongly_connected_components.cmo \
++  utils/build_path_prefix_map.cmo \
+   utils/targetint.cmo
+ 
+ PARSING=parsing/location.cmo parsing/longident.cmo \
+--- a/debugger/Makefile
++++ b/debugger/Makefile
+@@ -39,6 +39,7 @@
+   ../utils/identifiable.cmo ../utils/numbers.cmo \
+   ../utils/arg_helper.cmo ../utils/clflags.cmo \
+   ../utils/consistbl.cmo ../utils/warnings.cmo \
++  ../utils/build_path_prefix_map.cmo \
+   ../utils/terminfo.cmo \
+   ../parsing/location.cmo ../parsing/longident.cmo ../parsing/docstrings.cmo \
+   ../parsing/syntaxerr.cmo \
+--- a/ocamldoc/.depend
++++ b/ocamldoc/.depend
+@@ -218,19 +218,19 @@
+     ../parsing/parsetree.cmi odoc_value.cmo odoc_types.cmi odoc_type.cmo \
+     odoc_parameter.cmo odoc_module.cmo odoc_misc.cmi odoc_messages.cmo \
+     odoc_merge.cmi odoc_global.cmi odoc_extension.cmo odoc_exception.cmo \
+-    odoc_env.cmi odoc_class.cmo ../utils/misc.cmi ../parsing/location.cmi \
+-    ../typing/ident.cmi ../typing/ctype.cmi ../typing/btype.cmi \
+-    ../parsing/asttypes.cmi odoc_sig.cmi
++    odoc_env.cmi odoc_class.cmo ../utils/misc.cmi ../parsing/longident.cmi \
++    ../parsing/location.cmi ../typing/ident.cmi ../typing/ctype.cmi \
++    ../typing/btype.cmi ../parsing/asttypes.cmi odoc_sig.cmi
+ odoc_sig.cmx : ../typing/types.cmx ../typing/typedtree.cmx \
+     ../parsing/parsetree.cmi odoc_value.cmx odoc_types.cmx odoc_type.cmx \
+     odoc_parameter.cmx odoc_module.cmx odoc_misc.cmx odoc_messages.cmx \
+     odoc_merge.cmx odoc_global.cmx odoc_extension.cmx odoc_exception.cmx \
+-    odoc_env.cmx odoc_class.cmx ../utils/misc.cmx ../parsing/location.cmx \
+-    ../typing/ident.cmx ../typing/ctype.cmx ../typing/btype.cmx \
+-    ../parsing/asttypes.cmi odoc_sig.cmi
++    odoc_env.cmx odoc_class.cmx ../utils/misc.cmx ../parsing/longident.cmx \
++    ../parsing/location.cmx ../typing/ident.cmx ../typing/ctype.cmx \
++    ../typing/btype.cmx ../parsing/asttypes.cmi odoc_sig.cmi
+ odoc_sig.cmi : ../typing/types.cmi ../typing/typedtree.cmi \
+     ../parsing/parsetree.cmi odoc_types.cmi odoc_type.cmo odoc_name.cmi \
+-    odoc_module.cmo odoc_env.cmi odoc_class.cmo
++    odoc_module.cmo odoc_env.cmi odoc_class.cmo ../parsing/location.cmi
+ odoc_str.cmo : ../typing/types.cmi ../typing/printtyp.cmi odoc_value.cmo \
+     odoc_type.cmo odoc_print.cmi odoc_name.cmi odoc_misc.cmi \
+     odoc_messages.cmo odoc_extension.cmo odoc_exception.cmo odoc_class.cmo \
+--- a/ocamldoc/Makefile
++++ b/ocamldoc/Makefile
+@@ -97,8 +97,8 @@
+ #############
+ 
+ INCLUDES_DEP=\
+-  -I $(ROOTDIR)/parsing \
+   -I $(ROOTDIR)/utils \
++  -I $(ROOTDIR)/parsing \
+   -I $(ROOTDIR)/typing \
+   -I $(ROOTDIR)/driver \
+   -I $(ROOTDIR)/bytecomp \
+--- a/otherlibs/dynlink/Makefile
++++ b/otherlibs/dynlink/Makefile
+@@ -43,6 +43,7 @@
+   ../../utils/arg_helper.cmo ../../utils/clflags.cmo \
+   ../../utils/tbl.cmo ../../utils/consistbl.cmo \
+   ../../utils/terminfo.cmo ../../utils/warnings.cmo \
++  ../../utils/build_path_prefix_map.cmo \
+   ../../parsing/asttypes.cmi \
+   ../../parsing/location.cmo ../../parsing/longident.cmo \
+   ../../parsing/docstrings.cmo ../../parsing/syntaxerr.cmo \
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -128,6 +128,7 @@
+ CSLPROF=ocamlprof.cmo
+ CSLPROF_IMPORTS=misc.cmo config.cmo identifiable.cmo numbers.cmo \
+   arg_helper.cmo clflags.cmo terminfo.cmo \
++  build_path_prefix_map.cmo \
+   warnings.cmo location.cmo longident.cmo docstrings.cmo \
+   syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo
+ 
+@@ -179,7 +180,7 @@
+ # Converter olabl/ocaml 2.99 to ocaml 3
+ 
+ OCAML299TO3= lexer299.cmo ocaml299to3.cmo
+-LIBRARY3= misc.cmo warnings.cmo location.cmo
++LIBRARY3= misc.cmo warnings.cmo build_path_prefix_map.cmo location.cmo
+ 
+ ocaml299to3: $(OCAML299TO3)
+ 	$(CAMLC) $(LINKFLAGS) -o ocaml299to3 $(LIBRARY3) $(OCAML299TO3)
+@@ -213,6 +214,7 @@
+ 
+ ADDLABELS_IMPORTS=misc.cmo config.cmo arg_helper.cmo clflags.cmo \
+   identifiable.cmo numbers.cmo terminfo.cmo \
++  build_path_prefix_map.cmo \
+   warnings.cmo location.cmo longident.cmo docstrings.cmo \
+   syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo
+ 
diff --git a/debian/patches/0003-honor-the-BUILD_PATH_PREFIX_MAP-variable-if-it-exist.patch b/debian/patches/0003-honor-the-BUILD_PATH_PREFIX_MAP-variable-if-it-exist.patch
new file mode 100644
index 0000000..1aec080
--- /dev/null
+++ b/debian/patches/0003-honor-the-BUILD_PATH_PREFIX_MAP-variable-if-it-exist.patch
@@ -0,0 +1,116 @@
+From 67f79f7cdff12605437e84c7c4abb845335dab85 Mon Sep 17 00:00:00 2001
+From: Gabriel Scherer <gabriel.scherer at gmail.com>
+Date: Mon, 4 Dec 2017 23:39:06 +0000
+Subject: [PATCH 3/3] honor the BUILD_PATH_PREFIX_MAP variable if it exists:
+
+  <https://reproducible-builds.org/specs/build-path-prefix-map/>
+---
+ Changes              |  4 ++++
+ bytecomp/bytelink.ml |  6 +++---
+ bytecomp/emitcode.ml |  6 ++++--
+ parsing/location.ml  | 22 +++++++++++++++++++++-
+ parsing/location.mli |  5 +++++
+ typing/cmt_format.ml |  2 +-
+ 6 files changed, 38 insertions(+), 7 deletions(-)
+
+--- a/Changes
++++ b/Changes
+@@ -5,6 +5,10 @@
+ 
+ ### Language features:
+ 
++- GPR#1515: honor the BUILD_PATH_PREFIX_MAP environment variable
++  to enable reproducible builds
++  (Gabriel Scherer, with help from Ximin Luo in Marrakech)
++
+ ### Code generation and optimizations:
+ 
+ - MPR#7201, GPR#954: Correct wrong optimisation of "0 / <expr>"
+--- a/bytecomp/bytelink.ml
++++ b/bytecomp/bytelink.ml
+@@ -295,9 +295,9 @@
+ (* Transform a file name into an absolute file name *)
+ 
+ let make_absolute file =
+-  if Filename.is_relative file
+-  then Filename.concat (Sys.getcwd()) file
+-  else file
++  if not (Filename.is_relative file) then file
++  else Location.rewrite_absolute_path
++         (Filename.concat (Sys.getcwd()) file)
+ 
+ (* Create a bytecode executable file *)
+ 
+--- a/bytecomp/emitcode.ml
++++ b/bytecomp/emitcode.ml
+@@ -146,8 +146,10 @@
+   let path = ev.ev_loc.Location.loc_start.Lexing.pos_fname in
+   let abspath = Location.absolute_path path in
+   debug_dirs := StringSet.add (Filename.dirname abspath) !debug_dirs;
+-  if Filename.is_relative path then
+-    debug_dirs := StringSet.add (Sys.getcwd ()) !debug_dirs;
++  if Filename.is_relative path then begin
++    let cwd = Location.rewrite_absolute_path (Sys.getcwd ()) in
++    debug_dirs := StringSet.add cwd !debug_dirs;
++  end;
+   ev.ev_pos <- !out_position;
+   events := ev :: !events
+ 
+--- a/parsing/location.ml
++++ b/parsing/location.ml
+@@ -222,9 +222,29 @@
+ 
+ open Format
+ 
++let rewrite_absolute_path =
++  let init = ref false in
++  let map_cache = ref None in
++  fun path ->
++    if not !init then begin
++      init := true;
++      match Sys.getenv "BUILD_PATH_PREFIX_MAP" with
++      | exception Not_found -> ()
++      | encoded_map ->
++        match Build_path_prefix_map.decode_map encoded_map with
++          | Error err -> failwith err (* TODO improve *)
++          | Ok map -> map_cache := Some map
++    end;
++    match !map_cache with
++    | None -> path
++    | Some map -> Build_path_prefix_map.rewrite map path
++
+ let absolute_path s = (* This function could go into Filename *)
+   let open Filename in
+-  let s = if is_relative s then concat (Sys.getcwd ()) s else s in
++  let s =
++    if not (is_relative s) then s
++    else (rewrite_absolute_path (concat (Sys.getcwd ()) s))
++  in
+   (* Now simplify . and .. components *)
+   let rec aux s =
+     let base = basename s in
+--- a/parsing/location.mli
++++ b/parsing/location.mli
+@@ -83,6 +83,11 @@
+ val print_compact: formatter -> t -> unit
+ val print_filename: formatter -> string -> unit
+ 
++val rewrite_absolute_path: string -> string
++    (** rewrite absolute path to honor the BUILD_PATH_PREFIX_MAP
++        variable (https://reproducible-builds.org/specs/build-path-prefix-map/)
++        if it is set. *)
++
+ val absolute_path: string -> string
+ 
+ val show_filename: string -> string
+--- a/typing/cmt_format.ml
++++ b/typing/cmt_format.ml
+@@ -180,7 +180,7 @@
+       cmt_comments = Lexer.comments ();
+       cmt_args = Sys.argv;
+       cmt_sourcefile = sourcefile;
+-      cmt_builddir =  Sys.getcwd ();
++      cmt_builddir = Location.rewrite_absolute_path (Sys.getcwd ());
+       cmt_loadpath = !Config.load_path;
+       cmt_source_digest = source_digest;
+       cmt_initial_env = if need_to_clear_env then
diff --git a/debian/patches/series b/debian/patches/series
index 1196040..dda5f49 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -9,3 +9,6 @@
 0011-arm64-hide-symbols-for-stricter-binutils.patch
 0013-Use-CCLINKFLAGS-for-linking-all-executables-and-shar.patch
 0014-Compute-a-stable-name-for-preprocessed-files.patch
+0001-utils-import-build_path_prefix_map-library.patch
+0002-build_path_prefix_map-update-.depend-and-Makefiles.patch
+0003-honor-the-BUILD_PATH_PREFIX_MAP-variable-if-it-exist.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/ocaml.git



More information about the Reproducible-commits mailing list