Commit 07ac3f8e authored by Tamar Christina's avatar Tamar Christina Committed by Ben Gamari
Browse files

Add short library names support to Windows linker

Make Linker.hs try asking gcc for lib%s.dll as well, also changed tryGcc
to pass -L to all components by using -B instead. These two fix
shortnames linking on windows.

re-enabled tests: ghcilink003, ghcilink006 and T3333
Added two tests: load_short_name and enabled T1407 on windows.

Reviewed By: thomie, bgamari

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

GHC Trac Issues: #9878, #1407, #1883, #5289
parent 58e05c8c
......@@ -1201,7 +1201,7 @@ locateLib dflags is_hs dirs lib
-- for a dynamic library (#5289)
-- otherwise, assume loadDLL can find it
--
= findDll `orElse` findArchive `orElse` tryGcc `orElse` assumeDll
= findDll `orElse` findArchive `orElse` tryGcc `orElse` tryGccPrefixed `orElse` assumeDll
| not dynamicGhc
-- When the GHC package was not compiled as dynamic library
......@@ -1222,6 +1222,7 @@ locateLib dflags is_hs dirs lib
mk_hs_dyn_lib_path dir = dir </> mkHsSOName platform hs_dyn_lib_name
so_name = mkSOName platform lib
lib_so_name = "lib" ++ so_name
mk_dyn_lib_path dir = case (arch, os) of
(ArchX86_64, OSSolaris2) -> dir </> ("64/" ++ so_name)
_ -> dir </> so_name
......@@ -1232,6 +1233,7 @@ locateLib dflags is_hs dirs lib
findHSDll = liftM (fmap DLLPath) $ findFile mk_hs_dyn_lib_path dirs
findDll = liftM (fmap DLLPath) $ findFile mk_dyn_lib_path dirs
tryGcc = liftM (fmap DLLPath) $ searchForLibUsingGcc dflags so_name dirs
tryGccPrefixed = liftM (fmap DLLPath) $ searchForLibUsingGcc dflags lib_so_name dirs
assumeDll = return (DLL lib)
infixr `orElse`
......@@ -1246,7 +1248,9 @@ locateLib dflags is_hs dirs lib
searchForLibUsingGcc :: DynFlags -> String -> [FilePath] -> IO (Maybe FilePath)
searchForLibUsingGcc dflags so dirs = do
str <- askCc dflags (map (FileOption "-L") dirs
-- GCC does not seem to extend the library search path (using -L) when using
-- --print-file-name. So instead pass it a new base location.
str <- askCc dflags (map (FileOption "-B") dirs
++ [Option "--print-file-name", Option so])
let file = case lines str of
[] -> ""
......
......@@ -40,7 +40,11 @@ ghcilink002 :
.PHONY: ghcilink003
ghcilink003 :
ifeq "$(WINDOWS)" "YES"
echo ":q" | "$(TEST_HC)" --interactive -ignore-dot-ghci -v0 -lstdc++-6
else
echo ":q" | "$(TEST_HC)" --interactive -ignore-dot-ghci -v0 -lstdc++
endif
# Test 4:
# package P
......@@ -114,7 +118,11 @@ ghcilink006 :
echo "version: 1.0" >>$(PKG006)
echo "id: test-XXX" >>$(PKG006)
echo "key: test-1.0" >>$(PKG006)
ifeq "$(WINDOWS)" "YES"
echo "extra-libraries: stdc++-6" >>$(PKG006)
else
echo "extra-libraries: stdc++" >>$(PKG006)
endif
'$(GHC_PKG)' init $(LOCAL_PKGCONF006)
'$(GHC_PKG)' --no-user-package-db -f $(LOCAL_PKGCONF006) register $(PKG006) -v0
#
......
:set -ldl
import Foreign
import Foreign.C.String
foreign import ccall "dlerror" dle :: IO CString
......@@ -12,8 +12,6 @@ test('ghcilink002',
test('ghcilink003',
[
# still cannot load libstdc++ on Windows. See also #4468.
when(opsys('mingw32'), expect_broken(5289)),
unless(doing_ghci, skip),
extra_clean(['dir003/*','dir003'])
],
......@@ -33,8 +31,6 @@ test('ghcilink005',
test('ghcilink006',
[
# still cannot load libstdc++ on Windows. See also #4468.
when(opsys('mingw32'), expect_broken(5289)),
unless(doing_ghci, skip),
extra_clean(['dir006/*','dir006'])
],
......@@ -44,8 +40,7 @@ test('ghcilink006',
test('T3333',
[extra_clean('T3333.o'),
unless(doing_ghci, skip),
unless(opsys('linux') or ghci_dynamic(), expect_broken(3333))],
unless(ghci_dynamic(), expect_broken(3333))],
run_command,
['$MAKE -s --no-print-directory T3333'])
test('T1407', normal, ghci_script, ['T1407.script'])
#if defined(_MSC_VER)
// Microsoft
#define EXPORT __declspec(dllexport)
#elif defined(_GCC)
// GCC
#define EXPORT __attribute__((visibility("default")))
#else
// do nothing and hope for the best?
#define EXPORT
#endif
extern EXPORT int foo();
EXPORT int foo()
{
return 2;
}
TOP=../../../..
include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
ifeq "$(WINDOWS)" "YES"
DLL = lib$1.dll
else ifeq "$(DARWIN)" "YES"
DLL = lib$1.dylib
else
DLL = lib$1.so
endif
.PHONY: load_short_name
load_short_name:
rm -rf bin_short
mkdir bin_short
gcc -shared A.c -o "bin_short/$(call DLL,A)"
echo ":q" | "$(TEST_HC)" --interactive -L"$(PWD)/bin_short" -lA -v0
.PHONY: compile_libAS
compile_libAS:
gcc -shared A.c -o $(call DLL,AS)
:set -lAS
import Foreign
import Foreign.C.Types
foreign import ccall "foo" dle :: IO CInt
test('load_short_name',
[unless(doing_ghci, skip),
extra_clean(['bin_short/*', 'bin_short'])],
run_command,
['$MAKE -s --no-print-directory load_short_name'])
test('T1407',
[unless(doing_ghci, skip),
extra_clean(['libAS.*']),
pre_cmd('$MAKE -s --no-print-directory compile_libAS'),
extra_hc_opts('-L.')],
ghci_script, ['T1407.script'])
......@@ -204,7 +204,7 @@ test('T9878',
ghci_script, ['T9878.script'])
test('T9878b',
[ extra_run_opts('-fobject-code'),
extra_clean(['T9878.hi','T9878.o'])],
extra_clean(['T9878b.hi','T9878b.o'])],
ghci_script, ['T9878b.script'])
test('T10321', normal, ghci_script, ['T10321.script'])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment