#ifdef _WIN32 not getting detected - c++

I can not get the #ifdef rule to work at least on windows (64 bit).
Compiler version is g++ 5.4.0
I have tried:
#ifdef _WIN32
#ifdef _WIN64
#ifdef OS_WINDOWS
I have compiled the following test with:
g++ main.cpp
Even with a simple code as this:
#include <iostream>
int main()
{
std::cout << "you are on...";
#ifdef _WIN32
std::cout << "Windows" << std::endl;
#elif __linux__
std::cout << "Linux" << std::endl;
#endif
return 0;
}
Output is:
"you are on..."
...and nothing else gets couted out.

#ifdef _WIN32
#ifdef _WIN64
These are pre-defined macros defined by the MSVC compiler. You appear to be using g++ instead. That probably means either MinGW, or Cygwin.
Here and here are collections of macros pre-defined by several compilers.
MinGW __MINGW32__
Cygwin __CYGWIN__
If you prefer to not to build hefty ifdef - else trees, and scour the internet for macros defined by obscure compilers, and their different versions, I recommend to instead include a few headers from boost. They have already done the hard part of the work. Although, note that BOOST_OS_WINDOWS is separate from BOOST_OS_CYGWIN.

Use __CYGWIN32__ to detect Windows when compiling g++ in cygwin. (This is defined in both 32 and 64 bit).
_WIN32 &c. may not be defined in that case. It isn't for me.
(As also mentioned in a comment; using echo | g++ -dM -E to output the list of what is defined can be helpful.)

yes, it is true that this:
#ifdef _WIN32
sometimes doesn't work on Windows (!) In this case, use the following form instead:
#if defined(_WIN32)
I was surprised but I have seen that problem and it helped me!

Related

How I can check that the system that I build is for linux or not? [duplicate]

