Find C++ platform target at compile time in visual studio - c++

I am building my solution for x86 and x64 platforms.
Does Visual Studio have any target platform variables so I find which platform I am building for in compile time?
For example:
HINSTANCE hinstLib;
#ifdef TARGET_X86
hinstLib = LoadLibrary("32lib.dll");
#endif
#ifdef TARGET_X64
hinstLib = LoadLibrary("64lib.dll");
#endif

This is what I use:
#if defined(_MSC_VER)
// Microsoft VC compiler
# if defined(_WIN32)
# if defined(_WIN64)
// 64 bit windows
# else
// 32 bit windows
# endif
# endif
#endif
Note that _WIN32 is defined for 64 bit too.

Have a look here: http://msdn.microsoft.com/en-US/library/b0084kay.aspx
_WIN64 or _M_X64 should work.
So for your example:
HINSTANCE hinstLib;
#ifdef _WIN64
hinstLib = LoadLibrary("64lib.dll");
#else
hinstLib = LoadLibrary("32lib.dll");
#endif

Related

using #if to run a function

I'm trying to run the expression _setmode only if I'm using Windows, and setlocale only if I'm using Linux, but I can't manage to make them work with a simple if-else inside a function due to Linux having errors with the Windows libraries, and vice versa.
#if defined(_WIN32) || defined(_WIN64) || (defined(__CYGWIN__) && !defined(_WIN32))
#define PLATFORM_NAME 0
#include <io.h>
#include <fcntl.h>
#elif defined(__linux__)
#define PLATFORM_NAME 1
#include <locale>
#elif defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_OS_MAC == 1
#define PLATFORM_NAME 2
#endif
#else
#define PLATFORM_NAME NULL
#endif
#if PLATFORM_NAME == 0
_setmode(_fileno(stdout), _O_U8TEXT);
#endif
#if PLATFORM_NAME == 1
setlocale(LC_CTYPE, "");
#endif
If you write OS-dependent* code (as in this case), you can manage it at compile-time**. To do this, we need two parts:
Define OS-dependent constants (optional, if condition simple, this part can be omitted):
#if defined(_WIN32)
#define PLATFORM_NAME 0
#include <fcntl.h>
#include <io.h>
#elif defined(__linux__)
#define PLATFORM_NAME 1
#include <locale>
#endif
In needed place call OS-dependent code with preprocessor conditions:
#if PLATFORM_NAME == 0
//Windows code here
#endif
You can write more complex conditions:
#if PLATFORM_NAME == 0
//Windows code here
#elif PLATFORM_NAME != 0
//Non-Windows code here
#if PLATFORM_NAME == 1 || PLATFORM_NAME == 2
//Linux or unknown OS code here
#endif
#endif
See restrictions of conditions here
Tip: If your code have entrypoint (main function as example), you can call most of OS-dependent code at main if this help to reduce code. In library you can place OS-dependent code to dedicated source-file functions like there. Usage preprocessor-time code is good method for writing zero-cost runtime code because of preprocessor just remove all sources,if they're not met conditions.
* - or whatever-dependent 😃
** - more precisely, preprocessor-time
Source: GNU, Microsoft docs.

Tesseract cross-compile aarch64 (arm64-v8a) error this header is for x86 only

