Add unique package identifiers (InstalledPackageId) in the package DB
[ghc-hetmet.git] / utils / ghc-cabal / ghc-cabal.hs
index 7bed090..8ee1304 100644 (file)
@@ -1,41 +1,39 @@
 
 module Main (main) where
 
-import Distribution.Compat.Exception
 import qualified Distribution.ModuleName as ModuleName
 import Distribution.PackageDescription
+import Distribution.PackageDescription.Check hiding (doesFileExist)
 import Distribution.PackageDescription.Configuration
 import Distribution.PackageDescription.Parse
 import Distribution.Simple
 import Distribution.Simple.Configure
 import Distribution.Simple.LocalBuildInfo
 import Distribution.Simple.Program
-import Distribution.Simple.Utils (defaultPackageDesc, withTempFile)
+import Distribution.Simple.Utils (defaultPackageDesc, writeFileAtomic)
 import Distribution.Simple.Build (writeAutogenFiles)
-import Distribution.Simple.Register (writeInstalledConfig)
-import Distribution.Simple.PackageIndex
-import Distribution.System
+import Distribution.Simple.Register
 import Distribution.Text
 import Distribution.Verbosity
 import qualified Distribution.InstalledPackageInfo as Installed
-         ( InstalledPackageInfo_(..) )
 import qualified Distribution.Simple.PackageIndex as PackageIndex
-         ( topologicalOrder, lookupPackageName, insert )
 
-import Control.Exception
-import Control.Monad
+import Data.List
 import Data.Maybe
 import System.IO
 import System.Directory
 import System.Environment
 import System.Exit
 import System.FilePath
+import Data.Char
 
 main :: IO ()
 main = do args <- getArgs
           case args of
               "haddock" : distDir : dir : args' ->
                   runHaddock distDir dir args'
+              "check" : dir : [] ->
+                  doCheck dir
               "install" : ghcpkg : ghcpkgconfig : directory : distDir
                         : myDestDir : myPrefix : myLibdir : myDocdir : args' ->
                   doInstall ghcpkg ghcpkgconfig directory distDir
@@ -71,6 +69,20 @@ withCurrentDirectory directory io
 userHooks :: UserHooks
 userHooks = autoconfUserHooks
 
+doCheck :: FilePath -> IO ()
+doCheck directory
+ = withCurrentDirectory directory
+ $ do let verbosity = normal
+      gpdFile <- defaultPackageDesc verbosity
+      gpd <- readPackageDescription verbosity gpdFile
+      case partition isFailure $ checkPackage gpd Nothing of
+          ([],   [])       -> return ()
+          ([],   warnings) -> mapM_ print warnings
+          (errs, _)        -> do mapM_ print errs
+                                 exitWith (ExitFailure 1)
+    where isFailure (PackageDistSuspicious {}) = False
+          isFailure _ = True
+
 runHaddock :: FilePath -> FilePath -> [String] -> IO ()
 runHaddock distdir directory args
  = withCurrentDirectory directory
@@ -131,7 +143,7 @@ doInstall ghcpkg ghcpkgconf directory distDir myDestDir myPrefix myLibdir myDocd
                     idts' = idts { prefix    = toPathTemplate myPrefix,
                                    libdir    = toPathTemplate myLibdir,
                                    libsubdir = toPathTemplate "$pkgid",
-                                   docdir    = toPathTemplate (myDocdir </> "$pkgid"),
+                                   docdir    = toPathTemplate (myDocdir </> "$pkg"),
                                    htmldir   = toPathTemplate "$docdir" }
                     progs = withPrograms lbi
                     prog = ConfiguredProgram {
@@ -163,24 +175,20 @@ generate config_args distdir directory
       withArgs (["configure", "--distdir", distdir] ++ config_args)
           (case buildType (flattenPackageDescription gpd) of
               Just Configure -> defaultMainWithHooks autoconfUserHooks
-              _other         -> defaultMain)
-              -- not quite right, but good enough for us
+              -- time has a "Custom" Setup.hs, but it's actually Configure
+              -- plus a "./Setup test" hook. However, Cabal is also
+              -- "Custom", but doesn't have a configure script.
+              Just Custom ->
+                  do configureExists <- doesFileExist "configure"
+                     if configureExists
+                         then defaultMainWithHooks autoconfUserHooks
+                         else defaultMain
+              -- not quite right, but good enough for us:
+              _ -> defaultMain)
 
       lbi <- getPersistBuildConfig distdir
       let pd0 = localPkgDescr lbi
 
