Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find a base architecture inside Makefile?

I want to find inside a Makefile, whether I'm running on a 32-bit or 64-bit machine.

Is there any macro or environment variables that can be simply accessed from within Makefile?

I found this related answer on-line:

LBITS := $(shell getconf LONG_BIT)
ifeq ($(LBITS),64)
   # do 64 bit stuff here, like set some CFLAGS
else
   # do 32 bit stuff here
endif

However, I doubt in all system getconf tool would be available or not.

like image 497
Vicky Avatar asked Jul 20 '16 11:07

Vicky


1 Answers

tl;dr;

If all you need is to get the number of bits in long type in C in a portable way, it's ok to use getconf LONG_BIT.

Otherwise:

  • to detect host architecture, use config.guess shell script
  • to detect target architecture, use gcc -dumpmachine or gcc --help=target

Detecting host architecture

1) getconf

As mentioned by @Dummy00001, getconf is part of POSIX and is widely available, but it doesn't provide enough information.

Note that getconf LONG_BIT is just the number of bits in long type in C. E.g., it may be 32 on 16-bit or 64-bit machines. It's quite useless for determining host architecture.

2) uname

uname is part of POSIX as well, and it doesn't provide enough information too.

For example, it doesn't distinguish between hardfloat and softfloat ARM on Linux. Also, its architecture naming is not really portable.

3) /proc

You can use /proc to gather architecture info, e.g. /proc/cpuinfo on Linux. However, it's not portable and hard to parse.

4) config.guess

Finally, I recommend GNU config.guess script (source code). It is a standalone script that you can copy to your project. It is written in portable shell and should work on any UNIX.

$ sh config.guess
x86_64-pc-linux-gnu

This script is used in autotools, but you can use it without autotools too.


Detecting default target architecture of your toolchain

It usually makes sense to detect target architecture of toolchain being used. It's different from host architecture when cross-compiling.

1) gcc -E

You can parse gcc -E output to get toolchain tuple for target architecture of gcc:

$ gcc -v -E - </dev/null |& grep Target:
Target: x86_64-linux-gnu

This should work on any UNIX if you use GCC or clang.

Notes:

  • It prints the value of --target option passed to configure script when GCC was built. It's not affected by current compilations flags passed to GCC, like -m32 or -march.
  • Unlike config.guess, this toolchain tuple is distro-specific. E.g., different schemes are used in prebuilt toolchains in Debian and Gentoo.

2) gcc -dumpmachine

It seems that gcc -dumpmachine prints the same value as previous recipe:

$ gcc -dumpmachine
x86_64-linux-gnu

It works with GCC and clang.

3) gcc -print-multiarch

Another way to get toolchain tuple:

$ gcc -print-multiarch
x86_64-linux-gnu

It works with GCC, but not clang. Also, this option is known not to work in various cases:

  • on Debian, it's empty if multilib is disabled
  • on Gentoo, it's always empty
  • as mentioned by @Dummy00001, it may be empty for cross-compilation toolchains (I guess it depends on how toolchain was built)

Detecting target architecture depending on current flags

Some GCC options like -m32 or -march can affect target architecture.

1) gcc --help=target

This will print value of -march option deduced from default target architecture (configured when GCC was built) and current compilation options.

$ gcc -Q --help=target |& grep -e -march | awk '{print $2}'
x86-64

$ gcc -m32 -Q --help=target |& grep -e -march | awk '{print $2}'
i686

$ gcc -march=i386 -Q --help=target |& grep -e -march | awk '{print $2}'
i386

It doesn't work with clang.

like image 109
gavv Avatar answered Sep 28 '22 06:09

gavv