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.
I am trying to cross-compile with arm-none-eabi-gcc-9.2.x and had the following problem:
undefined symbol 'PRIu64'
(message shortened to necessary minimum by me) which was caused by the Newlib header inttypes.h doing a:
#include <stdint.h>
which motivated gcc to include its onboard stdint.h from
/usr/lib/gcc/arm-none-eabi/9.2.1/include
instead of the Newlib one in
/usr/include/newlib
thereby breaking the compilation with the above error.
Of course I first tried to prefix the include path search with the usual
arm-none-eabi-gcc-9.2.1 -I/usr/include/newlib ...
but to my big surprise gcc spew it back at me (via -xc -E -v) with:
ignoring duplicate directory "/usr/include/newlib"
as it is a non-system directory that duplicates a system directory
Only a
arm-none-eabi-gcc-9.2.1 -isystem /usr/include/newlib ...
convinced it to include the Newlib directory in its search.
Is this due to a broken installation? And how dare gcc to not include a path I am supplying?
Do the ARM people ship their gcc with both, Newlib and a set of vanilla gcc system headers or where did this misconfiguration come from?
Indeed, newlib provides <stdint.h> while gcc also provides it. So, when <inttypes.h> includes <stdint.h> it does not include <stdint.h> from newlib but the one from gcc. It wouldn't be a big deal if <stdint.h> wouldn't define some macro used internally by <inttypes.h>.
The best thing to do is to fix newlib, change your compiler or patch your system headers.
If it is not possible you can include <sys/types.h> before <inttypes.h>. <sys/types.h> includes <_stdint.h> that define the necessary macros.
It seems the problem is specific to arm-none-gcc provided by Debian:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=953844
I am doing an assignment which states: "The skeleton code given uses getopt. If you compile the code with -std=c99, there will be compilation
error. To fix the error, include -D_POSIX_C_SOURCE=200809 when you compile the code."
I am very new to this. Ordinarily I compile a C program with GCC (program name) and then I type ./a.out.
What am I required to do here?
The sentence “To fix the error, include -D_POSIX_C_SOURCE=200809 when you compile the code” means to include the characters -D_POSIX_C_SOURCE=200809 in the command you use to compile the program.
For example, if you normally use gcc -o foo foo.c, change it to gcc -o foo -D_POSIX_C_SOURCE=200809 foo.c.
This is a command line argument that tells the compiler to define a preprocessor macro named _POSIX_C_SOURCE to be replaced by 200809. This preprocessor macro is used by various header files to adapt to different versions of POSIX (by using #if statements to test the macro). For example, if you specify _POSIX_C_SOURCE to be 200809 or leave it undefined, the headers will not declare routines that were only added to POSIX after the 2008-09 version of POSIX. Among other things, this avoids causing conflicts with programs written before then that might have happened to use names of those routines for other purposes (since they would have had no way of knowing what names POSIX header would define in the future).
You can also define the macro in your source code, before any headers that use it are included, with:
#define _POSIX_C_SOURCE 200809
The getopt function is a relatively recent addition to the Single UNIX Specification/POSIX Standard. While Linux doesn't comply with POSIX, it does roughly use this standard as a reference point. However, it's mostly implementing XSH (System Headers) of POSIX '03 or earlier by default for compatibility. If you want more recent additions exposed (Note: #JonathanLeffler mentions that getopt is there for quite some time already, but Linux doesn't expose it by default anyway), you can tell the GNU libc (the C Library commonly used on GNU/Linux systems) to also provide some of that functionality which are hidden behind Feature Test Macros. Lookup the man-page man -s 7 feature_test_macros 2 in combination with man -s 3 getopt 1 for more. Basically, in the respective headers there's some code similar to the following:
#if _POSIX_C_SOURCE >= 200809L
/* declaration of getopt() and other newer functions */
#endif
If you then include that file and do not define the feature test macro to have a value greater than (newer/more recent than) the date of that POSIX standard you need (2008-09), the C Preprocessor will throw away all those forward declarations, making your code error out.
Using -DFOO=bar you #define FOO bar on the command line for the standard C Compiler. By the way, the GNU C Compiler also sets some of such flags when you use -std=c99.
In the end, your command line should look more or less like this:
$ c99 -D_POSIX_C_SOURCE=200809L -o foo foo.c
This will compile and link foo.c to the output file foo adhering to the C99 standard and using features from POSIX '08 3.
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?
When defining macros that headers rely on, such as _FILE_OFFSET_BITS, FUSE_USE_VERSION, _GNU_SOURCE among others, where is the best place to put them?
Some possibilities I've considered include
At the top of the any source files that rely on definitions exposed by headers included in that file
Immediately before the include for the relevant header(s)
Define at the CPPFLAGS level via the compiler? (such as -D_FILE_OFFSET_BITS=64) for the:
Entire source repo
The whole project
Just the sources that require it
In project headers, which should also include those relevant headers to which the macros apply
Some other place I haven't thought of, but is infinitely superior
A note: Justification by applicability to make, autotools, and other build systems is a factor in my decision.
If the macros affect system headers, they probably ought to go somewhere where they affect every source file that includes those system headers (which includes those that include them indirectly). The most logical place would therefore be on the command line, assuming your build system allows you to set e.g. CPPFLAGS to affect the compilation of every file.
If you use precompiled headers, and have a precompiled header that must therefore be included first in every source file (e.g. stdafx.h for MSVC projects) then you could put them in there too.
For macros that affect self-contained libraries (whether third-party or written by you), I would create a wrapper header that defines the macros and then includes the library header. All uses of the library from your project should then include your wrapper header rather than including the library header directly. This avoids defining macros unnecessarily, and makes it clear that they relate to that library. If there are dependencies between libraries then you might want to make the macros global (in the build system or precompiled header) just to be on the safe side.
Well, it depends.
Most, I'd define via the command line - in a Makefile or whatever build system you use.
As for _FILE_OFFSET_BITS I really wouldn't define it explicitly, but rather use getconf LFS_CFLAGS and getconf LFS_LDFLAGS.
I would always put them on the command line via CPPFLAGS for the whole project. If you put them any other place, there's a danger that you might forget to copy them into a new source file or include a system header before including the project header that defines them, and this could lead to extremely nasty bugs (like one file declaring a legacy 32-bit struct stat and passing its address to a function in another file which expects a 64-bit struct stat).
BTW, it's really ridiculous that _FILE_OFFSET_BITS=64 still isn't the default on glibc.
Most projects that I've seen use them did it via -D command line options. They are there because that eases building the source with different compilers and system headers. If you were to build with a system compiler for another system that didn't need them or needed a different set of them then a configure script can easily change the command line arguments that a make file passes to the compiler.
It's probably best to do it for the entire program because some of the flags effect which version of a function gets brought in or the size/layout of a struct and mixing those up could cause crazy things if you aren't careful.
They certainly are annoying to keep up with.
For _GNU_SOURCE and the autotools in particular, you could use AC_USE_SYSTEM_EXTENSIONS (citing liberally from the autoconf manual here):
-- Macro: AC_USE_SYSTEM_EXTENSIONS
This macro was introduced in Autoconf 2.60. If possible, enable
extensions to C or Posix on hosts that normally disable the
extensions, typically due to standards-conformance namespace
issues. This should be called before any macros that run the C
compiler. The following preprocessor macros are defined where
appropriate:
_GNU_SOURCE
Enable extensions on GNU/Linux.
__EXTENSIONS__
Enable general extensions on Solaris.
_POSIX_PTHREAD_SEMANTICS
Enable threading extensions on Solaris.
_TANDEM_SOURCE
Enable extensions for the HP NonStop platform.
_ALL_SOURCE
Enable extensions for AIX 3, and for Interix.
_POSIX_SOURCE
Enable Posix functions for Minix.
_POSIX_1_SOURCE
Enable additional Posix functions for Minix.
_MINIX
Identify Minix platform. This particular preprocessor macro
is obsolescent, and may be removed in a future release of
Autoconf.
For _FILE_OFFSET_BITS, you need to call AC_SYS_LARGEFILE and AC_FUNC_FSEEKO:
— Macro: AC_SYS_LARGEFILE
Arrange for 64-bit file offsets, known as large-file support. On some hosts, one must use special compiler options to build programs that can access large files. Append any such options to the output variable CC. Define _FILE_OFFSET_BITS and _LARGE_FILES if necessary.
Large-file support can be disabled by configuring with the --disable-largefile option.
If you use this macro, check that your program works even when off_t is wider than long int, since this is common when large-file support is enabled. For example, it is not correct to print an arbitrary off_t value X with printf("%ld", (long int) X).
The LFS introduced the fseeko and ftello functions to replace their C counterparts fseek and ftell that do not use off_t. Take care to use AC_FUNC_FSEEKO to make their prototypes available when using them and large-file support is enabled.
If you are using autoheader to generate a config.h, you could define the other macros you care about using AC_DEFINE or AC_DEFINE_UNQUOTED:
AC_DEFINE([FUSE_VERSION], [28], [FUSE Version.])
The definition will then get passed to the command line or placed in config.h, if you're using autoheader. The real benefit of AC_DEFINE is that it easily allows preprocessor definitions as a result of configure checks and separates system-specific cruft from the important details.
When writing the .c file, #include "config.h" first, then the interface header (e.g., foo.h for foo.c - this ensures that the header has no missing dependencies), then all other headers.
I usually put them as close as practicable to the things that need them, whilst ensuring you don't set them incorrectly.
Related pieces of information should be kept close to make it easier to identify. A classic example is the ability for C to now allow variable definitions anywhere in the code rather than just at the top of a function:
void something (void) {
// 600 lines of code here
int x = fn(y);
// more code here
}
is a lot better than:
void something (void) {
int x;
// 600 lines of code here
x = fn(y);
// more code here
}
since you don't have to go searching for the type of x in the latter case.
By way of example, if you need to compile a single source file multiple times with different values, you have to do it with the compiler:
gcc -Dmydefine=7 -o binary7 source.c
gcc -Dmydefine=9 -o binary9 source.c
However, if every compilation of that file will use 7, it can be moved closer to the place where it's used:
source.c:
#include <stdio.h>
#define mydefine 7
#include "header_that_uses_mydefine.h"
#define mydefine 7
#include "another_header_that_uses_mydefine.h"
Note that I've done it twice so that it's more localised. This isn't a problem since, if you change only one, the compiler will tell you about it, but it ensures that you know those defines are set for the specific headers.
And, if you're certain that you will never include (for example) bitio.h without first setting BITCOUNT to 8, you can even go so far as to create a bitio8.h file containing nothing but:
#define BITCOUNT 8
#include "bitio.h"
and then just include bitio8.h in your source files.
Global, project-wide constants that are target specific are best put in CCFLAGS in your makefile. Constants you use all over the place can go in appropriate header files which are included by any file that uses them.
For example,
// bool.h - a boolean type for C
#ifndef __BOOL_H__
#define BOOL_H
typedef int bool_t
#define TRUE 1
#define FALSE 0
#endif
Then, in some other header,
`#include "bool.h"`
// blah
Using header files is what I recommend because it allows you to have a code base built by make files and other build systems as well as IDE projects such as Visual Studio. This gives you a single point of definition that can be accompanied by comments (I'm a fan of doxygen which allows you to generate macro documentation).
The other benefit with header files is that you can easily write unit tests to verify that only valid combinations of macros are defined.