7

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.

Jason Dagit
  • 13,684
  • 8
  • 33
  • 56
  • 1
    I can use this to get the word size from GHC, but I don't know if it's the right value to use: WORDSIZE := $(shell ghc +RTS --info | ghc -e "do c <- getContents; let { r = read c :: [(String,String)]; wsize = Data.Maybe.fromJust (lookup \"Word size\" r) }; putStrLn wsize") – Jason Dagit Jun 02 '11 at 17:02
  • Is it reasonable to compile a test program and read the result with the Elf library (on hackage)? – Thomas M. DuBuisson Jun 02 '11 at 17:44
  • You might be able use the result of `ghc -e 'print (maxBound :: Int)'` which should differ depending on whether you have 32bit or 64bit GHC... – hvr Jun 02 '11 at 19:38
  • `ghc --info` gives the platform information among other things (like `("Gcc Linker flags","[\"-m64\"]")`) – Ed'ka Jun 02 '11 at 22:14
  • Can you just call ghc instead of gcc? Then it will add the right flag automatically. – John L Jun 03 '11 at 00:46
  • @Ed'ka, oh that looks really good. – Jason Dagit Jun 03 '11 at 01:36
  • @John L, see the "PS" comment. I wish I could do that, but part of the problem is that some of the files are objective-c and the only GHC that will handle them correctly is not released yet. – Jason Dagit Jun 03 '11 at 01:37

3 Answers3

6

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
Don Stewart
  • 137,316
  • 36
  • 365
  • 468
2

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!

Jason Dagit
  • 13,684
  • 8
  • 33
  • 56
  • Seems you need something like `getContents >>= putStrLn . Data.Maybe.fromJust . lookup "C compiler link flags" . read` – Steven Shaw May 13 '15 at 00:26
1

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
Thomas M. DuBuisson
  • 64,245
  • 7
  • 109
  • 166