Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I detect if GHC is set to generate 32bit or 64bit code by default?

I have the following bits in my makefile:

GLFW_FLAG := -m32 -O2 -Iglfw/include -Iglfw/lib -Iglfw/lib/cocoa $(CFLAGS)
...
$(BUILD_DIR)/%.o : %.c
    $(CC) -c $(GLFW_FLAG) $< -o $@
$(BUILD_DIR)/%.o : %.m
    $(CC) -c $(GLFW_FLAG) $< -o $@

The -m32 instructs GCC to generate 32bit code. It's there because on some configurations GHC is set to build 32bit code but GCC's default is sometimes 64bit. I would like to generalize this so that it autodetects whether GHC is building 32bit or 64bit code and then passes the correct flag to GCC.

Question: How can I ask GHC what type of code (32bit vs. 64bit) it will build?

PS: My cabal file calls this makefile during the build to workaround limitations in cabal. I do wish I could just list these as c-sources in my cabal file.

like image 225
Jason Dagit Avatar asked Jun 02 '11 16:06

Jason Dagit


3 Answers

The usual trick I see is to ask for the size in bytes or bits of an Int or Word, since this varies in GHC based on the word size of the machine,

Prelude> :m + Foreign
Prelude Foreign> sizeOf (undefined :: Int)
8
Prelude Foreign> bitSize (undefined :: Int)
64

Or use system tools:

$ cat A.hs
main = print ()

$ ghc --make A.hs
[1 of 1] Compiling Main             ( A.hs, A.o )
Linking A ...

$ file A
A: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), 
     dynamically linked (uses shared libs), for GNU/Linux 2.6.27, not stripped
like image 165
Don Stewart Avatar answered Oct 07 '22 21:10

Don Stewart


Thanks to Ed'ka I know the correct answer now.

The Makefile now has a rule like this:

GCCFLAGS  := $(shell ghc --info | ghc -e "fmap read getContents >>= putStrLn . unwords . read . Data.Maybe.fromJust . lookup \"Gcc Linker flags\"")

It's a bit long, but all it does is extract the "Gcc Linker flags" from ghc's output. Note: This is the output of ghc --info and not ghc +RTS --info.

This is better than the other suggested ways as it gives me all the flags that need to be specified and not just the -m flag. It's also empty when no flags are needed.

Thank you everyone!

like image 45
Jason Dagit Avatar answered Oct 07 '22 21:10

Jason Dagit


As per my comment, it should be possible to compile a test program and read the resulting binary.

$ cabal install elf

And the code is just

readElf testFile'sPath >>= \e -> if elfClass e == ELFCLASS64 then print 64 else print 32

Or in GHCi we see:

> e <- readElf "/bin/ls"
> elfClass e
ELFCLASS64
like image 30
Thomas M. DuBuisson Avatar answered Oct 07 '22 20:10

Thomas M. DuBuisson