-      -- Sigh, haskeline proper uses stuff in Setup.hs to handle whether
-      -- or not -liconv is used. We don't use Setup.hs, so we replicate
-      -- what it does here. We should do this better somehow.
-      when ((display (pkgName (package pd0)) == "haskeline") &&
-            (buildOS /= Windows)) $
-          case library pd0 of
-              Nothing -> fail "Can't happen: No haskeline library"
-              Just lib -> do
-                  d <- getCurrentDirectory
-                  print d
-                  maybeSetLibiconv verbosity (libBuildInfo lib) lbi
-
       hooked_bi <-
            if (buildType pd0 == Just Configure) || (buildType pd0 == Just Custom)
            then do
@@ -197,9 +205,17 @@ generate config_args distdir directory
       writeAutogenFiles verbosity pd lbi
 
       -- generate inplace-pkg-config
-      when (isJust $ library pd) $
-          writeInstalledConfig distdir pd lbi True
-                               (distdir </> "inplace-pkg-config")
+      case (library pd, libraryConfig lbi) of
+          (Nothing, Nothing) -> return ()
+          (Just lib, Just clbi) -> do
+              cwd <- getCurrentDirectory
+              let ipid = InstalledPackageId (display (packageId pd) ++ "-inplace")
+              let installedPkgInfo = inplaceInstalledPackageInfo cwd distdir
+                                         pd lib lbi clbi
+                  final_ipi = installedPkgInfo{ Installed.installedPackageId = ipid }
+                  content = Installed.showInstalledPackageInfo final_ipi ++ "\n"
+              writeFileAtomic (distdir </> "inplace-pkg-config") content
+          _ -> error "Inconsistent lib components; can't happen?"
 
       let
           libBiModules lib = (libBuildInfo lib, libModules lib)
@@ -229,22 +245,26 @@ generate config_args distdir directory
           -- stricter than gnu ld). Thus we remove the ldOptions for
           -- GHC's rts package:
           hackRtsPackage index =
-            case PackageIndex.lookupPackageName index (PackageName "rts") of
-              [rts] -> PackageIndex.insert rts { Installed.ldOptions = [] } index
+            case PackageIndex.lookupInstalledPackageByName index (PackageName "rts") of
+              [rts] -> PackageIndex.addToInstalledPackageIndex rts { Installed.ldOptions = [] } index
               _ -> error "No (or multiple) ghc rts package is registered!!"
 
