Cabal-3.10.3.0: src/Distribution/Simple/Program/Builtin.hs
-----------------------------------------------------------------------------
-- |
-- Module : Distribution.Simple.Program.Builtin
-- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009
--
-- Maintainer : cabal-devel@haskell.org
-- Portability : portable
--
-- The module defines all the known built-in 'Program's.
--
-- Where possible we try to find their version numbers.
--
module Distribution.Simple.Program.Builtin (
-- * The collection of unconfigured and configured programs
builtinPrograms,
-- * Programs that Cabal knows about
ghcProgram,
ghcPkgProgram,
runghcProgram,
ghcjsProgram,
ghcjsPkgProgram,
hmakeProgram,
jhcProgram,
haskellSuiteProgram,
haskellSuitePkgProgram,
uhcProgram,
gccProgram,
arProgram,
stripProgram,
happyProgram,
alexProgram,
hsc2hsProgram,
c2hsProgram,
cpphsProgram,
hscolourProgram,
doctestProgram,
haddockProgram,
greencardProgram,
ldProgram,
tarProgram,
cppProgram,
pkgConfigProgram,
hpcProgram,
) where
import Prelude ()
import Distribution.Compat.Prelude
import Distribution.Simple.Program.GHC
import Distribution.Simple.Program.Find
import Distribution.Simple.Program.Internal
import Distribution.Simple.Program.Run
import Distribution.Simple.Program.Types
import Distribution.Simple.Utils
import Distribution.Verbosity
import Distribution.Version
import qualified Data.Map as Map
-- ------------------------------------------------------------
-- * Known programs
-- ------------------------------------------------------------
-- | The default list of programs.
-- These programs are typically used internally to Cabal.
builtinPrograms :: [Program]
builtinPrograms =
[
-- compilers and related progs
ghcProgram
, runghcProgram
, ghcPkgProgram
, ghcjsProgram
, ghcjsPkgProgram
, haskellSuiteProgram
, haskellSuitePkgProgram
, hmakeProgram
, jhcProgram
, uhcProgram
, hpcProgram
-- preprocessors
, hscolourProgram
, doctestProgram
, haddockProgram
, happyProgram
, alexProgram
, hsc2hsProgram
, c2hsProgram
, cpphsProgram
, greencardProgram
-- platform toolchain
, gccProgram
, arProgram
, stripProgram
, ldProgram
, tarProgram
-- configuration tools
, pkgConfigProgram
]
ghcProgram :: Program
ghcProgram = (simpleProgram "ghc") {
programFindVersion = findProgramVersion "--numeric-version" id,
-- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/8825
-- (spurious warning on non-english locales)
programPostConf = \_verbosity ghcProg ->
do let ghcProg' = ghcProg {
programOverrideEnv = ("LANGUAGE", Just "en")
: programOverrideEnv ghcProg
}
-- Only the 7.8 branch seems to be affected. Fixed in 7.8.4.
affectedVersionRange = intersectVersionRanges
(laterVersion $ mkVersion [7,8,0])
(earlierVersion $ mkVersion [7,8,4])
return $ maybe ghcProg
(\v -> if withinRange v affectedVersionRange
then ghcProg' else ghcProg)
(programVersion ghcProg),
programNormaliseArgs = normaliseGhcArgs
}
runghcProgram :: Program
runghcProgram = (simpleProgram "runghc") {
programFindVersion = findProgramVersion "--version" $ \str ->
case words str of
-- "runghc 7.10.3"
(_:ver:_) -> ver
_ -> ""
}
ghcPkgProgram :: Program
ghcPkgProgram = (simpleProgram "ghc-pkg") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- Invoking "ghc-pkg --version" gives a string like
-- "GHC package manager version 6.4.1"
case words str of
(_:_:_:_:ver:_) -> ver
_ -> ""
}
ghcjsProgram :: Program
ghcjsProgram = (simpleProgram "ghcjs") {
programFindVersion = findProgramVersion "--numeric-ghcjs-version" id
}
-- note: version is the version number of the GHC version that ghcjs-pkg was built with
ghcjsPkgProgram :: Program
ghcjsPkgProgram = (simpleProgram "ghcjs-pkg") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- Invoking "ghcjs-pkg --version" gives a string like
-- "GHCJS package manager version 6.4.1"
case words str of
(_:_:_:_:ver:_) -> ver
_ -> ""
}
hmakeProgram :: Program
hmakeProgram = (simpleProgram "hmake") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- Invoking "hmake --version" gives a string line
-- "/usr/local/bin/hmake: 3.13 (2006-11-01)"
case words str of
(_:ver:_) -> ver
_ -> ""
}
jhcProgram :: Program
jhcProgram = (simpleProgram "jhc") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- invoking "jhc --version" gives a string like
-- "jhc 0.3.20080208 (wubgipkamcep-2)
-- compiled by ghc-6.8 on a x86_64 running linux"
case words str of
(_:ver:_) -> ver
_ -> ""
}
uhcProgram :: Program
uhcProgram = (simpleProgram "uhc") {
programFindVersion = findProgramVersion "--version-dotted" id
}
hpcProgram :: Program
hpcProgram = (simpleProgram "hpc")
{
programFindVersion = findProgramVersion "version" $ \str ->
case words str of
(_ : _ : _ : ver : _) -> ver
_ -> ""
}
-- This represents a haskell-suite compiler. Of course, the compiler
-- itself probably is not called "haskell-suite", so this is not a real
-- program. (But we don't know statically the name of the actual compiler,
-- so this is the best we can do.)
--
-- Having this Program value serves two purposes:
--
-- 1. We can accept options for the compiler in the form of
--
-- --haskell-suite-option(s)=...
--
-- 2. We can find a program later using this static id (with
-- requireProgram).
--
-- The path to the real compiler is found and recorded in the ProgramDb
-- during the configure phase.
haskellSuiteProgram :: Program
haskellSuiteProgram = (simpleProgram "haskell-suite") {
-- pretend that the program exists, otherwise it won't be in the
-- "configured" state
programFindLocation = \_verbosity _searchPath ->
return $ Just ("haskell-suite-dummy-location", [])
}
-- This represent a haskell-suite package manager. See the comments for
-- haskellSuiteProgram.
haskellSuitePkgProgram :: Program
haskellSuitePkgProgram = (simpleProgram "haskell-suite-pkg") {
programFindLocation = \_verbosity _searchPath ->
return $ Just ("haskell-suite-pkg-dummy-location", [])
}
happyProgram :: Program
happyProgram = (simpleProgram "happy") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- Invoking "happy --version" gives a string like
-- "Happy Version 1.16 Copyright (c) ...."
case words str of
(_:_:ver:_) -> ver
_ -> ""
}
alexProgram :: Program
alexProgram = (simpleProgram "alex") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- Invoking "alex --version" gives a string like
-- "Alex version 2.1.0, (c) 2003 Chris Dornan and Simon Marlow"
case words str of
(_:_:ver:_) -> takeWhile (\x -> isDigit x || x == '.') ver
_ -> ""
}
gccProgram :: Program
gccProgram = (simpleProgram "gcc") {
programFindVersion = findProgramVersion "-dumpversion" id
}
arProgram :: Program
arProgram = simpleProgram "ar"
stripProgram :: Program
stripProgram = (simpleProgram "strip") {
programFindVersion = findProgramVersion "--version" stripExtractVersion . lessVerbose
}
hsc2hsProgram :: Program
hsc2hsProgram = (simpleProgram "hsc2hs") {
programFindVersion =
findProgramVersion "--version" $ \str ->
-- Invoking "hsc2hs --version" gives a string like "hsc2hs version 0.66"
case words str of
(_:_:ver:_) -> ver
_ -> ""
}
c2hsProgram :: Program
c2hsProgram = (simpleProgram "c2hs") {
programFindVersion = findProgramVersion "--numeric-version" id
}
cpphsProgram :: Program
cpphsProgram = (simpleProgram "cpphs") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- Invoking "cpphs --version" gives a string like "cpphs 1.3"
case words str of
(_:ver:_) -> ver
_ -> ""
}
hscolourProgram :: Program
hscolourProgram = (simpleProgram "hscolour") {
programFindLocation = \v p -> findProgramOnSearchPath v p "HsColour",
programFindVersion = findProgramVersion "-version" $ \str ->
-- Invoking "HsColour -version" gives a string like "HsColour 1.7"
case words str of
(_:ver:_) -> ver
_ -> ""
}
-- TODO: Ensure that doctest is built against the same GHC as the one
-- that's being used. Same for haddock. @phadej pointed this out.
doctestProgram :: Program
doctestProgram = (simpleProgram "doctest") {
programFindLocation = \v p -> findProgramOnSearchPath v p "doctest"
, programFindVersion = findProgramVersion "--version" $ \str ->
-- "doctest version 0.11.2"
case words str of
(_:_:ver:_) -> ver
_ -> ""
}
haddockProgram :: Program
haddockProgram = (simpleProgram "haddock") {
programFindVersion = findProgramVersion "--version" $ \str ->
-- Invoking "haddock --version" gives a string like
-- "Haddock version 0.8, (c) Simon Marlow 2006"
case words str of
(_:_:ver:_) -> takeWhile (`elem` ('.':['0'..'9'])) ver
_ -> "",
programNormaliseArgs = \_ _ args -> args
}
greencardProgram :: Program
greencardProgram = simpleProgram "greencard"
ldProgram :: Program
ldProgram = (simpleProgram "ld")
{ programPostConf = \verbosity ldProg -> do
-- The `lld` linker cannot create merge (relocatable) objects so we
-- want to detect this.
-- If the linker does support relocatable objects, we want to use that
-- to create partially pre-linked objects for GHCi, so we get much
-- faster loading as we do not have to do the separate loading and
-- in-memory linking the static linker in GHC does, but can offload
-- parts of this process to a pre-linking step.
-- However this requires the linker to support this features. Not all
-- linkers do, and notably as of this writing `lld` which is a popular
-- choice for windows linking does not support this feature. However
-- if using binutils ld or another linker that supports --relocatable,
-- we should still be good to generate pre-linked objects.
ldHelpOutput <-
getProgramInvocationOutput
verbosity
(programInvocation ldProg ["--help"])
-- In case the linker does not support '--help'. Eg the LLVM linker,
-- `lld` only accepts `-help`.
`catchIO` (\_ -> return "")
let k = "Supports relocatable output"
-- Standard GNU `ld` uses `--relocatable` while `ld.gold` uses
-- `-relocatable` (single `-`).
v
| "-relocatable" `isInfixOf` ldHelpOutput = "YES"
-- ld64 on macOS has this lovely response for "--help"
--
-- ld64: For information on command line options please use 'man ld'.
--
-- it does however support -r, if you read the manpage
-- (e.g. https://www.manpagez.com/man/1/ld64/)
| "ld64:" `isPrefixOf` ldHelpOutput = "YES"
| otherwise = "NO"
m = Map.insert k v (programProperties ldProg)
return $ ldProg{programProperties = m}
}
tarProgram :: Program
tarProgram = (simpleProgram "tar") {
-- See #1901. Some versions of 'tar' (OpenBSD, NetBSD, ...) don't support the
-- '--format' option.
programPostConf = \verbosity tarProg -> do
tarHelpOutput <- getProgramInvocationOutput
verbosity (programInvocation tarProg ["--help"])
-- Some versions of tar don't support '--help'.
`catchIO` (\_ -> return "")
let k = "Supports --format"
v = if "--format" `isInfixOf` tarHelpOutput then "YES" else "NO"
m = Map.insert k v (programProperties tarProg)
return $ tarProg { programProperties = m }
}
cppProgram :: Program
cppProgram = simpleProgram "cpp"
pkgConfigProgram :: Program
pkgConfigProgram =
(simpleProgram "pkg-config")
{ programFindVersion = findProgramVersion "--version" id
, programPostConf = \_ pkgConfProg ->
let programOverrideEnv' =
programOverrideEnv pkgConfProg
++ [ ("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS", Just "1")
, ("PKG_CONFIG_ALLOW_SYSTEM_LIBS", Just "1")
]
in pure $ pkgConfProg{programOverrideEnv = programOverrideEnv'}
}