I need my code to do different things based on the operating system on which it gets compiled. I'm looking for something like this:
#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif
Is there a way to do this? Is there a better way to do the same thing?
The Predefined Macros for OS site has a very complete list of checks. Here are a few of them, with links to where they're found:
Windows
_WIN32   Both 32 bit and 64 bit
_WIN64   64 bit only
__CYGWIN__
Unix (Linux, *BSD, but not Mac OS X)
See this related question on some of the pitfalls of using this check.
unix
__unix
__unix__
Mac OS X
__APPLE__ Also used for classic
__MACH__
Both are defined; checking for either should work.
Linux
__linux__
linux Obsolete (not POSIX compliant)
__linux Obsolete (not POSIX compliant)
FreeBSD
__FreeBSD__
Android
__ANDROID__
show GCC defines on Windows:
gcc -dM -E - <NUL:
on Linux:
gcc -dM -E - </dev/null
Predefined macros in MinGW:
WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386
on UNIXes:
unix __unix__ __unix
Based on nadeausoftware and Lambda Fairy's answer.
#include <stdio.h>
/**
* Determination a platform of an operation system
* Fully supported supported only GNU GCC/G++, partially on Clang/LLVM
*/
#if defined(_WIN32)
#define PLATFORM_NAME "windows" // Windows
#elif defined(_WIN64)
#define PLATFORM_NAME "windows" // Windows
#elif defined(__CYGWIN__) && !defined(_WIN32)
#define PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window)
#elif defined(__ANDROID__)
#define PLATFORM_NAME "android" // Android (implies Linux, so it must come first)
#elif defined(__linux__)
#define PLATFORM_NAME "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
#include <sys/param.h>
#if defined(BSD)
#define PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
#endif
#elif defined(__hpux)
#define PLATFORM_NAME "hp-ux" // HP-UX
#elif defined(_AIX)
#define PLATFORM_NAME "aix" // IBM AIX
#elif defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
#define PLATFORM_NAME "ios" // Apple iOS
#elif TARGET_OS_IPHONE == 1
#define PLATFORM_NAME "ios" // Apple iOS
#elif TARGET_OS_MAC == 1
#define PLATFORM_NAME "osx" // Apple OSX
#endif
#elif defined(__sun) && defined(__SVR4)
#define PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana
#else
#define PLATFORM_NAME NULL
#endif
// Return a name of platform, if determined, otherwise - an empty string
const char *get_platform_name() {
return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}
int main(int argc, char *argv[]) {
puts(get_platform_name());
return 0;
}
Tested with GCC and clang on:
Debian 8
Windows (MinGW)
Windows (Cygwin)
Microsoft C/C++ compiler (MSVC) Predefined Macros can be found here
I think you are looking for:
_WIN32 - Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. Otherwise, undefined
_WIN64 - Defined as 1 when the compilation target is 64-bit ARM or x64. Otherwise, undefined.
gcc compiler PreDefined MAcros can be found here
I think you are looking for:
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
Do a google for your appropriate compilers pre-defined.
In most cases it is better to check whether a given functionality is present or not. For example: if the function pipe() exists or not.
#ifdef _WIN32
// do something for windows like include <windows.h>
#elif defined __unix__
// do something for unix like include <unistd.h>
#elif defined __APPLE__
// do something for mac
#endif
On MinGW, the _WIN32 define check isn't working. Here's a solution:
#if defined(_WIN32) || defined(__CYGWIN__)
// Windows (x86 or x64)
// ...
#elif defined(__linux__)
// Linux
// ...
#elif defined(__APPLE__) && defined(__MACH__)
// Mac OS
// ...
#elif defined(unix) || defined(__unix__) || defined(__unix)
// Unix like OS
// ...
#else
#error Unknown environment!
#endif
For more information please look: https://sourceforge.net/p/predef/wiki/OperatingSystems/
There is no standard macro that is set according to C standard. Some C compilers will set one on some platforms (e.g. Apple's patched GCC sets a macro to indicate that it is compiling on an Apple system and for the Darwin platform). Your platform and/or your C compiler might set something as well, but there is no general way.
Like hayalci said, it's best to have these macros set in your build process somehow. It is easy to define a macro with most compilers without modifying the code. You can simply pass -D MACRO to GCC, i.e.
gcc -D Windows
gcc -D UNIX
And in your code:
#if defined(Windows)
// do some cool Windows stuff
#elif defined(UNIX)
// do some cool Unix stuff
#else
# error Unsupported operating system
#endif
Sorry for the external reference, but I think it is suited to your question:
C/C++ tip: How to detect the operating system type using compiler predefined macros
You can use Boost.Predef which contains various predefined macros for the target platform including the OS (BOOST_OS_*). Yes boost is often thought as a C++ library, but this one is a preprocessor header that works with C as well!
This library defines a set of compiler, architecture, operating system, library, and other version numbers from the information it can gather of C, C++, Objective C, and Objective C++ predefined macros or those defined in generally available headers. The idea for this library grew out of a proposal to extend the Boost Config library to provide more, and consistent, information than the feature definitions it supports. What follows is an edited version of that brief proposal.
For example
#include <boost/predef.h>
// or just include the necessary header
// #include <boost/predef/os.h>
#if BOOST_OS_WINDOWS
#elif BOOST_OS_ANDROID
#elif BOOST_OS_LINUX
#elif BOOST_OS_BSD
#elif BOOST_OS_AIX
#elif BOOST_OS_HAIKU
...
#endif
The full list can be found in BOOST_OS operating system macros
Demo on Godbolt
See also How to get platform IDs from boost?
Use #define OSsymbol and #ifdef OSsymbol
where OSsymbol is a #define'able symbol identifying your target OS.
Typically you would include a central header file defining the selected OS symbol and use OS-specific include and library directories to compile and build.
You did not specify your development environment, but I'm pretty sure your compiler provides global defines for common platforms and OSes.
See also http://en.wikibooks.org/wiki/C_Programming/Preprocessor
Just to sum it all up, here are a bunch of helpful links.
GCC Common Predefined Macros
SourceForge predefined Operating Systems
MSDN Predefined Macros
The Much-Linked NaudeaSoftware Page
Wikipedia!!!
SourceForge's "Overview of pre-defined compiler macros for standards, compilers, operating systems, and hardware architectures."
FreeBSD's "Differentiating Operating Systems"
All kinds of predefined macros
libportable
I did not find Haiku definition here. To be complete, Haiku-os definition is simple __HAIKU__
Some compilers will generate #defines that can help you with this. Read the compiler documentation to determine what they are. MSVC defines one that's __WIN32__, GCC has some you can see with touch foo.h; gcc -dM foo.h
You can use pre-processor directives as warning or error to check at compile time you don't need to run this program at all just simply compile it .
#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
#error Windows_OS
#elif defined(__linux__)
#error Linux_OS
#elif defined(__APPLE__) && defined(__MACH__)
#error Mach_OS
#elif defined(unix) || defined(__unix__) || defined(__unix)
#error Unix_OS
#else
#error Unknown_OS
#endif
#include <stdio.h>
int main(void)
{
return 0;
}
I wrote an small library to get the operating system you are on, it can be installed using clib (The C package manager), so it is really simple to use it as a dependency for your projects.
Install
$ clib install abranhe/os.c
Usage
#include <stdio.h>
#include "os.h"
int main()
{
printf("%s\n", operating_system());
// macOS
return 0;
}
It returns a string (char*) with the name of the operating system you are using, for further information about this project check it out the documentation on Github.

MinGW Forward dll call

I'm trying to forward calls from my DLL to another DLL. I can't find any documentation about how to do that with MinGW.
Using Visual C++ compiler I would go with:
#pragma comment (linker, "/export:DllInitialize=api.DllInitialize,#2")
Or by using a .def definition file:
EXPORTS
DllInitialize=api.DllInitialize
But none of these work when compiling with MinGW32. I am using Code::Blocks as IDE if it matters. How can I do this with MinGW32?
i am sorry, i added a bit too many double-quotes in the above code. instead it should be this way:
asm (".section .drectve\n\t.ascii \" -export:DllInitialize=api.DllInitialize #2\"");
If you need to use it many times, consider putting it in a macro, e.g.
#ifdef _MSC_VER
#define FORWARDED_EXPORT_WITH_ORDINAL(exp_name, ordinal, target_name) __pragma (comment (linker, "/export:" #exp_name "=" #target_name ",#" #ordinal))
#endif
#ifdef __GNUC__
#define FORWARDED_EXPORT_WITH_ORDINAL(exp_name, ordinal, target_name) asm (".section .drectve\n\t.ascii \" -export:" #exp_name "= " #target_name " #" #ordinal "\"");
#endif
FORWARDED_EXPORT_WITH_ORDINAL(DllInitialize, 2, api.DllInitialize)
FORWARDED_EXPORT_WITH_ORDINAL(my_create_file_a, 100, kernel32.CreateFileA)
you get the idea
here is how you can do it:
#ifdef _MSC_VER
#pragma comment (linker, "/export:DllInitialize=api.DllInitialize,#2")
#endif
#ifdef __GNUC__
asm (".section .drectve\n\t.ascii \" -export:\\\"DllInitialize=api.DllInitialize\\\" #2\"");
#endif
Note that "drectve" is not a typo, thats how it must be written however odd it may seem. By the way, this strange abbreviation is a microsoft's idea, not GCC's.

Why use preprocessor #if statements instead of if() else?

I see this being done all the time for example in the Linux Kernel. What is the purpose of using the preprocessor commands vs just normal C++ if else block? Is there a speed advantage or something?
A preprocessor changes the C/C++ code before it gets compiled (hence pre processor).
Preprocessor ifs are evaluated at compile-time.
C/C++ ifs are evaluated at run-time.
You can do things that can't be done at run-time.
Adjust code for different platforms or different compilers:
#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
#include <unistd.h>
#elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
#include <windows.h>
#endif
Ensure header file definitions are included only once (equivalent of #pragma once, but more portable):
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Example { ... };
#endif
You can make things faster than at run-time.
void some_debug_function() {
#ifdef DEBUG
printf("Debug!\n");
#endif
}
Now, when compiling with DEBUG not defined (likely a command line parameter to your compiler), any calls to some_debug_function can be optimized away by the compiler.
Preprocessor is run before the compilation pass, so the compiler won't even see anything that was in the not-taken #if branch.
#if DEBUG
int a;
#else
double b;
#endif
gcc -c -DDEBUG=1 file.c will see "int a"
gcc -c file.c will see "double b"
Preprocessor allows you to actually cut out or paste in to your source file, code to be compiled. If its cut out, its gone, its like a comment, does nothing, is not compiled, produces no code in the binary. Devs will often use this technique to add code only in debug build for debugging purposes or for adding or excluding code for specific operating systems.

how to undefine _MSC_VER?

I work in Visual Studio but my project is for a POSIX-based environment (marmalade sdk). In this project, the release
build is compiled with gcc for ARM but the debug version works on windows and is compiled by MS compiler. Also this environmet has its own implementation of STL and other standard libraries.
Many of these c++ librares have code like this:
#if defined( _MSC_VER )
#include <Windows.h>
#else
#include <pthread.h>
#endif
Is it possible to undefine the _MSC_VER macro? - So that the C++ libraries will detect a POSIX system here.
_MSC_VER is (and always should be) defined when compiling with the Microsoft compiler so that it "evaluates to the major and minor number components of the compiler's version number". Therefore, the code is using the wrong macro test, since it will always be defined to some value for your compiler regardless of the Windows environment differences.
Rather than destroy the definition of _MSC_VER (which could lead to other problems if any code really does want to know the compiler version), what you really should do instead is to correct the condition so that a more appropriate macro test is used that distinguishes between the kinds of Windows environments that you might encounter.
See the more complete list of predefined macros you could consider here
You could either replace the condition ...
#if someOtherConditionGoesHere
... or extend it with additional conditions, e.g.
#if defined(_MSC_VER) && someOtherConditionGoesHere
Of course:
#undef _MSC_VER
#if defined( _MSC_VER )
#include <Windows.h>
#else
#include <pthread.h>
#endif
Or, #undef it before you include the file where _MSC_VER is used.

C++ compiling on Windows and Linux: ifdef switch [duplicate]

This question already has answers here:
How do I check OS with a preprocessor directive?
(16 answers)
Closed 7 years ago.
I want to run some c++ code on Linux and Windows. There are some pieces of code that I want to include only for one operating system and not the other. Is there a standard #ifdef that once can use?
Something like:
#ifdef LINUX_KEY_WORD
... // linux code goes here.
#elif WINDOWS_KEY_WORD
... // windows code goes here.
#else
#error "OS not supported!"
#endif
The question is indeed a duplicate but the answers here are much better, especially the accepted one.
use:
#ifdef __linux__
//linux code goes here
#elif _WIN32
// windows code goes here
#else
#endif
You can do:
#if MACRO0
//code...
#elif MACRO1
//code...
#endif
…where the identifier can be:
__linux__ Defined on Linux
__sun Defined on Solaris
__FreeBSD__ Defined on FreeBSD
__NetBSD__ Defined on NetBSD
__OpenBSD__ Defined on OpenBSD
__APPLE__ Defined on Mac OS X
__hpux Defined on HP-UX
__osf__ Defined on Tru64 UNIX (formerly DEC OSF1)
__sgi Defined on Irix
_AIX Defined on AIX
_WIN32 Defined on Windows
I know it is not answer but added if someone looking same in Qt
In Qt
https://wiki.qt.io/Get-OS-name-in-Qt
QString Get::osName()
{
#if defined(Q_OS_ANDROID)
return QLatin1String("android");
#elif defined(Q_OS_BLACKBERRY)
return QLatin1String("blackberry");
#elif defined(Q_OS_IOS)
return QLatin1String("ios");
#elif defined(Q_OS_MAC)
return QLatin1String("osx");
#elif defined(Q_OS_WINCE)
return QLatin1String("wince");
#elif defined(Q_OS_WIN)
return QLatin1String("windows");
#elif defined(Q_OS_LINUX)
return QLatin1String("linux");
#elif defined(Q_OS_UNIX)
return QLatin1String("unix");
#else
return QLatin1String("unknown");
#endif
}
It depends on the used compiler.
For example, Windows' definition can be WIN32 or _WIN32.
And Linux' definition can be UNIX or __unix__ or LINUX or __linux__.
This response isn't about macro war, but producing error if no matching platform is found.
#ifdef LINUX_KEY_WORD
... // linux code goes here.
#elif WINDOWS_KEY_WORD
... // windows code goes here.
#else
#error Platform not supported
#endif
If #error is not supported, you may use static_assert (C++0x) keyword. Or you may implement custom STATIC_ASSERT, or just declare an array of size 0, or have switch that has duplicate cases. In short, produce error at compile time and not at runtime
It depends on the compiler. If you compile with, say, G++ on Linux and VC++ on Windows, this will do :
#ifdef linux
...
#elif _WIN32
...
#else
...
#endif
No, these defines are compiler dependent. What you can do, use your own set of defines, and set them on the Makefile. See this thread for more info.