Always allow -staticlib
authorMoritz Angermann <moritz.angermann@gmail.com>
Tue, 11 Jul 2017 15:57:48 +0000 (11:57 -0400)
committerBen Gamari <ben@smart-cactus.org>
Tue, 11 Jul 2017 17:41:55 +0000 (13:41 -0400)
the `-staticlib` flag is currently only supported on apple platforms,
due to the avaiablity of libtool (the apple version, which is unlike the
gnu version).  This however prevents the use of -staticlib in cases
where it would be beneficial as well.  The functionality that
`-staticlib` uses from `libtool` can be stubbed with a small script like
the following:

```
#!/bin/bash

# This script pretends to be libtool.  And supports
# only a limited set of flags.
#
# It is supposed to be a stand in for libtool -static, whic
# creates a static archive.  This is done by locating all -l<lib>
# libs in the provied -L<lib path> library paths, and building an
# MRI script to create the final archive from all the libraries, and
# other provided inputs.
#

name=${0##*/}
target=${name%-*}

set -e

ldflags_L=()
ldflags_l=()
output=""
inputs=()
STATIC=0
DYNAMIC=1
mode=$DYNAMIC
verbose=0

# find_lib <name> path path path path
function find_lib () {
        lib=$1; shift 1;
        for dir in $@; do
                if [ -f "$dir/$lib" ]; then
                        echo "$dir/$lib"
                        break
                fi
        done
}

while [ "$#" -gt 0 ]; do
        case "$1" in
                -v|--verbose) verbose=1; shift 1;;
                -o) output="$2"; shift 2;;
                -L*) ldflags_L+=("${1:2:${#1}-2}"); shift 1;;
                -l*) ldflags_l+=("lib${1:2:${#1}-2}.a"); shift 1;;
                -static) mode=$STATIC; shift 1;;
                -dynamic) mode=$DYNAMIC; shift 1;;
                -Wl,*) ldflags+=("${1#*,}"); shift 1;;
                -*) echo "unknown option: $1" >&2; exit 1;;
                *) inputs+=("$1"); shift 1;;
        esac
done

if [ ! $mode == $STATIC ]; then
        echo "-dynamic not supported!" >&2; exit 1;
fi

MRI="create ${output}\n"
for input in "${ldflags_l[@]}"; do
        lib=$(find_lib $input ${ldflags_L[@]})
        if [ -z $lib ]; then
                echo "Failed to find lib $input" >&2
                exit 1
        else
                MRI+="addlib $lib\n"
                continue
        fi
done
for input in "${inputs[@]}"; do
        MRI+="addmod $input\n"
done
MRI+="save\nend\n"
echo -e "$MRI" | $target-ar -M
$target-ranlib $output
```

if `ar` supports MRI scripts.

Reviewers: austin, bgamari

Reviewed By: bgamari

Subscribers: rwbarton, thomie

Differential Revision: https://phabricator.haskell.org/D3706

compiler/main/DriverPipeline.hs
docs/users_guide/phases.rst
utils/mkUserGuidePart/Options/Linking.hs

index eed66b2..ad0e0c8 100644 (file)
@@ -2082,10 +2082,7 @@ linkDynLibCheck dflags o_files dep_packages
 
 linkStaticLibCheck :: DynFlags -> [String] -> [InstalledUnitId] -> IO ()
 linkStaticLibCheck dflags o_files dep_packages
- = do
-    when (platformOS (targetPlatform dflags) `notElem` [OSiOS, OSDarwin]) $
-      throwGhcExceptionIO (ProgramError "Static archive creation only supported on Darwin/OS X/iOS")
-    linkBinary' True dflags o_files dep_packages
+ = linkBinary' True dflags o_files dep_packages
 
 -- -----------------------------------------------------------------------------
 -- Running CPP
index 1efe6a4..f35ba1b 100644 (file)
@@ -539,11 +539,9 @@ for example).
 
 .. ghc-flag:: -staticlib
 
-    On Darwin/OS X/iOS only, link all passed files into a static library
-    suitable for linking into an iOS (when using a cross-compiler) or
-    Mac Xcode project. To control the name, use the :ghc-flag:`-o` ⟨name⟩ option
-    as usual. The default name is ``liba.a``. This should nearly always
-    be passed when compiling for iOS with a cross-compiler.
+    Link all passed files into a static library suitable for linking.
+    To control the name, use the :ghc-flag:`-o` ⟨name⟩ option
+    as usual. The default name is ``liba.a``.
 
 .. ghc-flag:: -L ⟨dir⟩
 
index 9edc7c3..3142020 100644 (file)
@@ -11,9 +11,10 @@ linkingOptions =
          }
   , flag { flagName = "-staticlib"
          , flagDescription =
-           "On Darwin/OS X/iOS only, generate a standalone static library " ++
-           "(as opposed to an executable). This is the usual way to " ++
-           "compile for iOS."
+           "Generate a standalone static library (as opposed to an " ++
+           "executable). This is useful when cross compiling. The " ++
+           "library together with all its dependencies ends up in in a " ++
+           "single static library that can be linked against."
          , flagType = DynamicFlag
          }
   , flag { flagName = "-fPIC"