packages feed

intel-aes-0.1.1: Setup.hs

#!/usr/bin/env runhaskell
import Distribution.Simple

import Distribution.Simple.UserHooks
import Distribution.Simple.PreProcess
import Distribution.Simple.Setup
import Distribution.PackageDescription	
import Distribution.Simple.LocalBuildInfo	
import System.Cmd(system) 
import System.Exit
import qualified System.Info as Info
import System.IO.Unsafe
import System.Directory
import Data.Maybe
import Data.List
import Data.IORef
import Debug.Trace

main = do
  putStrLn$ "  [intel-aes] Running Setup.hs..."

  defaultMainWithHooks $
   simpleUserHooks 
    { postConf  = my_postConf
    , confHook  = my_conf
    , preBuild  = my_preBuild
    , buildHook = my_build
    , instHook  = my_install
    , cleanHook = my_clean
    }

-- A file will be our global variable:
tmpfile = ".temp.install_dir.txt"

--------------------------------------------------------------------------------
my_clean :: PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()
my_clean desc () hooks flags = do 
  putStrLn$ "\n  [intel-aes] Running external clean via Makefile"
  setCurrentDirectory "./cbits/"
  system "make clean"
  setCurrentDirectory ".."
  putStrLn$ "  [intel-aes] Done.  Now running normal cabal clean action.\n"
  (cleanHook simpleUserHooks) desc () hooks flags

--------------------------------------------------------------------------------
my_conf :: (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo
my_conf (gpd,hbi) flags = do 
  (confHook simpleUserHooks) (gpd,hbi) flags

--------------------------------------------------------------------------------
-- we override postConf to keep it from complaining about a missing library:
my_postConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
my_postConf args conf desc localinfo = do
  let buildinfos = allBuildInfo desc
      desc2 = stripDesc desc
  putStrLn$ "  [intel-aes] Extra libraries initially: "++ show (map extraLibs buildinfos)
  putStrLn$ "  [intel-aes] Stripped extra libraries to: "++ show (map extraLibs $ allBuildInfo desc2)

  desc3 <- patchDesc desc2 localinfo
  -- Now call the default hook with a stripped down version:
  (postConf simpleUserHooks) args conf desc3 localinfo


--------------------------------------------------------------------------------
-- Patch a package description for our quirky builda:
patchDesc desc localinfo = do
  let libd  = libdir$ absoluteInstallDirs desc localinfo NoCopyDest
  -- This is lame but I'm not sure how to get the same information at the preBuild step.
  -- writeIORef global_var_hack libd
  putStrLn$ "  [intel-aes] Determined install dir to be: " ++ show libd 
  writeFile tmpfile libd
  putStrLn$ "  [intel-aes] Recorded install dir in " ++ show tmpfile
 
  root <- getCurrentDirectory
  -- Let's try a friendlier way to change the options:
  let Just lib = library desc
      lbi  = libBuildInfo lib 
      oldO = ldOptions  lbi
      -- I'm not sure what the best policy is.  For now I'm adding
      -- BOTH the build dir and the eventual install dir...
      -- This will allow the package to function when it is built-but-not-installed.
      newO = ("-Wl,-rpath=" ++ libd) : 
	     ("-Wl,-rpath=" ++ cbitsd) : 
	     oldO
      cbitsd = root++"/cbits/"
      newlbi = lbi { ldOptions = newO 
		   , extraLibDirs = cbitsd : extraLibDirs lbi }
      -- Whew... nested record updates are painful:
      desc3 = desc { library = Just (lib { libBuildInfo = newlbi})}

  putStrLn$ "  [intel-aes] Modified package info. " 
  return desc3


----------------------------------------
-- Strip out the special extra-libraries: entry
stripDesc desc = 
       desc { library     = fmap stripLib (library desc) 
  	    , executables = map  stripExe (executables desc)
	    }
stripLib lib = lib { libBuildInfo = stripBI (libBuildInfo lib) }
stripExe exe = exe { buildInfo = stripBI (buildInfo exe) }
stripBI bi   = bi  { extraLibs = filter filt (extraLibs bi) }

filt str = not (isInfixOf "intel_aes" str)

------------------------------------------------------------
my_preBuild :: Args -> BuildFlags -> IO HookedBuildInfo
my_preBuild args flags = do 
  putStrLn$ "\n================================================================================"
  let 
      ext = case Info.os of 
	      "linux"   -> ".so"
	      "mac"     -> ".dylib"
	      "windows" -> ".dll"
	      _         -> error$ "Unexpected "
      cached_so = "./cbits/prebuilt/libintel_aes_"++ Info.os ++"_"++ Info.arch ++ ext
      dest = "./cbits/libintel_aes"++ext
  e <- doesFileExist cached_so
  if e then do 
      putStrLn$ "  [intel-aes] Using prebuilt dynamic library: "++ cached_so
      copyFile cached_so dest
      putStrLn$ "  [intel-aes] Done copying into position: "++ dest
  else do     
      putStrLn$ "  [intel-aes] Running Makefile to build C/asm source..."
      rootdir <- getCurrentDirectory 
      setCurrentDirectory "./cbits/"
      system "make"
      setCurrentDirectory rootdir
      putStrLn$ "  [intel-aes] Done with external build job."
  putStrLn$ "================================================================================\n"

  (preBuild simpleUserHooks) args flags

--------------------------------------------------------------------------------
my_build :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
my_build desc linfo hooks flags = do 
  putStrLn$ "  [intel-aes] Build action started."
  desc2 <- patchDesc desc linfo
  (buildHook simpleUserHooks) desc2 linfo hooks flags
  putStrLn$ "  [intel-aes] Build action finished.\n\n"

--------------------------------------------------------------------------------
my_install :: PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()
my_install desc linfo hooks flags = do 
  putStrLn$ "  [intel-aes] Install action:"
  putStrLn$ "\n================================================================================"
  desc2 <- patchDesc desc linfo
  libd <- readFile tmpfile 
  let dest = (libd ++ "/libintel_aes.so")
  putStrLn$ "  [intel-aes] Copying shared library to: " ++ show dest
  system$ "mkdir -p "++ libd -- NONPORTABLE
  copyFile "./cbits/libintel_aes.so" dest
  putStrLn$ "  [intel-aes] Done copying."
  -- removeFile tmpfile -- Might install more than once, right?
  putStrLn$ "================================================================================\n"
  (instHook simpleUserHooks) desc2 linfo hooks flags