[MLton-commit] r6683

Wesley Terpstra wesley at mlton.org
Thu Jul 31 13:57:39 PDT 2008


Create static libraries using an ar wrapper script.
The included default wrapper says it all:

# This script creates a static library (archive).
# It is invoked as: static-library ARCH OUTPUT objects* libraries*
# eg: static-library self foo.a /tmp/obj1.o /tmp/obj2.o /lib/libmlton.a

# A safe fallback for unsupported platforms is:
#  rm -f foo.a
#  ar rc foo.a /tmp/obj1.o /tmp/obj2.o
#  ranlib foo.a

# However, this script tries to mimic the behaviour of shared libraries as
# closely as possible. It links in the required bits of dependent libraries,
# links together the given objects, and then hides all non-public symbols.
#
# The end result of this process is that two MLton produced static libraries
# can safely be used at the same time since their symbols don't overlap. It
# is even possible to use libraries produced using different versions of the
# runtime.

An example of how the end result works:
	mlton -export-header foo.h -format archive foo.sml
	gcc -Wall -o main main.c foo.a -lgmp -lm
Notice that the user's link line does not include libraries from MLton.


----------------------------------------------------------------------

U   mlton/trunk/Makefile
U   mlton/trunk/bin/mlton-script
A   mlton/trunk/bin/static-library
U   mlton/trunk/mlton/main/main.fun

----------------------------------------------------------------------

Modified: mlton/trunk/Makefile
===================================================================
--- mlton/trunk/Makefile	2008-07-31 19:20:40 UTC (rev 6682)
+++ mlton/trunk/Makefile	2008-07-31 20:57:39 UTC (rev 6683)
@@ -305,6 +305,7 @@
 	$(CP) bin/mlton-script "$(MLTON)"
 	chmod a+x "$(MLTON)"
 	$(CP) "$(SRC)/bin/platform" "$(LIB)"
+	$(CP) "$(SRC)/bin/static-library" "$(LIB)"
 
 .PHONY: targetmap
 targetmap:

Modified: mlton/trunk/bin/mlton-script
===================================================================
--- mlton/trunk/bin/mlton-script	2008-07-31 19:20:40 UTC (rev 6682)
+++ mlton/trunk/bin/mlton-script	2008-07-31 20:57:39 UTC (rev 6683)
@@ -81,6 +81,7 @@
 fi
 
 doit "$lib" \
+        -ar-script "$lib/static-library"                         \
         -cc "$gcc"                                               \
         -cc-opt-quote "-I$lib/include"                           \
         -cc-opt '-O1'                                            \

Added: mlton/trunk/bin/static-library
===================================================================
--- mlton/trunk/bin/static-library	2008-07-31 19:20:40 UTC (rev 6682)
+++ mlton/trunk/bin/static-library	2008-07-31 20:57:39 UTC (rev 6683)
@@ -0,0 +1,51 @@
+#! /usr/bin/env bash
+
+# This script creates a static library (archive).
+# It is invoked as: static-library ARCH OUTPUT objects* libraries*
+# eg: static-library self foo.a /tmp/obj1.o /tmp/obj2.o /lib/libmlton.a
+
+# A safe fallback for unsupported platforms is:
+#  rm -f foo.a
+#  ar rc foo.a /tmp/obj1.o /tmp/obj2.o
+#  ranlib foo.a
+
+# However, this script tries to mimic the behaviour of shared libraries as
+# closely as possible. It links in the required bits of dependent libraries,
+# links together the given objects, and then hides all non-public symbols.
+#
+# The end result of this process is that two MLton produced static libraries
+# can safely be used at the same time since their symbols don't overlap. It
+# is even possible to use libraries produced using different versions of the
+# runtime.
+
+set -e
+
+target="$1"
+shift
+output="$1"
+shift
+
+if [ "$target" = "self" ]; then target=""; else target="$target-"; fi
+
+# Change this to false is partial linking does not work on your platform
+partialLink='true'
+
+rm -f "${output}"
+
+if "$partialLink"; then
+  "${target}ld" -r -d -o "$output.o" "$@"
+  # The osx linker already makes hidden symbols local, so we can skip this
+  if [ "$(uname -s)" != "Darwin" ]; then
+    "${target}objdump" -t "$output.o" \
+      | grep ' \.hidden ' \
+      | sed 's/^.* \.hidden //' \
+      > "$output.locals"
+    "${target}objcopy" --localize-symbols "$output.locals" "$output.o"
+  fi
+  "${target}ar" rc "$output" "$output.o"
+  "${target}ranlib" "$output"
+  rm -f "$output.o" "$output.locals"
+else
+  "${target}ar" rc "$output" "$@"
+  "${target}ranlib" "$output"
+fi


