1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE RankNTypes #-}
4 -----------------------------------------------------------------------------
7 -- Module : Distribution.Simple.PreProcess
8 -- Copyright : (c) 2003-2005, Isaac Jones, Malcolm Wallace
11 -- Maintainer : cabal-devel@haskell.org
12 -- Portability : portable
14 -- This defines a 'PreProcessor' abstraction which represents a pre-processor
15 -- that can transform one kind of file into another. There is also a
16 -- 'PPSuffixHandler' which is a combination of a file extension and a function
17 -- for configuring a 'PreProcessor'. It defines a bunch of known built-in
18 -- preprocessors like @cpp@, @cpphs@, @c2hs@, @hsc2hs@, @happy@, @alex@ etc and
19 -- lists them in 'knownSuffixHandlers'. On top of this it provides a function
20 -- for actually preprocessing some sources given a bunch of known suffix
21 -- handlers. This module is not as good as it could be, it could really do with
22 -- a rewrite to address some of the problems we have with pre-processors.
23 module Distribution
.Simple
.PreProcess
30 , mkSimplePreProcessor
31 , runSimplePreProcessor
45 import Distribution
.Compat
.Prelude
46 import Distribution
.Compat
.Stack
49 import Distribution
.Backpack
.DescribeUnitId
50 import qualified Distribution
.InstalledPackageInfo
as Installed
51 import Distribution
.ModuleName
(ModuleName
)
52 import qualified Distribution
.ModuleName
as ModuleName
53 import Distribution
.Package
54 import Distribution
.PackageDescription
as PD
55 import Distribution
.Simple
.BuildPaths
56 import Distribution
.Simple
.CCompiler
57 import Distribution
.Simple
.Compiler
58 import Distribution
.Simple
.Errors
59 import Distribution
.Simple
.LocalBuildInfo
60 import qualified Distribution
.Simple
.PackageIndex
as PackageIndex
61 import Distribution
.Simple
.PreProcess
.Unlit
62 import Distribution
.Simple
.Program
63 import Distribution
.Simple
.Program
.ResponseFile
64 import Distribution
.Simple
.Test
.LibV09
65 import Distribution
.Simple
.Utils
66 import Distribution
.System
67 import Distribution
.Types
.PackageName
.Magic
68 import Distribution
.Utils
.Path
69 import Distribution
.Verbosity
70 import Distribution
.Version
71 import System
.Directory
(doesDirectoryExist, doesFileExist)
72 import System
.FilePath
82 import System
.Info
(arch
, os
)
84 -- | The interface to a preprocessor, which may be implemented using an
85 -- external program, but need not be. The arguments are the name of
86 -- the input file, the name of the output file and a verbosity level.
87 -- Here is a simple example that merely prepends a comment to the given
90 -- > ppTestHandler :: PreProcessor
93 -- > platformIndependent = True,
94 -- > runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->
95 -- > do info verbosity (inFile++" has been preprocessed to "++outFile)
96 -- > stuff <- readFile inFile
97 -- > writeFile outFile ("-- preprocessed as a test\n\n" ++ stuff)
98 -- > return ExitSuccess
100 -- We split the input and output file names into a base directory and the
101 -- rest of the file name. The input base dir is the path in the list of search
102 -- dirs that this file was found in. The output base dir is the build dir where
103 -- all the generated source files are put.
105 -- The reason for splitting it up this way is that some pre-processors don't
106 -- simply generate one output .hs file from one input file but have
107 -- dependencies on other generated files (notably c2hs, where building one
108 -- .hs file may require reading other .chi files, and then compiling the .hs
109 -- file may require reading a generated .h file). In these cases the generated
110 -- files need to embed relative path names to each other (eg the generated .hs
111 -- file mentions the .h file in the FFI imports). This path must be relative to
112 -- the base directory where the generated files are located, it cannot be
113 -- relative to the top level of the build tree because the compilers do not
114 -- look for .h files relative to there, ie we do not use \"-I .\", instead we
115 -- use \"-I dist\/build\" (or whatever dist dir has been set by the user)
117 -- Most pre-processors do not care of course, so mkSimplePreProcessor and
118 -- runSimplePreProcessor functions handle the simple case.
119 data PreProcessor
= PreProcessor
120 { -- Is the output of the pre-processor platform independent? eg happy output
121 -- is portable haskell but c2hs's output is platform dependent.
122 -- This matters since only platform independent generated code can be
123 -- included into a source tarball.
124 platformIndependent
:: Bool
125 , -- TODO: deal with pre-processors that have implementation dependent output
126 -- eg alex and happy have --ghc flags. However we can't really include
127 -- ghc-specific code into supposedly portable source tarballs.
131 -> [FilePath] -- Source directories
132 -> [ModuleName
] -- Module names
133 -> IO [ModuleName
] -- Sorted modules
135 -- ^ This function can reorder /all/ modules, not just those that the
136 -- require the preprocessor in question. As such, this function should be
137 -- well-behaved and not reorder modules it doesn't have dominion over!
141 :: (FilePath, FilePath) -- Location of the source file relative to a base dir
142 -> (FilePath, FilePath) -- Output file name, relative to an output base dir
143 -> Verbosity
-- verbosity
144 -> IO () -- Should exit if the preprocessor fails
147 -- | Just present the modules in the order given; this is the default and it is
148 -- appropriate for preprocessors which do not have any sort of dependencies
155 unsorted _ _ ms
= pure ms
157 -- | Function to determine paths to possible extra C sources for a
158 -- preprocessor: just takes the path to the build directory and uses
159 -- this to search for C sources with names that match the
160 -- preprocessor's output name format.
161 type PreProcessorExtras
= FilePath -> IO [FilePath]
164 :: (FilePath -> FilePath -> Verbosity
-> IO ())
165 -> (FilePath, FilePath)
166 -> (FilePath, FilePath)
171 (inBaseDir
, inRelativeFile
)
172 (outBaseDir
, outRelativeFile
)
173 verbosity
= simplePP inFile outFile verbosity
175 inFile
= normalise
(inBaseDir
</> inRelativeFile
)
176 outFile
= normalise
(outBaseDir
</> outRelativeFile
)
178 runSimplePreProcessor
184 runSimplePreProcessor pp inFile outFile verbosity
=
185 runPreProcessor pp
(".", inFile
) (".", outFile
) verbosity
187 -- | A preprocessor for turning non-Haskell files with the given extension
188 -- into plain Haskell source files.
189 type PPSuffixHandler
=
190 (String, BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
)
192 -- | Apply preprocessors to the sources from 'hsSourceDirs' for a given
193 -- component (lib, exe, or test suite).
195 -- XXX: This is terrible
197 :: PackageDescription
200 -> ComponentLocalBuildInfo
205 preprocessComponent pd comp lbi clbi isSrcDist verbosity handlers
=
206 -- Skip preprocessing for scripts since they should be regular Haskell files,
207 -- but may have no or unknown extensions.
208 when (package pd
/= fakePackageId
) $ do
209 -- NB: never report instantiation here; we'll report it properly when
215 (componentLocalName clbi
)
216 (Nothing
:: Maybe [(ModuleName
, Module
)])
218 (CLib lib
@Library
{libBuildInfo
= bi
}) -> do
220 map getSymbolicPath
(hsSourceDirs bi
)
221 ++ [autogenComponentModulesDir lbi clbi
, autogenPackageModulesDir lbi
]
222 let hndlrs
= localHandlers bi
223 mods
<- orderingFromHandlers verbosity dirs hndlrs
(allLibModules lib clbi
)
224 for_
(map ModuleName
.toFilePath mods
) $
225 pre dirs
(componentBuildDir lbi clbi
) hndlrs
226 (CFLib flib
@ForeignLib
{foreignLibBuildInfo
= bi
, foreignLibName
= nm
}) -> do
227 let nm
' = unUnqualComponentName nm
228 let flibDir
= buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
230 map getSymbolicPath
(hsSourceDirs bi
)
231 ++ [ autogenComponentModulesDir lbi clbi
232 , autogenPackageModulesDir lbi
234 let hndlrs
= localHandlers bi
235 mods
<- orderingFromHandlers verbosity dirs hndlrs
(foreignLibModules flib
)
236 for_
(map ModuleName
.toFilePath mods
) $
237 pre dirs flibDir hndlrs
238 (CExe exe
@Executable
{buildInfo
= bi
, exeName
= nm
}) -> do
239 let nm
' = unUnqualComponentName nm
240 let exeDir
= buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
242 map getSymbolicPath
(hsSourceDirs bi
)
243 ++ [ autogenComponentModulesDir lbi clbi
244 , autogenPackageModulesDir lbi
246 let hndlrs
= localHandlers bi
247 mods
<- orderingFromHandlers verbosity dirs hndlrs
(otherModules bi
)
248 for_
(map ModuleName
.toFilePath mods
) $
249 pre dirs exeDir hndlrs
250 pre
(map getSymbolicPath
(hsSourceDirs bi
)) exeDir
(localHandlers bi
) $
251 dropExtensions
(modulePath exe
)
252 CTest test
@TestSuite
{testName
= nm
} -> do
253 let nm
' = unUnqualComponentName nm
254 case testInterface test
of
255 TestSuiteExeV10 _ f
->
256 preProcessTest test f
$ buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
257 TestSuiteLibV09 _ _
-> do
263 writeSimpleTestStub test testDir
264 preProcessTest test
(stubFilePath test
) testDir
265 TestSuiteUnsupported tt
->
266 dieWithException verbosity
$ NoSupportForPreProcessingTest tt
267 CBench bm
@Benchmark
{benchmarkName
= nm
} -> do
268 let nm
' = unUnqualComponentName nm
269 case benchmarkInterface bm
of
270 BenchmarkExeV10 _ f
->
271 preProcessBench bm f
$ buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
272 BenchmarkUnsupported tt
->
273 dieWithException verbosity
$ NoSupportForPreProcessingBenchmark tt
275 orderingFromHandlers v d hndlrs mods
=
276 foldM (\acc
(_
, pp
) -> ppOrdering pp v d acc
) mods hndlrs
277 builtinHaskellSuffixes
= ["hs", "lhs", "hsig", "lhsig"]
278 builtinCSuffixes
= cSourceExtensions
279 builtinSuffixes
= builtinHaskellSuffixes
++ builtinCSuffixes
280 localHandlers bi
= [(ext
, h bi lbi clbi
) |
(ext
, h
) <- handlers
]
281 pre dirs dir lhndlrs fp
=
282 preprocessFile
(map unsafeMakeSymbolicPath dirs
) dir isSrcDist fp verbosity builtinSuffixes lhndlrs
True
283 preProcessTest test
=
289 (benchmarkBuildInfo bm
)
290 (benchmarkModules bm
)
298 preProcessComponent bi modules exePath dir
= do
299 let biHandlers
= localHandlers bi
301 map getSymbolicPath
(hsSourceDirs bi
)
302 ++ [ autogenComponentModulesDir lbi clbi
303 , autogenPackageModulesDir lbi
307 (map unsafeMakeSymbolicPath sourceDirs
)
310 (ModuleName
.toFilePath modu
)
317 -- XXX: what we do here (re SymbolicPath dir)
318 -- XXX: 2020-10-15 do we rely here on CWD being the PackageDir?
319 -- Note we don't fail on missing in this case, because the main file may be generated later (i.e. by a test code generator)
321 (unsafeMakeSymbolicPath dir
: hsSourceDirs bi
)
324 (dropExtensions
$ exePath
)
330 -- TODO: try to list all the modules that could not be found
331 -- not just the first one. It's annoying and slow due to the need
332 -- to reconfigure after editing the .cabal file each time.
334 -- | Find the first extension of the file that exists, and preprocess it
337 :: [SymbolicPath PackageDir SourceDir
]
338 -- ^ source directories
342 -- ^ preprocess for sdist
344 -- ^ module file name
348 -- ^ builtin suffixes
349 -> [(String, PreProcessor
)]
350 -- ^ possible preprocessors
352 -- ^ fail on missing file
354 preprocessFile searchLoc buildLoc forSDist baseFile verbosity builtinSuffixes handlers failOnMissing
= do
355 -- look for files in the various source dirs with this module name
356 -- and a file extension of a known preprocessor
357 psrcFiles
<- findFileWithExtension
' (map fst handlers
) (map getSymbolicPath searchLoc
) baseFile
359 -- no preprocessor file exists, look for an ordinary source file
360 -- just to make sure one actually exists at all for this module.
361 -- Note: by looking in the target/output build dir too, we allow
362 -- source files to appear magically in the target build dir without
363 -- any corresponding "real" source file. This lets custom Setup.hs
364 -- files generate source modules directly into the build dir without
365 -- the rest of the build system being aware of it (somewhat dodgy)
367 bsrcFiles
<- findFileWithExtension builtinSuffixes
(buildLoc
: map getSymbolicPath searchLoc
) baseFile
368 case (bsrcFiles
, failOnMissing
) of
370 dieWithException verbosity
$
371 CantFindSourceForPreProcessFile
$
372 "can't find source for "
375 ++ intercalate
", " (map getSymbolicPath searchLoc
)
377 -- found a pre-processable file in one of the source dirs
378 Just
(psrcLoc
, psrcRelFile
) -> do
379 let (srcStem
, ext
) = splitExtension psrcRelFile
380 psrcFile
= psrcLoc
</> psrcRelFile
383 (error "Distribution.Simple.PreProcess: Just expected")
384 (lookup (safeTail ext
) handlers
)
385 -- Preprocessing files for 'sdist' is different from preprocessing
386 -- for 'build'. When preprocessing for sdist we preprocess to
387 -- avoid that the user has to have the preprocessors available.
388 -- ATM, we don't have a way to specify which files are to be
389 -- preprocessed and which not, so for sdist we only process
390 -- platform independent files and put them into the 'buildLoc'
391 -- (which we assume is set to the temp. directory that will become
393 -- TODO: eliminate sdist variant, just supply different handlers
394 when (not forSDist || forSDist
&& platformIndependent pp
) $ do
395 -- look for existing pre-processed source file in the dest dir to
396 -- see if we really have to re-run the preprocessor.
397 ppsrcFiles
<- findFileWithExtension builtinSuffixes
[buildLoc
] baseFile
398 recomp
<- case ppsrcFiles
of
399 Nothing
-> return True
401 psrcFile `moreRecentFile` ppsrcFile
403 let destDir
= buildLoc
</> dirName srcStem
404 createDirectoryIfMissingVerbose verbosity
True destDir
405 runPreProcessorWithHsBootHack
407 (psrcLoc
, psrcRelFile
)
408 (buildLoc
, srcStem
<.> "hs")
410 dirName
= takeDirectory
412 -- FIXME: This is a somewhat nasty hack. GHC requires that hs-boot files
413 -- be in the same place as the hs files, so if we put the hs file in dist/
414 -- then we need to copy the hs-boot file there too. This should probably be
415 -- done another way. Possibly we should also be looking for .lhs-boot
416 -- files, but I think that preprocessors only produce .hs files.
417 runPreProcessorWithHsBootHack
419 (inBaseDir
, inRelativeFile
)
420 (outBaseDir
, outRelativeFile
) = do
423 (inBaseDir
, inRelativeFile
)
424 (outBaseDir
, outRelativeFile
)
427 exists
<- doesFileExist inBoot
428 when exists
$ copyFileVerbose verbosity inBoot outBoot
430 inBoot
= replaceExtension inFile
"hs-boot"
431 outBoot
= replaceExtension outFile
"hs-boot"
433 inFile
= normalise
(inBaseDir
</> inRelativeFile
)
434 outFile
= normalise
(outBaseDir
</> outRelativeFile
)
436 -- ------------------------------------------------------------
438 -- * known preprocessors
440 -- ------------------------------------------------------------
442 ppGreenCard
:: BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
443 ppGreenCard _ lbi _
=
445 { platformIndependent
= False
446 , ppOrdering
= unsorted
447 , runPreProcessor
= mkSimplePreProcessor
$ \inFile outFile verbosity
->
452 (["-tffi", "-o" ++ outFile
, inFile
])
455 -- This one is useful for preprocessors that can't handle literate source.
456 -- We also need a way to chain preprocessors.
457 ppUnlit
:: PreProcessor
460 { platformIndependent
= True
461 , ppOrdering
= unsorted
462 , runPreProcessor
= mkSimplePreProcessor
$ \inFile outFile verbosity
->
463 withUTF8FileContents inFile
$ \contents
->
464 either (writeUTF8File outFile
) (dieWithException verbosity
) (unlit inFile contents
)
467 ppCpp
:: BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
470 ppCpp
' :: [String] -> BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
471 ppCpp
' extraArgs bi lbi clbi
=
472 case compilerFlavor
(compiler lbi
) of
473 GHC
-> ppGhcCpp ghcProgram
(const True) args bi lbi clbi
474 GHCJS
-> ppGhcCpp ghcjsProgram
(const True) args bi lbi clbi
475 _
-> ppCpphs args bi lbi clbi
477 cppArgs
= getCppOptions bi lbi
478 args
= cppArgs
++ extraArgs
486 -> ComponentLocalBuildInfo
488 ppGhcCpp program xHs extraArgs _bi lbi clbi
=
490 { platformIndependent
= False
491 , ppOrdering
= unsorted
492 , runPreProcessor
= mkSimplePreProcessor
$ \inFile outFile verbosity
-> do
493 (prog
, version
, _
) <-
494 requireProgramVersion
499 runProgram verbosity prog
$
501 -- This is a bit of an ugly hack. We're going to
502 -- unlit the file ourselves later on if appropriate,
503 -- so we need GHC not to unlit it now or it'll get
504 -- double-unlitted. In the future we might switch to
505 -- using cpphs --unlit instead.
506 ++ (if xHs version
then ["-x", "hs"] else [])
507 ++ ["-optP-include", "-optP" ++ (autogenComponentModulesDir lbi clbi
</> cppHeaderName
)]
508 ++ ["-o", outFile
, inFile
]
512 ppCpphs
:: [String] -> BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
513 ppCpphs extraArgs _bi lbi clbi
=
515 { platformIndependent
= False
516 , ppOrdering
= unsorted
517 , runPreProcessor
= mkSimplePreProcessor
$ \inFile outFile verbosity
-> do
518 (cpphsProg
, cpphsVersion
, _
) <-
519 requireProgramVersion
524 runProgram verbosity cpphsProg
$
529 : ( if cpphsVersion
>= mkVersion
[1, 6]
530 then ["--include=" ++ (autogenComponentModulesDir lbi clbi
</> cppHeaderName
)]
536 ppHsc2hs
:: BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
537 ppHsc2hs bi lbi clbi
=
539 { platformIndependent
= False
540 , ppOrdering
= unsorted
541 , runPreProcessor
= mkSimplePreProcessor
$ \inFile outFile verbosity
-> do
542 (gccProg
, _
) <- requireProgram verbosity gccProgram
(withPrograms lbi
)
543 (hsc2hsProg
, hsc2hsVersion
, _
) <-
544 requireProgramVersion
549 -- See Trac #13896 and https://github.com/haskell/cabal/issues/3122.
550 let isCross
= hostPlatform lbi
/= buildPlatform
551 prependCrossFlags
= if isCross
then ("-x" :) else id
552 let hsc2hsSupportsResponseFiles
= hsc2hsVersion
>= mkVersion
[0, 68, 4]
553 pureArgs
= genPureArgs hsc2hsVersion gccProg inFile outFile
554 if hsc2hsSupportsResponseFiles
558 defaultTempFileOptions
559 (takeDirectory outFile
)
560 "hsc2hs-response.txt"
563 ( \responseFileName
->
564 runProgram verbosity hsc2hsProg
(prependCrossFlags
["@" ++ responseFileName
])
566 else runProgram verbosity hsc2hsProg
(prependCrossFlags pureArgs
)
569 -- Returns a list of command line arguments that can either be passed
570 -- directly, or via a response file.
571 genPureArgs
:: Version
-> ConfiguredProgram
-> String -> String -> [String]
572 genPureArgs hsc2hsVersion gccProg inFile outFile
=
573 -- Additional gcc options
576 programDefaultArgs gccProg
577 ++ programOverrideArgs gccProg
579 ++ [ "--lflag=" ++ opt
581 programDefaultArgs gccProg
582 ++ programOverrideArgs gccProg
585 ++ [ what
++ "=-F" ++ opt
587 , opt
<- nub (concatMap Installed
.frameworkDirs pkgs
)
588 , what
<- ["--cflag", "--lflag"]
590 ++ [ "--lflag=" ++ arg
592 , opt
<- PD
.frameworks bi
++ concatMap Installed
.frameworks pkgs
593 , arg
<- ["-framework", opt
]
595 -- Note that on ELF systems, wherever we use -L, we must also use -R
596 -- because presumably that -L dir is not on the normal path for the
597 -- system's dynamic linker. This is needed because hsc2hs works by
598 -- compiling a C program and then running it.
600 ++ ["--cflag=" ++ opt | opt
<- platformDefines lbi
]
601 -- Options from the current package:
602 ++ ["--cflag=-I" ++ dir | dir
<- PD
.includeDirs bi
]
603 ++ ["--cflag=-I" ++ buildDir lbi
</> dir | dir
<- PD
.includeDirs bi
]
604 ++ [ "--cflag=" ++ opt
608 -- hsc2hs uses the C ABI
609 -- We assume that there are only C sources
610 -- and C++ functions are exported via a C
611 -- interface and wrapped in a C source file.
612 -- Therefore we do not supply C++ flags
613 -- because there will not be C++ sources.
615 -- DO NOT add PD.cxxOptions unless this changes!
617 ++ [ "--cflag=" ++ opt
619 [ "-I" ++ autogenComponentModulesDir lbi clbi
620 , "-I" ++ autogenPackageModulesDir lbi
622 , autogenComponentModulesDir lbi clbi
</> cppHeaderName
625 ++ [ "--lflag=-L" ++ opt
627 if withFullyStaticExe lbi
628 then PD
.extraLibDirsStatic bi
629 else PD
.extraLibDirs bi
631 ++ [ "--lflag=-Wl,-R," ++ opt
634 if withFullyStaticExe lbi
635 then PD
.extraLibDirsStatic bi
636 else PD
.extraLibDirs bi
638 ++ ["--lflag=-l" ++ opt | opt
<- PD
.extraLibs bi
]
639 ++ ["--lflag=" ++ opt | opt
<- PD
.ldOptions bi
]
640 -- Options from dependent packages
641 ++ [ "--cflag=" ++ opt
644 ["-I" ++ opt | opt
<- Installed
.includeDirs pkg
]
645 ++ Installed
.ccOptions pkg
647 ++ [ "--lflag=" ++ opt
650 ["-L" ++ opt | opt
<- Installed
.libraryDirs pkg
]
651 ++ [ "-Wl,-R," ++ opt | isELF
, opt
<- Installed
.libraryDirs pkg
655 if withFullyStaticExe lbi
656 then Installed
.extraLibrariesStatic pkg
657 else Installed
.extraLibraries pkg
659 ++ Installed
.ldOptions pkg
664 ++ ["-o", outFile
, inFile
]
666 -- hsc2hs flag parsing was wrong
667 -- (see -- https://github.com/haskell/hsc2hs/issues/35)
668 -- so we need to put -- --cc/--ld *after* hsc2hsOptions,
669 -- for older hsc2hs (pre 0.68.8) so that they can be overridden.
671 [ "--cc=" ++ programPath gccProg
672 , "--ld=" ++ programPath gccProg
675 (preccldFlags
, postccldFlags
)
676 | hsc2hsVersion
>= mkVersion
[0, 68, 8] = (ccldFlags
, [])
677 |
otherwise = ([], ccldFlags
)
679 hacked_index
= packageHacks
(installedPkgs lbi
)
680 -- Look only at the dependencies of the current component
681 -- being built! This relies on 'installedPkgs' maintaining
682 -- 'InstalledPackageInfo' for internal deps too; see #2971.
683 pkgs
= PackageIndex
.topologicalOrder
$
684 case PackageIndex
.dependencyClosure
686 (map fst (componentPackageDeps clbi
)) of
687 Left
index' -> index'
689 error ("ppHsc2hs: broken closure: " ++ show inf
)
690 isOSX
= case buildOS
of OSX
-> True; _
-> False
691 isELF
= case buildOS
of OSX
-> False; Windows
-> False; AIX
-> False; _
-> True
692 packageHacks
= case compilerFlavor
(compiler lbi
) of
693 GHC
-> hackRtsPackage
694 GHCJS
-> hackRtsPackage
696 -- We don't link in the actual Haskell libraries of our dependencies, so
697 -- the -u flags in the ldOptions of the rts package mean linking fails on
698 -- OS X (its ld is a tad stricter than gnu ld). Thus we remove the
699 -- ldOptions for GHC's rts package:
700 hackRtsPackage
index =
701 case PackageIndex
.lookupPackageName
index (mkPackageName
"rts") of
703 PackageIndex
.insert rts
{Installed
.ldOptions
= []} index
704 _
-> error "No (or multiple) ghc rts package is registered!!"
706 ppHsc2hsExtras
:: PreProcessorExtras
707 ppHsc2hsExtras buildBaseDir
=
708 filter ("_hsc.c" `
isSuffixOf`
)
709 `
fmap` getDirectoryContentsRecursive buildBaseDir
711 ppC2hs
:: BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
714 { platformIndependent
= False
715 , ppOrdering
= unsorted
717 \(inBaseDir
, inRelativeFile
)
718 (outBaseDir
, outRelativeFile
)
721 requireProgramVersion
724 (orLaterVersion
(mkVersion
[0, 15]))
726 (gccProg
, _
) <- requireProgram verbosity gccProgram
(withPrograms lbi
)
727 runProgram verbosity c2hsProg
$
728 -- Options from the current package:
729 ["--cpp=" ++ programPath gccProg
, "--cppopts=-E"]
730 ++ ["--cppopts=" ++ opt | opt
<- getCppOptions bi lbi
]
731 ++ ["--cppopts=-include" ++ (autogenComponentModulesDir lbi clbi
</> cppHeaderName
)]
732 ++ ["--include=" ++ outBaseDir
]
733 -- Options from dependent packages
734 ++ [ "--cppopts=" ++ opt
737 ["-I" ++ opt | opt
<- Installed
.includeDirs pkg
]
738 ++ [ opt | opt
@('-' : c
: _
) <- Installed
.ccOptions pkg
,
739 -- c2hs uses the C ABI
740 -- We assume that there are only C sources
741 -- and C++ functions are exported via a C
742 -- interface and wrapped in a C source file.
743 -- Therefore we do not supply C++ flags
744 -- because there will not be C++ sources.
747 -- DO NOT add Installed.cxxOptions unless this changes!
751 -- TODO: install .chi files for packages, so we can --include
752 -- those dirs here, for the dependencies
754 -- input and output files
755 ++ [ "--output-dir=" ++ outBaseDir
756 , "--output=" ++ outRelativeFile
757 , inBaseDir
</> inRelativeFile
761 pkgs
= PackageIndex
.topologicalOrder
(installedPkgs lbi
)
763 ppC2hsExtras
:: PreProcessorExtras
765 filter (\p
-> takeExtensions p
== ".chs.c")
766 `
fmap` getDirectoryContentsRecursive d
768 -- TODO: perhaps use this with hsc2hs too
769 -- TODO: remove cc-options from cpphs for cabal-version: >= 1.10
770 -- TODO: Refactor and add separate getCppOptionsForHs, getCppOptionsForCxx, & getCppOptionsForC
771 -- instead of combining all these cases in a single function. This blind combination can
772 -- potentially lead to compilation inconsistencies.
773 getCppOptions
:: BuildInfo
-> LocalBuildInfo
-> [String]
774 getCppOptions bi lbi
=
777 ++ ["-I" ++ dir | dir
<- PD
.includeDirs bi
]
778 ++ [opt | opt
@('-' : c
: _
) <- PD
.ccOptions bi
++ PD
.cxxOptions bi
, c `
elem`
"DIU"]
780 platformDefines
:: LocalBuildInfo
-> [String]
781 platformDefines lbi
=
782 case compilerFlavor comp
of
784 ["-D__GLASGOW_HASKELL__=" ++ versionInt version
]
785 ++ ["-D" ++ os
++ "_BUILD_OS=1"]
786 ++ ["-D" ++ arch
++ "_BUILD_ARCH=1"]
787 ++ map (\os
' -> "-D" ++ os
' ++ "_HOST_OS=1") osStr
788 ++ map (\arch
' -> "-D" ++ arch
' ++ "_HOST_ARCH=1") archStr
791 ++ ["-D__GHCJS__=" ++ versionInt version
]
792 ++ ["-D" ++ os
++ "_BUILD_OS=1"]
793 ++ ["-D" ++ arch
++ "_BUILD_ARCH=1"]
794 ++ map (\os
' -> "-D" ++ os
' ++ "_HOST_OS=1") osStr
795 ++ map (\arch
' -> "-D" ++ arch
' ++ "_HOST_ARCH=1") archStr
797 ["-D__HASKELL_SUITE__"]
798 ++ map (\os
' -> "-D" ++ os
' ++ "_HOST_OS=1") osStr
799 ++ map (\arch
' -> "-D" ++ arch
' ++ "_HOST_ARCH=1") archStr
803 Platform hostArch hostOS
= hostPlatform lbi
804 version
= compilerVersion comp
805 compatGlasgowHaskell
=
808 (\v -> ["-D__GLASGOW_HASKELL__=" ++ versionInt v
])
809 (compilerCompatVersion GHC comp
)
810 -- TODO: move this into the compiler abstraction
811 -- FIXME: this forces GHC's crazy 4.8.2 -> 408 convention on all
812 -- the other compilers. Check if that's really what they want.
813 versionInt
:: Version
-> String
814 versionInt v
= case versionNumbers v
of
825 in s1
++ middle
++ s2
827 osStr
= case hostOS
of
829 Windows
-> ["mingw32"]
831 FreeBSD
-> ["freebsd"]
832 OpenBSD
-> ["openbsd"]
834 DragonFly
-> ["dragonfly"]
835 Solaris
-> ["solaris2"]
841 Android
-> ["android"]
847 archStr
= case hostArch
of
851 PPC64
-> ["powerpc64"]
854 AArch64
-> ["aarch64"]
865 RISCV64
-> ["riscv64"]
866 LoongArch64
-> ["loongarch64"]
867 JavaScript
-> ["javascript"]
871 ppHappy
:: BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
872 ppHappy _ lbi _
= pp
{platformIndependent
= True}
874 pp
= standardPP lbi happyProgram
(hcFlags hc
)
875 hc
= compilerFlavor
(compiler lbi
)
876 hcFlags GHC
= ["-agc"]
877 hcFlags GHCJS
= ["-agc"]
880 ppAlex
:: BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
881 ppAlex _ lbi _
= pp
{platformIndependent
= True}
883 pp
= standardPP lbi alexProgram
(hcFlags hc
)
884 hc
= compilerFlavor
(compiler lbi
)
886 hcFlags GHCJS
= ["-g"]
889 standardPP
:: LocalBuildInfo
-> Program
-> [String] -> PreProcessor
890 standardPP lbi prog args
=
892 { platformIndependent
= False
893 , ppOrdering
= unsorted
894 , runPreProcessor
= mkSimplePreProcessor
$ \inFile outFile verbosity
->
899 (args
++ ["-o", outFile
, inFile
])
902 -- | Convenience function; get the suffixes of these preprocessors.
903 ppSuffixes
:: [PPSuffixHandler
] -> [String]
906 -- | Standard preprocessors: GreenCard, c2hs, hsc2hs, happy, alex and cpphs.
907 knownSuffixHandlers
:: [PPSuffixHandler
]
908 knownSuffixHandlers
=
909 [ ("gc", ppGreenCard
)
918 -- | Standard preprocessors with possible extra C sources: c2hs, hsc2hs.
919 knownExtrasHandlers
:: [PreProcessorExtras
]
920 knownExtrasHandlers
= [ppC2hsExtras
, ppHsc2hsExtras
]
922 -- | Find any extra C sources generated by preprocessing that need to
923 -- be added to the component (addresses issue #238).
929 preprocessExtras verbosity comp lbi
= case comp
of
930 CLib _
-> pp
$ buildDir lbi
931 (CExe Executable
{exeName
= nm
}) -> do
932 let nm
' = unUnqualComponentName nm
933 pp
$ buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
934 (CFLib ForeignLib
{foreignLibName
= nm
}) -> do
935 let nm
' = unUnqualComponentName nm
936 pp
$ buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
938 let nm
' = unUnqualComponentName
$ testName test
939 case testInterface test
of
940 TestSuiteExeV10 _ _
->
941 pp
$ buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
942 TestSuiteLibV09 _ _
->
943 pp
$ buildDir lbi
</> stubName test
</> stubName test
++ "-tmp"
944 TestSuiteUnsupported tt
->
945 dieWithException verbosity
$ NoSupportPreProcessingTestExtras tt
947 let nm
' = unUnqualComponentName
$ benchmarkName bm
948 case benchmarkInterface bm
of
949 BenchmarkExeV10 _ _
->
950 pp
$ buildDir lbi
</> nm
' </> nm
' ++ "-tmp"
951 BenchmarkUnsupported tt
->
952 dieWithException verbosity
$ NoSupportPreProcessingBenchmarkExtras tt
954 pp
:: FilePath -> IO [FilePath]
956 b
<- doesDirectoryExist dir
959 (map (dir
</>) . filter not_sub
. concat)
962 (withLexicalCallStack
(\f -> f dir
))
964 -- TODO: This is a terrible hack to work around #3545 while we don't
965 -- reorganize the directory layout. Basically, for the main
966 -- library, we might accidentally pick up autogenerated sources for
967 -- our subcomponents, because they are all stored as subdirectories
968 -- in dist/build. This is a cheap and cheerful check to prevent
969 -- this from happening. It is not particularly correct; for example
970 -- if a user has a test suite named foobar and puts their C file in
971 -- foobar/foo.c, this test will incorrectly exclude it. But I
972 -- didn't want to break BC...
973 not_sub p
= and [not (pre `
isPrefixOf` p
) | pre
<- component_dirs
]
974 component_dirs
= component_names
(localPkgDescr lbi
)
976 component_names pkg_descr
=
977 fmap unUnqualComponentName
$
978 mapMaybe (libraryNameString
. libName
) (subLibraries pkg_descr
)
979 ++ map exeName
(executables pkg_descr
)
980 ++ map testName
(testSuites pkg_descr
)
981 ++ map benchmarkName
(benchmarks pkg_descr
)