How can I make compiler version specific ifdef? - c++

I've got the problem that my program will compile with g++10.2 and c++11 activated through cmake. but it will not compile with arduino dues arm-none-eabi-g++.exe compiler which also has c++11. The failure occurs because of one line that needs to be added for the arm compiler, but when I add that line to g++10.2 it won't compile.
So I need an #ifdef or some alternative to activate and deactivate the line specific for the compiler.

Like Deumaudit said in the comments:
Try to use __arm__, __aarch64__ or __ARM_ARCH macro
You'll probably be ok if you use #ifdef __arm__ or even #if defined(__arm__) || defined(__aarch64__)
If you're planning to add more supported platforms to your program, it might be a good idea to define some macros when building for a specific platform. I have my own _MY_APP_ARM macro defined in my CMakeLists.txt:
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
add_definitions(-D_MY_APP_ARM)
endif()
Which I can then use as #ifdef _MY_APP_ARM

Related

Upgrading from C++98 to C++11 causes error

I am using QT Creator to make a C++ program on Ubuntu. The program I had written was compiling fine, until I decided to start using C++11 rather than C++98 (which is the default in QT Creator). I am using my own cmake file, rather than qmake, and so to do this, I included the following line in my CMakeLists.txt file:
set(CMAKE_CXX_FLAGS "-std=c++0x")
Now, part of my code has the following (which was not written by me):
#if (linux && (i386 || __x86_64__))
# include "Linux-x86/OniPlatformLinux-x86.h"
#elif (linux && __arm__)
# include "Linux-Arm/OniPlatformLinux-Arm.h"
#else
# error Unsupported Platform!
#endif
After transferring to C++11, I get an error at the line error Unsupported Platform!. This is because, from what I can see, the variable linux is not defined anywhere, although the variable __x86_64__ is defined.
Therefore, I have two questions:
1) Why is the variable linux not defined, even though I am using Linux?
2) How can I tell C++11 to ignore this error?
Thanks.
The identifier linux is not reserved. A conforming compiler may not predefine it as a macro. For example, this program:
int main() {
int linux = 0;
return linux;
}
is perfectly valid, and a conforming compiler must accept it. Predefining linux causes the declaration to be a syntax error.
Some older compilers (including the compiler you were using, with the options you were giving it) predefine certain symbols to provide information about the target platform -- including linux to indicate a Linux system. This convention goes back to early C compilers, written before there was a distinction between reserved and unreserved identifiers.
The identifier __linux__, since it starts with two underscores, is reserved for use by the implementation, so compilers are allowed to predefine it -- and compilers for Linux systems typically do predefine it as a macro expanding to 1.
Confirm that your compiler predefines __linux__, and then change your code so it tests __linux__ rather than linux. You should also find out what reserved symbol is used instead of i386 (likely __i386__).
Related: Why does the C preprocessor interpret the word "linux" as the constant "1"?
Change your standard-selection flag to -std=gnu++0x instead of c++0x. The gnu flavors provide some non-standard extensions, apparently including predefining the macro linux. Alternatively, check for __linux__ instead.

Is it possible to determine or set compiler options from within the source code in gcc?

