Skip to content

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

Optional:

  • Operating System: Fedora 30
  • System Architecture: x86_64
Edited by Stefan Schulze Frielinghaus
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information