diff options
Diffstat (limited to 'hadrian/src/Rules/Libffi.hs')
-rw-r--r-- | hadrian/src/Rules/Libffi.hs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/hadrian/src/Rules/Libffi.hs b/hadrian/src/Rules/Libffi.hs new file mode 100644 index 0000000000..58ac1efbdc --- /dev/null +++ b/hadrian/src/Rules/Libffi.hs @@ -0,0 +1,109 @@ +module Rules.Libffi (libffiRules, libffiDependencies) where + +import Hadrian.Utilities + +import Packages +import Settings.Builders.Common +import Target +import Utilities + +libffiDependencies :: [FilePath] +libffiDependencies = ["ffi.h", "ffitarget.h"] + +libffiLibrary :: FilePath +libffiLibrary = "inst/lib/libffi.a" + +rtsLibffiLibrary :: Way -> Action FilePath +rtsLibffiLibrary way = do + name <- libffiLibraryName + suf <- libsuf way + rtsPath <- rtsBuildPath + return $ rtsPath -/- "lib" ++ name ++ suf + +fixLibffiMakefile :: FilePath -> String -> String +fixLibffiMakefile top = + replace "-MD" "-MMD" + . replace "@toolexeclibdir@" "$(libdir)" + . replace "@INSTALL@" ("$(subst ../install-sh," ++ top ++ "/install-sh,@INSTALL@)") + +-- TODO: check code duplication w.r.t. ConfCcArgs +configureEnvironment :: Action [CmdOption] +configureEnvironment = do + cFlags <- interpretInContext libffiContext $ mconcat + [ cArgs + , getStagedSettingList ConfCcArgs ] + ldFlags <- interpretInContext libffiContext ldArgs + sequence [ builderEnvironment "CC" $ Cc CompileC Stage1 + , builderEnvironment "CXX" $ Cc CompileC Stage1 + , builderEnvironment "LD" (Ld Stage1) + , builderEnvironment "AR" (Ar Unpack Stage1) + , builderEnvironment "NM" Nm + , builderEnvironment "RANLIB" Ranlib + , return . AddEnv "CFLAGS" $ unwords cFlags ++ " -w" + , return . AddEnv "LDFLAGS" $ unwords ldFlags ++ " -w" ] + +libffiRules :: Rules () +libffiRules = do + root <- buildRootRules + fmap ((root <//> "rts/build") -/-) libffiDependencies &%> \_ -> do + libffiPath <- libffiBuildPath + need [libffiPath -/- libffiLibrary] + + -- we set a higher priority because this overlaps + -- with the static lib rule from Rules.Library.libraryRules. + priority 2.0 $ root <//> libffiLibrary %> \_ -> do + useSystemFfi <- flag UseSystemFfi + rtsPath <- rtsBuildPath + if useSystemFfi + then do + ffiIncludeDir <- setting FfiIncludeDir + putBuild "| System supplied FFI library will be used" + forM_ ["ffi.h", "ffitarget.h"] $ \file -> + copyFile (ffiIncludeDir -/- file) (rtsPath -/- file) + putSuccess "| Successfully copied system FFI library header files" + else do + libffiPath <- libffiBuildPath + build $ target libffiContext (Make libffiPath) [] [] + + hs <- getDirectoryFiles "" [libffiPath -/- "inst/include/*"] + forM_ hs $ \header -> + copyFile header (rtsPath -/- takeFileName header) + + ways <- interpretInContext libffiContext (getLibraryWays <> getRtsWays) + forM_ (nubOrd ways) $ \way -> do + rtsLib <- rtsLibffiLibrary way + copyFileUntracked (libffiPath -/- libffiLibrary) rtsLib + + putSuccess "| Successfully built custom library 'libffi'" + + root <//> "libffi/build/Makefile.in" %> \mkIn -> do + libffiPath <- libffiBuildPath + removeDirectory libffiPath + tarball <- unifyPath . fromSingleton "Exactly one LibFFI tarball is expected" + <$> getDirectoryFiles "" ["libffi-tarballs/libffi*.tar.gz"] + + need [tarball] + -- Go from 'libffi-3.99999+git20171002+77e130c.tar.gz' to 'libffi-3.99999' + let libname = takeWhile (/= '+') $ takeFileName tarball + + root <- buildRoot + removeDirectory (root -/- libname) + -- TODO: Simplify. + actionFinally (do + build $ target libffiContext (Tar Extract) [tarball] [root] + moveDirectory (root -/- libname) libffiPath) $ + removeFiles root [libname <//> "*"] + + top <- topDirectory + fixFile mkIn (fixLibffiMakefile top) + + -- TODO: Get rid of hard-coded @libffi@. + root <//> "libffi/build/Makefile" %> \mk -> do + need [mk <.> "in"] + libffiPath <- libffiBuildPath + forM_ ["config.guess", "config.sub"] $ \file -> + copyFile file (libffiPath -/- file) + + env <- configureEnvironment + buildWithCmdOptions env $ + target libffiContext (Configure libffiPath) [mk <.> "in"] [mk] |