GHC.hs 54.7 KB
Newer Older
1
2
{-# LANGUAGE PatternGuards #-}

3
4
5
-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.Simple.GHC
Simon Marlow's avatar
Simon Marlow committed
6
-- Copyright   :  Isaac Jones 2003-2007
7
-- License     :  BSD3
8
--
Duncan Coutts's avatar
Duncan Coutts committed
9
-- Maintainer  :  cabal-devel@haskell.org
10
11
-- Portability :  portable
--
Duncan Coutts's avatar
Duncan Coutts committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
-- This is a fairly large module. It contains most of the GHC-specific code for
-- configuring, building and installing packages. It also exports a function
-- for finding out what packages are already installed. Configuring involves
-- finding the @ghc@ and @ghc-pkg@ programs, finding what language extensions
-- this version of ghc supports and returning a 'Compiler' value.
--
-- 'getInstalledPackages' involves calling the @ghc-pkg@ program to find out
-- what packages are installed.
--
-- Building is somewhat complex as there is quite a bit of information to take
-- into account. We have to build libs and programs, possibly for profiling and
-- shared libs. We have to support building libraries that will be usable by
-- GHCi and also ghc's @-split-objs@ feature. We have to compile any C files
-- using ghc. Linking, especially for @split-objs@ is remarkably complex,
-- partly because there tend to be 1,000's of @.o@ files and this can often be
-- more than we can pass to the @ld@ or @ar@ programs in one go.
--
-- Installing for libs and exes involves finding the right files and copying
-- them to the right places. One of the more tricky things about this module is
-- remembering the layout of files in the build directory (which is not
-- explicitly documented) and thus what search dirs are used for various kinds
-- of files.
34
35

module Distribution.Simple.GHC (
36
        getGhcInfo,
37
38
39
40
        configure,
        getInstalledPackages,
        getInstalledPackagesMonitorFiles,
        getPackageDBContents,
41
        buildLib, buildExe,
42
        replLib, replExe,
43
        startInterpreter,
44
        installLib, installExe,
45
        libAbiHash,
46
        hcPkgInfo,
47
        registerPackage,
48
        componentGhcOptions,
Edsko de Vries's avatar
Edsko de Vries committed
49
        componentCcGhcOptions,
50
51
52
        getLibDir,
        isDynamic,
        getGlobalPackageDB,
53
        pkgRoot
54
55
 ) where

56
57
import qualified Distribution.Simple.GHC.IPI641 as IPI641
import qualified Distribution.Simple.GHC.IPI642 as IPI642
58
import qualified Distribution.Simple.GHC.Internal as Internal
59
import Distribution.Simple.GHC.ImplInfo
60
import Distribution.PackageDescription as PD
61
62
63
         ( PackageDescription(..), BuildInfo(..), Executable(..), Library(..)
         , allExtensions, libModules, exeModules
         , hcOptions, hcSharedOptions, hcProfOptions )
64
import Distribution.InstalledPackageInfo
65
         ( InstalledPackageInfo )
66
import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
67
                                ( InstalledPackageInfo(..) )
68
import Distribution.Simple.PackageIndex (InstalledPackageIndex)
69
import qualified Distribution.Simple.PackageIndex as PackageIndex
70
import Distribution.Simple.LocalBuildInfo
71
         ( LocalBuildInfo(..), ComponentLocalBuildInfo(..)
tibbe's avatar
tibbe committed
72
         , absoluteInstallDirs, depLibraryPaths )
73
import qualified Distribution.Simple.Hpc as Hpc
74
import Distribution.Simple.InstallDirs hiding ( absoluteInstallDirs )
75
import Distribution.Simple.BuildPaths
76
import Distribution.Simple.Utils
77
import Distribution.Package
78
         ( PackageName(..) )
79
import qualified Distribution.ModuleName as ModuleName
80
import Distribution.Simple.Program
81
         ( Program(..), ConfiguredProgram(..), ProgramConfiguration
82
         , ProgramSearchPath
83
         , rawSystemProgramStdout, rawSystemProgramStdoutConf
84
         , getProgramInvocationOutput, requireProgramVersion, requireProgram
85
         , userMaybeSpecifyPath, programPath, lookupProgram, addKnownProgram
86
         , ghcProgram, ghcPkgProgram, haddockProgram, hsc2hsProgram, ldProgram )
87
import qualified Distribution.Simple.Program.HcPkg as HcPkg
88
89
import qualified Distribution.Simple.Program.Ar    as Ar
import qualified Distribution.Simple.Program.Ld    as Ld
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
90
import qualified Distribution.Simple.Program.Strip as Strip
91
import Distribution.Simple.Program.GHC
92
import Distribution.Simple.Setup
lukexi's avatar
lukexi committed
93
         ( toFlag, fromFlag, fromFlagOrDefault, configCoverage, configDistPref )
94
import qualified Distribution.Simple.Setup as Cabal
95
        ( Flag(..) )
96
import Distribution.Simple.Compiler
97
         ( CompilerFlavor(..), CompilerId(..), Compiler(..), compilerVersion
98
         , PackageDB(..), PackageDBStack, AbiTag(..) )
99
import Distribution.Version
100
         ( Version(..), anyVersion, orLaterVersion )
101
import Distribution.System
102
         ( Platform(..), OS(..) )
103
import Distribution.Verbosity
104
import Distribution.Text
105
         ( display )
106
import Distribution.Utils.NubList
107
         ( NubListR, overNubListR, toNubListR )
tibbe's avatar
tibbe committed
108
import Language.Haskell.Extension (Extension(..), KnownExtension(..))
109

110
import Control.Monad            ( unless, when )
111
import Data.Char                ( isDigit, isSpace )
112
import Data.List
113
import qualified Data.Map as M  ( fromList, lookup )
114
import Data.Maybe               ( catMaybes )
115
import Data.Monoid as Mon       ( Monoid(..) )
116
import Data.Version             ( showVersion )
117
import System.Directory
118
119
         ( doesFileExist, getAppUserDataDirectory, createDirectoryIfMissing
         , canonicalizePath )
Ross Paterson's avatar
Ross Paterson committed
120
import System.FilePath          ( (</>), (<.>), takeExtension,
refold's avatar
refold committed
121
                                  takeDirectory, replaceExtension,
122
                                  splitExtension, isRelative )
123
import qualified System.Info
124

125
126
127
-- -----------------------------------------------------------------------------
-- Configuring

128
configure :: Verbosity -> Maybe FilePath -> Maybe FilePath
refold's avatar
refold committed
129
130
          -> ProgramConfiguration
          -> IO (Compiler, Maybe Platform, ProgramConfiguration)
131
configure verbosity hcPath hcPkgPath conf0 = do
132

133
  (ghcProg, ghcVersion, conf1) <-
134
135
    requireProgramVersion verbosity ghcProgram
      (orLaterVersion (Version [6,4] []))
136
      (userMaybeSpecifyPath "ghc" hcPath conf0)
137
  let implInfo = ghcVersionImplInfo ghcVersion
138
139
140
141

  -- This is slightly tricky, we have to configure ghc first, then we use the
  -- location of ghc to help find ghc-pkg in the case that the user did not
  -- specify the location of ghc-pkg directly:
142
  (ghcPkgProg, ghcPkgVersion, conf2) <-
143
144
145
    requireProgramVersion verbosity ghcPkgProgram {
      programFindLocation = guessGhcPkgFromGhcPath ghcProg
    }
146
    anyVersion (userMaybeSpecifyPath "ghc-pkg" hcPkgPath conf1)
147
148

  when (ghcVersion /= ghcPkgVersion) $ die $
149
       "Version mismatch between ghc and ghc-pkg: "
150
151
    ++ programPath ghcProg ++ " is version " ++ display ghcVersion ++ " "
    ++ programPath ghcPkgProg ++ " is version " ++ display ghcPkgVersion
152

153
  -- Likewise we try to find the matching hsc2hs and haddock programs.
154
155
156
  let hsc2hsProgram' = hsc2hsProgram {
                           programFindLocation = guessHsc2hsFromGhcPath ghcProg
                       }
