From 65874bd5808285c84149f80a6eece77e834e3538 Mon Sep 17 00:00:00 2001 From: Pierre Villemot Date: Tue, 30 Jul 2024 14:14:20 +0200 Subject: [PATCH] Rewrite the gen_link_flags script in OCaml --- src/bin/text/dune | 13 ++++- src/bin/text/gen-link-flags.sh | 56 -------------------- src/bin/text/gen_link_flags.ml | 97 ++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 58 deletions(-) delete mode 100755 src/bin/text/gen-link-flags.sh create mode 100644 src/bin/text/gen_link_flags.ml diff --git a/src/bin/text/dune b/src/bin/text/dune index 793e68dc2..c1c868de4 100644 --- a/src/bin/text/dune +++ b/src/bin/text/dune @@ -1,9 +1,18 @@ (documentation (package alt-ergo)) +(executable + (name gen_link_flags) + (libraries unix fmt stdcompat cmdliner) + (modules gen_link_flags) + (promote (until-clean))) + (rule - (with-stdout-to link_flags.dune - (run ./gen-link-flags.sh %{env:LINK_MODE=dynamic} %{ocaml-config:system}))) + (target link_flags.dune) + (deps (:gen gen_link_flags.exe)) + (action + (with-stdout-to link_flags.dune + (run %{gen} --link-mode %{env:LINK_MODE=dynamic} --os %{ocaml-config:system})))) (executable (name Main_text) diff --git a/src/bin/text/gen-link-flags.sh b/src/bin/text/gen-link-flags.sh deleted file mode 100755 index 5baf95db4..000000000 --- a/src/bin/text/gen-link-flags.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh - -set -ue - -LINK_MODE="$1" -OS="$2" -FLAGS= -CCLIB= - -case "$LINK_MODE" in - dynamic) - ;; # No extra flags needed - static) - case "$OS" in - linux) - CCLIB="-static -no-pie";; - *) - echo "No known static compilation flags for '$OS'" >&2 - exit 1 - esac;; - mixed) - FLAGS="-noautolink" - # Note: for OCaml 5, use -lcamlstrnat and -lunixnat and mind zlib - # https://github.com/ocaml/ocaml/issues/12562 - CCLIB="-lcamlzip -lnums -lzarith -lcamlstr -lunix -lz" - LIBS="gmp" - case "$OS" in - linux) - for lib in $LIBS; do - CCLIB="$CCLIB -l$lib" - done - CCLIB="-Wl,-Bstatic $CCLIB -Wl,-Bdynamic";; - macosx) - for lib in $LIBS; do - if [[ $lib == lib* ]]; then - archive="$lib.a" - else - archive="lib$lib.a" - fi - CCLIB="$CCLIB $(pkg-config $lib --variable libdir)/$archive" - done;; - *) - echo "No known mixed compilation flags for '$OS'" >&2 - exit 1 - esac;; - - *) - echo "Invalid link mode '$LINK_MODE'" >&2 - exit 2 -esac - -echo '(' -echo ' -linkall' -for f in $FLAGS; do echo " $f"; done -for f in $CCLIB; do echo " -cclib $f"; done -echo ')' diff --git a/src/bin/text/gen_link_flags.ml b/src/bin/text/gen_link_flags.ml new file mode 100644 index 000000000..949757936 --- /dev/null +++ b/src/bin/text/gen_link_flags.ml @@ -0,0 +1,97 @@ +type os = Linux | Macos +type link_mode = Dynamic | Static | Mixed + +module Cmd = struct + open Cmdliner + + let show l = List.map (fun (s, _) -> s) l + + let os_term = + let all = [ + ("linux", Linux); + ("macosx", Macos) + ] + in + let doc = + Fmt.str "Choose the operating system, $(docv) must be %s." + (Arg.doc_alts @@ show all) + in + Arg.(value & opt (enum all) Linux & info ["os"] ~docv:"OS" ~doc) + + let link_mode_term = + let all = [ + ("dynamic", Dynamic); + ("static", Static); + ("mixed", Mixed) + ] + in + let doc = + Fmt.str "Choose the operating system, $(docv) must be %s." + (Arg.doc_alts @@ show all) + in + Arg.(value & opt (enum all) Dynamic & + info ["link-mode"] ~docv:"MODE" ~doc) + + let parse k = + let info = Cmd.info "rewrite-gen-link-flags" in + Cmd.v info Term.(ret (const k $ link_mode_term $ os_term)) + |> Cmd.eval +end + +let pkgconfig lib archive = + let cmd = Fmt.str "pkg-config %s --variable libdir" lib in + let output = + Unix.open_process_in cmd + |> In_channel.input_line + |> Option.get + in + Fmt.str "%s/%s" output archive + +let pp_lib ppf s = Fmt.pf ppf "-cclib %s" s + + +let () = + let mixed_flags = ["-noautolink"] in + let mixed_cclib = [ + "-lstdcompat_stubs"; + "-lcamlzip"; + "-lzarith"; + "-lcamlstr"; + "-lunix"; + "-lnums"; + "-lz" + ] + in + let libs = ["gmp"] in + let rc = + Cmd.parse @@ fun link_mode os -> + let flags, cclib = + match link_mode, os with + | Dynamic, _ -> [], [] + | Static, Linux -> [], ["-static"; "-no-pie"] + | Mixed, Linux -> + let cclib = mixed_cclib @ List.map (fun s -> "-l" ^ s) libs in + mixed_flags, "-Wl,-Bdynamic" :: "-Wl,-Bstatic" :: cclib + | Mixed, Macos -> + let cclib = mixed_cclib @ + List.map + (fun lib -> + let archive = + if Stdcompat.String.starts_with + ~prefix:"lib" lib then + Fmt.str "%s.a" lib + else + Fmt.str "lib%s.a" lib + in + pkgconfig lib archive + ) libs + in + mixed_flags, cclib + | _ -> Fmt.invalid_arg "unsupported mode and OS" + in + Fmt.pr "@[(-linkall %a %a)@]" + Fmt.(list ~sep:sp string) flags + Fmt.(list ~sep:sp pp_lib) cclib; + `Ok () + in + exit rc