Property changes on: mlton/trunk/bin/static-library
___________________________________________________________________
Name: svn:executable
   + *

Modified: mlton/trunk/mlton/main/main.fun
===================================================================
--- mlton/trunk/mlton/main/main.fun	2008-07-31 19:20:40 UTC (rev 6682)
+++ mlton/trunk/mlton/main/main.fun	2008-07-31 20:57:39 UTC (rev 6683)
@@ -53,7 +53,7 @@
    end
 
 val gcc: string ref = ref "<unset>"
-val ar: string ref = ref "ar"
+val arScript: string ref = ref "<unset>"
 val asOpts: {opt: string, pred: OptPred.t} list ref = ref []
 val ccOpts: {opt: string, pred: OptPred.t} list ref = ref []
 val linkOpts: {opt: string, pred: OptPred.t} list ref = ref []
@@ -204,8 +204,8 @@
                                 | "8" => Align8
                                 | _ => usage (concat ["invalid -align flag: ",
                                                       s]))))),
-       (Expert, "ar", " <ar>", "path to ar executable",
-        SpaceString (fn s => ar := s)),
+       (Expert, "ar-script", " <ar>", "path to a script producing archives",
+        SpaceString (fn s => arScript := s)),
        (Normal, "as-opt", " <opt>", "pass option to assembler",
         (SpaceString o tokenizeOpt)
         (fn s => List.push (asOpts, {opt = s, pred = OptPred.Yes}))),
@@ -887,18 +887,7 @@
                    file = s ^ "-" ^ gccFile}
                end 
           | Self => !gcc
-      val ar = 
-         case target of 
-            Cross s => 
-               let
-                  val {dir = arDir, file = arFile} =
-                     OS.Path.splitDirFile (!ar)
-               in 
-                  OS.Path.joinDirFile
-                  {dir = arDir,
-                   file = s ^ "-" ^ arFile}
-               end 
-          | Self => !ar
+      val arScript = !arScript
 
       fun addTargetOpts opts =
          List.fold
@@ -925,6 +914,13 @@
                       else 
                       ["-lmlton", "-lgdtoa"],
                       addTargetOpts linkOpts]
+      val linkArchives =
+         if !debugRuntime then 
+         [!libTargetDir ^ "/libmlton-gdb.a", 
+          !libTargetDir ^ "/libgdtoa-gdb.a"]
+         else 
+         [!libTargetDir ^ "/libmlton.a", 
+          !libTargetDir ^ "/libgdtoa.a"]
       val _ =
          if not (hasCodegen (!codegen))
             then usage (concat ["can't use ",
@@ -1133,9 +1129,12 @@
                               trace (Top, "Link")
                               (fn () =>
                                if !format = Archive 
-                               then (File.remove output
-                                    ;System.system
-                                     (ar, List.concat [["rcs", output], inputs]))
+                               then System.system
+                                    (arScript, 
+                                     List.concat 
+                                      [[targetStr, output],
+                                       inputs,
+                                       linkArchives])
                                else System.system
                                     (gcc,
                                      List.concat




More information about the MLton-commit mailing list