157
158
159
160
161
      haddockProgram' = haddockProgram {
                           programFindLocation = guessHaddockFromGhcPath ghcProg
                       }
      conf3 = addKnownProgram haddockProgram' $
              addKnownProgram hsc2hsProgram' conf2
162

163
  languages  <- Internal.getLanguages verbosity implInfo ghcProg
164
  extensions0 <- Internal.getExtensions verbosity implInfo ghcProg
165

166
  ghcInfo <- Internal.getGhcInfo verbosity implInfo ghcProg
167
  let ghcInfoMap = M.fromList ghcInfo
168

169
170
171
172
173
174
175
176
177
      -- starting with GHC 8.0, `TemplateHaskell` will be omitted from
      -- `--supported-extensions` when it's not available.
      -- for older GHCs we can use the "Have interpreter" property to
      -- filter out `TemplateHaskell`
      extensions | ghcVersion < Version [8] []
                 , Just "NO" <- M.lookup "Have interpreter" ghcInfoMap
                   = filter ((/= EnableExtension TemplateHaskell) . fst) extensions0
                 | otherwise = extensions0

178
  let comp = Compiler {
179
        compilerId         = CompilerId GHC ghcVersion,
180
181
        compilerAbiTag     = NoAbiTag,
        compilerCompat     = [],
182
183
184
        compilerLanguages  = languages,
        compilerExtensions = extensions,
        compilerProperties = ghcInfoMap
185
      }
186
      compPlatform = Internal.targetPlatform ghcInfo
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
187
188
      -- configure gcc and ld
      conf4 = Internal.configureToolchain implInfo ghcProg ghcInfoMap conf3
189
190
  return (comp, compPlatform, conf4)

191
192
193
-- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find
-- the corresponding tool; e.g. if the tool is ghc-pkg, we try looking
-- for a versioned or unversioned ghc-pkg in the same dir, that is:
194
--
195
-- > /usr/local/bin/ghc-pkg-ghc-6.6.1(.exe)
196
197
198
-- > /usr/local/bin/ghc-pkg-6.6.1(.exe)
-- > /usr/local/bin/ghc-pkg(.exe)
--
199
200
guessToolFromGhcPath :: Program -> ConfiguredProgram
                     -> Verbosity -> ProgramSearchPath
201
                     -> IO (Maybe (FilePath, [FilePath]))
202
203
guessToolFromGhcPath tool ghcProg verbosity searchpath
  = do let toolname          = programName tool
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
           given_path        = programPath ghcProg
           given_dir         = takeDirectory given_path
       real_path <- canonicalizePath given_path
       let real_dir           = takeDirectory real_path
           versionSuffix path = takeVersionSuffix (dropExeExtension path)
           guessNormal       dir = dir </> toolname <.> exeExtension
           guessGhcVersioned dir = dir </> (toolname ++ "-ghc" ++ versionSuffix dir)
                                       <.> exeExtension
           guessVersioned    dir = dir </> (toolname ++ versionSuffix dir)
                                       <.> exeExtension
           mkGuesses dir | null (versionSuffix dir) = [guessNormal dir]
                         | otherwise                = [guessGhcVersioned dir,
                                                       guessVersioned dir,
                                                       guessNormal dir]
           guesses = mkGuesses given_dir ++
                            if real_path == given_path
                                then []
                                else mkGuesses real_dir
222
       info verbosity $ "looking for tool " ++ toolname
223
         ++ " near compiler in " ++ given_dir
224
225
       exists <- mapM doesFileExist guesses
       case [ file | (file, True) <- zip guesses exists ] of
refold's avatar
refold committed
226
227
                   -- If we can't find it near ghc, fall back to the usual
                   -- method.
228
229
         []     -> programFindLocation tool verbosity searchpath
         (fp:_) -> do info verbosity $ "found " ++ toolname ++ " in " ++ fp
230
231
232
233
                      let lookedAt = map fst
                                   . takeWhile (\(_file, exist) -> not exist)
                                   $ zip guesses exists
                      return (Just (fp, lookedAt))
234
235

  where takeVersionSuffix :: FilePath -> String
236
        takeVersionSuffix = takeWhileEndLE isSuffixChar
