2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE RankNTypes #-}
4 {-# LANGUAGE TupleSections #-}
6 module Distribution
.Simple
.GHCJS
10 , getInstalledPackagesMonitorFiles
11 , getPackageDBContents
26 , Internal
.componentCcGhcOptions
33 -- * Constructing and deconstructing GHC environment files
34 , Internal
.GhcEnvironmentFileEntry
(..)
35 , Internal
.simpleGhcEnvironmentFile
36 , Internal
.renderGhcEnvironmentFile
37 , Internal
.writeGhcEnvironmentFile
38 , Internal
.ghcPlatformAndVersionString
39 , readGhcEnvironmentFile
40 , parseGhcEnvironmentFile
43 -- * Version-specific implementation quirks
48 import Distribution
.Compat
.Prelude
51 import Distribution
.CabalSpecVersion
52 import Distribution
.InstalledPackageInfo
(InstalledPackageInfo
)
53 import qualified Distribution
.InstalledPackageInfo
as InstalledPackageInfo
54 import Distribution
.ModuleName
(ModuleName
)
55 import qualified Distribution
.ModuleName
as ModuleName
56 import Distribution
.Package
57 import Distribution
.PackageDescription
as PD
58 import Distribution
.PackageDescription
.Utils
(cabalBug
)
59 import Distribution
.Pretty
60 import Distribution
.Simple
.BuildPaths
61 import Distribution
.Simple
.Compiler
62 import Distribution
.Simple
.Errors
63 import Distribution
.Simple
.Flag
64 import Distribution
.Simple
.GHC
.EnvironmentParser
65 import Distribution
.Simple
.GHC
.ImplInfo
66 import qualified Distribution
.Simple
.GHC
.Internal
as Internal
67 import qualified Distribution
.Simple
.Hpc
as Hpc
68 import Distribution
.Simple
.LocalBuildInfo
69 import Distribution
.Simple
.PackageIndex
(InstalledPackageIndex
)
70 import qualified Distribution
.Simple
.PackageIndex
as PackageIndex
71 import Distribution
.Simple
.PreProcess
.Types
72 import Distribution
.Simple
.Program
73 import Distribution
.Simple
.Program
.GHC
74 import qualified Distribution
.Simple
.Program
.HcPkg
as HcPkg
75 import qualified Distribution
.Simple
.Program
.Strip
as Strip
76 import Distribution
.Simple
.Setup
.Common
77 import Distribution
.Simple
.Utils
78 import Distribution
.System
79 import Distribution
.Types
.ComponentLocalBuildInfo
80 import Distribution
.Types
.PackageName
.Magic
81 import Distribution
.Types
.ParStrat
82 import Distribution
.Utils
.NubList
83 import Distribution
.Utils
.Path
84 import Distribution
.Verbosity
(Verbosity
)
85 import Distribution
.Version
87 import Control
.Monad
(msum)
88 import Data
.Char (isLower)
89 import qualified Data
.Map
as Map
90 import System
.Directory
92 , createDirectoryIfMissing
94 , getAppUserDataDirectory
98 import System
.FilePath
106 import qualified System
.Info
108 -- -----------------------------------------------------------------------------
116 -> IO (Compiler
, Maybe Platform
, ProgramDb
)
117 configure verbosity hcPath hcPkgPath conf0
= do
118 (ghcjsProg
, ghcjsVersion
, progdb1
) <-
119 requireProgramVersion
122 (orLaterVersion
(mkVersion
[0, 1]))
123 (userMaybeSpecifyPath
"ghcjs" hcPath conf0
)
125 Just ghcjsGhcVersion
<- findGhcjsGhcVersion verbosity
(programPath ghcjsProg
)
126 unless (ghcjsGhcVersion
< mkVersion
[8, 8]) $
128 "Unknown/unsupported 'ghc' version detected "
130 ++ prettyShow cabalVersion
131 ++ " supports 'ghc' version < 8.8): "
132 ++ programPath ghcjsProg
133 ++ " is based on GHC version "
134 ++ prettyShow ghcjsGhcVersion
136 let implInfo
= ghcjsVersionImplInfo ghcjsVersion ghcjsGhcVersion
138 -- This is slightly tricky, we have to configure ghc first, then we use the
139 -- location of ghc to help find ghc-pkg in the case that the user did not
140 -- specify the location of ghc-pkg directly:
141 (ghcjsPkgProg
, ghcjsPkgVersion
, progdb2
) <-
142 requireProgramVersion
145 { programFindLocation
= guessGhcjsPkgFromGhcjsPath ghcjsProg
148 (userMaybeSpecifyPath
"ghcjs-pkg" hcPkgPath progdb1
)
150 Just ghcjsPkgGhcjsVersion
<-
151 findGhcjsPkgGhcjsVersion
153 (programPath ghcjsPkgProg
)
155 when (ghcjsVersion
/= ghcjsPkgGhcjsVersion
) $
156 dieWithException verbosity
$
158 (programPath ghcjsProg
)
160 (programPath ghcjsPkgProg
)
163 when (ghcjsGhcVersion
/= ghcjsPkgVersion
) $
164 dieWithException verbosity
$
165 VersionMismatchGHCJS
(programPath ghcjsProg
) ghcjsGhcVersion
(programPath ghcjsPkgProg
) ghcjsPkgVersion
167 -- Likewise we try to find the matching hsc2hs and haddock programs.
170 { programFindLocation
=
171 guessHsc2hsFromGhcjsPath ghcjsProg
175 { programFindLocation
=
176 guessHaddockFromGhcjsPath ghcjsProg
180 { programFindLocation
= guessHpcFromGhcjsPath ghcjsProg
183 runghcProgram' = runghcProgram {
184 programFindLocation = guessRunghcFromGhcjsPath ghcjsProg
187 addKnownProgram haddockProgram
' $
188 addKnownProgram hsc2hsProgram
' $
189 addKnownProgram hpcProgram
' $
190 {- addKnownProgram runghcProgram' -} progdb2
192 languages
<- Internal
.getLanguages verbosity implInfo ghcjsProg
193 extensions
<- Internal
.getExtensions verbosity implInfo ghcjsProg
195 ghcjsInfo
<- Internal
.getGhcInfo verbosity implInfo ghcjsProg
196 let ghcInfoMap
= Map
.fromList ghcjsInfo
200 { compilerId
= CompilerId GHCJS ghcjsVersion
203 "ghc" ++ intercalate
"_" (map show . versionNumbers
$ ghcjsGhcVersion
)
204 , compilerCompat
= [CompilerId GHC ghcjsGhcVersion
]
205 , compilerLanguages
= languages
206 , compilerExtensions
= extensions
207 , compilerProperties
= ghcInfoMap
209 compPlatform
= Internal
.targetPlatform ghcjsInfo
210 return (comp
, compPlatform
, progdb3
)
212 guessGhcjsPkgFromGhcjsPath
216 -> IO (Maybe (FilePath, [FilePath]))
217 guessGhcjsPkgFromGhcjsPath
= guessToolFromGhcjsPath ghcjsPkgProgram
219 guessHsc2hsFromGhcjsPath
223 -> IO (Maybe (FilePath, [FilePath]))
224 guessHsc2hsFromGhcjsPath
= guessToolFromGhcjsPath hsc2hsProgram
226 guessHaddockFromGhcjsPath
230 -> IO (Maybe (FilePath, [FilePath]))
231 guessHaddockFromGhcjsPath
= guessToolFromGhcjsPath haddockProgram
233 guessHpcFromGhcjsPath
237 -> IO (Maybe (FilePath, [FilePath]))
238 guessHpcFromGhcjsPath
= guessToolFromGhcjsPath hpcProgram
240 guessToolFromGhcjsPath
245 -> IO (Maybe (FilePath, [FilePath]))
246 guessToolFromGhcjsPath tool ghcjsProg verbosity searchpath
=
248 let toolname
= programName tool
249 given_path
= programPath ghcjsProg
250 given_dir
= takeDirectory given_path
251 real_path
<- canonicalizePath given_path
252 let real_dir
= takeDirectory real_path
253 versionSuffix path
= takeVersionSuffix
(dropExeExtension path
)
254 given_suf
= versionSuffix given_path
255 real_suf
= versionSuffix real_path
256 guessNormal dir
= dir
</> toolname
<.> exeExtension buildPlatform
259 </> (toolname
++ "-ghcjs")
260 <.> exeExtension buildPlatform
261 guessGhcjsVersioned dir suf
=
263 </> (toolname
++ "-ghcjs" ++ suf
)
264 <.> exeExtension buildPlatform
265 guessVersioned dir suf
=
267 </> (toolname
++ suf
)
268 <.> exeExtension buildPlatform
270 |
null suf
= [guessGhcjs dir
, guessNormal dir
]
272 [ guessGhcjsVersioned dir suf
273 , guessVersioned dir suf
278 mkGuesses given_dir given_suf
279 ++ if real_path
== given_path
281 else mkGuesses real_dir real_suf
285 ++ " near compiler in "
287 debug verbosity
$ "candidate locations: " ++ show guesses
288 exists
<- traverse
doesFileExist guesses
289 case [file |
(file
, True) <- zip guesses exists
] of
290 -- If we can't find it near ghc, fall back to the usual
292 [] -> programFindLocation tool verbosity searchpath
294 info verbosity
$ "found " ++ toolname
++ " in " ++ fp
297 . takeWhile (\(_file
, exist
) -> not exist
)
299 return (Just
(fp
, lookedAt
))
301 takeVersionSuffix
:: FilePath -> String
302 takeVersionSuffix
= takeWhileEndLE isSuffixChar
304 isSuffixChar
:: Char -> Bool
305 isSuffixChar c
= isDigit c || c
== '.' || c
== '-'
307 getGhcInfo
:: Verbosity
-> ConfiguredProgram
-> IO [(String, String)]
308 getGhcInfo verbosity ghcjsProg
= Internal
.getGhcInfo verbosity implInfo ghcjsProg
310 version
= fromMaybe (error "GHCJS.getGhcInfo: no version") $ programVersion ghcjsProg
311 implInfo
= ghcVersionImplInfo version
313 -- | Given a single package DB, return all installed packages.
318 -> IO InstalledPackageIndex
319 getPackageDBContents verbosity packagedb progdb
= do
320 pkgss
<- getInstalledPackages
' verbosity
[packagedb
] progdb
321 toPackageIndex verbosity pkgss progdb
323 -- | Given a package DB stack, return all installed packages.
328 -> IO InstalledPackageIndex
329 getInstalledPackages verbosity packagedbs progdb
= do
330 checkPackageDbEnvVar verbosity
331 checkPackageDbStack verbosity packagedbs
332 pkgss
<- getInstalledPackages
' verbosity packagedbs progdb
333 index <- toPackageIndex verbosity pkgss progdb
338 -> [(PackageDB
, [InstalledPackageInfo
])]
340 -> IO InstalledPackageIndex
341 toPackageIndex verbosity pkgss progdb
= do
342 -- On Windows, various fields have $topdir/foo rather than full
343 -- paths. We need to substitute the right value in so that when
344 -- we, for example, call gcc, we have proper paths to give it.
345 topDir
<- getLibDir
' verbosity ghcjsProg
347 [ PackageIndex
.fromList
(map (Internal
.substTopDir topDir
) pkgs
)
350 return $! (mconcat
indices)
352 ghcjsProg
= fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb
354 getLibDir
:: Verbosity
-> LocalBuildInfo
-> IO FilePath
355 getLibDir verbosity lbi
=
356 dropWhileEndLE
isSpace
357 `
fmap` getDbProgramOutput
363 getLibDir
' :: Verbosity
-> ConfiguredProgram
-> IO FilePath
364 getLibDir
' verbosity ghcjsProg
=
365 dropWhileEndLE
isSpace
366 `
fmap` getProgramOutput verbosity ghcjsProg
["--print-libdir"]
368 -- | Return the 'FilePath' to the global GHC package database.
369 getGlobalPackageDB
:: Verbosity
-> ConfiguredProgram
-> IO FilePath
370 getGlobalPackageDB verbosity ghcProg
=
371 dropWhileEndLE
isSpace
372 `
fmap` getProgramOutput verbosity ghcProg
["--print-global-package-db"]
374 -- | Return the 'FilePath' to the per-user GHC package database.
375 getUserPackageDB
:: Verbosity
-> ConfiguredProgram
-> Platform
-> IO FilePath
376 getUserPackageDB _verbosity ghcjsProg platform
= do
377 -- It's rather annoying that we have to reconstruct this, because ghc
378 -- hides this information from us otherwise. But for certain use cases
379 -- like change monitoring it really can't remain hidden.
380 appdir
<- getAppUserDataDirectory
"ghcjs"
381 return (appdir
</> platformAndVersion
</> packageConfFileName
)
384 Internal
.ghcPlatformAndVersionString
387 packageConfFileName
= "package.conf.d"
388 ghcjsVersion
= fromMaybe (error "GHCJS.getUserPackageDB: no version") $ programVersion ghcjsProg
390 checkPackageDbEnvVar
:: Verbosity
-> IO ()
391 checkPackageDbEnvVar verbosity
=
392 Internal
.checkPackageDbEnvVar verbosity
"GHCJS" "GHCJS_PACKAGE_PATH"
394 checkPackageDbStack
:: Verbosity
-> PackageDBStack
-> IO ()
395 checkPackageDbStack _
(GlobalPackageDB
: rest
)
396 | GlobalPackageDB `
notElem` rest
= return ()
397 checkPackageDbStack verbosity rest
398 | GlobalPackageDB `
notElem` rest
=
399 dieWithException verbosity GlobalPackageDBLimitation
400 checkPackageDbStack verbosity _
=
401 dieWithException verbosity GlobalPackageDBSpecifiedFirst
403 getInstalledPackages
'
407 -> IO [(PackageDB
, [InstalledPackageInfo
])]
408 getInstalledPackages
' verbosity packagedbs progdb
=
411 pkgs
<- HcPkg
.dump
(hcPkgInfo progdb
) verbosity packagedb
412 return (packagedb
, pkgs
)
413 | packagedb
<- packagedbs
416 -- | Get the packages from specific PackageDBs, not cumulative.
417 getInstalledPackagesMonitorFiles
423 getInstalledPackagesMonitorFiles verbosity platform progdb
=
424 traverse getPackageDBPath
426 getPackageDBPath
:: PackageDB
-> IO FilePath
427 getPackageDBPath GlobalPackageDB
=
428 selectMonitorFile
=<< getGlobalPackageDB verbosity ghcjsProg
429 getPackageDBPath UserPackageDB
=
430 selectMonitorFile
=<< getUserPackageDB verbosity ghcjsProg platform
431 getPackageDBPath
(SpecificPackageDB path
) = selectMonitorFile path
433 -- GHC has old style file dbs, and new style directory dbs.
434 -- Note that for dir style dbs, we only need to monitor the cache file, not
435 -- the whole directory. The ghc program itself only reads the cache file
436 -- so it's safe to only monitor this one file.
437 selectMonitorFile path
= do
438 isFileStyle
<- doesFileExist path
441 else return (path
</> "package.cache")
443 ghcjsProg
= fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb
445 toJSLibName
:: String -> String
447 | takeExtension lib `
elem`
[".dll", ".dylib", ".so"] =
448 replaceExtension lib
"js_so"
449 | takeExtension lib
== ".a" = replaceExtension lib
"js_a"
450 |
otherwise = lib
<.> "js_a"
452 -- -----------------------------------------------------------------------------
453 -- Building a library
458 -> PackageDescription
461 -> ComponentLocalBuildInfo
463 buildLib
= buildOrReplLib Nothing
469 -> PackageDescription
472 -> ComponentLocalBuildInfo
474 replLib
= buildOrReplLib
. Just
480 -> PackageDescription
483 -> ComponentLocalBuildInfo
485 buildOrReplLib mReplFlags verbosity numJobs _pkg_descr lbi lib clbi
= do
486 let uid
= componentUnitId clbi
487 libTargetDir
= componentBuildDir lbi clbi
488 whenVanillaLib forceVanilla
=
489 when (forceVanilla || withVanillaLib lbi
)
490 whenProfLib
= when (withProfLib lbi
)
491 whenSharedLib forceShared
=
492 when (forceShared || withSharedLib lbi
)
493 whenStaticLib forceStatic
=
494 when (forceStatic || withStaticLib lbi
)
495 -- whenGHCiLib = when (withGHCiLib lbi)
496 forRepl
= maybe False (const True) mReplFlags
497 -- ifReplLib = when forRepl
499 implInfo
= getImplInfo comp
500 platform
@(Platform _hostArch _hostOS
) = hostPlatform lbi
501 has_code
= not (componentIsIndefinite clbi
)
503 (ghcjsProg
, _
) <- requireProgram verbosity ghcjsProgram
(withPrograms lbi
)
504 let runGhcjsProg
= runGHC verbosity ghcjsProg comp platform
506 let libBi
= libBuildInfo lib
508 -- fixme flags shouldn't depend on ghcjs being dynamic or not
509 let isGhcjsDynamic
= isDynamic comp
510 dynamicTooSupported
= supportsDynamicToo comp
511 doingTH
= usesTemplateHaskellOrQQ libBi
512 forceVanillaLib
= doingTH
&& not isGhcjsDynamic
513 forceSharedLib
= doingTH
&& isGhcjsDynamic
514 -- TH always needs default libs, even when building for profiling
516 -- Determine if program coverage should be enabled and if so, what
517 -- '-hpcdir' should be.
518 let isCoverageEnabled
= libCoverage lbi
520 | forRepl
= mempty
-- HPC is not supported in ghci
521 | isCoverageEnabled
= toFlag
$ Hpc
.mixDir
(libTargetDir
</> extraCompilationArtifacts
) way
524 createDirectoryIfMissingVerbose verbosity
True libTargetDir
525 -- TODO: do we need to put hs-boot files into place for mutually recursive
527 let cLikeFiles
= fromNubListR
$ toNubListR
(cSources libBi
) <> toNubListR
(cxxSources libBi
)
528 jsSrcs
= jsSources libBi
529 cObjs
= map (`replaceExtension` objExtension
) cLikeFiles
530 baseOpts
= componentGhcOptions verbosity lbi libBi clbi libTargetDir
535 , getHSLibraryName uid
536 , "-js-lib-outputdir"
544 { ghcOptMode
= toFlag GhcModeMake
545 , ghcOptNumJobs
= numJobs
546 , ghcOptInputModules
= toNubListR
$ allLibModules lib clbi
547 , ghcOptHPCDir
= hpcdir Hpc
.Vanilla
549 vanillaOpts
= vanillaOptsNoJsLib `mappend` linkJsLibOpts
552 adjustExts
"p_hi" "p_o" vanillaOpts
554 { ghcOptProfilingMode
= toFlag
True
555 , ghcOptProfilingAuto
=
556 Internal
.profDetailLevelFlag
558 (withProfLibDetail lbi
)
559 , -- ghcOptHiSuffix = toFlag "p_hi",
560 -- ghcOptObjSuffix = toFlag "p_o",
561 ghcOptExtra
= hcProfOptions GHC libBi
562 , ghcOptHPCDir
= hpcdir Hpc
.Prof
566 adjustExts
"dyn_hi" "dyn_o" vanillaOpts
568 { ghcOptDynLinkMode
= toFlag GhcDynamicOnly
569 , ghcOptFPic
= toFlag
True
570 , -- ghcOptHiSuffix = toFlag "dyn_hi",
571 -- ghcOptObjSuffix = toFlag "dyn_o",
572 ghcOptExtra
= hcSharedOptions GHC libBi
573 , ghcOptHPCDir
= hpcdir Hpc
.Dyn
579 { ghcOptDynLinkMode
= toFlag GhcStaticAndDynamic
580 , ghcOptDynHiSuffix
= toFlag
"js_dyn_hi"
581 , ghcOptDynObjSuffix
= toFlag
"js_dyn_o"
582 , ghcOptHPCDir
= hpcdir Hpc
.Dyn
585 unless (forRepl ||
null (allLibModules lib clbi
) && null jsSrcs
&& null cObjs
) $
587 let vanilla
= whenVanillaLib forceVanillaLib
(runGhcjsProg vanillaOpts
)
588 shared
= whenSharedLib forceSharedLib
(runGhcjsProg sharedOpts
)
591 && (forceVanillaLib || withVanillaLib lbi
)
592 && (forceSharedLib || withSharedLib lbi
)
593 && null (hcSharedOptions GHC libBi
)
599 runGhcjsProg vanillaSharedOpts
600 case (hpcdir Hpc
.Dyn
, hpcdir Hpc
.Vanilla
) of
601 (Flag dynDir
, Flag vanillaDir
) ->
602 -- When the vanilla and shared library builds are done
603 -- in one pass, only one set of HPC module interfaces
604 -- are generated. This set should suffice for both
605 -- static and dynamically linked executables. We copy
606 -- the modules interfaces so they are available under
608 copyDirectoryRecursive verbosity dynDir vanillaDir
612 then do shared
; vanilla
613 else do vanilla
; shared
614 whenProfLib
(runGhcjsProg profOpts
)
616 -- Build any C++ sources separately.
618 unless (not has_code || null (cxxSources libBi) || not nativeToo) $ do
619 info verbosity "Building C++ Sources..."
621 [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo
622 lbi libBi clbi libTargetDir filename
623 vanillaCxxOpts = if isGhcjsDynamic
624 then baseCxxOpts { ghcOptFPic = toFlag True }
626 profCxxOpts = vanillaCxxOpts `mappend` mempty {
627 ghcOptProfilingMode = toFlag True,
628 ghcOptObjSuffix = toFlag "p_o"
630 sharedCxxOpts = vanillaCxxOpts `mappend` mempty {
631 ghcOptFPic = toFlag True,
632 ghcOptDynLinkMode = toFlag GhcDynamicOnly,
633 ghcOptObjSuffix = toFlag "dyn_o"
635 odir = fromFlag (ghcOptObjDir vanillaCxxOpts)
636 createDirectoryIfMissingVerbose verbosity True odir
637 let runGhcProgIfNeeded cxxOpts = do
638 needsRecomp <- checkNeedsRecompilation filename cxxOpts
639 when needsRecomp $ runGhcjsProg cxxOpts
640 runGhcProgIfNeeded vanillaCxxOpts
642 whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCxxOpts)
643 unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts)
644 | filename <- cxxSources libBi]
647 when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"
648 ifReplLib (runGhcjsProg replOpts)
650 -- build any C sources
651 -- TODO: Add support for S and CMM files.
653 unless (not has_code || null (cSources libBi) || not nativeToo) $ do
654 info verbosity "Building C Sources..."
656 [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo
657 lbi libBi clbi libTargetDir filename
658 vanillaCcOpts = if isGhcjsDynamic
659 -- Dynamic GHC requires C sources to be built
660 -- with -fPIC for REPL to work. See #2207.
661 then baseCcOpts { ghcOptFPic = toFlag True }
663 profCcOpts = vanillaCcOpts `mappend` mempty {
664 ghcOptProfilingMode = toFlag True,
665 ghcOptObjSuffix = toFlag "p_o"
667 sharedCcOpts = vanillaCcOpts `mappend` mempty {
668 ghcOptFPic = toFlag True,
669 ghcOptDynLinkMode = toFlag GhcDynamicOnly,
670 ghcOptObjSuffix = toFlag "dyn_o"
672 odir = fromFlag (ghcOptObjDir vanillaCcOpts)
673 createDirectoryIfMissingVerbose verbosity True odir
674 let runGhcProgIfNeeded ccOpts = do
675 needsRecomp <- checkNeedsRecompilation filename ccOpts
676 when needsRecomp $ runGhcjsProg ccOpts
677 runGhcProgIfNeeded vanillaCcOpts
679 whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCcOpts)
680 unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts)
681 | filename <- cSources libBi]
683 -- TODO: problem here is we need the .c files built first, so we can load them
684 -- with ghci, but .c files can depend on .h files generated by ghc by ffi
689 when has_code
. when False {- fixme nativeToo -} . unless forRepl
$ do
690 info verbosity
"Linking..."
693 (`replaceExtension`
("dyn_" ++ objExtension
))
694 (cSources libBi
++ cxxSources libBi
)
695 compiler_id
= compilerId
(compiler lbi
)
696 sharedLibFilePath
= libTargetDir
</> mkSharedLibName
(hostPlatform lbi
) compiler_id uid
697 staticLibFilePath
= libTargetDir
</> mkStaticLibName
(hostPlatform lbi
) compiler_id uid
703 stubObjs <- catMaybes <$> sequenceA
704 [ findFileWithExtension [objExtension] [libTargetDir]
705 (ModuleName.toFilePath x ++"_stub")
706 | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files
707 , x <- allLibModules lib clbi ]
708 stubProfObjs <- catMaybes <$> sequenceA
709 [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]
710 (ModuleName.toFilePath x ++"_stub")
711 | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files
712 , x <- allLibModules lib clbi ]
713 stubSharedObjs <- catMaybes <$> sequenceA
714 [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]
715 (ModuleName.toFilePath x ++"_stub")
716 | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files
717 , x <- allLibModules lib clbi ]
720 Internal
.getHaskellObjects
731 Internal
.getHaskellObjects
737 ("dyn_" ++ objExtension
)
741 unless (null hObjs
&& null cObjs
&& null stubObjs
) $ do
742 rpaths
<- getRPaths lbi clbi
744 let staticObjectFiles
=
746 ++ map (libTargetDir
</>) cObjs
750 ++ map (libTargetDir
</>) cSharedObjs
752 -- After the relocation lib is created we invoke ghc -shared
753 -- with the dependencies spelled out as -package arguments
754 -- and ghc invokes the linker with the proper library paths
757 { ghcOptShared
= toFlag
True
758 , ghcOptDynLinkMode
= toFlag GhcDynamicOnly
759 , ghcOptInputFiles
= toNubListR dynamicObjectFiles
760 , ghcOptOutputFile
= toFlag sharedLibFilePath
761 , ghcOptExtra
= hcSharedOptions GHC libBi
762 , -- For dynamic libs, Mac OS/X needs to know the install location
763 -- at build time. This only applies to GHC < 7.8 - see the
764 -- discussion in #1660.
766 ghcOptDylibName = if hostOS == OSX
767 && ghcVersion < mkVersion [7,8]
768 then toFlag sharedLibInstallPath
770 ghcOptHideAllPackages
= toFlag
True
771 , ghcOptNoAutoLinkPackages
= toFlag
True
772 , ghcOptPackageDBs
= withPackageDB lbi
773 , ghcOptThisUnitId
= case clbi
of
774 LibComponentLocalBuildInfo
{componentCompatPackageKey
= pk
} ->
777 , ghcOptThisComponentId
= case clbi
of
778 LibComponentLocalBuildInfo
{componentInstantiatedWith
= insts
} ->
781 else toFlag
(componentComponentId clbi
)
783 , ghcOptInstantiatedWith
= case clbi
of
784 LibComponentLocalBuildInfo
{componentInstantiatedWith
= insts
} ->
789 Internal
.mkGhcOptPackages mempty clbi
790 , ghcOptLinkLibs
= extraLibs libBi
791 , ghcOptLinkLibPath
= toNubListR
$ extraLibDirs libBi
792 , ghcOptLinkFrameworks
= toNubListR
$ PD
.frameworks libBi
793 , ghcOptLinkFrameworkDirs
=
794 toNubListR
$ PD
.extraFrameworkDirs libBi
795 , ghcOptRPaths
= rpaths
799 { ghcOptStaticLib
= toFlag
True
800 , ghcOptInputFiles
= toNubListR staticObjectFiles
801 , ghcOptOutputFile
= toFlag staticLibFilePath
802 , ghcOptExtra
= hcStaticOptions GHC libBi
803 , ghcOptHideAllPackages
= toFlag
True
804 , ghcOptNoAutoLinkPackages
= toFlag
True
805 , ghcOptPackageDBs
= withPackageDB lbi
806 , ghcOptThisUnitId
= case clbi
of
807 LibComponentLocalBuildInfo
{componentCompatPackageKey
= pk
} ->
810 , ghcOptThisComponentId
= case clbi
of
811 LibComponentLocalBuildInfo
{componentInstantiatedWith
= insts
} ->
814 else toFlag
(componentComponentId clbi
)
816 , ghcOptInstantiatedWith
= case clbi
of
817 LibComponentLocalBuildInfo
{componentInstantiatedWith
= insts
} ->
822 Internal
.mkGhcOptPackages mempty clbi
823 , ghcOptLinkLibs
= extraLibs libBi
824 , ghcOptLinkLibPath
= toNubListR
$ extraLibDirs libBi
827 info verbosity
(show (ghcOptPackages ghcSharedLinkArgs
))
829 whenVanillaLib False $ do
830 Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles
832 (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
833 Ld.combineObjectFiles verbosity lbi ldProg
834 ghciLibFilePath staticObjectFiles
838 Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles
840 (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
841 Ld.combineObjectFiles verbosity lbi ldProg
842 ghciProfLibFilePath profObjectFiles
844 whenSharedLib
False $
845 runGhcjsProg ghcSharedLinkArgs
847 whenStaticLib
False $
848 runGhcjsProg ghcStaticLinkArgs
850 -- | Start a REPL without loading any source files.
858 startInterpreter verbosity progdb comp platform packageDBs
= do
861 { ghcOptMode
= toFlag GhcModeInteractive
862 , ghcOptPackageDBs
= packageDBs
864 checkPackageDbStack verbosity packageDBs
865 (ghcjsProg
, _
) <- requireProgram verbosity ghcjsProgram progdb
866 runGHC verbosity ghcjsProg comp platform replOpts
868 -- -----------------------------------------------------------------------------
869 -- Building an executable or foreign library
871 -- | Build a foreign library
875 -> PackageDescription
878 -> ComponentLocalBuildInfo
880 buildFLib v njobs pkg lbi
= gbuild v njobs pkg lbi
. GBuildFLib
886 -> PackageDescription
889 -> ComponentLocalBuildInfo
891 replFLib replFlags v njobs pkg lbi
=
892 gbuild v njobs pkg lbi
. GReplFLib replFlags
894 -- | Build an executable with GHC.
898 -> PackageDescription
901 -> ComponentLocalBuildInfo
903 buildExe v njobs pkg lbi
= gbuild v njobs pkg lbi
. GBuildExe
909 -> PackageDescription
912 -> ComponentLocalBuildInfo
914 replExe replFlags v njobs pkg lbi
=
915 gbuild v njobs pkg lbi
. GReplExe replFlags
917 -- | Building an executable, starting the REPL, and building foreign
918 -- libraries are all very similar and implemented in 'gbuild'. The
919 -- 'GBuildMode' distinguishes between the various kinds of operation.
921 = GBuildExe Executable
922 | GReplExe
[String] Executable
923 | GBuildFLib ForeignLib
924 | GReplFLib
[String] ForeignLib
926 gbuildInfo
:: GBuildMode
-> BuildInfo
927 gbuildInfo
(GBuildExe exe
) = buildInfo exe
928 gbuildInfo
(GReplExe _ exe
) = buildInfo exe
929 gbuildInfo
(GBuildFLib flib
) = foreignLibBuildInfo flib
930 gbuildInfo
(GReplFLib _ flib
) = foreignLibBuildInfo flib
932 gbuildName
:: GBuildMode
-> String
933 gbuildName
(GBuildExe exe
) = unUnqualComponentName
$ exeName exe
934 gbuildName
(GReplExe _ exe
) = unUnqualComponentName
$ exeName exe
935 gbuildName
(GBuildFLib flib
) = unUnqualComponentName
$ foreignLibName flib
936 gbuildName
(GReplFLib _ flib
) = unUnqualComponentName
$ foreignLibName flib
938 gbuildTargetName
:: LocalBuildInfo
-> GBuildMode
-> String
939 gbuildTargetName lbi
(GBuildExe exe
) = exeTargetName
(hostPlatform lbi
) exe
940 gbuildTargetName lbi
(GReplExe _ exe
) = exeTargetName
(hostPlatform lbi
) exe
941 gbuildTargetName lbi
(GBuildFLib flib
) = flibTargetName lbi flib
942 gbuildTargetName lbi
(GReplFLib _ flib
) = flibTargetName lbi flib
944 exeTargetName
:: Platform
-> Executable
-> String
945 exeTargetName platform exe
= unUnqualComponentName
(exeName exe
) `withExt` exeExtension platform
947 -- | Target name for a foreign library (the actual file name)
949 -- We do not use mkLibName and co here because the naming for foreign libraries
950 -- is slightly different (we don't use "_p" or compiler version suffices, and we
951 -- don't want the "lib" prefix on Windows).
953 -- TODO: We do use `dllExtension` and co here, but really that's wrong: they
954 -- use the OS used to build cabal to determine which extension to use, rather
955 -- than the target OS (but this is wrong elsewhere in Cabal as well).
956 flibTargetName
:: LocalBuildInfo
-> ForeignLib
-> String
957 flibTargetName lbi flib
=
958 case (os
, foreignLibType flib
) of
959 (Windows
, ForeignLibNativeShared
) -> nm
<.> "dll"
960 (Windows
, ForeignLibNativeStatic
) -> nm
<.> "lib"
961 (Linux
, ForeignLibNativeShared
) -> "lib" ++ nm
<.> versionedExt
962 (_other
, ForeignLibNativeShared
) -> "lib" ++ nm
<.> dllExtension
(hostPlatform lbi
)
963 (_other
, ForeignLibNativeStatic
) -> "lib" ++ nm
<.> staticLibExtension
(hostPlatform lbi
)
964 (_any
, ForeignLibTypeUnknown
) -> cabalBug
"unknown foreign lib type"
967 nm
= unUnqualComponentName
$ foreignLibName flib
971 let (Platform _ os
') = hostPlatform lbi
974 -- If a foreign lib foo has lib-version-info 5:1:2 or
975 -- lib-version-linux 3.2.1, it should be built as libfoo.so.3.2.1
976 -- Libtool's version-info data is translated into library versions in a
977 -- nontrivial way: so refer to libtool documentation.
978 versionedExt
:: String
980 let nums
= foreignLibVersion flib os
981 in foldl (<.>) "so" (map show nums
)
983 -- | Name for the library when building.
985 -- If the `lib-version-info` field or the `lib-version-linux` field of
986 -- a foreign library target is set, we need to incorporate that
987 -- version into the SONAME field.
989 -- If a foreign library foo has lib-version-info 5:1:2, it should be
990 -- built as libfoo.so.3.2.1. We want it to get soname libfoo.so.3.
991 -- However, GHC does not allow overriding soname by setting linker
992 -- options, as it sets a soname of its own (namely the output
993 -- filename), after the user-supplied linker options. Hence, we have
994 -- to compile the library with the soname as its filename. We rename
995 -- the compiled binary afterwards.
997 -- This method allows to adjust the name of the library at build time
998 -- such that the correct soname can be set.
999 flibBuildName
:: LocalBuildInfo
-> ForeignLib
-> String
1000 flibBuildName lbi flib
1001 -- On linux, if a foreign-library has version data, the first digit is used
1002 -- to produce the SONAME.
1003 |
(os
, foreignLibType flib
)
1004 == (Linux
, ForeignLibNativeShared
) =
1005 let nums
= foreignLibVersion flib os
1006 in "lib" ++ nm
<.> foldl (<.>) "so" (map show (take 1 nums
))
1007 |
otherwise = flibTargetName lbi flib
1011 let (Platform _ os
') = hostPlatform lbi
1015 nm
= unUnqualComponentName
$ foreignLibName flib
1017 gbuildIsRepl
:: GBuildMode
-> Bool
1018 gbuildIsRepl
(GBuildExe _
) = False
1019 gbuildIsRepl
(GReplExe _ _
) = True
1020 gbuildIsRepl
(GBuildFLib _
) = False
1021 gbuildIsRepl
(GReplFLib _ _
) = True
1023 gbuildNeedDynamic
:: LocalBuildInfo
-> GBuildMode
-> Bool
1024 gbuildNeedDynamic lbi bm
=
1026 GBuildExe _
-> withDynExe lbi
1027 GReplExe _ _
-> withDynExe lbi
1028 GBuildFLib flib
-> withDynFLib flib
1029 GReplFLib _ flib
-> withDynFLib flib
1032 case foreignLibType flib
of
1033 ForeignLibNativeShared
->
1034 ForeignLibStandalone `
notElem` foreignLibOptions flib
1035 ForeignLibNativeStatic
->
1037 ForeignLibTypeUnknown
->
1038 cabalBug
"unknown foreign lib type"
1040 gbuildModDefFiles
:: GBuildMode
-> [FilePath]
1041 gbuildModDefFiles
(GBuildExe _
) = []
1042 gbuildModDefFiles
(GReplExe _ _
) = []
1043 gbuildModDefFiles
(GBuildFLib flib
) = foreignLibModDefFile flib
1044 gbuildModDefFiles
(GReplFLib _ flib
) = foreignLibModDefFile flib
1046 -- | "Main" module name when overridden by @ghc-options: -main-is ...@
1047 -- or 'Nothing' if no @-main-is@ flag could be found.
1049 -- In case of 'Nothing', 'Distribution.ModuleName.main' can be assumed.
1050 exeMainModuleName
:: Executable
-> Maybe ModuleName
1051 exeMainModuleName Executable
{buildInfo
= bnfo
} =
1052 -- GHC honors the last occurrence of a module name updated via -main-is
1054 -- Moreover, -main-is when parsed left-to-right can update either
1055 -- the "Main" module name, or the "main" function name, or both,
1056 -- see also 'decodeMainIsArg'.
1057 msum $ reverse $ map decodeMainIsArg
$ findIsMainArgs ghcopts
1059 ghcopts
= hcOptions GHC bnfo
1061 findIsMainArgs
[] = []
1062 findIsMainArgs
("-main-is" : arg
: rest
) = arg
: findIsMainArgs rest
1063 findIsMainArgs
(_
: rest
) = findIsMainArgs rest
1065 -- | Decode argument to '-main-is'
1067 -- Returns 'Nothing' if argument set only the function name.
1069 -- This code has been stolen/refactored from GHC's DynFlags.setMainIs
1070 -- function. The logic here is deliberately imperfect as it is
1071 -- intended to be bug-compatible with GHC's parser. See discussion in
1072 -- https://github.com/haskell/cabal/pull/4539#discussion_r118981753.
1073 decodeMainIsArg
:: String -> Maybe ModuleName
1075 | headOf main_fn
isLower =
1076 -- The arg looked like "Foo.Bar.baz"
1077 Just
(ModuleName
.fromString main_mod
)
1078 | headOf arg
isUpper -- The arg looked like "Foo" or "Foo.Bar"
1080 Just
(ModuleName
.fromString arg
)
1081 |
otherwise -- The arg looked like "baz"
1085 headOf
:: String -> (Char -> Bool) -> Bool
1086 headOf str
pred' = any pred' (safeHead str
)
1088 (main_mod
, main_fn
) = splitLongestPrefix arg
(== '.')
1090 splitLongestPrefix
:: String -> (Char -> Bool) -> (String, String)
1091 splitLongestPrefix str
pred'
1092 |
null r_pre
= (str
, [])
1093 |
otherwise = (reverse (safeTail r_pre
), reverse r_suf
)
1095 -- 'safeTail' drops the char satisfying 'pred'
1096 (r_suf
, r_pre
) = break pred' (reverse str
)
1098 -- | A collection of:
1100 -- * C++ input files
1101 -- * GHC input files
1102 -- * GHC input modules
1104 -- Used to correctly build and link sources.
1105 data BuildSources
= BuildSources
1106 { cSourcesFiles
:: [FilePath]
1107 , cxxSourceFiles
:: [FilePath]
1108 , inputSourceFiles
:: [FilePath]
1109 , inputSourceModules
:: [ModuleName
]
1112 -- | Locate and return the 'BuildSources' required to build and link.
1120 gbuildSources verbosity pkgId specVer tmpDir bm
=
1122 GBuildExe exe
-> exeSources exe
1123 GReplExe _ exe
-> exeSources exe
1124 GBuildFLib flib
-> return $ flibSources flib
1125 GReplFLib _ flib
-> return $ flibSources flib
1127 exeSources
:: Executable
-> IO BuildSources
1128 exeSources exe
@Executable
{buildInfo
= bnfo
, modulePath
= modPath
} = do
1129 main
<- findFileEx verbosity
(tmpDir
: map getSymbolicPath
(hsSourceDirs bnfo
)) modPath
1130 let mainModName
= fromMaybe ModuleName
.main
$ exeMainModuleName exe
1131 otherModNames
= exeModules exe
1133 -- Scripts have fakePackageId and are always Haskell but can have any extension.
1134 if isHaskell main || pkgId
== fakePackageId
1136 if specVer
< CabalSpecV2_0
&& (mainModName `
elem` otherModNames
)
1138 -- The cabal manual clearly states that `other-modules` is
1139 -- intended for non-main modules. However, there's at least one
1140 -- important package on Hackage (happy-1.19.5) which
1141 -- violates this. We workaround this here so that we don't
1142 -- invoke GHC with e.g. 'ghc --make Main src/Main.hs' which
1143 -- would result in GHC complaining about duplicate Main
1146 -- Finally, we only enable this workaround for
1147 -- specVersion < 2, as 'cabal-version:>=2.0' cabal files
1148 -- have no excuse anymore to keep doing it wrong... ;-)
1150 "Enabling workaround for Main module '"
1151 ++ prettyShow mainModName
1152 ++ "' listed in 'other-modules' illegally!"
1156 { cSourcesFiles
= cSources bnfo
1157 , cxxSourceFiles
= cxxSources bnfo
1158 , inputSourceFiles
= [main
]
1159 , inputSourceModules
= filter (/= mainModName
) $ exeModules exe
1164 { cSourcesFiles
= cSources bnfo
1165 , cxxSourceFiles
= cxxSources bnfo
1166 , inputSourceFiles
= [main
]
1167 , inputSourceModules
= exeModules exe
1171 | isCxx main
= (cSources bnfo
, main
: cxxSources bnfo
)
1172 -- if main is not a Haskell source
1173 -- and main is not a C++ source
1174 -- then we assume that it is a C source
1175 |
otherwise = (main
: cSources bnfo
, cxxSources bnfo
)
1178 { cSourcesFiles
= csf
1179 , cxxSourceFiles
= cxxsf
1180 , inputSourceFiles
= []
1181 , inputSourceModules
= exeModules exe
1184 flibSources
:: ForeignLib
-> BuildSources
1185 flibSources flib
@ForeignLib
{foreignLibBuildInfo
= bnfo
} =
1187 { cSourcesFiles
= cSources bnfo
1188 , cxxSourceFiles
= cxxSources bnfo
1189 , inputSourceFiles
= []
1190 , inputSourceModules
= foreignLibModules flib
1193 isCxx
:: FilePath -> Bool
1194 isCxx fp
= elem (takeExtension fp
) [".cpp", ".cxx", ".c++"]
1196 -- | FilePath has a Haskell extension: .hs or .lhs
1197 isHaskell
:: FilePath -> Bool
1198 isHaskell fp
= elem (takeExtension fp
) [".hs", ".lhs"]
1200 -- | Generic build function. See comment for 'GBuildMode'.
1204 -> PackageDescription
1207 -> ComponentLocalBuildInfo
1209 gbuild verbosity numJobs pkg_descr lbi bm clbi
= do
1210 (ghcjsProg
, _
) <- requireProgram verbosity ghcjsProgram
(withPrograms lbi
)
1211 let replFlags
= case bm
of
1212 GReplExe flags _
-> flags
1213 GReplFLib flags _
-> flags
1214 GBuildExe
{} -> mempty
1215 GBuildFLib
{} -> mempty
1217 platform
= hostPlatform lbi
1218 runGhcProg
= runGHC verbosity ghcjsProg comp platform
1220 let (bnfo
, threaded
) = case bm
of
1221 GBuildFLib _
-> popThreadedFlag
(gbuildInfo bm
)
1222 _
-> (gbuildInfo bm
, False)
1224 -- the name that GHC really uses (e.g., with .exe on Windows for executables)
1225 let targetName
= gbuildTargetName lbi bm
1226 let targetDir
= buildDir lbi
</> (gbuildName bm
)
1227 let tmpDir
= targetDir
</> (gbuildName bm
++ "-tmp")
1228 createDirectoryIfMissingVerbose verbosity
True targetDir
1229 createDirectoryIfMissingVerbose verbosity
True tmpDir
1231 -- TODO: do we need to put hs-boot files into place for mutually recursive
1232 -- modules? FIX: what about exeName.hi-boot?
1234 -- Determine if program coverage should be enabled and if so, what
1235 -- '-hpcdir' should be.
1236 let isCoverageEnabled
= exeCoverage lbi
1238 | gbuildIsRepl bm
= mempty
-- HPC is not supported in ghci
1239 | isCoverageEnabled
= toFlag
$ Hpc
.mixDir
(tmpDir
</> extraCompilationArtifacts
) way
1240 |
otherwise = mempty
1242 rpaths
<- getRPaths lbi clbi
1243 buildSources
<- gbuildSources verbosity
(package pkg_descr
) (specVersion pkg_descr
) tmpDir bm
1245 let cSrcs
= cSourcesFiles buildSources
1246 cxxSrcs
= cxxSourceFiles buildSources
1247 inputFiles
= inputSourceFiles buildSources
1248 inputModules
= inputSourceModules buildSources
1249 isGhcDynamic
= isDynamic comp
1250 dynamicTooSupported
= supportsDynamicToo comp
1251 cObjs
= map (`replaceExtension` objExtension
) cSrcs
1252 cxxObjs
= map (`replaceExtension` objExtension
) cxxSrcs
1253 needDynamic
= gbuildNeedDynamic lbi bm
1254 needProfiling
= withProfExe lbi
1256 -- build executables
1257 buildRunner
= case clbi
of
1258 LibComponentLocalBuildInfo
{} -> False
1259 FLibComponentLocalBuildInfo
{} -> False
1260 ExeComponentLocalBuildInfo
{} -> True
1261 TestComponentLocalBuildInfo
{} -> True
1262 BenchComponentLocalBuildInfo
{} -> True
1264 (componentGhcOptions verbosity lbi bnfo clbi tmpDir
)
1266 { ghcOptMode
= toFlag GhcModeMake
1267 , ghcOptInputFiles
=
1269 if package pkg_descr
== fakePackageId
1270 then filter isHaskell inputFiles
1272 , ghcOptInputScripts
=
1274 if package pkg_descr
== fakePackageId
1275 then filter (not . isHaskell
) inputFiles
1277 , ghcOptInputModules
= toNubListR inputModules
1278 , -- for all executable components (exe/test/bench),
1279 -- GHCJS must be passed the "-build-runner" option
1282 then ["-build-runner"]
1288 { ghcOptDynLinkMode
= toFlag GhcStaticOnly
1289 , ghcOptHPCDir
= hpcdir Hpc
.Vanilla
1294 { ghcOptProfilingMode
= toFlag
True
1295 , ghcOptProfilingAuto
=
1296 Internal
.profDetailLevelFlag
1298 (withProfExeDetail lbi
)
1299 , ghcOptHiSuffix
= toFlag
"p_hi"
1300 , ghcOptObjSuffix
= toFlag
"p_o"
1301 , ghcOptExtra
= hcProfOptions GHC bnfo
1302 , ghcOptHPCDir
= hpcdir Hpc
.Prof
1307 { ghcOptDynLinkMode
= toFlag GhcDynamicOnly
1308 , -- TODO: Does it hurt to set -fPIC for executables?
1309 ghcOptFPic
= toFlag
True
1310 , ghcOptHiSuffix
= toFlag
"dyn_hi"
1311 , ghcOptObjSuffix
= toFlag
"dyn_o"
1312 , ghcOptExtra
= hcSharedOptions GHC bnfo
1313 , ghcOptHPCDir
= hpcdir Hpc
.Dyn
1318 { ghcOptDynLinkMode
= toFlag GhcStaticAndDynamic
1319 , ghcOptDynHiSuffix
= toFlag
"dyn_hi"
1320 , ghcOptDynObjSuffix
= toFlag
"dyn_o"
1321 , ghcOptHPCDir
= hpcdir Hpc
.Dyn
1325 { ghcOptLinkOptions
= PD
.ldOptions bnfo
1326 , ghcOptLinkLibs
= extraLibs bnfo
1327 , ghcOptLinkLibPath
= toNubListR
$ extraLibDirs bnfo
1328 , ghcOptLinkFrameworks
=
1331 , ghcOptLinkFrameworkDirs
=
1333 PD
.extraFrameworkDirs bnfo
1334 , ghcOptInputFiles
=
1336 [tmpDir
</> x | x
<- cObjs
++ cxxObjs
]
1340 { ghcOptRPaths
= rpaths
1345 Internal
.filterGhciFlags
1346 (ghcOptExtra baseOpts
)
1349 -- For a normal compile we do separate invocations of ghc for
1350 -- compiling as for linking. But for repl we have to do just
1351 -- the one invocation, so that one has to include all the
1352 -- linker stuff too, like -l flags and any .o files from C
1354 `mappend` linkerOpts
1356 { ghcOptMode
= toFlag GhcModeInteractive
1357 , ghcOptOptimisation
= toFlag GhcNoOptimisation
1360 | needProfiling
= profOpts
1361 | needDynamic
= dynOpts
1362 |
otherwise = staticOpts
1364 | useDynToo
= dynTooOpts
1365 |
otherwise = commonOpts
1366 withStaticExe
= not needProfiling
&& not needDynamic
1368 -- For building exe's that use TH with -prof or -dynamic we actually have
1369 -- to build twice, once without -prof/-dynamic and then again with
1370 -- -prof/-dynamic. This is because the code that TH needs to run at
1371 -- compile time needs to be the vanilla ABI so it can be loaded up and run
1373 -- With dynamic-by-default GHC the TH object files loaded at compile-time
1374 -- need to be .dyn_o instead of .o.
1375 doingTH
= usesTemplateHaskellOrQQ bnfo
1376 -- Should we use -dynamic-too instead of compiling twice?
1382 && null (hcSharedOptions GHC bnfo
)
1384 | isGhcDynamic
= dynOpts
1385 |
otherwise = staticOpts
1387 | gbuildIsRepl bm
= False
1389 | isGhcDynamic
= doingTH
&& (needProfiling || withStaticExe
)
1390 |
otherwise = doingTH
&& (needProfiling || needDynamic
)
1392 -- Build static/dynamic object files for TH, if needed.
1396 { ghcOptNoLink
= toFlag
True
1397 , ghcOptNumJobs
= numJobs
1400 -- Do not try to build anything if there are no input files.
1401 -- This can happen if the cabal file ends up with only cSrcs
1402 -- but no Haskell modules.
1404 ( (null inputFiles
&& null inputModules
)
1409 { ghcOptNoLink
= toFlag
True
1410 , ghcOptNumJobs
= numJobs
1413 -- build any C++ sources
1414 unless (null cxxSrcs
) $ do
1415 info verbosity
"Building C++ Sources..."
1419 Internal
.componentCxxGhcOptions
1428 then -- Dynamic GHC requires C++ sources to be built
1429 -- with -fPIC for REPL to work. See #2207.
1430 baseCxxOpts
{ghcOptFPic
= toFlag
True}
1435 { ghcOptProfilingMode
= toFlag
True
1440 { ghcOptFPic
= toFlag
True
1441 , ghcOptDynLinkMode
= toFlag GhcDynamicOnly
1444 | needProfiling
= profCxxOpts
1445 | needDynamic
= sharedCxxOpts
1446 |
otherwise = vanillaCxxOpts
1447 -- TODO: Placing all Haskell, C, & C++ objects in a single directory
1448 -- Has the potential for file collisions. In general we would
1449 -- consider this a user error. However, we should strive to
1450 -- add a warning if this occurs.
1451 odir
= fromFlag
(ghcOptObjDir opts
)
1452 createDirectoryIfMissingVerbose verbosity
True odir
1453 needsRecomp
<- checkNeedsRecompilation filename opts
1456 | filename
<- cxxSrcs
1459 -- build any C sources
1460 unless (null cSrcs
) $ do
1461 info verbosity
"Building C Sources..."
1465 Internal
.componentCcGhcOptions
1474 then -- Dynamic GHC requires C sources to be built
1475 -- with -fPIC for REPL to work. See #2207.
1476 baseCcOpts
{ghcOptFPic
= toFlag
True}
1481 { ghcOptProfilingMode
= toFlag
True
1486 { ghcOptFPic
= toFlag
True
1487 , ghcOptDynLinkMode
= toFlag GhcDynamicOnly
1490 | needProfiling
= profCcOpts
1491 | needDynamic
= sharedCcOpts
1492 |
otherwise = vanillaCcOpts
1493 odir
= fromFlag
(ghcOptObjDir opts
)
1494 createDirectoryIfMissingVerbose verbosity
True odir
1495 needsRecomp
<- checkNeedsRecompilation filename opts
1501 -- TODO: problem here is we need the .c files built first, so we can load them
1502 -- with ghci, but .c files can depend on .h files generated by ghc by ffi
1505 GReplExe _ _
-> runGhcProg replOpts
1506 GReplFLib _ _
-> runGhcProg replOpts
1510 `mappend` linkerOpts
1512 { ghcOptLinkNoHsMain
= toFlag
(null inputFiles
)
1514 `mappend`
(if withDynExe lbi
then dynLinkerOpts
else mempty
)
1516 info verbosity
"Linking..."
1517 -- Work around old GHCs not relinking in this
1518 -- situation, see #3294
1519 let target
= targetDir
</> targetName
1520 when (compilerVersion comp
< mkVersion
[7, 7]) $ do
1521 e
<- doesFileExist target
1522 when e
(removeFile target
)
1523 runGhcProg linkOpts
{ghcOptOutputFile
= toFlag target
}
1524 GBuildFLib flib
-> do
1525 let rtsInfo
= extractRtsInfo lbi
1530 then dynRtsThreadedLib
(rtsDynamicInfo rtsInfo
)
1531 else dynRtsVanillaLib
(rtsDynamicInfo rtsInfo
)
1534 then statRtsThreadedLib
(rtsStaticInfo rtsInfo
)
1535 else statRtsVanillaLib
(rtsStaticInfo rtsInfo
)
1537 linkOpts
= case foreignLibType flib
of
1538 ForeignLibNativeShared
->
1540 `mappend` linkerOpts
1541 `mappend` dynLinkerOpts
1543 { ghcOptLinkNoHsMain
= toFlag
True
1544 , ghcOptShared
= toFlag
True
1545 , ghcOptLinkLibs
= rtsOptLinkLibs
1546 , ghcOptLinkLibPath
= toNubListR
$ rtsLibPaths rtsInfo
1547 , ghcOptFPic
= toFlag
True
1548 , ghcOptLinkModDefFiles
= toNubListR
$ gbuildModDefFiles bm
1550 ForeignLibNativeStatic
->
1551 -- this should be caught by buildFLib
1552 -- (and if we do implement this, we probably don't even want to call
1553 -- ghc here, but rather Ar.createArLibArchive or something)
1554 cabalBug
"static libraries not yet implemented"
1555 ForeignLibTypeUnknown
->
1556 cabalBug
"unknown foreign lib type"
1557 -- We build under a (potentially) different filename to set a
1558 -- soname on supported platforms. See also the note for
1560 info verbosity
"Linking..."
1561 let buildName
= flibBuildName lbi flib
1562 runGhcProg linkOpts
{ghcOptOutputFile
= toFlag
(targetDir
</> buildName
)}
1563 renameFile (targetDir
</> buildName
) (targetDir
</> targetName
)
1565 data DynamicRtsInfo
= DynamicRtsInfo
1566 { dynRtsVanillaLib
:: FilePath
1567 , dynRtsThreadedLib
:: FilePath
1568 , dynRtsDebugLib
:: FilePath
1569 , dynRtsEventlogLib
:: FilePath
1570 , dynRtsThreadedDebugLib
:: FilePath
1571 , dynRtsThreadedEventlogLib
:: FilePath
1574 data StaticRtsInfo
= StaticRtsInfo
1575 { statRtsVanillaLib
:: FilePath
1576 , statRtsThreadedLib
:: FilePath
1577 , statRtsDebugLib
:: FilePath
1578 , statRtsEventlogLib
:: FilePath
1579 , statRtsThreadedDebugLib
:: FilePath
1580 , statRtsThreadedEventlogLib
:: FilePath
1581 , statRtsProfilingLib
:: FilePath
1582 , statRtsThreadedProfilingLib
:: FilePath
1585 data RtsInfo
= RtsInfo
1586 { rtsDynamicInfo
:: DynamicRtsInfo
1587 , rtsStaticInfo
:: StaticRtsInfo
1588 , rtsLibPaths
:: [FilePath]
1591 -- | Extract (and compute) information about the RTS library
1593 -- TODO: This hardcodes the name as @HSrts-ghc<version>@. I don't know if we can
1594 -- find this information somewhere. We can lookup the 'hsLibraries' field of
1595 -- 'InstalledPackageInfo' but it will tell us @["HSrts", "Cffi"]@, which
1596 -- doesn't really help.
1597 extractRtsInfo
:: LocalBuildInfo
-> RtsInfo
1598 extractRtsInfo lbi
=
1599 case PackageIndex
.lookupPackageName
(installedPkgs lbi
) (mkPackageName
"rts") of
1600 [(_
, [rts
])] -> aux rts
1601 _otherwise
-> error "No (or multiple) ghc rts package is registered"
1603 aux
:: InstalledPackageInfo
-> RtsInfo
1608 { dynRtsVanillaLib
= withGhcVersion
"HSrts"
1609 , dynRtsThreadedLib
= withGhcVersion
"HSrts_thr"
1610 , dynRtsDebugLib
= withGhcVersion
"HSrts_debug"
1611 , dynRtsEventlogLib
= withGhcVersion
"HSrts_l"
1612 , dynRtsThreadedDebugLib
= withGhcVersion
"HSrts_thr_debug"
1613 , dynRtsThreadedEventlogLib
= withGhcVersion
"HSrts_thr_l"
1617 { statRtsVanillaLib
= "HSrts"
1618 , statRtsThreadedLib
= "HSrts_thr"
1619 , statRtsDebugLib
= "HSrts_debug"
1620 , statRtsEventlogLib
= "HSrts_l"
1621 , statRtsThreadedDebugLib
= "HSrts_thr_debug"
1622 , statRtsThreadedEventlogLib
= "HSrts_thr_l"
1623 , statRtsProfilingLib
= "HSrts_p"
1624 , statRtsThreadedProfilingLib
= "HSrts_thr_p"
1626 , rtsLibPaths
= InstalledPackageInfo
.libraryDirs rts
1628 withGhcVersion
= (++ ("-ghc" ++ prettyShow
(compilerVersion
(compiler lbi
))))
1630 -- | Returns True if the modification date of the given source file is newer than
1631 -- the object file we last compiled for it, or if no object file exists yet.
1632 checkNeedsRecompilation
:: FilePath -> GhcOptions
-> IO Bool
1633 checkNeedsRecompilation filename opts
= filename `moreRecentFile` oname
1635 oname
= getObjectFileName filename opts
1637 -- | Finds the object file name of the given source file
1638 getObjectFileName
:: FilePath -> GhcOptions
-> FilePath
1639 getObjectFileName filename opts
= oname
1641 odir
= fromFlag
(ghcOptObjDir opts
)
1642 oext
= fromFlagOrDefault
"o" (ghcOptObjSuffix opts
)
1643 oname
= odir
</> replaceExtension filename oext
1645 -- | Calculate the RPATHs for the component we are building.
1647 -- Calculates relative RPATHs when 'relocatable' is set.
1650 -> ComponentLocalBuildInfo
1651 -- ^ Component we are building
1652 -> IO (NubListR
FilePath)
1653 getRPaths lbi clbi | supportRPaths hostOS
= do
1654 libraryPaths
<- depLibraryPaths
False (relocatable lbi
) lbi clbi
1655 let hostPref
= case hostOS
of
1656 OSX
-> "@loader_path"
1658 relPath p
= if isRelative p
then hostPref
</> p
else p
1659 rpaths
= toNubListR
(map relPath libraryPaths
)
1662 (Platform _ hostOS
) = hostPlatform lbi
1663 compid
= compilerId
. compiler
$ lbi
1665 -- The list of RPath-supported operating systems below reflects the
1666 -- platforms on which Cabal's RPATH handling is tested. It does _NOT_
1667 -- reflect whether the OS supports RPATH.
1669 -- E.g. when this comment was written, the *BSD operating systems were
1670 -- untested with regards to Cabal RPATH handling, and were hence set to
1671 -- 'False', while those operating systems themselves do support RPATH.
1672 supportRPaths Linux
= True
1673 supportRPaths Windows
= False
1674 supportRPaths OSX
= True
1675 supportRPaths FreeBSD
=
1677 CompilerId GHC ver | ver
>= mkVersion
[7, 10, 2] -> True
1679 supportRPaths OpenBSD
= False
1680 supportRPaths NetBSD
= False
1681 supportRPaths DragonFly
= False
1682 supportRPaths Solaris
= False
1683 supportRPaths AIX
= False
1684 supportRPaths HPUX
= False
1685 supportRPaths IRIX
= False
1686 supportRPaths HaLVM
= False
1687 supportRPaths IOS
= False
1688 supportRPaths Android
= False
1689 supportRPaths Ghcjs
= False
1690 supportRPaths Wasi
= False
1691 supportRPaths Hurd
= True
1692 supportRPaths Haiku
= False
1693 supportRPaths
(OtherOS _
) = False
1694 -- Do _not_ add a default case so that we get a warning here when a new OS
1697 getRPaths _ _
= return mempty
1699 -- | Remove the "-threaded" flag when building a foreign library, as it has no
1700 -- effect when used with "-shared". Returns the updated 'BuildInfo', along
1701 -- with whether or not the flag was present, so we can use it to link against
1702 -- the appropriate RTS on our own.
1703 popThreadedFlag
:: BuildInfo
-> (BuildInfo
, Bool)
1704 popThreadedFlag bi
=
1705 ( bi
{options
= filterHcOptions
(/= "-threaded") (options bi
)}
1706 , hasThreaded
(options bi
)
1711 -> PerCompilerFlavor
[String]
1712 -> PerCompilerFlavor
[String]
1713 filterHcOptions p
(PerCompilerFlavor ghc ghcjs
) =
1714 PerCompilerFlavor
(filter p ghc
) ghcjs
1716 hasThreaded
:: PerCompilerFlavor
[String] -> Bool
1717 hasThreaded
(PerCompilerFlavor ghc _
) = elem "-threaded" ghc
1719 -- | Extracts a String representing a hash of the ABI of a built
1720 -- library. It can fail if the library has not yet been built.
1723 -> PackageDescription
1726 -> ComponentLocalBuildInfo
1728 libAbiHash verbosity _pkg_descr lbi lib clbi
= do
1730 libBi
= libBuildInfo lib
1732 platform
= hostPlatform lbi
1734 (componentGhcOptions verbosity lbi libBi clbi
(componentBuildDir lbi clbi
))
1736 { ghcOptMode
= toFlag GhcModeAbiHash
1737 , ghcOptInputModules
= toNubListR
$ exposedModules lib
1742 { ghcOptDynLinkMode
= toFlag GhcDynamicOnly
1743 , ghcOptFPic
= toFlag
True
1744 , ghcOptHiSuffix
= toFlag
"js_dyn_hi"
1745 , ghcOptObjSuffix
= toFlag
"js_dyn_o"
1746 , ghcOptExtra
= hcSharedOptions GHC libBi
1751 { ghcOptProfilingMode
= toFlag
True
1752 , ghcOptProfilingAuto
=
1753 Internal
.profDetailLevelFlag
1755 (withProfLibDetail lbi
)
1756 , ghcOptHiSuffix
= toFlag
"js_p_hi"
1757 , ghcOptObjSuffix
= toFlag
"js_p_o"
1758 , ghcOptExtra
= hcProfOptions GHC libBi
1761 | withVanillaLib lbi
= vanillaArgs
1762 | withSharedLib lbi
= sharedArgs
1763 | withProfLib lbi
= profArgs
1764 |
otherwise = error "libAbiHash: Can't find an enabled library way"
1766 (ghcjsProg
, _
) <- requireProgram verbosity ghcjsProgram
(withPrograms lbi
)
1768 getProgramInvocationOutput
1770 =<< ghcInvocation verbosity ghcjsProg comp platform ghcArgs
1771 return (takeWhile (not . isSpace) hash
)
1777 -> ComponentLocalBuildInfo
1780 componentGhcOptions verbosity lbi bi clbi odir
=
1781 let opts
= Internal
.componentGhcOptions verbosity lbi bi clbi odir
1783 { ghcOptExtra
= ghcOptExtra opts `mappend` hcOptions GHCJS bi
1786 -- -----------------------------------------------------------------------------
1789 -- | Install executables for GHCJS.
1794 -- ^ Where to copy the files to
1797 -> (FilePath, FilePath)
1798 -- ^ Executable (prefix,suffix)
1799 -> PackageDescription
1807 (progprefix
, progsuffix
)
1810 createDirectoryIfMissingVerbose verbosity
True binDir
1811 let exeName
' = unUnqualComponentName
$ exeName exe
1812 exeFileName
= exeName
'
1813 fixedExeBaseName
= progprefix
++ exeName
' ++ progsuffix
1814 installBinary dest
= do
1815 runDbProgram verbosity ghcjsProgram
(withPrograms lbi
) $
1816 [ "--install-executable"
1817 , buildPref
</> exeName
' </> exeFileName
1821 ++ case (stripExes lbi
, lookupProgram stripProgram
$ withPrograms lbi
) of
1822 (True, Just strip
) -> ["-strip-program", programPath strip
]
1824 installBinary
(binDir
</> fixedExeBaseName
)
1826 -- | Install foreign library for GHC.
1831 -- ^ install location
1834 -> PackageDescription
1837 installFLib verbosity lbi targetDir builtDir _pkg flib
=
1839 (foreignLibIsShared flib
)
1842 (flibTargetName lbi flib
)
1844 install _isShared srcDir dstDir name
= do
1845 let src
= srcDir
</> name
1846 dst
= dstDir
</> name
1847 createDirectoryIfMissingVerbose verbosity
True targetDir
1848 installOrdinaryFile verbosity src dst
1850 -- | Install for ghc, .hi, .a and, if --with-ghci given, .o
1855 -- ^ install location
1857 -- ^ install location for dynamic libraries
1860 -> PackageDescription
1862 -> ComponentLocalBuildInfo
1864 installLib verbosity lbi targetDir dynlibTargetDir _builtDir _pkg lib clbi
= do
1865 whenVanilla
$ copyModuleFiles
$ Suffix
"js_hi"
1866 whenProf
$ copyModuleFiles
$ Suffix
"js_p_hi"
1867 whenShared
$ copyModuleFiles
$ Suffix
"js_dyn_hi"
1869 -- whenVanilla $ installOrdinary builtDir targetDir $ toJSLibName vanillaLibName
1870 -- whenProf $ installOrdinary builtDir targetDir $ toJSLibName profileLibName
1871 -- whenShared $ installShared builtDir dynlibTargetDir $ toJSLibName sharedLibName
1872 -- fixme do these make the correct lib names?
1876 [ installOrdinary builtDir
' targetDir
(toJSLibName
$ mkGenericStaticLibName
(l
++ f
))
1877 | l
<- getHSLibraryName
(componentUnitId clbi
) : (extraBundledLibs
(libBuildInfo lib
))
1878 , f
<- "" : extraLibFlavours
(libBuildInfo lib
)
1880 -- whenGHCi $ installOrdinary builtDir targetDir (toJSLibName ghciLibName)
1882 installOrdinary builtDir
' targetDir
(toJSLibName profileLibName
)
1883 -- whenGHCi $ installOrdinary builtDir targetDir (toJSLibName ghciProfLibName)
1889 (toJSLibName
$ mkGenericSharedLibName platform compiler_id
(l
++ f
))
1890 | l
<- getHSLibraryName uid
: extraBundledLibs
(libBuildInfo lib
)
1891 , f
<- "" : extraDynLibFlavours
(libBuildInfo lib
)
1894 builtDir
' = componentBuildDir lbi clbi
1896 install isShared isJS srcDir dstDir name
= do
1897 let src
= srcDir
</> name
1898 dst
= dstDir
</> name
1899 createDirectoryIfMissingVerbose verbosity
True dstDir
1902 then installExecutableFile verbosity src dst
1903 else installOrdinaryFile verbosity src dst
1905 when (stripLibs lbi
&& not isJS
) $
1912 installOrdinary
= install
False True
1913 installShared
= install
True True
1915 copyModuleFiles ext
=
1916 findModuleFilesEx verbosity
[builtDir
'] [ext
] (allLibModules lib clbi
)
1917 >>= installOrdinaryFiles verbosity targetDir
1919 compiler_id
= compilerId
(compiler lbi
)
1920 platform
= hostPlatform lbi
1921 uid
= componentUnitId clbi
1922 -- vanillaLibName = mkLibName uid
1923 profileLibName
= mkProfLibName uid
1924 -- sharedLibName = (mkSharedLibName (hostPlatform lbi) compiler_id) uid
1928 null (allLibModules lib clbi
)
1929 && null (cSources
(libBuildInfo lib
))
1930 && null (cxxSources
(libBuildInfo lib
))
1931 && null (jsSources
(libBuildInfo lib
))
1932 has_code
= not (componentIsIndefinite clbi
)
1933 whenHasCode
= when has_code
1934 whenVanilla
= when (hasLib
&& withVanillaLib lbi
)
1935 whenProf
= when (hasLib
&& withProfLib lbi
&& has_code
)
1936 -- whenGHCi = when (hasLib && withGHCiLib lbi && has_code)
1937 whenShared
= when (hasLib
&& withSharedLib lbi
&& has_code
)
1939 adjustExts
:: String -> String -> GhcOptions
-> GhcOptions
1940 adjustExts hiSuf objSuf opts
=
1943 { ghcOptHiSuffix
= toFlag hiSuf
1944 , ghcOptObjSuffix
= toFlag objSuf
1947 isDynamic
:: Compiler
-> Bool
1948 isDynamic
= Internal
.ghcLookupProperty
"GHC Dynamic"
1950 supportsDynamicToo
:: Compiler
-> Bool
1951 supportsDynamicToo
= Internal
.ghcLookupProperty
"Support dynamic-too"
1953 withExt
:: FilePath -> String -> FilePath
1954 withExt fp ext
= fp
<.> if takeExtension fp
/= ('.' : ext
) then ext
else ""
1956 findGhcjsGhcVersion
:: Verbosity
-> FilePath -> IO (Maybe Version
)
1957 findGhcjsGhcVersion verbosity pgm
=
1958 findProgramVersion
"--numeric-ghc-version" id verbosity pgm
1960 findGhcjsPkgGhcjsVersion
:: Verbosity
-> FilePath -> IO (Maybe Version
)
1961 findGhcjsPkgGhcjsVersion verbosity pgm
=
1962 findProgramVersion
"--numeric-ghcjs-version" id verbosity pgm
1964 -- -----------------------------------------------------------------------------
1967 hcPkgInfo
:: ProgramDb
-> HcPkg
.HcPkgInfo
1970 { HcPkg
.hcPkgProgram
= ghcjsPkgProg
1971 , HcPkg
.noPkgDbStack
= False
1972 , HcPkg
.noVerboseFlag
= False
1973 , HcPkg
.flagPackageConf
= False
1974 , HcPkg
.supportsDirDbs
= True
1975 , HcPkg
.requiresDirDbs
= ver
>= v7_10
1976 , HcPkg
.nativeMultiInstance
= ver
>= v7_10
1977 , HcPkg
.recacheMultiInstance
= True
1978 , HcPkg
.suppressFilesCheck
= True
1981 v7_10
= mkVersion
[7, 10]
1982 ghcjsPkgProg
= fromMaybe (error "GHCJS.hcPkgInfo no ghcjs program") $ lookupProgram ghcjsPkgProgram progdb
1983 ver
= fromMaybe (error "GHCJS.hcPkgInfo no ghcjs version") $ programVersion ghcjsPkgProg
1989 -> InstalledPackageInfo
1990 -> HcPkg
.RegisterOptions
1992 registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions
=
2000 pkgRoot
:: Verbosity
-> LocalBuildInfo
-> PackageDB
-> IO FilePath
2001 pkgRoot verbosity lbi
= pkgRoot
'
2003 pkgRoot
' GlobalPackageDB
=
2004 let ghcjsProg
= fromMaybe (error "GHCJS.pkgRoot: no ghcjs program") $ lookupProgram ghcjsProgram
(withPrograms lbi
)
2005 in fmap takeDirectory
(getGlobalPackageDB verbosity ghcjsProg
)
2006 pkgRoot
' UserPackageDB
= do
2007 appDir
<- getAppUserDataDirectory
"ghcjs"
2008 -- fixme correct this version
2009 let ver
= compilerVersion
(compiler lbi
)
2016 rootDir
= appDir
</> subdir
2017 -- We must create the root directory for the user package database if it
2018 -- does not yet exists. Otherwise '${pkgroot}' will resolve to a
2019 -- directory at the time of 'ghc-pkg register', and registration will
2021 createDirectoryIfMissing
True rootDir
2023 pkgRoot
' (SpecificPackageDB fp
) = return (takeDirectory fp
)
2025 -- | Get the JavaScript file name and command and arguments to run a
2026 -- program compiled by GHCJS
2027 -- the exe should be the base program name without exe extension
2031 -> (FilePath, FilePath, [String])
2034 , programPath ghcjsProg
2035 , programDefaultArgs ghcjsProg
++ programOverrideArgs ghcjsProg
++ ["--run"]
2038 script
= exe
<.> "jsexe" </> "all" <.> "js"
2039 ghcjsProg
= fromMaybe (error "GHCJS.runCmd: no ghcjs program") $ lookupProgram ghcjsProgram progdb