summaryrefslogtreecommitdiff
path: root/hadrian
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2021-11-10 14:52:24 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-11-15 13:19:42 -0500
commitd9f5490591c290295e161431008d60a4495c2390 (patch)
tree27e517234d40307e0ebe4e434ce9e249a6e5f90f /hadrian
parent3302f42a57a9e26423e30221e455de5a173cd6c5 (diff)
downloadhaskell-d9f5490591c290295e161431008d60a4495c2390.tar.gz
Hadrian: fix windows cross-build (#20657)
Many small things to fix: * Hadrian: platform triple is "x86_64-w64-mingw32" and this wasn't recognized by Hadrian (note "w64" instead of "unknown") * Hadrian was using the build platform ("isWindowsHost") to detect the use of the Windows toolchain, which was wrong. We now use the "targetOs" setting. * Hadrian was doing the same thing for Darwin so we fixed both at once, even if cross-compilation to Darwin is unlikely to happen afaik (cf "osxHost" vs "osxTarget" changes) * Hadrian: libffi name was computed in two different places and one of them wasn't taking the different naming on Windows into account. * Hadrian was passing "-Irts/include" when building the stage1 compiler leading to the same error as in #18143 (which is using make). stage1's RTS is stage0's one so mustn't do this. * Hadrian: Windows linker doesn't seem to support "-zorigin" so we don't pass it (similarly to Darwin) * Hadrian: hsc2hs in cross-compilation mode uses a trick (taken from autoconf): it defines "static int test_array[SOME_EXPR]" where SOME_EXPR is a constant expression. However GCC reports an error because SOME_EXPR is supposedly not constant. This is fixed by using another method enabled with the `--via-asm` flag of hsc2hs. It has been fixed in `make` build system (5f6fcf7808b16d066ad0fb2068225b3f2e8363f7) but not in Hadrian. * Hadrian: some packages are specifically built only on Windows but they shouldn't be when building a cross-compiler (`touchy` and `ghci-wrapper`). We now correctly detect this case and disable these packages. * Base: we use `iNVALID_HANDLE_VALUE` in a few places. It fixed some hsc2hs issues before we switched to `--via-asm` (see above). I've kept these changes are they make the code nicer. * Base: `base`'s configure tries to detect if it is building for Windows but for some reason the `$host_alias` value is `x86_64-windows` in my case and it wasn't properly detected. * Base: libraries/base/include/winio_structs.h imported "Windows.h" with a leading uppercase. It doesn't work on case-sensitive systems when cross-compiling so we have to use "windows.h". * RTS: rts/win32/ThrIOManager.c was importin "rts\OSThreads.h" but this path isn't valid when cross-compiling. We replaced "\" with "/". * DeriveConstants: this tool derives the constants from the target RTS header files. However these header files define `StgAsyncIOResult` only when `mingw32_HOST_OS` is set hence it seems we have to set it explicitly. Note that deriveConstants is called more than once (why? there is only one target for now so it shouldn't) and in the second case this value is correctly defined (probably coming indirectly from the import of "rts/PosixSource.h"). A better fix would probably be to disable the unneeded first run of deriveconstants.
Diffstat (limited to 'hadrian')
-rw-r--r--hadrian/src/Oracles/Flag.hs7
-rw-r--r--hadrian/src/Oracles/Setting.hs8
-rw-r--r--hadrian/src/Packages.hs12
-rw-r--r--hadrian/src/Rules/Libffi.hs35
-rw-r--r--hadrian/src/Rules/Rts.hs4
-rw-r--r--hadrian/src/Settings/Builders/Common.hs3
-rw-r--r--hadrian/src/Settings/Builders/Ghc.hs11
-rw-r--r--hadrian/src/Settings/Builders/Hsc2Hs.hs9
-rw-r--r--hadrian/src/Settings/Default.hs82
-rw-r--r--hadrian/src/Settings/Packages.hs6
10 files changed, 102 insertions, 75 deletions
diff --git a/hadrian/src/Oracles/Flag.hs b/hadrian/src/Oracles/Flag.hs
index 5b41698be1..535a0a0138 100644
--- a/hadrian/src/Oracles/Flag.hs
+++ b/hadrian/src/Oracles/Flag.hs
@@ -60,12 +60,11 @@ getFlag = expr . flag
platformSupportsSharedLibs :: Action Bool
platformSupportsSharedLibs = do
- badPlatform <- anyTargetPlatform [ "powerpc-unknown-linux"
- , "x86_64-unknown-mingw32"
- , "i386-unknown-mingw32" ]
+ windows <- isWinTarget
+ ppc_linux <- anyTargetPlatform [ "powerpc-unknown-linux" ]
solaris <- anyTargetPlatform [ "i386-unknown-solaris2" ]
solarisBroken <- flag SolarisBrokenShld
- return $ not (badPlatform || solaris && solarisBroken)
+ return $ not (windows || ppc_linux || solaris && solarisBroken)
-- | Does the target support the threaded runtime system?
targetSupportsSMP :: Action Bool
diff --git a/hadrian/src/Oracles/Setting.hs b/hadrian/src/Oracles/Setting.hs
index 73fd1ce273..b1db240f34 100644
--- a/hadrian/src/Oracles/Setting.hs
+++ b/hadrian/src/Oracles/Setting.hs
@@ -11,7 +11,7 @@ module Oracles.Setting (
-- ** Target platform things
anyTargetPlatform, anyTargetOs, anyTargetArch, anyHostOs,
- isElfTarget,
+ isElfTarget, isOsxTarget, isWinTarget,
ArmVersion(..),
targetArmVersion,
ghcWithInterpreter
@@ -240,6 +240,12 @@ anyTargetPlatform = matchSetting TargetPlatformFull
anyTargetOs :: [String] -> Action Bool
anyTargetOs = matchSetting TargetOs
+isWinTarget :: Action Bool
+isWinTarget = anyTargetOs ["mingw32"]
+
+isOsxTarget :: Action Bool
+isOsxTarget = anyTargetOs ["darwin"]
+
-- | Check whether the target architecture setting matches one of the given
-- strings.
anyTargetArch :: [String] -> Action Bool
diff --git a/hadrian/src/Packages.hs b/hadrian/src/Packages.hs
index 1a7fbbe5cd..2616f097fe 100644
--- a/hadrian/src/Packages.hs
+++ b/hadrian/src/Packages.hs
@@ -13,7 +13,7 @@ module Packages (
-- * Package information
programName, nonHsMainPackage, autogenPath, programPath, timeoutPath,
- rtsContext, rtsBuildPath, libffiBuildPath, libffiLibraryName,
+ rtsContext, rtsBuildPath, libffiBuildPath,
ensureConfigured
) where
@@ -219,16 +219,6 @@ libffiBuildPath stage = buildPath $ Context
libffi
(error "libffiBuildPath: way not set.")
--- | Name of the 'libffi' library.
-libffiLibraryName :: Action FilePath
-libffiLibraryName = do
- useSystemFfi <- flag UseSystemFfi
- return $ case (useSystemFfi, windowsHost) of
- (True , False) -> "ffi"
- (False, False) -> "Cffi"
- (_ , True ) -> "Cffi-6"
-
-
{-
Note [Hadrian's ghci-wrapper package]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/hadrian/src/Rules/Libffi.hs b/hadrian/src/Rules/Libffi.hs
index 86238c30a4..27a4a3e9f2 100644
--- a/hadrian/src/Rules/Libffi.hs
+++ b/hadrian/src/Rules/Libffi.hs
@@ -81,16 +81,24 @@ libffiContext stage = do
then dynamic
else vanilla
--- | The name of the (locally built) library
+-- | The name of the library
libffiName :: Expr String
libffiName = do
- way <- getWay
- return $ libffiName' (Dynamic `wayUnit` way)
+ useSystemFfi <- expr (flag UseSystemFfi)
+ if useSystemFfi
+ then pure "ffi"
+ else libffiLocalName Nothing
-- | The name of the (locally built) library
-libffiName' :: Bool -> String
-libffiName' dynamic = (if dynamic then "" else "C")
- ++ (if windowsHost then "ffi-6" else "ffi")
+libffiLocalName :: Maybe Bool -> Expr String
+libffiLocalName force_dynamic = do
+ way <- getWay
+ winTarget <- expr isWinTarget
+ let dynamic = fromMaybe (Dynamic `wayUnit` way) force_dynamic
+ pure $ mconcat
+ [ if dynamic then "" else "C"
+ , if winTarget then "ffi-6" else "ffi"
+ ]
libffiLibrary :: FilePath
libffiLibrary = "inst/lib/libffi.a"
@@ -164,21 +172,24 @@ libffiRules = do
-- Note this build needs the Makefile, triggering the rules bellow.
build $ target context (Make libffiPath) [] []
+ libffiName' <- interpretInContext context (libffiLocalName (Just True))
-- Produces all install files.
produces =<< (\\ topLevelTargets)
<$> liftIO (getDirectoryFilesIO "." [libffiPath -/- "inst//*"])
-- Find dynamic libraries.
+ osxTarget <- isOsxTarget
+ winTarget <- isWinTarget
+
dynLibFiles <- do
let libfilesDir = libffiPath -/-
- (if windowsHost then "inst" -/- "bin" else "inst" -/- "lib")
- libffiName'' = libffiName' True
+ (if winTarget then "inst" -/- "bin" else "inst" -/- "lib")
dynlibext
- | windowsHost = "dll"
- | osxHost = "dylib"
- | otherwise = "so"
- filepat = "lib" ++ libffiName'' ++ "." ++ dynlibext ++ "*"
+ | winTarget = "dll"
+ | osxTarget = "dylib"
+ | otherwise = "so"
+ filepat = "lib" ++ libffiName' ++ "." ++ dynlibext ++ "*"
liftIO $ getDirectoryFilesIO "." [libfilesDir -/- filepat]
writeFileLines dynLibMan dynLibFiles
diff --git a/hadrian/src/Rules/Rts.hs b/hadrian/src/Rules/Rts.hs
index efcd5f614a..a6abcdeb3e 100644
--- a/hadrian/src/Rules/Rts.hs
+++ b/hadrian/src/Rules/Rts.hs
@@ -1,6 +1,6 @@
module Rules.Rts (rtsRules, needRtsLibffiTargets, needRtsSymLinks) where
-import Packages (rts, rtsBuildPath, libffiBuildPath, libffiLibraryName, rtsContext)
+import Packages (rts, rtsBuildPath, libffiBuildPath, rtsContext)
import Rules.Libffi
import Hadrian.Utilities
import Settings.Builders.Common
@@ -103,7 +103,7 @@ copyLibffiDynamicWin stage target = do
rtsLibffiLibrary :: Stage -> Way -> Action FilePath
rtsLibffiLibrary stage way = do
- name <- libffiLibraryName
+ name <- interpretInContext (rtsContext stage) libffiName
suf <- libsuf stage way
rtsPath <- rtsBuildPath stage
return $ rtsPath -/- "lib" ++ name ++ suf
diff --git a/hadrian/src/Settings/Builders/Common.hs b/hadrian/src/Settings/Builders/Common.hs
index 8daa8a1f88..11b6f20ef5 100644
--- a/hadrian/src/Settings/Builders/Common.hs
+++ b/hadrian/src/Settings/Builders/Common.hs
@@ -15,7 +15,6 @@ import Base
import Expression
import Oracles.Flag
import Oracles.Setting
-import Packages
import Settings
import UserSettings
@@ -31,7 +30,7 @@ cIncludeArgs = do
ffiIncludeDir <- getSetting FfiIncludeDir
libdwIncludeDir <- getSetting FfiIncludeDir
libPath <- expr $ stageLibPath stage
- mconcat [ notStage0 ||^ package compiler ? arg "-Irts/include"
+ mconcat [ notStage0 ? arg "-Irts/include"
, arg $ "-I" ++ libPath
, arg $ "-I" ++ path
, pure . map ("-I"++) . filter (/= "") $ [iconvIncludeDir, gmpIncludeDir]
diff --git a/hadrian/src/Settings/Builders/Ghc.hs b/hadrian/src/Settings/Builders/Ghc.hs
index b4c129562e..1d315e50ea 100644
--- a/hadrian/src/Settings/Builders/Ghc.hs
+++ b/hadrian/src/Settings/Builders/Ghc.hs
@@ -104,6 +104,9 @@ ghcLinkArgs = builder (Ghc LinkHs) ? do
libffiName' <- libffiName
debugged <- ghcDebugged <$> expr flavour
+ osxTarget <- expr isOsxTarget
+ winTarget <- expr isWinTarget
+
let
dynamic = Dynamic `wayUnit` way
distPath = libPath' -/- distDir
@@ -115,7 +118,7 @@ ghcLinkArgs = builder (Ghc LinkHs) ? do
-- libraries will all end up in the lib dir, so just use $ORIGIN
| otherwise = metaOrigin
where
- metaOrigin | osxHost = "@loader_path"
+ metaOrigin | osxTarget = "@loader_path"
| otherwise = "$ORIGIN"
-- TODO: an alternative would be to generalize by linking with extra
@@ -144,8 +147,8 @@ ghcLinkArgs = builder (Ghc LinkHs) ? do
, hostSupportsRPaths ? mconcat
[ arg ("-optl-Wl,-rpath," ++ rpath)
, isProgram pkg ? arg ("-optl-Wl,-rpath," ++ bindistRpath)
- -- The darwin linker doesn't support/require the -zorigin option
- , not osxHost ? arg "-optl-Wl,-zorigin"
+ -- The darwin and Windows linkers don't support/require the -zorigin option
+ , not (osxTarget || winTarget) ? arg "-optl-Wl,-zorigin"
-- We set RPATH directly (relative to $ORIGIN). There's
-- no reason for GHC to inject further RPATH entries.
-- See #19485.
@@ -158,7 +161,7 @@ ghcLinkArgs = builder (Ghc LinkHs) ? do
, pure [ "-l" ++ lib | lib <- libs ]
, pure [ "-L" ++ libDir | libDir <- libDirs ]
, rtsFfiArg
- , osxHost ? pure (concat [ ["-framework", fmwk] | fmwk <- fmwks ])
+ , osxTarget ? pure (concat [ ["-framework", fmwk] | fmwk <- fmwks ])
, debugged ? packageOneOf [ghc, iservProxy, iserv, remoteIserv] ?
arg "-debug"
diff --git a/hadrian/src/Settings/Builders/Hsc2Hs.hs b/hadrian/src/Settings/Builders/Hsc2Hs.hs
index 67c32c5ed4..f1a44b5e87 100644
--- a/hadrian/src/Settings/Builders/Hsc2Hs.hs
+++ b/hadrian/src/Settings/Builders/Hsc2Hs.hs
@@ -22,7 +22,7 @@ hsc2hsBuilderArgs = builder Hsc2Hs ? do
tmpl <- (top -/-) <$> expr (templateHscPath Stage0)
mconcat [ arg $ "--cc=" ++ ccPath
, arg $ "--ld=" ++ ccPath
- , not windowsHost ? notM (flag CrossCompiling) ? arg "--cross-safe"
+ , notM isWinTarget ? notM (flag CrossCompiling) ? arg "--cross-safe"
, pure $ map ("-I" ++) (words gmpDir)
, map ("--cflag=" ++) <$> getCFlags
, map ("--lflag=" ++) <$> getLFlags
@@ -33,6 +33,13 @@ hsc2hsBuilderArgs = builder Hsc2Hs ? do
, notStage0 ? arg ("--cflag=-D" ++ tOs ++ "_HOST_OS=1" )
, arg $ "--cflag=-D__GLASGOW_HASKELL__=" ++ version
, arg $ "--template=" ++ tmpl
+ -- We'll assume we compile with gcc or clang, and both support
+ -- `-S` and can as such use the --via-asm flag, which should be
+ -- faster and is required for cross compiling to windows, as the c
+ -- compiler complains about non-constant expressions even though
+ -- they are constant and end up as constants in the assembly.
+ -- See #12849
+ , flag CrossCompiling ? isWinTarget ? arg "--via-asm"
, arg =<< getInput
, arg "-o", arg =<< getOutput ]
diff --git a/hadrian/src/Settings/Default.hs b/hadrian/src/Settings/Default.hs
index 2da096efdb..a20a1d821d 100644
--- a/hadrian/src/Settings/Default.hs
+++ b/hadrian/src/Settings/Default.hs
@@ -22,6 +22,7 @@ import CommandLine
import Expression
import Flavour.Type
import Oracles.Flag
+import Oracles.Setting
import Packages
import Settings.Builders.Alex
import Settings.Builders.DeriveConstants
@@ -92,42 +93,51 @@ stage1Packages :: Action [Package]
stage1Packages = do
libraries0 <- filter isLibrary <$> stage0Packages
cross <- flag CrossCompiling
- return $ libraries0 -- Build all Stage0 libraries in Stage1
- ++ [ array
- , base
- , bytestring
- , containers
- , deepseq
- , directory
- , exceptions
- , filepath
- , ghc
- , ghcBignum
- , ghcCompact
- , ghcPkg
- , ghcPrim
- , haskeline
- , hp2ps
- , hsc2hs
- , integerGmp
- , pretty
- , process
- , rts
- , stm
- , time
- , unlit
- , xhtml
- ]
- ++ [ haddock | not cross ]
- ++ [ hpcBin | not cross ]
- ++ [ iserv | not cross ]
- ++ [ libiserv | not cross ]
- ++ [ runGhc | not cross ]
- ++ [ touchy | windowsHost ]
- -- See Note [Hadrian's ghci-wrapper package]
- ++ [ ghciWrapper | windowsHost ]
- ++ [ unix | not windowsHost ]
- ++ [ win32 | windowsHost ]
+ winTarget <- isWinTarget
+
+ let when c xs = if c then xs else mempty
+
+ return $ mconcat
+ [ libraries0 -- Build all Stage0 libraries in Stage1
+ , [ array
+ , base
+ , bytestring
+ , containers
+ , deepseq
+ , directory
+ , exceptions
+ , filepath
+ , ghc
+ , ghcBignum
+ , ghcCompact
+ , ghcPkg
+ , ghcPrim
+ , haskeline
+ , hp2ps
+ , hsc2hs
+ , integerGmp
+ , pretty
+ , process
+ , rts
+ , stm
+ , time
+ , unlit
+ , xhtml
+ ]
+ , when (not cross)
+ [ haddock
+ , hpcBin
+ , iserv
+ , libiserv
+ , runGhc
+ ]
+ , if winTarget then [ win32 ] else [ unix ]
+ , when (winTarget && not cross)
+ [ touchy
+ -- See Note [Hadrian's ghci-wrapper package]
+ , ghciWrapper
+ ]
+ ]
-- | Packages built in 'Stage2' by default. You can change this in "UserSettings".
stage2Packages :: Action [Package]
diff --git a/hadrian/src/Settings/Packages.hs b/hadrian/src/Settings/Packages.hs
index 6099b66055..bcdd62191a 100644
--- a/hadrian/src/Settings/Packages.hs
+++ b/hadrian/src/Settings/Packages.hs
@@ -6,6 +6,7 @@ import Oracles.Setting
import Oracles.Flag
import Packages
import Settings
+import Rules.Libffi
-- | Package-specific command-line arguments.
packageArgs :: Args
@@ -13,6 +14,7 @@ packageArgs = do
stage <- getStage
path <- getBuildPath
compilerPath <- expr $ buildPath (vanillaContext stage compiler)
+
let -- Do not bind the result to a Boolean: this forces the configure rule
-- immediately and may lead to cyclic dependencies.
-- See: https://gitlab.haskell.org/ghc/ghc/issues/16809.
@@ -240,7 +242,7 @@ rtsPackageArgs = package rts ? do
path <- getBuildPath
top <- expr topDirectory
useSystemFfi <- expr $ flag UseSystemFfi
- libffiName <- expr libffiLibraryName
+ ffiLibName <- libffiName
ffiIncludeDir <- getSetting FfiIncludeDir
ffiLibraryDir <- getSetting FfiLibDir
libdwIncludeDir <- getSetting LibdwIncludeDir
@@ -370,7 +372,7 @@ rtsPackageArgs = package rts ? do
[ "-DTOP=" ++ show top
, "-DFFI_INCLUDE_DIR=" ++ show ffiIncludeDir
, "-DFFI_LIB_DIR=" ++ show ffiLibraryDir
- , "-DFFI_LIB=" ++ show libffiName
+ , "-DFFI_LIB=" ++ show ffiLibName
, "-DLIBDW_LIB_DIR=" ++ show libdwLibraryDir ]
, builder HsCpp ? flag WithLibdw ? arg "-DUSE_LIBDW"