237
238
239

        isSuffixChar :: Char -> Bool
        isSuffixChar c = isDigit c || c == '.' || c == '-'
240
241
242
243
244
245
246

        dropExeExtension :: FilePath -> FilePath
        dropExeExtension filepath =
          case splitExtension filepath of
            (filepath', extension) | extension == exeExtension -> filepath'
                                   | otherwise                 -> filepath

247
248
249
250
251
252
253
254
-- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find a
-- corresponding ghc-pkg, we try looking for both a versioned and unversioned
-- ghc-pkg in the same dir, that is:
--
-- > /usr/local/bin/ghc-pkg-ghc-6.6.1(.exe)
-- > /usr/local/bin/ghc-pkg-6.6.1(.exe)
-- > /usr/local/bin/ghc-pkg(.exe)
--
255
guessGhcPkgFromGhcPath :: ConfiguredProgram
256
257
                       -> Verbosity -> ProgramSearchPath
                       -> IO (Maybe (FilePath, [FilePath]))
258
guessGhcPkgFromGhcPath = guessToolFromGhcPath ghcPkgProgram
259
260
261
262
263
264
265
266
267

-- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find a
-- corresponding hsc2hs, we try looking for both a versioned and unversioned
-- hsc2hs in the same dir, that is:
--
-- > /usr/local/bin/hsc2hs-ghc-6.6.1(.exe)
-- > /usr/local/bin/hsc2hs-6.6.1(.exe)
-- > /usr/local/bin/hsc2hs(.exe)
--
268
guessHsc2hsFromGhcPath :: ConfiguredProgram
269
270
                       -> Verbosity -> ProgramSearchPath
                       -> IO (Maybe (FilePath, [FilePath]))
271
guessHsc2hsFromGhcPath = guessToolFromGhcPath hsc2hsProgram
272

273
274
275
276
277
278
279
280
281
-- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find a
-- corresponding haddock, we try looking for both a versioned and unversioned
-- haddock in the same dir, that is:
--
-- > /usr/local/bin/haddock-ghc-6.6.1(.exe)
-- > /usr/local/bin/haddock-6.6.1(.exe)
-- > /usr/local/bin/haddock(.exe)
--
guessHaddockFromGhcPath :: ConfiguredProgram
282
283
                       -> Verbosity -> ProgramSearchPath
                       -> IO (Maybe (FilePath, [FilePath]))
284
285
guessHaddockFromGhcPath = guessToolFromGhcPath haddockProgram

Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
286
getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)]
287
288
289
290
getGhcInfo verbosity ghcProg = Internal.getGhcInfo verbosity implInfo ghcProg
  where
    Just version = programVersion ghcProg
    implInfo = ghcVersionImplInfo version
291

292
293
-- | Given a single package DB, return all installed packages.
getPackageDBContents :: Verbosity -> PackageDB -> ProgramConfiguration
294
                        -> IO InstalledPackageIndex
295
296
297
298
299
getPackageDBContents verbosity packagedb conf = do
  pkgss <- getInstalledPackages' verbosity [packagedb] conf
  toPackageIndex verbosity pkgss conf

-- | Given a package DB stack, return all installed packages.
300
getInstalledPackages :: Verbosity -> Compiler -> PackageDBStack -> ProgramConfiguration
301
                     -> IO InstalledPackageIndex
302
getInstalledPackages verbosity comp packagedbs conf = do
303
  checkPackageDbEnvVar
304
  checkPackageDbStack comp packagedbs
305
  pkgss <- getInstalledPackages' verbosity packagedbs conf
306
307
  index <- toPackageIndex verbosity pkgss conf
  return $! hackRtsPackage index
308
309
310
311
312
313

  where
    hackRtsPackage index =
      case PackageIndex.lookupPackageName index (PackageName "rts") of
        [(_,[rts])]
           -> PackageIndex.insert (removeMingwIncludeDir rts) index
314
        _  -> index -- No (or multiple) ghc rts package is registered!!
Ian D. Bollinger's avatar
Ian D. Bollinger committed
315
                    -- Feh, whatever, the ghc test suite does some crazy stuff.
316

317
318
319
320
321
322
-- | Given a list of @(PackageDB, InstalledPackageInfo)@ pairs, produce a
-- @PackageIndex@. Helper function used by 'getPackageDBContents' and
-- 'getInstalledPackages'.
toPackageIndex :: Verbosity
               -> [(PackageDB, [InstalledPackageInfo])]
               -> ProgramConfiguration
323
               -> IO InstalledPackageIndex
324
325
326
327
toPackageIndex verbosity pkgss conf = do
  -- On Windows, various fields have $topdir/foo rather than full
  -- paths. We need to substitute the right value in so that when
  -- we, for example, call gcc, we have proper paths to give it.
328
  topDir <- getLibDir' verbosity ghcProg
329
  let indices = [ PackageIndex.fromList (map (Internal.substTopDir topDir) pkgs)
330
331
332
333
334
335
                | (_, pkgs) <- pkgss ]
  return $! (mconcat indices)

  where
    Just ghcProg = lookupProgram ghcProgram conf

336
337
getLibDir :: Verbosity -> LocalBuildInfo -> IO FilePath
getLibDir verbosity lbi =
338
    dropWhileEndLE isSpace `fmap`
refold's avatar
refold committed
339
340
     rawSystemProgramStdoutConf verbosity ghcProgram
     (withPrograms lbi) ["--print-libdir"]
341

342
343
getLibDir' :: Verbosity -> ConfiguredProgram -> IO FilePath
getLibDir' verbosity ghcProg =
344
    dropWhileEndLE isSpace `fmap`
345
346
     rawSystemProgramStdout verbosity ghcProg ["--print-libdir"]

347

348
-- | Return the 'FilePath' to the global GHC package database.
349
350
getGlobalPackageDB :: Verbosity -> ConfiguredProgram -> IO FilePath
getGlobalPackageDB verbosity ghcProg =
351
    dropWhileEndLE isSpace `fmap`
352
353
     rawSystemProgramStdout verbosity ghcProg ["--print-global-package-db"]

354
-- | Return the 'FilePath' to the per-user GHC package database.
355
356
getUserPackageDB :: Verbosity -> ConfiguredProgram -> Platform -> IO FilePath
getUserPackageDB _verbosity ghcProg (Platform arch os) = do
357
358
359
    -- It's rather annoying that we have to reconstruct this, because ghc
    -- hides this information from us otherwise. But for certain use cases
    -- like change monitoring it really can't remain hidden.
360
361
362
363
364
365
366
367
368
369
370
    appdir <- getAppUserDataDirectory "ghc"
    return (appdir </> platformAndVersion </> packageConfFileName)
  where
    platformAndVersion = intercalate "-" [ Internal.showArchString arch
                                         , Internal.showOsString os
                                         , display ghcVersion ]
    packageConfFileName
      | ghcVersion >= Version [6,12] []  = "package.conf.d"
      | otherwise                        = "package.conf"
    Just ghcVersion = programVersion ghcProg

371
checkPackageDbEnvVar :: IO ()
372
373
checkPackageDbEnvVar =
    Internal.checkPackageDbEnvVar "GHC" "GHC_PACKAGE_PATH"
374

375
checkPackageDbStack :: Compiler -> PackageDBStack -> IO ()
376
377
378
379
checkPackageDbStack comp = if flagPackageConf implInfo
                              then checkPackageDbStackPre76
                              else checkPackageDbStackPost76
  where implInfo = ghcVersionImplInfo (compilerVersion comp)
380
381
382
383
384
385
386
387
388
389
390
391

checkPackageDbStackPost76 :: PackageDBStack -> IO ()
checkPackageDbStackPost76 (GlobalPackageDB:rest)
  | GlobalPackageDB `notElem` rest = return ()
checkPackageDbStackPost76 rest
  | GlobalPackageDB `elem` rest =
  die $ "If the global package db is specified, it must be "
     ++ "specified first and cannot be specified multiple times"
checkPackageDbStackPost76 _ = return ()

checkPackageDbStackPre76 :: PackageDBStack -> IO ()
checkPackageDbStackPre76 (GlobalPackageDB:rest)
392
  | GlobalPackageDB `notElem` rest = return ()
393
checkPackageDbStackPre76 rest
394
395
  | GlobalPackageDB `notElem` rest =
  die $ "With current ghc versions the global package db is always used "
396
397
398
     ++ "and must be listed first. This ghc limitation is lifted in GHC 7.6,"
     ++ "see http://hackage.haskell.org/trac/ghc/ticket/5977"
checkPackageDbStackPre76 _ =
399
  die $ "If the global package db is specified, it must be "
400
401
     ++ "specified first and cannot be specified multiple times"