+          dep_ids = map (packageId.getLocalPackageInfo lbi) $
+                       externalPackageDeps lbi
+
       let variablePrefix = directory ++ '_':distdir
       let xs = [variablePrefix ++ "_VERSION = " ++ display (pkgVersion (package pd)),
                 variablePrefix ++ "_MODULES = " ++ unwords (map display modules),
                 variablePrefix ++ "_HS_SRC_DIRS = " ++ unwords (hsSourceDirs bi),
-                variablePrefix ++ "_DEPS = " ++ unwords (map display (externalPackageDeps lbi)),
-                variablePrefix ++ "_DEP_NAMES = " ++ unwords (map (display . packageName) (externalPackageDeps lbi)),
+                variablePrefix ++ "_DEPS = " ++ unwords (map display dep_ids),
+                variablePrefix ++ "_DEP_NAMES = " ++ unwords (map (display . packageName) dep_ids),
                 variablePrefix ++ "_INCLUDE_DIRS = " ++ unwords (includeDirs bi),
                 variablePrefix ++ "_INCLUDES = " ++ unwords (includes bi),
                 variablePrefix ++ "_INSTALL_INCLUDES = " ++ unwords (installIncludes bi),
                 variablePrefix ++ "_EXTRA_LIBRARIES = " ++ unwords (extraLibs bi),
                 variablePrefix ++ "_EXTRA_LIBDIRS = " ++ unwords (extraLibDirs bi),
                 variablePrefix ++ "_C_SRCS  = " ++ unwords (cSources bi),
+                variablePrefix ++ "_CMM_SRCS  = $(addprefix cbits/,$(notdir $(wildcard " ++ directory ++ "/cbits/*.cmm)))",
                 -- XXX This includes things it shouldn't, like:
                 -- -odir dist-bootstrapping/build
                 variablePrefix ++ "_HC_OPTS = " ++ escape (unwords 
@@ -263,68 +283,3 @@ generate config_args distdir directory
   where
      escape = foldr (\c xs -> if c == '#' then '\\':'#':xs else c:xs) []
 
-----------------------------------------------------------------------
--- haskeline-specific hacks
-
--- Sigh, haskeline proper uses stuff in Setup.hs to handle whether
--- or not -liconv is used. We don't use Setup.hs, so we replicate
--- what it does here. We should do this better somehow.
-
--- Test whether compiling a c program that links against libiconv needs -liconv.
-maybeSetLibiconv :: Verbosity -> BuildInfo -> LocalBuildInfo -> IO ()
-maybeSetLibiconv verb bi lbi = do
-    let biWithIconv = addIconv bi
-    worksWithout <- tryCompile iconv_prog bi lbi verb
-    if worksWithout
-        then writeBuildInfo ""
-        else do
-    worksWith <- tryCompile iconv_prog biWithIconv lbi verb
-    if worksWith
-        then do
-            writeBuildInfo "iconv"
-        else fail "Unable to link against the iconv library."
-  where
-    -- Cabal (at least 1.6.0.1) won't parse an empty buildinfo file.
-    writeBuildInfo libs = writeFile "haskeline.buildinfo"
-                            $ unlines ["extra-libraries: " ++ libs]
-
-tryCompile :: String -> BuildInfo -> LocalBuildInfo -> Verbosity -> IO Bool
-tryCompile program bi lbi verb = flip catchIO processException $ flip catchExit processExit $ do
-    tempDir <- getTemporaryDirectory
-    withTempFile tempDir ".c" $ \fname h -> do
-        hPutStr h program
-        hClose h
-        -- TODO take verbosity from the args.
-        rawSystemProgramStdoutConf verb gccProgram (withPrograms lbi) (fname : args)
-        return True
-  where
-    processException :: IOException -> IO Bool
-    processException _ = return False
-    processExit = return . (==ExitSuccess)
-    -- Mimicing Distribution.Simple.Configure
-    deps = topologicalOrder (installedPkgs lbi)
-    args = concat
-                  [ ccOptions bi
-                  , cppOptions bi
-                  , ldOptions bi
-                  -- --extra-include-dirs and --extra-lib-dirs are included
-                  -- in the below fields.
-                  -- Also sometimes a dependency like rts points to a nonstandard
-                  -- include/lib directory where iconv can be found.
-                  , map ("-I" ++) (includeDirs bi ++ concatMap Installed.includeDirs deps)
-                  , map ("-L" ++) (extraLibDirs bi ++ concatMap Installed.libraryDirs deps)
-                  , map ("-l" ++) (extraLibs bi)
-                  ]
-
-addIconv :: BuildInfo -> BuildInfo
-addIconv bi = bi {extraLibs = "iconv" : extraLibs bi}
-
-iconv_prog :: String
-iconv_prog = unlines $
-    [ "#include <iconv.h>"
-    , "int main(void) {"
-    , "    iconv_t t = iconv_open(\"UTF-8\", \"UTF-8\");"
-    , "    return 0;"
-    , "}"
-    ]
-