Commit 3b8aa927 authored by Andrey Mokhov's avatar Andrey Mokhov
Browse files

Build libffi library, fix #75.

parent d3eef6dc
......@@ -49,6 +49,7 @@ executable ghc-shake
, Rules.Generators.GhcPlatformH
, Rules.Generators.GhcVersionH
, Rules.Generators.VersionHs
, Rules.Libffi
, Rules.Library
, Rules.Oracles
, Rules.Package
......@@ -73,6 +74,7 @@ executable ghc-shake
, Settings.Builders.Hsc2Hs
, Settings.Builders.HsCpp
, Settings.Builders.Ld
, Settings.Builders.Tar
, Settings.Packages
, Settings.Packages.Base
, Settings.Packages.Compiler
......
......@@ -4,9 +4,9 @@ module GHC (
deepseq, deriveConstants, directory, dllSplit, filepath, genapply,
genprimopcode, ghc, ghcBoot, ghcCabal, ghci, ghcPkg, ghcPrim, ghcPwd,
ghcTags, haddock, haskeline, hsc2hs, hoopl, hp2ps, hpc, hpcBin, integerGmp,
integerSimple, iservBin, mkUserGuidePart, parallel, pretty, primitive,
process, rts, runGhc, stm, templateHaskell, terminfo, time, transformers,
unix, win32, xhtml,
integerSimple, iservBin, libffi, mkUserGuidePart, parallel, pretty,
primitive, process, rts, runGhc, stm, templateHaskell, terminfo, time,
transformers, unix, win32, xhtml,
defaultKnownPackages, defaultTargetDirectory, defaultProgramPath
) where
......@@ -26,18 +26,18 @@ defaultKnownPackages =
, deepseq, deriveConstants, directory, dllSplit, filepath, genapply
, genprimopcode, ghc, ghcBoot, ghcCabal, ghci, ghcPkg, ghcPrim
, ghcPwd, ghcTags, haddock, haskeline, hsc2hs, hoopl, hp2ps, hpc, hpcBin
, integerGmp, integerSimple, iservBin, mkUserGuidePart, parallel, pretty
, primitive, process, rts, runGhc, stm, templateHaskell, terminfo, time
, transformers, unix, win32, xhtml ]
, integerGmp, integerSimple, iservBin, libffi, mkUserGuidePart, parallel
, pretty, primitive, process, rts, runGhc, stm, templateHaskell, terminfo
, time, transformers, unix, win32, xhtml ]
-- Package definitions (see Package.hs)
array, base, binary, bytestring, cabal, compiler, containers, compareSizes,
deepseq, deriveConstants, directory, dllSplit, filepath, genapply,
genprimopcode, ghc, ghcBoot, ghcCabal, ghci, ghcPkg, ghcPrim, ghcPwd,
ghcTags, haddock, haskeline, hsc2hs, hoopl, hp2ps, hpc, hpcBin, integerGmp,
integerSimple, iservBin, mkUserGuidePart, parallel, pretty, primitive,
process, rts, runGhc, stm, templateHaskell, terminfo, time, transformers,
unix, win32, xhtml :: Package
integerSimple, iservBin, libffi, mkUserGuidePart, parallel, pretty,
primitive, process, rts, runGhc, stm, templateHaskell, terminfo, time,
transformers, unix, win32, xhtml :: Package
array = library "array"
base = library "base"
......@@ -72,6 +72,7 @@ hpcBin = utility "hpc-bin" `setPath` "utils/hpc"
integerGmp = library "integer-gmp"
integerSimple = library "integer-simple"
iservBin = topLevel "iserv-bin" `setPath` "iserv" `setType` Program
libffi = topLevel "libffi"
mkUserGuidePart = utility "mkUserGuidePart"
parallel = library "parallel"
pretty = library "pretty"
......
......@@ -4,6 +4,7 @@ import Rules.Cabal
import Rules.Config
import Rules.Generate
import Rules.Copy
import Rules.Libffi
import Rules.Oracles
main :: IO ()
......@@ -13,6 +14,7 @@ main = shakeArgs options $ do
copyRules -- see Rules.Copy
generateTargets -- see Rules
generateRules -- see Rules.Generate
libffiRules -- see Rules.Libffi
oracleRules -- see Rules.Oracles
packageRules -- see Rules
where
......
......@@ -14,7 +14,7 @@ generateTargets :: Rules ()
generateTargets = action $ do
targets <- fmap concat . forM [Stage0 ..] $ \stage -> do
pkgs <- interpretWithStage stage getPackages
let libPkgs = filter isLibrary pkgs \\ [rts]
let libPkgs = filter isLibrary pkgs \\ [rts, libffi]
libTargets <- fmap concat . forM libPkgs $ \pkg -> do
let target = PartialTarget stage pkg
needHaddock <- interpretPartial target buildHaddock
......
......@@ -29,14 +29,17 @@ cabalRules = do
-- Cache package dependencies
packageDependencies %> \out -> do
pkgs <- interpretWithStage Stage1 getPackages
pkgDeps <- forM (sort pkgs) $ \pkg -> if pkg == rts then return [] else do
need [pkgCabalFile pkg]
pd <- liftIO . readPackageDescription silent $ pkgCabalFile pkg
let depsLib = collectDeps $ condLibrary pd
depsExes = map (collectDeps . Just . snd) $ condExecutables pd
deps = concat $ depsLib : depsExes
depNames = [ name | Dependency (DP.PackageName name) _ <- deps ]
return . unwords $ pkgNameString pkg : sort depNames
pkgDeps <- forM (sort pkgs) $ \pkg ->
if pkg == rts
then return $ pkgNameString pkg
else do
need [pkgCabalFile pkg]
pd <- liftIO . readPackageDescription silent $ pkgCabalFile pkg
let depsLib = collectDeps $ condLibrary pd
depsExes = map (collectDeps . Just . snd) $ condExecutables pd
deps = concat $ depsLib : depsExes
depNames = [ name | Dependency (DP.PackageName name) _ <- deps ]
return . unwords $ pkgNameString pkg : sort depNames
writeFileChanged out . unlines $ pkgDeps
-- When the file exists, the packageConfiguration has been initialised
......
......@@ -4,6 +4,7 @@ import Base
import Expression
import GHC
import Rules.Generate
import Rules.Libffi
import Settings.TargetDirectory
installTargets :: [FilePath]
......@@ -14,9 +15,11 @@ installTargets = [ "inplace/lib/template-hsc.h"
copyRules :: Rules ()
copyRules = do
targetPath Stage1 rts -/- "build/ffi*.h" %> \ffih -> do
need [libffiLibrary]
ffiHPaths <- getDirectoryFiles "" ["libffi/build/inst/lib/*/include/ffi.h"]
when (length ffiHPaths /= 1) $
putError "copyRules: cannot determine location of ffi.h"
putError $ "copyRules: exactly one ffi.h header expected"
++ "(found: " ++ show ffiHPaths ++ ")."
let ffiHPath = takeDirectory $ head ffiHPaths
copy ffih ffiHPath
......
module Rules.Libffi (libffiRules, libffiLibrary) where
import System.Directory
import Base
import Expression
import GHC
import Oracles.Config.Setting
import Rules.Actions
import Settings.Builders.Common
-- We use this file to track the whole libffi library
libffiLibrary :: FilePath
libffiLibrary = libffiBuild -/- "inst/lib/libffi.a"
libffiBuild :: FilePath
libffiBuild = "libffi/build"
libffiMakefile :: FilePath
libffiMakefile = libffiBuild -/- "Makefile.in"
fixLibffiMakefile :: String -> String
fixLibffiMakefile = unlines . map
( replace "-MD" "-MMD"
. replace "@toolexeclibdir@" "$(libdir)"
. replace "@INSTALL@" "$(subst ../install-sh,C:/msys/home/chEEtah/ghc/install-sh,@INSTALL@)"
) . lines
target :: PartialTarget
target = PartialTarget Stage0 libffi
-- Not efficient, but simple and works fast enough for libffi Makefile.in
replace :: String -> String -> String -> String
replace from to = go
where
skipFrom = drop $ length from
go [] = []
go s @ (x : xs)
| from `isPrefixOf` s = to ++ go (skipFrom s)
| otherwise = x : go xs
-- TODO: remove code duplication (see Settings/Builders/GhcCabal.hs)
configureEnvironment :: Action [CmdOption]
configureEnvironment = do
cFlags <- interpretPartial target . fromDiffExpr $ mconcat
[ cArgs
, argStagedSettingList ConfCcArgs ]
ldFlags <- interpretPartial target $ fromDiffExpr ldArgs
sequence [ builderEnv "CC" $ Gcc Stage1
, builderEnv "CXX" $ Gcc Stage1
, builderEnv "LD" Ld
, builderEnv "AR" Ar
, builderEnv "NM" Nm
, builderEnv "RANLIB" Ranlib
, return . AddEnv "CFLAGS" $ unwords cFlags ++ " -w"
, return . AddEnv "LDFLAGS" $ unwords ldFlags ++ " -w" ]
where
builderEnv var builder = do
needBuilder False builder
path <- builderPath builder
return $ AddEnv var path
configureArguments :: Action [String]
configureArguments = do
top <- setting GhcSourcePath
targetPlatform <- setting TargetPlatform
return [ "--prefix=" ++ top ++ "/libffi/build/inst"
, "--libdir=" ++ top ++ "/libffi/build/inst/lib"
, "--enable-static=yes"
, "--enable-shared=no" -- TODO: add support for yes
, "--host=" ++ targetPlatform ]
libffiRules :: Rules ()
libffiRules = do
libffiLibrary %> \_ -> do
need [sourcePath -/- "Rules/Libffi.hs"]
liftIO $ removeFiles libffiBuild ["//*"]
tarballs <- getDirectoryFiles "" ["libffi-tarballs/libffi*.tar.gz"]
when (length tarballs /= 1) $
putError $ "libffiRules: exactly one libffi tarball expected"
++ "(found: " ++ show tarballs ++ ")."
let libname = dropExtension . dropExtension . takeFileName $ head tarballs
need tarballs
build $ fullTarget target Tar tarballs ["libffi-tarballs"]
let libffiExtracted = "libffi-tarballs" -/- libname
liftIO $ renameDirectory libffiExtracted libffiBuild
putBuild $ "| Move " ++ libffiExtracted ++ " -> " ++ libffiBuild
old <- liftIO $ readFile libffiMakefile
let new = fixLibffiMakefile old
length new `seq` liftIO $ writeFile libffiMakefile new
putBuild $ "| Fix " ++ libffiMakefile
forM_ ["config.guess", "config.sub"] $ \file -> do
copyFileChanged file $ libffiBuild -/- file
putBuild $ "| Copy " ++ file ++ " -> " ++ (libffiBuild -/- file)
putBuild $ "| Running libffi configure..."
envs <- configureEnvironment
args <- configureArguments
unit $ cmd Shell [Cwd libffiBuild] "bash configure" envs args
putBuild $ "| Running make..."
unit $ cmd Shell "make" ["-C", libffiBuild, "MAKEFLAGS="]
putBuild $ "| Running make install..."
unit $ cmd Shell "make" ["-C", libffiBuild, "MAKEFLAGS= install"]
putSuccess $ "| Successfully built custom library 'libffi'"
"libffi/build/inst/lib/*/include/*.h" %> \_ -> need [libffiLibrary]
-- chmod +x libffi/ln
-- # wc on OS X has spaces in its output, which libffi's Makefile
-- # doesn't expect, so we tweak it to sed them out
-- mv libffi/build/Makefile libffi/build/Makefile.orig
-- sed "s#wc -w#wc -w | sed 's/ //g'#" < libffi/build/Makefile.orig > libffi/build/Makefile
......@@ -51,10 +51,10 @@ buildPackageLibrary _ target @ (PartialTarget stage pkg) = do
synopsis <- interpretPartial target $ getPkgData Synopsis
unless isLib0 . putSuccess $ renderBox
[ "Successfully built package library '"
[ "Successfully built library '"
++ pkgNameString pkg
++ "' (" ++ show stage ++ ", way "++ show way ++ ")."
, "Package synopsis: " ++ dropWhileEnd isPunctuation synopsis ++ "." ]
, "Library synopsis: " ++ dropWhileEnd isPunctuation synopsis ++ "." ]
-- TODO: this looks fragile as haskell objects can match this rule if their
-- names start with "HS" and they are on top of the module hierarchy.
......
......@@ -103,4 +103,4 @@ buildBinary target @ (PartialTarget stage pkg) bin = do
[ "Successfully built program '"
++ pkgNameString pkg ++ "' (" ++ show stage ++ ")."
, "Executable: " ++ bin
, "Package synopsis: " ++ dropWhileEnd isPunctuation synopsis ++ "." ]
, "Program synopsis: " ++ dropWhileEnd isPunctuation synopsis ++ "." ]
module Settings.Builders.Common (
includesArgs, cIncludeArgs, cArgs, cWarnings,
includesArgs, cIncludeArgs, ldArgs, cArgs, cWarnings,
argSetting, argSettingList, argStagedBuilderPath, argStagedSettingList
) where
......@@ -28,6 +28,9 @@ cIncludeArgs = do
, append [ "-I" ++ pkgPath pkg -/- dir | dir <- incDirs ]
, append [ "-I" ++ dir | dir <- depDirs ] ]
ldArgs :: Args
ldArgs = mempty
-- TODO: put all validating options together in one file
cArgs :: Args
cArgs = validating ? cWarnings
......
......@@ -99,9 +99,6 @@ packageConstraints = stage0 ? do
constraints <- lift . readFileLines $ bootPackageConstraints
append $ concat [ ["--constraint", c] | c <- constraints ]
ldArgs :: Args
ldArgs = mempty
cppArgs :: Args
cppArgs = includesArgs
......
......@@ -63,13 +63,13 @@ getCFlags = fromDiffExpr $ do
getLFlags :: Expr [String]
getLFlags = fromDiffExpr $ do
ldArgs <- getPkgDataList LdArgs
pkgLdArgs <- getPkgDataList LdArgs
libDirs <- getPkgDataList DepLibDirs
extraLibs <- getPkgDataList DepExtraLibs
depLdArgs <- getPkgDataList DepLdArgs
mconcat [ argStagedSettingList ConfGccLinkerArgs
--, ldArgs -- TODO: resolve name conflict (ldArgs is currently empty)
, append ldArgs
, ldArgs
, append pkgLdArgs
, append $ [ "-L" ++ unifyPath dir | dir <- libDirs ]
, append $ [ "-l" ++ unifyPath dir | dir <- extraLibs ]
, append depLdArgs ]
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