402
403
404
405
406
407
408
409
-- GHC < 6.10 put "$topdir/include/mingw" in rts's installDirs. This
-- breaks when you want to use a different gcc, so we need to filter
-- it out.
removeMingwIncludeDir :: InstalledPackageInfo -> InstalledPackageInfo
removeMingwIncludeDir pkg =
    let ids = InstalledPackageInfo.includeDirs pkg
        ids' = filter (not . ("mingw" `isSuffixOf`)) ids
    in pkg { InstalledPackageInfo.includeDirs = ids' }
410

411
412
413
414
415
416
417
-- | Get the packages from specific PackageDBs, not cumulative.
--
getInstalledPackages' :: Verbosity -> [PackageDB] -> ProgramConfiguration
                     -> IO [(PackageDB, [InstalledPackageInfo])]
getInstalledPackages' verbosity packagedbs conf
  | ghcVersion >= Version [6,9] [] =
  sequence
418
    [ do pkgs <- HcPkg.dump (hcPkgInfo conf) verbosity packagedb
419
         return (packagedb, pkgs)
420
    | packagedb <- packagedbs ]
421

422
  where
423
    Just ghcProg    = lookupProgram ghcProgram conf
424
425
426
427
428
429
    Just ghcVersion = programVersion ghcProg

getInstalledPackages' verbosity packagedbs conf = do
    str <- rawSystemProgramStdoutConf verbosity ghcPkgProgram conf ["list"]
    let pkgFiles = [ init line | line <- lines str, last line == ':' ]
        dbFile packagedb = case (packagedb, pkgFiles) of
430
431
432
433
434
435
          (GlobalPackageDB, global:_)      -> return $ Just global
          (UserPackageDB,  _global:user:_) -> return $ Just user
          (UserPackageDB,  _global:_)      -> return $ Nothing
          (SpecificPackageDB specific, _)  -> return $ Just specific
          _ -> die "cannot read ghc-pkg package listing"
    pkgFiles' <- mapM dbFile packagedbs
436
437
438
    sequence [ withFileContents file $ \content -> do
                  pkgs <- readPackages file content
                  return (db, pkgs)
439
             | (db , Just file) <- zip packagedbs pkgFiles' ]
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  where
    -- Depending on the version of ghc we use a different type's Read
    -- instance to parse the package file and then convert.
    -- It's a bit yuck. But that's what we get for using Read/Show.
    readPackages
      | ghcVersion >= Version [6,4,2] []
      = \file content -> case reads content of
          [(pkgs, _)] -> return (map IPI642.toCurrent pkgs)
          _           -> failToRead file
      | otherwise
      = \file content -> case reads content of
          [(pkgs, _)] -> return (map IPI641.toCurrent pkgs)
          _           -> failToRead file
    Just ghcProg = lookupProgram ghcProgram conf
    Just ghcVersion = programVersion ghcProg
    failToRead file = die $ "cannot read ghc package database " ++ file
456

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
getInstalledPackagesMonitorFiles :: Verbosity -> Platform
                                 -> ProgramConfiguration
                                 -> [PackageDB]
                                 -> IO [FilePath]
getInstalledPackagesMonitorFiles verbosity platform progdb =
    mapM getPackageDBPath
  where
    getPackageDBPath :: PackageDB -> IO FilePath
    getPackageDBPath GlobalPackageDB =
      selectMonitorFile =<< getGlobalPackageDB verbosity ghcProg

    getPackageDBPath UserPackageDB =
      selectMonitorFile =<< getUserPackageDB verbosity ghcProg platform

    getPackageDBPath (SpecificPackageDB path) = selectMonitorFile path

    -- GHC has old style file dbs, and new style directory dbs.
474
475
476
    -- Note that for dir style dbs, we only need to monitor the cache file, not
    -- the whole directory. The ghc program itself only reads the cache file
    -- so it's safe to only monitor this one file.
477
478
479
480
481
482
483
484
    selectMonitorFile path = do
      isFileStyle <- doesFileExist path
      if isFileStyle then return path
                     else return (path </> "package.cache")

    Just ghcProg = lookupProgram ghcProgram progdb


485
486
487
-- -----------------------------------------------------------------------------
-- Building

488
489
-- | Build a library with GHC.
--
490
buildLib, replLib :: Verbosity          -> Cabal.Flag (Maybe Int)
491
492
493
494
495
                  -> PackageDescription -> LocalBuildInfo
                  -> Library            -> ComponentLocalBuildInfo -> IO ()
buildLib = buildOrReplLib False
replLib  = buildOrReplLib True

496
buildOrReplLib :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)
497
498
               -> PackageDescription -> LocalBuildInfo
               -> Library            -> ComponentLocalBuildInfo -> IO ()
499
buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do
500
  let libName = componentId clbi
501
      libTargetDir = buildDir lbi
502
      whenVanillaLib forceVanilla =
503
504
        when (forceVanilla || withVanillaLib lbi)
      whenProfLib = when (withProfLib lbi)
505
      whenSharedLib forceShared =
506
507
        when (forceShared || withSharedLib lbi)
      whenGHCiLib = when (withGHCiLib lbi && withVanillaLib lbi)
508
      ifReplLib = when forRepl
509
      comp = compiler lbi
510
      ghcVersion = compilerVersion comp
511
      implInfo  = getImplInfo comp
512
      (Platform _hostArch hostOS) = hostPlatform lbi
513

514
  (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)
515
  let runGhcProg = runGHC verbosity ghcProg comp
516

517
  libBi <- hackThreadedFlag verbosity
518
             comp (withProfLib lbi) (libBuildInfo lib)
519

520
521
  let isGhcDynamic        = isDynamic comp
      dynamicTooSupported = supportsDynamicToo comp
522
      doingTH = EnableExtension TemplateHaskell `elem` allExtensions libBi
refold's avatar
refold committed
523
524
      forceVanillaLib = doingTH && not isGhcDynamic
      forceSharedLib  = doingTH &&     isGhcDynamic
525
      -- TH always needs default libs, even when building for profiling
526

527
528
529
530
531
532
533
  -- Determine if program coverage should be enabled and if so, what
  -- '-hpcdir' should be.
  let isCoverageEnabled = fromFlag $ configCoverage $ configFlags lbi
      -- Component name. Not 'libName' because that has the "HS" prefix
      -- that GHC gives Haskell libraries.
      cname = display $ PD.package $ localPkgDescr lbi
      distPref = fromFlag $ configDistPref $ configFlags lbi
534
      hpcdir way
535
        | forRepl = Mon.mempty  -- HPC is not supported in ghci
536
537
        | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way cname
        | otherwise = mempty
538

539
  createDirectoryIfMissingVerbose verbosity True libTargetDir
refold's avatar
refold committed
540
541
  -- TODO: do we need to put hs-boot files into place for mutually recursive
  -- modules?
542
  let cObjs       = map (`replaceExtension` objExtension) (cSources libBi)
543
      baseOpts    = componentGhcOptions verbosity lbi libBi clbi libTargetDir
544
      vanillaOpts = baseOpts `mappend` mempty {
545
                      ghcOptMode         = toFlag GhcModeMake,
546
                      ghcOptNumJobs      = numJobs,
547
548
                      ghcOptInputModules = toNubListR $ libModules lib,
                      ghcOptHPCDir       = hpcdir Hpc.Vanilla
549
550
                    }

551
552
      profOpts    = vanillaOpts `mappend` mempty {
                      ghcOptProfilingMode = toFlag True,
553
554
                      ghcOptProfilingAuto = Internal.profDetailLevelFlag True
                                              (withProfLibDetail lbi),
555
556
557
558
559
                      ghcOptHiSuffix      = toFlag "p_hi",
                      ghcOptObjSuffix     = toFlag "p_o",
                      ghcOptExtra         = toNubListR $ hcProfOptions GHC libBi,
                      ghcOptHPCDir        = hpcdir Hpc.Prof
                    }
560

561
      sharedOpts  = vanillaOpts `mappend` mempty {
562
563
564
565
                      ghcOptDynLinkMode = toFlag GhcDynamicOnly,
                      ghcOptFPic        = toFlag True,
                      ghcOptHiSuffix    = toFlag "dyn_hi",
                      ghcOptObjSuffix   = toFlag "dyn_o",
566
567
                      ghcOptExtra       = toNubListR $ hcSharedOptions GHC libBi,
                      ghcOptHPCDir      = hpcdir Hpc.Dyn
568
                    }
569
      linkerOpts = mempty {
570
571
572
573
574
575
                      ghcOptLinkOptions    = toNubListR $ PD.ldOptions libBi,
                      ghcOptLinkLibs       = toNubListR $ extraLibs libBi,
                      ghcOptLinkLibPath    = toNubListR $ extraLibDirs libBi,
                      ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,
                      ghcOptInputFiles     = toNubListR
                                             [libTargetDir </> x | x <- cObjs]
576
                   }
577
      replOpts    = vanillaOpts {
578
579
                      ghcOptExtra        = overNubListR
                                           Internal.filterGhciFlags $
580
581
                                           (ghcOptExtra vanillaOpts),
                      ghcOptNumJobs      = mempty
582
                    }
583
                    `mappend` linkerOpts
584
                    `mappend` mempty {
585
586
587
                      ghcOptMode         = toFlag GhcModeInteractive,
                      ghcOptOptimisation = toFlag GhcNoOptimisation
                    }
588

589
      vanillaSharedOpts = vanillaOpts `mappend` mempty {
590
591
                      ghcOptDynLinkMode  = toFlag GhcStaticAndDynamic,
                      ghcOptDynHiSuffix  = toFlag "dyn_hi",
592
593
                      ghcOptDynObjSuffix = toFlag "dyn_o",
                      ghcOptHPCDir       = hpcdir Hpc.Dyn
594
                    }
595

596
  unless (forRepl || null (libModules lib)) $
597
598
    do let vanilla = whenVanillaLib forceVanillaLib (runGhcProg vanillaOpts)
           shared  = whenSharedLib  forceSharedLib  (runGhcProg sharedOpts)
599
600
601
           useDynToo = dynamicTooSupported &&
                       (forceVanillaLib || withVanillaLib lbi) &&
                       (forceSharedLib  || withSharedLib  lbi) &&
602
                       null (hcSharedOptions GHC libBi)
603
       if useDynToo
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
          then do
              runGhcProg vanillaSharedOpts
              case (hpcdir Hpc.Dyn, hpcdir Hpc.Vanilla) of
                (Cabal.Flag dynDir, Cabal.Flag vanillaDir) -> do
                    -- When the vanilla and shared library builds are done
                    -- in one pass, only one set of HPC module interfaces
                    -- are generated. This set should suffice for both
                    -- static and dynamically linked executables. We copy
                    -- the modules interfaces so they are available under
                    -- both ways.
                    copyDirectoryRecursive verbosity dynDir vanillaDir
                _ -> return ()
          else if isGhcDynamic
            then do shared;  vanilla
            else do vanilla; shared
619
       whenProfLib (runGhcProg profOpts)
620
621
622

  -- build any C sources
  unless (null (cSources libBi)) $ do
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
623
624
    info verbosity "Building C Sources..."
    sequence_
625
626
      [ do let baseCcOpts    = Internal.componentCcGhcOptions verbosity implInfo
                               lbi libBi clbi libTargetDir filename
627
628
629
630
631
               vanillaCcOpts = if isGhcDynamic
                               -- Dynamic GHC requires C sources to be built
                               -- with -fPIC for REPL to work. See #2207.
                               then baseCcOpts { ghcOptFPic = toFlag True }
                               else baseCcOpts
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
632
633
634
635
636
637
638
639
640
641
642
               profCcOpts    = vanillaCcOpts `mappend` mempty {
                                 ghcOptProfilingMode = toFlag True,
                                 ghcOptObjSuffix     = toFlag "p_o"
                               }
               sharedCcOpts  = vanillaCcOpts `mappend` mempty {
                                 ghcOptFPic        = toFlag True,
                                 ghcOptDynLinkMode = toFlag GhcDynamicOnly,
                                 ghcOptObjSuffix   = toFlag "dyn_o"
                               }
               odir          = fromFlag (ghcOptObjDir vanillaCcOpts)
           createDirectoryIfMissingVerbose verbosity True odir
lukexi's avatar
lukexi committed
643
644
645
646
647
648
           needsRecomp <- checkNeedsRecompilation filename vanillaCcOpts
           when needsRecomp $ do
               runGhcProg vanillaCcOpts
               unless forRepl $
                 whenSharedLib forceSharedLib (runGhcProg sharedCcOpts)
               unless forRepl $ whenProfLib (runGhcProg profCcOpts)
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
649
      | filename <- cSources libBi]
650

651
652
653
  -- TODO: problem here is we need the .c files built first, so we can load them
  -- with ghci, but .c files can depend on .h files generated by ghc by ffi
  -- exports.
654

655
656
657
  ifReplLib $ do
    when (null (libModules lib)) $ warn verbosity "No exposed modules"
    ifReplLib (runGhcProg replOpts)
658

659
  -- link:
660
661
662
663
664
665
666
667
668
669
  unless forRepl $ do
    info verbosity "Linking..."
    let cProfObjs   = map (`replaceExtension` ("p_" ++ objExtension))
                      (cSources libBi)
        cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))
                      (cSources libBi)
        cid = compilerId (compiler lbi)
        vanillaLibFilePath = libTargetDir </> mkLibName           libName
        profileLibFilePath = libTargetDir </> mkProfLibName       libName
        sharedLibFilePath  = libTargetDir </> mkSharedLibName cid libName
