diff --git a/Cabal/src/Distribution/Simple/Configure.hs b/Cabal/src/Distribution/Simple/Configure.hs index 4324d67a095..a82c0534d75 100644 --- a/Cabal/src/Distribution/Simple/Configure.hs +++ b/Cabal/src/Distribution/Simple/Configure.hs @@ -2622,18 +2622,18 @@ checkForeignLibSupported comp platform flib = go (compilerFlavor comp) ] goGhcPlatform :: Platform -> Maybe String - goGhcPlatform (Platform _ OSX) = goGhcOsx (foreignLibType flib) - goGhcPlatform (Platform _ Linux) = goGhcLinux (foreignLibType flib) - goGhcPlatform (Platform I386 Windows) = goGhcWindows (foreignLibType flib) - goGhcPlatform (Platform X86_64 Windows) = goGhcWindows (foreignLibType flib) + goGhcPlatform (Platform _ OSX) = goGhcOsx + goGhcPlatform (Platform _ Linux) = goGhcLinux + goGhcPlatform (Platform I386 Windows) = goGhcWindows + goGhcPlatform (Platform X86_64 Windows) = goGhcWindows goGhcPlatform _ = unsupported [ "Building foreign libraries is currently only supported on Mac OS, " , "Linux and Windows" ] - goGhcOsx :: ForeignLibType -> Maybe String - goGhcOsx ForeignLibNativeShared + goGhcOsx :: Maybe String + goGhcOsx | not (null (foreignLibModDefFile flib)) = unsupported [ "Module definition file not supported on OSX" @@ -2642,15 +2642,15 @@ checkForeignLibSupported comp platform flib = go (compilerFlavor comp) unsupported [ "Foreign library versioning not currently supported on OSX" ] + | ForeignLibTypeUnknown <- foreignLibType flib = + unsupported + [ "We don't support building unknown-type foreign libraries on OSX" + ] | otherwise = Nothing - goGhcOsx _ = - unsupported - [ "We can currently only build shared foreign libraries on OSX" - ] - goGhcLinux :: ForeignLibType -> Maybe String - goGhcLinux ForeignLibNativeShared + goGhcLinux :: Maybe String + goGhcLinux | not (null (foreignLibModDefFile flib)) = unsupported [ "Module definition file not supported on Linux" @@ -2660,15 +2660,15 @@ checkForeignLibSupported comp platform flib = go (compilerFlavor comp) unsupported [ "You must not specify both lib-version-info and lib-version-linux" ] + | ForeignLibTypeUnknown <- foreignLibType flib = + unsupported + [ "We don't support building unknown-type foreign libraries on Linux" + ] | otherwise = Nothing - goGhcLinux _ = - unsupported - [ "We can currently only build shared foreign libraries on Linux" - ] - goGhcWindows :: ForeignLibType -> Maybe String - goGhcWindows ForeignLibNativeShared + goGhcWindows :: Maybe String + goGhcWindows | not standalone = unsupported [ "We can currently only build standalone libraries on Windows. Use\n" @@ -2681,12 +2681,12 @@ checkForeignLibSupported comp platform flib = go (compilerFlavor comp) [ "Foreign library versioning not currently supported on Windows.\n" , "You can specify module definition files in the mod-def-file field." ] + | ForeignLibTypeUnknown <- foreignLibType flib = + unsupported + [ "We don't support building unknown-type foreign libraries on Windows" + ] | otherwise = Nothing - goGhcWindows _ = - unsupported - [ "We can currently only build shared foreign libraries on Windows" - ] standalone :: Bool standalone = ForeignLibStandalone `elem` foreignLibOptions flib diff --git a/Cabal/src/Distribution/Simple/GHC/Build.hs b/Cabal/src/Distribution/Simple/GHC/Build.hs index 227e17909a5..8e0ec7ee421 100644 --- a/Cabal/src/Distribution/Simple/GHC/Build.hs +++ b/Cabal/src/Distribution/Simple/GHC/Build.hs @@ -103,7 +103,7 @@ build numJobs pkg_descr = do let wantVanilla = if isLib then withVanillaLib lbi else False -- ROMES:TODO: Arguably, wantStatic should be "withFullyStaticExe lbi" for - -- executables, but it was not before the refactor. + -- executables, but it was not before the refactor, also, flibs should consider if is fully static flib. wantStatic = if isLib then withStaticLib lbi else not (wantDynamic || wantProf) wantDynamic = case component of CLib{} -> withSharedLib lbi diff --git a/Cabal/src/Distribution/Simple/GHC/Build/Link.hs b/Cabal/src/Distribution/Simple/GHC/Build/Link.hs index 23c0c6e22f8..451ff4bd43a 100644 --- a/Cabal/src/Distribution/Simple/GHC/Build/Link.hs +++ b/Cabal/src/Distribution/Simple/GHC/Build/Link.hs @@ -451,23 +451,21 @@ linkFLib flib bi lbi linkerOpts (wantedWays, buildOpts) targetDir runGhcProg = d else statRtsVanillaLib (rtsStaticInfo rtsInfo) ] - linkOpts :: BuildWay -> GhcOptions - linkOpts way = case foreignLibType flib of + linkOpts = case foreignLibType flib of ForeignLibNativeShared -> - (buildOpts way) - `mappend` linkerOpts - `mappend` rtsLinkOpts + (buildOpts DynWay) + { ghcOptShared = toFlag True + , ghcOptFPic = toFlag True + } + ForeignLibNativeStatic -> + (buildOpts StaticWay) `mappend` mempty - { ghcOptLinkNoHsMain = toFlag True - , ghcOptShared = toFlag True - , ghcOptFPic = toFlag True - , ghcOptLinkModDefFiles = toNubListR $ foreignLibModDefFile flib + { ghcOptStaticLib = toFlag True + -- ROMES:TODO: Currently ignoring linkerOpts already sets this, but + -- only for fully static exes... should converge to considering flibs + -- when defining fully static exe probably? + , ghcOptLinkOptions = ["-static"] } - ForeignLibNativeStatic -> - -- this should be caught by buildFLib - -- (and if we do implement this, we probably don't even want to call - -- ghc here, but rather Ar.createArLibArchive or something) - cabalBug "static libraries not yet implemented" ForeignLibTypeUnknown -> cabalBug "unknown foreign lib type" -- We build under a (potentially) different filename to set a @@ -476,8 +474,17 @@ linkFLib flib bi lbi linkerOpts (wantedWays, buildOpts) targetDir runGhcProg = d let buildName = flibBuildName lbi flib -- There should not be more than one wanted way when building an flib assert (Set.size wantedWays == 1) $ - forM_ wantedWays $ \way -> do - runGhcProg (linkOpts way){ghcOptOutputFile = toFlag (targetDir buildName)} + -- ROMES:TODO: Using the "wantedWay" is a bit senseless here, we likely + -- just want to use the Way of each ForeignLib type. + forM_ wantedWays $ \_way -> do + runGhcProg $ + (linkOpts + `mappend` linkerOpts + `mappend` rtsLinkOpts + `mappend` mempty + { ghcOptLinkNoHsMain = toFlag True + , ghcOptLinkModDefFiles = toNubListR $ foreignLibModDefFile flib + }){ ghcOptOutputFile = toFlag (targetDir buildName) } renameFile (targetDir buildName) (targetDir flibTargetName lbi flib) -- | Calculate the RPATHs for the component we are building. diff --git a/cabal-testsuite/PackageTests/ForeignLibStatic/CHANGELOG.md b/cabal-testsuite/PackageTests/ForeignLibStatic/CHANGELOG.md new file mode 100644 index 00000000000..4a5acab18ad --- /dev/null +++ b/cabal-testsuite/PackageTests/ForeignLibStatic/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for tmp-gvHDXD5qma + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/ForeignLibStatic/csrc/MyForeignLibWrapper.c b/cabal-testsuite/PackageTests/ForeignLibStatic/csrc/MyForeignLibWrapper.c new file mode 100644 index 00000000000..bfe3f68c50b --- /dev/null +++ b/cabal-testsuite/PackageTests/ForeignLibStatic/csrc/MyForeignLibWrapper.c @@ -0,0 +1,19 @@ +#include +#include "HsFFI.h" + +HsBool myForeignLibInit(void){ + int argc = 2; + char *argv[] = { "+RTS", "-A32m", NULL }; + char **pargv = argv; + + // Initialize Haskell runtime + hs_init(&argc, &pargv); + + // do any other initialization here and + // return false if there was a problem + return HS_BOOL_TRUE; +} + +void myForeignLibExit(void){ + hs_exit(); +} diff --git a/cabal-testsuite/PackageTests/ForeignLibStatic/flib/MyForeignLib.hs b/cabal-testsuite/PackageTests/ForeignLibStatic/flib/MyForeignLib.hs new file mode 100644 index 00000000000..0e0efd7688d --- /dev/null +++ b/cabal-testsuite/PackageTests/ForeignLibStatic/flib/MyForeignLib.hs @@ -0,0 +1,7 @@ +module MyForeignLib where + +import MyLib + +sayHi :: IO () +sayHi = someFunc + diff --git a/cabal-testsuite/PackageTests/ForeignLibStatic/foreignlibstatic.cabal b/cabal-testsuite/PackageTests/ForeignLibStatic/foreignlibstatic.cabal new file mode 100644 index 00000000000..537d5dbb8a4 --- /dev/null +++ b/cabal-testsuite/PackageTests/ForeignLibStatic/foreignlibstatic.cabal @@ -0,0 +1,82 @@ +cabal-version: 3.0 +-- The cabal-version field refers to the version of the .cabal specification, +-- and can be different from the cabal-install (the tool) version and the +-- Cabal (the library) version you are using. As such, the Cabal (the library) +-- version used must be equal or greater than the version stated in this field. +-- Starting from the specification version 2.2, the cabal-version field must be +-- the first thing in the cabal file. + +-- Initial package description 'tmp-gvHDXD5qma' generated by +-- 'cabal init'. For further documentation, see: +-- http://haskell.org/cabal/users-guide/ +-- +-- The name of the package. +name: foreignlibstatic + +-- The package version. +-- See the Haskell package versioning policy (PVP) for standards +-- guiding when and how versions should be incremented. +-- https://pvp.haskell.org +-- PVP summary: +-+------- breaking API changes +-- | | +----- non-breaking API additions +-- | | | +--- code changes with no API change +version: 0.1.0.0 + +-- A short (one-line) description of the package. +-- synopsis: + +-- A longer description of the package. +-- description: + +-- The license under which the package is released. +license: NONE + +-- The package author(s). +-- author: + +-- An email address to which users can send suggestions, bug reports, and patches. +-- maintainer: + +-- A copyright notice. +-- copyright: +build-type: Simple + +-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README. +extra-doc-files: CHANGELOG.md + +-- Extra source files to be distributed with the package, such as examples, or a tutorial module. +-- extra-source-files: + +common warnings + ghc-options: -Wall + +library + -- Import common warning flags. + import: warnings + + -- Modules exported by the library. + exposed-modules: MyLib + + -- Modules included in this library but not exported. + -- other-modules: + + -- LANGUAGE extensions used by modules in this package. + -- other-extensions: + + -- Other library packages from which modules are imported. + build-depends: base ^>=4.19.0.0 + + -- Directories containing source files. + hs-source-dirs: src + + -- Base language which the package is written in. + default-language: Haskell2010 + +foreign-library myflib + type: native-static + + other-modules: MyForeignLib + build-depends: base, foreignlibstatic + hs-source-dirs: flib + c-sources: csrc/MyForeignLibWrapper.c + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/ForeignLibStatic/src/MyLib.hs b/cabal-testsuite/PackageTests/ForeignLibStatic/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/ForeignLibStatic/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc"