Reputation: 553
I want to detect which operating system my .exe is being run on, so that I could perform specific operations depending on the underlying operating system. I want it to be just for windows and mac.
Upvotes: 1
Views: 5006
Reputation: 520
I had the same problem yesterday, this worked for me (main goal was detecting Android vs. other OS)
std::string get_os()
{
#ifdef __ANDROID__
return "android";
#elif _WIN32
return "windows";
#elif _WIN64
return "windows";
#elif __APPLE__ || __MACH__
return "mac";
#elif __linux__
return "linux";
#elif __FreeBSD__
return "freebsd";
#elif __unix || __unix__
return "unix";
#else
return "other";
#endif
}
Upvotes: 0
Reputation: 1391
You need to use argv[0]
which is path to your executable being ran and then:
M
Z
(Windows PE)0x7f
E
L
F
(Linux ELF)This should work if the binary is not a raw binary, which means that magic number says data
. This could deceive you if executable was cross-compiled for some other system. On Linux you can check the magic bytes with command:
file <your executable>
Upvotes: 0
Reputation: 21607
To solve this kind of problem you would need to check both at compile time and at run time. You are going to need different code for different both systems. You are going to need Windoze code to check the Windoze version and Mac code to check the Mac version.
You are going to have to use
#if defined ()
at compile time to check which of the two you are on. Then have separate code for each to get the version.
Upvotes: -1
Reputation: 1
I want to detect which operating system my .exe is being run on
(notice that on MacOSX executable files are traditionally not suffixed with .exe
; that convention is specific to Windows)
You cannot detect that in pure standard C++11 at runtime (so your question makes technically no sense), because the C++11 standard n3337 does not know about operating systems (some C++ source code may be compiled for the bare metal). I would recommend conditional compilation (e.g. #if
) and using operating system specific headers (and configuring your build automation to detect them). Some C++ frameworks (boost, poco, Qt....) could be helpful, but you need to decide to choose one (they might try to provide some common abstractions above several OSes, but the evil is still in the details, e.g. file paths are still different on Windows and on MacOSX).
MicroSoft Windows has its own API, called WinAPI (which is only, in practice, used by Windows. Perhaps some day ReactOS would implement most of that API), documented here. MacOSX is more or less conforming to POSIX, which is a standard API about a family of OSes (but Windows don't care much about that standard).
If you want to learn more about OSes in general (a sensible thing to do), read for example Operating Systems: Three Easy Pieces (freely downloadable textbook).
In practice, an executable file compiled from C++ source code is specific to the operating system it is designed to run on, and its file format is also specific to some OS (e.g. PE on Windows, ELF on Linux, Mach-O on MacOSX...). So a Windows executable won't run on MacOSX and vice versa (the fat binary idea is out of fashion in 2018). You probably would adjust your build procedure (e.g. your Makefile
, or with cmake, ninja, etc...) for your OS. That build procedure might (and often does) pass extra compilation flags (e.g. some -DBUILD_FOR_MACOSX
compiler flag for your preprocessor, if building for MacOSX; then you might -in few places- use some preprocessor directive like #if BUILD_FOR_MACOSX
in your C++ source code) specific to the target operating system. You could even customize your build so that on MacOSX some for-macosx.cc
C++ file is compiled (and its object file linked into) your software, but on Windows you'll use some other for_windows.cc
C++ file. Sometimes, the build procedure is flexible enough to auto-detect at build time what is the operating system (but how to do that is a different question. The GNU autoconf could be inspirational).
Once your build procedure has been configured for (or has auto-detected) your operating system, you could use preprocessor conditional facilities to #include
appropriate system-specific headers and to compile calls to OS specific functions (such as POSIX uname) querying further at runtime about the OS.
Some compilers predefine a set of preprocessor symbols, and that set depends upon the target operating system and processor and of your compiler. If you use GCC, you might create some empty file empty.cc
and compile it with g++ -c -C -E -dM
(perhaps also with other relevant flags, e.g. -std=c++11
) to find out which set of preprocessor symbols are predefined in your case.
Consider studying the source code (including the build procedure!) of some cross-platform free software projects (e.g. on github or somewhere else) for inspiration. You can also find many resources about multi-platform C++ builds (e.g. this one and many others).
Upvotes: 1
Reputation: 664
There are various ways you could do it, like testing for the presence of a C:\Windows directory to detect Windows (edit: if the OS accepts a path like that at all then it's at least part of the DOS family), but none of them are foolproof. Here's one way (although it's cheating):
#include<boost/predef.h>
enum class OperatingSystem {
// ...
Windows
// ...
};
OperatingSystem DetectOperatingSystem()
{
#ifdef BOOST_OS_WINDOWS
return OperatingSystem::Windows;
#endif
}
Also, if you just want a name to show the user, then on POSIX systems you can use uname(2).
Upvotes: 0