670
        ghciLibFilePath    = libTargetDir </> Internal.mkGHCiLibName libName
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
        libInstallPath = libdir $ absoluteInstallDirs pkg_descr lbi NoCopyDest
        sharedLibInstallPath = libInstallPath </> mkSharedLibName cid libName

    stubObjs <- fmap catMaybes $ sequence
      [ findFileWithExtension [objExtension] [libTargetDir]
          (ModuleName.toFilePath x ++"_stub")
      | ghcVersion < Version [7,2] [] -- ghc-7.2+ does not make _stub.o files
      , x <- libModules lib ]
    stubProfObjs <- fmap catMaybes $ sequence
      [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]
          (ModuleName.toFilePath x ++"_stub")
      | ghcVersion < Version [7,2] [] -- ghc-7.2+ does not make _stub.o files
      , x <- libModules lib ]
    stubSharedObjs <- fmap catMaybes $ sequence
      [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]
          (ModuleName.toFilePath x ++"_stub")
      | ghcVersion < Version [7,2] [] -- ghc-7.2+ does not make _stub.o files
      , x <- libModules lib ]

690
    hObjs     <- Internal.getHaskellObjects implInfo lib lbi
691
692
693
                      libTargetDir objExtension True
    hProfObjs <-
      if (withProfLib lbi)
694
              then Internal.getHaskellObjects implInfo lib lbi
695
696
697
698
                      libTargetDir ("p_" ++ objExtension) True
              else return []
    hSharedObjs <-
      if (withSharedLib lbi)
699
              then Internal.getHaskellObjects implInfo lib lbi
700
701
702
703
                      libTargetDir ("dyn_" ++ objExtension) False
              else return []

    unless (null hObjs && null cObjs && null stubObjs) $ do