I have some code that requires a certain gcc compiler option (otherwise it won't compile). Of course, I can make sure in the makefile that for this particular source file the required option is set. However, it would much more helpful, if this option could be set for the respective compilation unit (or part of it) from within the source_file.cpp.
I know that warning messages can be switched on or off using #pragma GCC diagnostic, but what about the -fsomething type of options? I take it from this question that this is impossible.
But perhaps there is at least a way to check from within the code whether a certain -f option is on or not?
Note I'm not interested in finding the compiler flags from the binary, as was asked previously, nor from the command line.
In my experience, no. This is not the way you go about this. Instead, you put compiler/platform/OS specific code in your source, and wrap it with the appropriate ifdef statements. These include:
#ifdef __GNUC__
/*code for GNU C compiler */
#elif _MSC_VER
/*usually has the version number in _MSC_VER*/
/*code specific to MSVC compiler*/
#elif __BORLANDC__
/*code specific to borland compilers*/
#elif __MINGW32__
/*code specific to mingw compilers*/
#endif
Within this, you can have version-specific requirements and code:
#ifdef __GNUC__
# include <features.h>
# if __GNUC_PREREQ(4,0)
// If gcc_version >= 4.0
# elif __GNUC_PREREQ(3,2)
// If gcc_version >= 3.2
# else
// Else
# endif
#else
// If not gcc
#endif
From there, you have your makefile pass the appropriate compiler flags based on the compiler type, version, etc, and you're all set.
You can try using some #pragma. See GCC diagnostic pragmas & GCC function specific pragmas.
Otherwise, develop your GCC plugin or your MELT extension and have it provide a pragma which sets the appropriate variables or compiler state inside GCC (actually cc1plus)

How to obtain debug/release conditional compiling in C++ program

In a large C++/Qt/QMake/qtcreator project I would like to perform some tests, but only when I am compiling with the debug flag.
Is there a way to tell g++ that some small parts of the code have to be compiled only in debug mode ?
The standard way to do this is to depend on the macro NDEBUG, which is used by the macro assert() defined in <cassert>:
#ifdef NDEBUG
// release mode code
#else
// debug mode code
#endif
The opposite of #ifdef is #ifndef, and of course #else branches are optional.
If this macro doesn't work (for whatever reason), you
can try the macro QT_NO_DEBUG, which Qt uses for a similar purpose with Q_ASSERT(); and
should fix it so that NDEBUG is (un)defined correctly; it's required for <cassert> to work properly, and code you use may depend on it.

How can I know what OS I'm working in?

I need a function that can clear the screen in both Linux and Windows. To do this, I want to know if there are some instructions that can tell me what operating system I'm working with.
I have searched for solution and I found the following code:
void clear_screen()
{
#ifdef WINDOWS
std::system ( "CLS" );
#else
// Assume POSIX
std::system("clear");
#endif
}
There are two problems with this function:
I don't understand it.
-> for #ifdef WINDOWS, where is WINDOWS defined?
This code works in Linux but it doesn't work in Windows.
Note :
I'm using Windows XP.
I don't want any non-standard functionality ... such "curses"
Macros such as _WIN32, __gnu_linux__, __linux__ are defined by the compiler in question. You can find a comprehensive list of pre-defined compiler macros here.
_WIN32 is defined for both 32-bit and 64-bit environments of Windows.
You're looking for
// Windows, all variants (including 64-bit and ARM)
#ifdef _WIN32
or
#ifdef __unix__
These are defined by your compiler, and are not stored in a header file. Because of that, you don't need to #include a file first, and these #ifdefs will always give the correct result (unless you mess with the compiler)
WINDOWS is defined by your compiler, so this defines can be compiler-dependant. It's usefull in order to compile specific code depending on your OS.
There are various compiler-dependant macros. Unfortunately, they are not particularly useful, because they are not standardized and a C compiler for a particular OS does not necessarily #define them. I also suspect that they actually violate the C standard C11 7.1.3.
The 100% portable solution, which will compile on all C compilers, is to create such a constant yourself. Since C is a compiled language, you will have to compile your code differently for each OS anyhow. Simply add a file called os.c where you put a relevant #define or constant, then link this to your program. The only thing you need to change when compiling for a different OS is the make file path to your OS-specific os.c.

CUDA compiler (nvcc) macro

Is there a #define compiler (nvcc) macro of CUDA which I can use? (Like _WIN32 for Windows and so on.)
I need this for header code that will be common between nvcc and VC++ compilers. I know I can go ahead and define my own and pass it as an argument to the nvcc compiler (-D), but it would be great if there is one already defined.
__CUDACC__
I don't think it will be that trivial. Check the following thread
http://forums.nvidia.com/index.php?showtopic=32369&st=0&p=179913&#entry179913
I know it has been long time now, but you might also find __CUDA_ARCH__ useful.