|
| 1 | +module Main where |
| 2 | + |
| 3 | +import Control.Monad |
| 4 | +import Data.Maybe |
| 5 | +import Distribution.PackageDescription.Utils |
| 6 | +import Distribution.Simple |
| 7 | +import Distribution.Simple.Build |
| 8 | +import Distribution.Simple.BuildPaths |
| 9 | +import Distribution.Simple.Setup |
| 10 | +import Distribution.Simple.Utils |
| 11 | +import Distribution.System |
| 12 | +import Distribution.Types.ForeignLib |
| 13 | +import Distribution.Types.ForeignLibType |
| 14 | +import Distribution.Types.GenericPackageDescription |
| 15 | +import Distribution.Types.HookedBuildInfo |
| 16 | +import Distribution.Types.LocalBuildInfo |
| 17 | +import Distribution.Types.PackageDescription |
| 18 | +import Distribution.Types.UnqualComponentName |
| 19 | +import Distribution.Verbosity |
| 20 | +import System.Directory |
| 21 | +import System.FilePath |
| 22 | + |
| 23 | +main :: IO () |
| 24 | +main = |
| 25 | + defaultMainWithHooks simpleUserHooks |
| 26 | + { postBuild = ffiPostBuild } |
| 27 | + |
| 28 | +ffiPostBuild |
| 29 | + :: Args |
| 30 | + -> BuildFlags |
| 31 | + -> PackageDescription |
| 32 | + -> LocalBuildInfo |
| 33 | + -> IO () |
| 34 | +ffiPostBuild args flags desc info = do |
| 35 | + -- Create lib/ in the project directory |
| 36 | + let outPath = takeDirectory (fromJust $ pkgDescrFile info) </> "lib" |
| 37 | + createDirectoryIfMissing True outPath |
| 38 | + |
| 39 | + -- Copy each foreign library to lib/ |
| 40 | + forM_ (foreignLibs desc) $ \flib -> |
| 41 | + let name = unUnqualComponentName (foreignLibName flib) |
| 42 | + dLib = buildDir info </> name </> flibTargetName info flib |
| 43 | + in copySoAsVpl outPath dLib |
| 44 | + |
| 45 | + -- Do the normal post-build hook action |
| 46 | + postBuild simpleUserHooks args flags desc info |
| 47 | + |
| 48 | +-- | Get the name of the library that will be written to disk when building |
| 49 | +-- the library. Lifted from `Distribution.Simple.GHC`. |
| 50 | +-- |
| 51 | +flibTargetName :: LocalBuildInfo -> ForeignLib -> String |
| 52 | +flibTargetName lbi flib = |
| 53 | + case (os, foreignLibType flib) of |
| 54 | + (Windows, ForeignLibNativeShared) -> nm <.> "dll" |
| 55 | + (Windows, ForeignLibNativeStatic) -> nm <.> "lib" |
| 56 | + (Linux, ForeignLibNativeShared) -> "lib" ++ nm <.> versionedExt |
| 57 | + (_other, ForeignLibNativeShared) -> |
| 58 | + "lib" ++ nm <.> dllExtension (hostPlatform lbi) |
| 59 | + (_other, ForeignLibNativeStatic) -> |
| 60 | + "lib" ++ nm <.> staticLibExtension (hostPlatform lbi) |
| 61 | + (_any, ForeignLibTypeUnknown) -> cabalBug "unknown foreign lib type" |
| 62 | + where |
| 63 | + nm :: String |
| 64 | + nm = unUnqualComponentName $ foreignLibName flib |
| 65 | + |
| 66 | + os :: OS |
| 67 | + os = let (Platform _ os') = hostPlatform lbi |
| 68 | + in os' |
| 69 | + |
| 70 | + -- If a foreign lib foo has lib-version-info 5:1:2 or |
| 71 | + -- lib-version-linux 3.2.1, it should be built as libfoo.so.3.2.1 |
| 72 | + -- Libtool's version-info data is translated into library versions in a |
| 73 | + -- nontrivial way: so refer to libtool documentation. |
| 74 | + versionedExt :: String |
| 75 | + versionedExt = |
| 76 | + let nums = foreignLibVersion flib os |
| 77 | + in foldl (<.>) "so" (map show nums) |
| 78 | + |
| 79 | +-- | Copy a file to the same directory, but change the extension to .vpl. This |
| 80 | +-- is needed for iverilog, as it will not load VPI modules which do not have |
| 81 | +-- either a .vpi or .vpl extension, unlike other simulators which will load |
| 82 | +-- the .so file that cabal normally produces. |
| 83 | +-- |
| 84 | +copySoAsVpl :: FilePath -> FilePath -> IO () |
| 85 | +copySoAsVpl outDir so = |
| 86 | + -- We use installMaybeExecutable file because it preserves the permissions |
| 87 | + -- of the original file. On my machine, just using installExecutableFile |
| 88 | + -- meant the permissions were *slightly* different. |
| 89 | + let outPath = replaceDirectory (replaceExtensions so "vpl") outDir |
| 90 | + in installMaybeExecutableFile verbose so outPath |
| 91 | + |
0 commit comments