704
      rpaths <- getRPaths lbi clbi
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728

      let staticObjectFiles =
                 hObjs
              ++ map (libTargetDir </>) cObjs
              ++ stubObjs
          profObjectFiles =
                 hProfObjs
              ++ map (libTargetDir </>) cProfObjs
              ++ stubProfObjs
          ghciObjFiles =
                 hObjs
              ++ map (libTargetDir </>) cObjs
              ++ stubObjs
          dynamicObjectFiles =
                 hSharedObjs
              ++ map (libTargetDir </>) cSharedObjs
              ++ stubSharedObjs
          -- After the relocation lib is created we invoke ghc -shared
          -- with the dependencies spelled out as -package arguments
          -- and ghc invokes the linker with the proper library paths
          ghcSharedLinkArgs =
              mempty {
                ghcOptShared             = toFlag True,
                ghcOptDynLinkMode        = toFlag GhcDynamicOnly,
729
                ghcOptInputFiles         = toNubListR dynamicObjectFiles,
730
731
732
733
734
735
736
737
738
739
                ghcOptOutputFile         = toFlag sharedLibFilePath,
                -- For dynamic libs, Mac OS/X needs to know the install location
                -- at build time. This only applies to GHC < 7.8 - see the
                -- discussion in #1660.
                ghcOptDylibName          = if (hostOS == OSX
                                               && ghcVersion < Version [7,8] [])
                                            then toFlag sharedLibInstallPath
                                            else mempty,
                ghcOptNoAutoLinkPackages = toFlag True,
                ghcOptPackageDBs         = withPackageDB lbi,
740
741
                ghcOptPackages           = toNubListR $
                                           Internal.mkGhcOptPackages clbi ,
742
                ghcOptLinkLibs           = toNubListR $ extraLibs libBi,
743
                ghcOptLinkLibPath        = toNubListR $ extraLibDirs libBi,
744
                ghcOptLinkFrameworks     = toNubListR $ PD.frameworks libBi,
745
                ghcOptRPaths             = rpaths
746
747
              }

748
749
      info verbosity (show (ghcOptPackages ghcSharedLinkArgs))

750
751
752
753
754
755
756
757
758
759
760
761
762
      whenVanillaLib False $ do
        Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles

      whenProfLib $ do
        Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles

      whenGHCiLib $ do
        (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
        Ld.combineObjectFiles verbosity ldProg
          ghciLibFilePath ghciObjFiles

      whenSharedLib False $
        runGhcProg ghcSharedLinkArgs
763

764
765
766
767
768
769
770
771
-- | Start a REPL without loading any source files.
startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler
                 -> PackageDBStack -> IO ()
startInterpreter verbosity conf comp packageDBs = do
  let replOpts = mempty {
        ghcOptMode       = toFlag GhcModeInteractive,
        ghcOptPackageDBs = packageDBs
        }
772
  checkPackageDbStack comp packageDBs
773
774
  (ghcProg, _) <- requireProgram verbosity ghcProgram conf
  runGHC verbosity ghcProg comp replOpts
775
776
777

-- | Build an executable with GHC.
--
778
buildExe, replExe :: Verbosity          -> Cabal.Flag (Maybe Int)
779
780
781
782
783
                  -> PackageDescription -> LocalBuildInfo
                  -> Executable         -> ComponentLocalBuildInfo -> IO ()
buildExe = buildOrReplExe False
replExe  = buildOrReplExe True

784
buildOrReplExe :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)
785
786
               -> PackageDescription -> LocalBuildInfo
               -> Executable         -> ComponentLocalBuildInfo -> IO ()
