How to tell if program is running on x86/x64 or ARM Linux platforms - c

In a c program I want to do different things. This program will run on x86/x64 based GNU/Linux system as well as ARM based one e.g. on a PC or RaspberryPI.
Is there predefined macros in GCC to tell the platform?
something like
#ifdef _X64_
/do x64 stuff
#elif _ARM_
//do arm stuff
#endif
Or maybe that is the wrong approach? I will be using Makefileto compile and I could get away with my own defines.
What would be the best/safest approach?

This has already been answered on these posts:
GCC predefined macros for architecture X, Detecting CPU architecture compile-time
You can have them here:
http://sourceforge.net/p/predef/wiki/Architectures/
Your approach should only be used for small portions of code or functions but it should work.
Edit:
Basically, because links can become invalid:
__arm__ should work on ARM.
__x86_64__ should work on x64 architecture.
And yes, you can do:
#ifdef __x86_64__
// do x64 stuff
#elif __arm__
// do arm stuff
#endif

Related

How to check that microprocessor is Altera Nios?

I writes some C-program code for Altera/Nios II microprocessor (uP). This code will be different with Altera Arm 9 microprocessor. So I need to write 2 different code pieces for different uP-s. How can I check in execution time which uP is present. Or more simple, current uP is Nios or not.
As the two processors are from different architectures, you will not be able to check which processor is running at run-time. You could do it at compile time, as you will have a specific define flag set by your toolchain (see https://sourceforge.net/p/predef/wiki/Architectures/). For Arm it should be __arm__ or similar, depending on the toolchain you are using for the HPS.
#ifdef __arm__
<specific code for HPS>
#else
<specific code for NIOS>
#endif /* __arm__ */
You can also look at the toolchain's defines using the c pre-processor command (cpp):
<toolchain>-cpp -dM /dev/null
Note: for Arm processor, the MIDR register could be used to know which type you are running and this one could be accessed at runtime. But when building for NIOS II, you would have a compilation error. So you need to use the preprocessor to call specific Arm register name and to remove the code when building for NiosII.
Presumably it will be compiled with a different compiler? These compilers will (very likely) have a #define of some sort which you can use to build different code for each one.
You can make the compiler dump all its default preprocessor defines using:
echo | ./nios2-elf-gcc.exe -dM -E -
This will in particular emit:
#define nios2 1

How do I identify x86 vs. x86_64 at compile time in gcc?

I want to compile part of my code only on x86 and x86_64 linux, but not s390 linux or others. How to use the macro define in C to achieve it? I know linux is to determine linux OS, and 386, 486 and 586 to determine CPU architecture. Is there an easy macro define to determine x86 linux and x86_64 linux? Thanks
You can detect whether or not you are in a 64 bit mode easily:
#if defined(__x86_64__)
/* 64 bit detected */
#endif
#if defined(__i386__)
/* 32 bit x86 detected */
#endif
If your compiler does not provide pre-defined macros and constants, you may define it yourself: gcc -D WHATEVER_YOU_WANT.
Additional reward: if you compile your code for, say, amd64, but you don't define amd64, you can compare the results (the version which use amd64-specific parts vs the generic version) and see, whether your amd64 optimalization worths the effort.
Another option instead of pre-processor macros is sizeof(void*) == 4 to detect 32-bit and/or sizeof(void*) == 8 for 64-bit. This is more portable, as it does not rely on any defined symbols or macros.
As long as your compiler has any level of optimization enabled, it should be able to see that this kind of statement is either always true or always false for the current build target, so the resulting binary should be no less efficient than if you'd used pre-processor macros.

Detecting users OS in terminal application, in C

How do I determine a user's OS in terminal application, in C?
For example, in the code below, what should I replace windows and linux with?
/* pseudo code */
if(windows)
{system(cls)}
else if(linux)
{system(clear)}
else{...}
I should mention that I am a beginner at C, and need something like this so my code can work on windows and/or linux, without making separate source for each.
Typically, this is done with macros in the build system (since you have to BUILD the code for each system anyway.
e.g. gcc -DLINUX myfile.c
and then in myfile.c
#ifdef LINUX
... do stuff for linux ...
#else if defined(WINDOWS)
... do something for windows ...
#else if ... and so on.
...
#endif
(Most of the time, you can find some way that doesn't actually require the addition of a -D<something> on the command line, by using predefined macros for the tools you are using to compile for that architecture).
Alternatively, you ca do the same thing, but much quicker and better (but not 100% portable) by printing the ANSI escape sequence for "clear screen":
putstr("\033" "2J");
yes, that's two strings, because if you write "\0332J" the compile will use the character 0332, not character 033, followed by the digit 2. So two strings next to each other will do the trick.
I believe you can avoid runtime check by specializing your 'functions' during compilation. So, how about this then:
#ifdef WIN32
CLEAR = cls
#elif __linux__
CLEAR = clear
#endif
Predefs vary from compiler to compiler, so here's a good list to have: http://sourceforge.net/p/predef/wiki/OperatingSystems/
It is probably better to detect the environment at compile time rather than runtime. With compiled languages like C you aren't going to have the same compiler output running on different platforms as you would with a lanugage such as Java so you don't need to do this kind of check at runtime.
This is the header I use to work out what platform my code is being compiled on. It will define different macros depending on the OS (as well as other things).
Something like this in use:
#if defined(UTIL_PLATFORM_WINDOWS)
printf("windows\n");
#elif defined(UTIL_PLATFORM_UNIXLIKE)
printf("Unix\n");
#endif

Is it possible to check whether you are building for 64-bit with Microsoft C Compiler?

Is there a simple preprocessor macro that is defined for a 64-bit build? I thought _WIN64 might have been it, but even when I build a 32-bit target, the parts enclosed in a #ifdef _WIN64 ... #endif are compiled in, and this is causing problems. It's Friday and I can't think straight, but I'm sure I'm overlooking something very simple here. Maybe even something involving sizeof.
I have always used _WIN64 to check if it is a 64 bit build.
N.B. _WIN32 is also always (automatically) defined by MSVC in 64 bit builds, so check for _WIN64 before you check for _WIN32:
#if defined( _WIN64 )
// Windows 64 bit code here
#elif defined( _WIN32 )
// Windows 32 bit code here
#else
// Non-Windows code here
#endif
It sounds like your problem might be related to a header or project setting improperly defining _WIN64 - that should be left to the compiler.
There's a subtle difference between WIN64 and _WIN64 (at least for the Microsoft compilers - other compilers should follow suit, but not all do):
_WIN64 is defined by the compiler when it's building a program for a Windows 64-bit platform. Note that this name is in the compiler implementor's namespace (leading underscore followed by a capital letter)
WIN64 is defined by the Windows Platform SDK (or whatever they're calling it this year) when targeting a 64-bit platform.
So if you're only including standard headers and don't take other measures to define it, WIN64 will not be defined.
There's a similar story for _WIN32 and WIN32 - but checking other compilers: GCC 3.4.5 does define WIN32 even if only standard headers are used. As does Digital Mars.
Microsoft's compilers and Comeau do not.
Another bit of (hopefully) well known trivia is that _WIN32 and WIN32 are set when targeting 64-bit Windows platforms. Too much stuff would have broken otherwise.
The Visual C++ compiler defines the following macros:
_M_IX86 - x86 platform
_M_IA64 - ia64 platform
_M_X64 - x64 platform
Check your project's build properties, particularly the preprocessor section. Are you defining _WIN64 somewhere in WIN32 builds? The sizeof thing probably won't work since you cannot use in a #if test.

How to identify a 64 Bit build on Linux using the preprocessor?

I am about to port a Windows 32 Bit application to 64 Bit, but might decide to port the whole thing to Linux later.
The code contains sections which are dependent on the amount of memory available to the application (which depends on whether I'm creating a 32 or 64 Bit build), while the ability to compile a 32 Bit version of the code should be preserved for backward compatibility.
On Windows, I am able to simply wrap the respective code sections into preprocessor statements to ensure the right version of the code is compiled.
Unfortunately I have very few experience on programming on the Linux platform, so the question occurred:
How am I able to identify a 64 Bit build on the Linux platform?
Is there any (preferably non-compiler-specific) preprocessor define I might check for this?
Thanks in advance!
\Bjoern
Assuming you are using a recent GNU GCC compiler for IA32 (32-bit) and amd64 (the non-Itanium 64-bit target for AMD64 / x86-64 / EM64T / Intel 64), since very few people need a different compiler for Linux (Intel and PGI).
There is the compiler line switch (which you can add to CFLAGS in a Makefile) -m64 / -m32 to control the build target.
For conditional C code:
#if defined(__LP64__) || defined(_LP64)
#define BUILD_64 1
#endif
or
#include <limits.h>
#if ( __WORDSIZE == 64 )
#define BUILD_64 1
#endif
While the first one is GCC specific, the second one is more portable, but may not be correct in some bizarre environment I cannot think of.
At present both should both work for IA-32 / x86 (x86-32) and x86-64 / amd64 environments correctly. I think they may work for IA-64 (Itanium) as well.
Also see Andreas Jaeger's paper from GCC Developer's Summit entitled, Porting to 64-bit GNU/Linux Systems which described 64-bit Linux environments in additional detail.
According to the GCC Manual:
__LP64__
_LP64
These macros are defined, with value 1, if (and only if) the
compilation is for a target where long
int and pointer both use 64-bits and
int uses 32-bit.
That's what you need, right?
Also, you can try
#define __64BIT (__SIZEOF_POINTER__ == 8)

Resources