Hadrian using system libffi support results in bad gcc command
Summary
Hadrian uses a wrong set of command line options for gcc
if the system version of libffi
is used:
$ make maintainer-clean && ./boot && ./configure --with-system-libffi && ./hadrian/build.sh --flavour=quick
[...]
Up to date
| Copy file: settings => _build/stage1/lib/settings
| Copy file: settings => _build/stage0/lib/settings
| Run Cc FindCDependencies Stage0: utils/unlit/fs.c => _build/stage0/utils/unlit/build/c/fs.o.d
gcc: error: c: No such file or directory
| Run Cc FindCDependencies Stage0: utils/unlit/unlit.c => _build/stage0/utils/unlit/build/c/unlit.o.d
gcc: error: c: No such file or directory
Error when running Shake build system:
at action, called at src/Rules.hs:35:19 in main:Rules
at need, called at src/Rules.hs:52:5 in main:Rules
* Depends on: _build/stage1/lib/bin/unlit
* Depends on: _build/stage0/lib/bin/unlit
* Depends on: _build/stage0/utils/unlit/build/c/unlit.o
* Raised the exception:
user error (Development.Shake.cmd, system command failed
Command line: /usr/bin/gcc -E -MM -MG -MF _build/stage0/utils/unlit/build/c/unlit.o.d -MT _build/stage0/utils/unlit/build/c/unlit.o -I_build/generated -I_build/stage0/utils/unlit/build -I -x c utils/unlit/unlit.c
Exit code: 1
Stderr:
gcc: error: c: No such file or directory
)
In case system libffi version is used, the following content ends up in file mk/config.mk
for me:
UseSystemLibFFI=YES
# Flags to go into package.conf for rts
FFILibDir=
FFIIncludeDir=
Note that FFIIncludeDir
is empty. This means that in file hadrian/src/Settings/Builders/Common.hs
variable ffiIncludeDir
will be holding the empty string resulting in a dangling -I
. The following patch fixes this:
diff --git a/hadrian/src/Settings/Builders/Common.hs b/hadrian/src/Settings/Builders/Common.hs
index 2c41d92493..9584c8fe57 100644
--- a/hadrian/src/Settings/Builders/Common.hs
+++ b/hadrian/src/Settings/Builders/Common.hs
@@ -22,38 +22,39 @@ import UserSettings
cIncludeArgs :: Args
cIncludeArgs = do
pkg <- getPackage
path <- getBuildPath
incDirs <- getContextData includeDirs
depDirs <- getContextData depIncludeDirs
stage <- getStage
iconvIncludeDir <- getSetting IconvIncludeDir
gmpIncludeDir <- getSetting GmpIncludeDir
ffiIncludeDir <- getSetting FfiIncludeDir
libPath <- expr $ stageLibPath stage
mconcat [ notStage0 ||^ package compiler ? arg "-Iincludes"
, arg $ "-I" ++ libPath
, arg $ "-I" ++ path
, pure . map ("-I"++) . filter (/= "") $ [iconvIncludeDir, gmpIncludeDir]
- , flag UseSystemFfi ? arg ("-I" ++ ffiIncludeDir)
+ , flag UseSystemFfi <&&> (pure $ not $ null ffiIncludeDir) ? arg ("-I" ++ ffiIncludeDir)
-- Add @incDirs@ in the build directory, since some files generated
-- with @autoconf@ may end up in the build directory.
, pure [ "-I" ++ path -/- dir | dir <- incDirs ]
-- Add @incDirs@ in the package directory for include files shipped
-- with the package.
, pure [ "-I" ++ pkgPath pkg -/- dir | dir <- incDirs ]
, pure [ "-I" ++ unifyPath dir | dir <- depDirs ] ]
+ where (<&&>) = liftA2 (&&)
ldArgs :: Args
ldArgs = mempty
However, it does not resolve the whole problem. A further run of hadrian then results in the following error:
$ ./hadrian/build.sh -j -V
...
| Run Cc FindCDependencies Stage1: rts/ClosureFlags.c => _build/stage1/rts/build/c/ClosureFlags.p_o.d
/usr/bin/cc -E -MM -MG -MF _build/stage1/rts/build/c/ClosureFlags.p_o.d -MT _build/stage1/rts/build/c/ClosureFlags.o -Iincludes -I_build/stage1/lib -I_build/stage1/rts/build -I_build/stage1/rts/build/build -I_build/stage1/rts/build/../includes -I_build/stage1/rts/build/includes -I_build/stage1/rts/build/includes/dist-derivedconstants/header -Irts/build -Irts/../includes -Irts/includes -Irts/includes/dist-derivedconstants/header -x c rts/ClosureFlags.c -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Winline -Wpointer-arith -Wmissing-noreturn -Wnested-externs -Wredundant-decls -Wundef -fno-strict-aliasing -I -fomit-frame-pointer -O2 -g -Irts -I_build/stage1/rts/build
Error when running Shake build system:
at action, called at src/Rules.hs:71:19 in main:Rules
at need, called at src/Rules.hs:93:5 in main:Rules
* Depends on: _build/stage1/bin/hp2ps
at need, called at src/Rules/Library.hs:151:18 in main:Rules.Library
* Depends on: _build/stage1/rts/build/ffitarget.h
at &%>, called at src/Rules/Rts.hs:29:9 in main:Rules.Rts
* Depends on: _build/stage1/rts/build/ffi.h _build/stage1/rts/build/ffitarget.h
at need, called at src/Hadrian/Utilities.hs:329:5 in main:Hadrian.Utilities
* Depends on: ffi.h
at error, called at src/Development/Shake/Internal/Rules/File.hs:179:58 in shake-0.18.3-a9de361a74bef613491c235c1a1f725e6f3f1e9824ca9a8fbdfa98ba6ccae272:Development.Shake.Internal.Rules.File
* Raised the exception:
Error, file does not exist and no rule available:
ffi.h
The error persists even if I add arg "-I/usr/include"
. How is hadrian supposed to refer to system header files? Should it copy system headers into its _build
directory? At this point I got stuck. Any ideas?
Environment
- GHC version used: master 4898df1c
Optional:
- Operating System: Fedora 30
- System Architecture: x86_64