787
buildOrReplExe forRepl verbosity numJobs _pkg_descr lbi
788
  exe@Executable { exeName = exeName', modulePath = modPath } clbi = do
789
790

  (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)
791
  let comp       = compiler lbi
792
      implInfo   = getImplInfo comp
793
      runGhcProg = runGHC verbosity ghcProg comp
794
795

  exeBi <- hackThreadedFlag verbosity
796
             comp (withProfExe lbi) (buildInfo exe)
797
798
799

  -- exeNameReal, the name that GHC really uses (with .exe on Windows)
  let exeNameReal = exeName' <.>
800
                    (if takeExtension exeName' /= ('.':exeExtension)
801
802
                       then exeExtension
                       else "")
803

804
  let targetDir = (buildDir lbi) </> exeName'
805
806
807
  let exeDir    = targetDir </> (exeName' ++ "-tmp")
  createDirectoryIfMissingVerbose verbosity True targetDir
  createDirectoryIfMissingVerbose verbosity True exeDir
refold's avatar
refold committed
808
809
  -- TODO: do we need to put hs-boot files into place for mutually recursive
  -- modules?  FIX: what about exeName.hi-boot?
810

811
812
813
814
  -- Determine if program coverage should be enabled and if so, what
  -- '-hpcdir' should be.
  let isCoverageEnabled = fromFlag $ configCoverage $ configFlags lbi
      distPref = fromFlag $ configDistPref $ configFlags lbi
815
      hpcdir way
Yuras's avatar
Yuras committed
816
        | forRepl = mempty  -- HPC is not supported in ghci
817
818
        | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way exeName'
        | otherwise = mempty
819

820
821
  -- build executables

822
  srcMainFile         <- findFile (exeDir : hsSourceDirs exeBi) modPath
823
  rpaths              <- getRPaths lbi clbi
824

825
826
  let isGhcDynamic        = isDynamic comp
      dynamicTooSupported = supportsDynamicToo comp
827
      isHaskellMain = elem (takeExtension srcMainFile) [".hs", ".lhs"]
828
829
      cSrcs         = cSources exeBi ++ [srcMainFile | not isHaskellMain]
      cObjs         = map (`replaceExtension` objExtension) cSrcs
830
      baseOpts   = (componentGhcOptions verbosity lbi exeBi clbi exeDir)
831
                    `mappend` mempty {
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
832
                      ghcOptMode         = toFlag GhcModeMake,
833
                      ghcOptInputFiles   = toNubListR
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
834
                        [ srcMainFile | isHaskellMain],
835
                      ghcOptInputModules = toNubListR
836
                        [ m | not isHaskellMain, m <- exeModules exe]
837
                    }
838
      staticOpts = baseOpts `mappend` mempty {
839
840
                      ghcOptDynLinkMode    = toFlag GhcStaticOnly,
                      ghcOptHPCDir         = hpcdir Hpc.Vanilla
841
                   }
842
843
      profOpts   = baseOpts `mappend` mempty {
                      ghcOptProfilingMode  = toFlag True,
844
845
                      ghcOptProfilingAuto  = Internal.profDetailLevelFlag False
                                               (withProfExeDetail lbi),
846
847
848
849
850
                      ghcOptHiSuffix       = toFlag "p_hi",
                      ghcOptObjSuffix      = toFlag "p_o",
                      ghcOptExtra          = toNubListR (hcProfOptions GHC exeBi),
                      ghcOptHPCDir         = hpcdir Hpc.Prof
                    }
851
      dynOpts    = baseOpts `mappend` mempty {
852
                      ghcOptDynLinkMode    = toFlag GhcDynamicOnly,
853
854
                      ghcOptHiSuffix       = toFlag "dyn_hi",
                      ghcOptObjSuffix      = toFlag "dyn_o",
855
                      ghcOptExtra          = toNubListR $
856
857
                                             hcSharedOptions GHC exeBi,
                      ghcOptHPCDir         = hpcdir Hpc.Dyn
858
                    }
859
      dynTooOpts = staticOpts `mappend` mempty {
860
861
                      ghcOptDynLinkMode    = toFlag GhcStaticAndDynamic,
                      ghcOptDynHiSuffix    = toFlag "dyn_hi",
862
863
                      ghcOptDynObjSuffix   = toFlag "dyn_o",
                      ghcOptHPCDir         = hpcdir Hpc.Dyn
864
                    }
865
      linkerOpts = mempty {
866
867
868
869
870
                      ghcOptLinkOptions    = toNubListR $ PD.ldOptions exeBi,
                      ghcOptLinkLibs       = toNubListR $ extraLibs exeBi,
                      ghcOptLinkLibPath    = toNubListR $ extraLibDirs exeBi,
                      ghcOptLinkFrameworks = toNubListR $ PD.frameworks exeBi,
                      ghcOptInputFiles     = toNubListR
871
872
873
                                             [exeDir </> x | x <- cObjs]
                    }
      dynLinkerOpts = mempty {
874
                      ghcOptRPaths         = rpaths
875
                   }
876
      replOpts   = baseOpts {
877
878
                      ghcOptExtra          = overNubListR
                                             Internal.filterGhciFlags
879
                                             (ghcOptExtra baseOpts)
880
                   }
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
881
882
883
884
885
                   -- For a normal compile we do separate invocations of ghc for
                   -- compiling as for linking. But for repl we have to do just
                   -- the one invocation, so that one has to include all the
                   -- linker stuff too, like -l flags and any .o files from C
                   -- files etc.
886
                   `mappend` linkerOpts
887
                   `mappend` mempty {
888
889
890
                      ghcOptMode           = toFlag GhcModeInteractive,
                      ghcOptOptimisation   = toFlag GhcNoOptimisation
                   }
891
      commonOpts  | withProfExe lbi = profOpts
892
893
                  | withDynExe  lbi = dynOpts
                  | otherwise       = staticOpts
894
895
      compileOpts | useDynToo = dynTooOpts
                  | otherwise = commonOpts
896
897
898
899
900
901
902
903
904
905
      withStaticExe = (not $ withProfExe lbi) && (not $ withDynExe lbi)

      -- For building exe's that use TH with -prof or -dynamic we actually have
      -- to build twice, once without -prof/-dynamic and then again with
      -- -prof/-dynamic. This is because the code that TH needs to run at
      -- compile time needs to be the vanilla ABI so it can be loaded up and run
      -- by the compiler.
      -- With dynamic-by-default GHC the TH object files loaded at compile-time
      -- need to be .dyn_o instead of .o.
      doingTH = EnableExtension TemplateHaskell `elem` allExtensions exeBi
Ian D. Bollinger's avatar
Ian D. Bollinger committed
906
      -- Should we use -dynamic-too instead of compiling twice?
907
      useDynToo = dynamicTooSupported && isGhcDynamic
908
909
                  && doingTH && withStaticExe
                  && null (hcSharedOptions GHC exeBi)
910
911
912
      compileTHOpts | isGhcDynamic = dynOpts
                    | otherwise    = staticOpts
      compileForTH
913
        | forRepl      = False
914
        | useDynToo    = False
915
916
        | isGhcDynamic = doingTH && (withProfExe lbi || withStaticExe)
        | otherwise    = doingTH && (withProfExe lbi || withDynExe lbi)
refold's avatar
refold committed
917

918
      linkOpts = commonOpts `mappend`
919
920
                 linkerOpts `mappend`
                 mempty { ghcOptLinkNoHsMain   = toFlag (not isHaskellMain) } `mappend`
921
                 (if withDynExe lbi then dynLinkerOpts else mempty)
922

923
924
  -- Build static/dynamic object files for TH, if needed.
  when compileForTH $
925
    runGhcProg compileTHOpts { ghcOptNoLink  = toFlag True
926
                             , ghcOptNumJobs = numJobs }
927

928
  unless forRepl $
929
    runGhcProg compileOpts { ghcOptNoLink  = toFlag True
930
                           , ghcOptNumJobs = numJobs }
931
932

  -- build any C sources
933
  unless (null cSrcs) $ do
934
935
   info verbosity "Building C Sources..."
   sequence_
936
937
     [ do let opts = (Internal.componentCcGhcOptions verbosity implInfo lbi exeBi
                         clbi exeDir filename) `mappend` mempty {
938
939
940
                       ghcOptDynLinkMode   = toFlag (if withDynExe lbi
                                                       then GhcDynamicOnly
                                                       else GhcStaticOnly),
941
942
                       ghcOptProfilingMode = toFlag (withProfExe lbi)
                     }
lukexi's avatar
lukexi committed
943
              odir  = fromFlag (ghcOptObjDir opts)
944
          createDirectoryIfMissingVerbose verbosity True odir
lukexi's avatar
lukexi committed
945
946
947
          needsRecomp <- checkNeedsRecompilation filename opts
          when needsRecomp $ 
            runGhcProg opts
948
     | filename <- cSrcs ]
949

950
951
952
  -- TODO: problem here is we need the .c files built first, so we can load them
  -- with ghci, but .c files can depend on .h files generated by ghc by ffi
  -- exports.