What is the compiler-defined macro for WASM? - c

What is the macro that clang and/or gcc would define when compiling for a WASM backend?
To clarify, one can write platform-specific code using macros the compiler defines like so:
#if _WIN32
// Windows-specific code
#elif __linux__
// Linux-specific code
#elif __APPLE__
// macOS-specific code
#else
#error Unsupported platform
#endif
I would like to do the same thing specifying WebAssembly as one of the potential backends.

As per #Jonathan Leffler's comment, there does not appear to be a standard macro that is defined across compilers.
My current solution for working with different compilers is to create a separate build job for WASM that defines a macro. For gcc and clang, it passes the flag -D__WASM__ to define a __WASM__ macro.
In my setup, I just change an environment variable and my build script selects the appropriate build flags.

Related

How to check if a feature macro has effect?

In C, what is the correct way to check if a feature macro has any effect?
For example, if configure.ac contains the macro AC_USE_SYSTEM_EXTENSIONS then it will define _GNU_SOURCE on whatever OS. However, if we compile on OSX then _GNU_SOURCE will not have any effect. But on GNU systems it does, so how can I check if _GNU_SOURCE enables a feature, such as qsort_r?
man feature_test_macros says I should not include features.h, since it could be different on every system, meaning I can not use __USE_GNU.
The other option would be to check if __GNUC__ is defined, or possibly if both __GNUC__ and _GNU_SOURCE are defined?

Predefined cpu target macro for Cortex-M0+

I am currently using predefined cpu target macros to make software run on multiple cpu targets.
#ifdef __TARGET_CPU_CORTEX_M0
[do something here]
#elif __TARGET_CPU_CORTEX_M3
[do something here]
#else
#error Unsupported compiler platform
#endif
Example:
This works for Cortex-M0 and Cortex-M3, but I can't figure out what macro to use for Cortex-M0+. Does anyone know which macro I can use?
I use the armcc compiler.
This is documented, albeit rather obliquely. The relevant macro name is derived from the command-line option, thus --cpu=Cortex-M0plus defines __TARGET_CPU_CORTEX_M0PLUS.
Annoyingly, whilst it doesn't show up in the --cpu=list output, the compiler (I tried armcc version 5.04) does also recognise the option --cpu=Cortex-M0+, for which it defines the macro __TARGET_CPU_CORTEX_M0_
In general, invoking armcc --cpu=xx --list_macros /dev/null will show what macros are defined for cpu option xx (or an error if it isn't supported).

Check for availablity of #warning preprocessor

I am going to use #warning in my portable C code for generating compile time warnings. But #warning is not supported in all platforms. Is there any way to find whether #warning is supported in that platform.
#ifdef warning //expecting similar check, not exactly this
#warning ("my message")
#endif
Because I will be compiling my code in so many platforms, in some platform it may give compilation error if its not supported. If some macro are available to find the availability of #warning then I will be able to avoid build failure in platforms where it's not supported.
You can use something like this to check for support:
#if defined(_MSC_VER) || defined(__GNUC__) || defined(__clang__)
# define HAVE_WARNING
#endif
#ifdef HAVE_WARNING
# pragma message("some warning")
#endif
Add more compiler-specific checks to the first #if when needed.
#pragma message("Warning...")
#pragma message "Oh NO!"
Are both supported by GCC and MSVC. Some please comment on Clang? I don't have a current version.
#warning is a gcc extension mainly, although some others may support. Microsoft will require something like #pragma message instead. You can not call it "portable" if you mean a standard C version rather than just where gcc is available.

Where is stdarg.h?

On my system (Mac OS 10.6) /usr/include/stdarg.h is:
/* This file is public domain. */
/* GCC uses its own copy of this header */
#if defined(__GNUC__)
#include_next <stdarg.h>
#elif defined(__MWERKS__)
#include "mw_stdarg.h"
#else
#error "This header only supports __MWERKS__."
#endif
So, if GCC uses its own copy of stdarg.h, where is it? I have no idea on what
that #include_next means (maybe a GCC extension?), nor something about
"MWERKS" (a compiler?).
<stdarg.h>, even more than most C library headers, tends to be very compiler-specific. As such, each of the compilers on OS X has it's own stdarg.h implementation, found in a compiler-specific location (which is included as part of the default search paths for that compiler). The compiler finds the generic stdarg.h, which basically tells it to "keep looking" (via the extension #include_next), and it then finds the compiler-specific implementation.
__MWERKS__ refers to an old compiler for PPC, "MetroWerks CodeWarrior".
#include_next is a gcc extension. As you should know, #include has a list of paths it searches for header files. #include_next tells the preprocessor to include the specified header checking only paths in the list after the one that contained the current header file.
__MWERKS__ is a preprocessor macro defined on old versions of CodeWarrior.

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.

Resources