I'm trying to cross compile Tesseract for arm64-v8a architecture settings are as follow.
set(ANDROID_TOOLCHAIN_NAME aarch64-linux-android)
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
Compiler checks working as follow.
Performing Test COMPILER_SUPPORTS_MARCH_NATIVE
Performing Test COMPILER_SUPPORTS_MARCH_NATIVE - Failed
Performing Test HAVE_AVX
Performing Test HAVE_AVX - Success
Performing Test HAVE_AVX2
Performing Test HAVE_AVX2 - Success
Performing Test HAVE_FMA
Performing Test HAVE_FMA - Success
Performing Test HAVE_SSE4_1
Performing Test HAVE_SSE4_1 - Success
Performing Test HAVE_NEON
Performing Test HAVE_NEON - Success
and tesseract simddetect.cpp have following macros.
#if defined(HAVE_AVX) || defined(HAVE_AVX2) || defined(HAVE_FMA) || defined(HAVE_SSE4_1)
#define HAS_CPUID
#endif
#if defined(HAS_CPUID)
#if defined(__GNUC__)
# include <cpuid.h>
#elif defined(_WIN32)
# include <intrin.h>
#endif
#endif
#if defined(HAVE_NEON) && !defined(__aarch64__)
#ifdef ANDROID
#include <cpu-features.h>
#else
/* Assume linux */
#include <sys/auxv.h>
#include <asm/hwcap.h>
#endif
#endif
SIMDDetect SIMDDetect::detector;
#if defined(__aarch64__)
// ARMv8 always has NEON.
bool SIMDDetect::neon_available_ = true;
#elif defined(HAVE_NEON)
// If true, then Neon has been detected.
bool SIMDDetect::neon_available_;
#else
// If true, then AVX has been detected.
bool SIMDDetect::avx_available_;
bool SIMDDetect::avx2_available_;
bool SIMDDetect::avx512F_available_;
bool SIMDDetect::avx512BW_available_;
// If true, then FMA has been detected.
bool SIMDDetect::fma_available_;
// If true, then SSe4.1 has been detected.
bool SIMDDetect::sse_available_;
#endif
compiler error
cpuid.h:11:2#error this header is for x86 only
Why tesseract include cpuid.h if it is only x86 file? what could be the fix for this error?
Based on error message problem is seems to be in your toolchain:
You try to build 64bit arm version (arm64-v8a, aarch64-linux-android)
But your compiler provide only x86 only version of cpuid.h (#error this header is for x86 only)

C++ Platform Support

I am planning to make my C++ application compatible with Windows/Mac/Linux. At the moment I came up with this "code":
#if defined(_WIN32) || defined(WIN32) || defined(__WIN32__) || defined(__NT__)
#include <Windows.h>
#elif defined(__APPLE__) || defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
#error "IOS simulator is not supported!"
#elif TARGET_OS_IPHONE == 1
#error "IOS is not supported!"
#elif TARGET_OS_MAC == 1
//MAC??????
#else
#error "Unknown Apple platform!"
#endif
#else
#error "The platform you are currently using is not compatible!"
#endif
I don't know if I implemented Windows correctly, but at least I know what to include. So my questions are:
What do I need to import to use the Mac system library?
How can I implement linux support and what do i need to include to use his library?
I need the system libraries because later I planned to make a window class based on the system's libraries, I think you can do it for Windows but I am not really if you can do it sure on linux/mac.
Update #1:
Ok so I figured out which macros to use but what libraries should I include?
#if defined(_WIN32) || defined(WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
#define PLATFORM_WINDOWS
#include <Windows.h>
#elif defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
#define PLATFORM_IPHONE_SIMULATOR
#error "Iphone simulator environment is not compatible!"
#elif TARGET_OS_IPHONE == 1
#define PLATFORM_IPHONE
#error "Iphone environment is not compatible!"
#elif TARGET_OS_MAC == 1
#define PLATFORM_MACOS
//what do I need to include here???
#endif
#elif defined(__ANDROID__)
#define PLATFORM_ANDROID
#error "Android environment is not compatible!"
#elif defined(__linux__) || defined(__linux) || defined(linux)
#define PLATFORM_LINUX
//what do i need to include here???
#else
#error "The platform you are currently using is not compatible!"
#endif

Chromium `debugger` equivalent, on `gdb` for Cygwin?

How do people trigger a breakpoint on gdb (for Cygwin, specifically) from the very source code?
Like when a JS script has the debugger word in it and Chromium dev tools trigger stop for debugging?
Here's how SDL2 implements this feature:
#if defined(_MSC_VER)
/* Don't include intrin.h here because it contains C++ code */
extern void __cdecl __debugbreak(void);
#define SDL_TriggerBreakpoint() __debugbreak()
#elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
#elif defined(__386__) && defined(__WATCOMC__)
#define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__)
#include <signal.h>
#define SDL_TriggerBreakpoint() raise(SIGTRAP)
#else
/* How do we trigger breakpoints on this platform? */
#define SDL_TriggerBreakpoint()
#endif
The conditionals should probably resolve to __asm__ __volatile__ ( "int $3\n\t" ) on Cygwin.

How do I find the name of an operating system?

The questions pretty simple. I want want a function (C++) or method which will, on call, returun something like
"Windows" //or
"Unix"
Nothing fancy, I dont need the version numbe or anything. Just the os name. A quick google searc didnt turn up anything useful, so I thought I'd post this here
Since you can not have a single binary file which runs over all operating systems, and you need to re-compile your code again. It's OK to use MACROs.
Use macros such as
_WIN32
_WIN64
__unix
__unix__
__APPLE__
__MACH__
__linux__
__FreeBSD__
like this
std::string getOsName()
{
#ifdef _WIN32
return "Windows 32-bit";
#elif _WIN64
return "Windows 64-bit";
#elif __APPLE__ || __MACH__
return "Mac OSX";
#elif __linux__
return "Linux";
#elif __FreeBSD__
return "FreeBSD";
#elif __unix || __unix__
return "Unix";
#else
return "Other";
#endif
}
You should read compiler's manuals and see what MACROS they provided to detect the OS on compile time.
From the Poco source code:
Win32:
std::string EnvironmentImpl::osNameImpl()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information");
switch (vi.dwPlatformId)
{
case VER_PLATFORM_WIN32s:
return "Windows 3.x";
case VER_PLATFORM_WIN32_WINDOWS:
return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98";
case VER_PLATFORM_WIN32_NT:
return "Windows NT";
default:
return "Unknown";
}
}
Unix:
std::string EnvironmentImpl::osNameImpl()
{
struct utsname uts;
uname(&uts);
return uts.sysname;
}