Why does OpenBSD's G++ make system headers default to C linkage? - gcc

I am porting some code to OpenBSD 5.0 and I ran into this very strange problem.
My build settings use -isystem /usr/local/include. It is hard to remember but I believe I did that to avoid masses of compiler warnings from my use of -Wall on system types -- like BSD -- that install Boost to /usr/local/include. This seems to work great on FreeBSD.
So take the following program:
#include <boost/array.hpp>
int main()
{
return 0;
}
Then build it with:
c++ -O2 -pipe -isystem /usr/local/include -std=c++98 -o test test.cxx
On OpenBSD I discovered that I get:
In file included from /usr/include/g++/string:46,
from /usr/include/g++/stdexcept:44,
from /usr/local/include/boost/array.hpp:35,
from test.cxx:1:
/usr/include/g++/bits/stringfwd.h:48: error: template with C linkage
And it only gets worse from there.
I discovered that I can change the error messages by doing things such as:
#include <stdexcept>
But that only pushes the problem farther back. It is as if the compiler is wrapping every include file inside an extern "C" block.
So far, the only working method seems to be to change back to using -I /usr/local/include and accept the noise from -Wall -W.
The question is, why did OpenBSD do this? It has to be some kind of custom hack to GCC to treat system includes this way.

Recently came across the same issue when working with a freestanding cross compiler.
It seems G++ will do this when targeting "old" systems as indicated here:
http://tigcc.ticalc.org/doc/cpp.html#SEC9a
On very old systems, some of the pre-defined system header directories get even more special treatment. GNU C++ considers code in headers found in those directories to be surrounded by an extern "C" block. There is no way to request this behavior with a #pragma, or from the command line.
Hope this may provide some insight to future travelers here.

Related

Compiling C code with gcc without a makefile on Mac M1

I am new to MacOS, I've always written code on Linux. I was used to compiling C files with gcc, simply like
gcc -o file file.c -lm -lgsl
where here I assumed the code to contain among its includes
#include <math.h>
#include <gsl/gsl_rng.h>
Of course the library gsl is correctly installed on my Mac via homebrew, and so are pkg-config and "Command line tools", but still when I try to compile file.c I get an error message,
fatal error: 'gsl/gsl_rng.h' file not found
#include <gsl/gsl_rng.h>
^~~~~~~~~~~~~~~
The problem is not specific to gsl (I tried for instance with the library fftw3 and got the same result).
I've seen tons of people with the same kind of problems on new M1 Macs; I've read that gcc on Mac is really "clang", and different rules apply. A ton of mocking answers were suggesting to add the correct library paths to the makefile or the like. But actually I've never before felt the need for a makefile on Linux, and surely I don't want to start adding cflags and paths whenever I compile a code (I'm working on several machines with different operating systems, with my code stored on Cloud servers, so I assume I should write a makefile for each of them? Really?).
Has anyone found a proper fix?

gcc undefined reference to with pthread [duplicate]

I picked up the following demo off the web from https://computing.llnl.gov/tutorials/pthreads/
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
But when I compile it on my machine (running Ubuntu Linux 9.04) I get the following error:
corey#ubuntu:~/demo$ gcc -o term term.c
term.c: In function ‘main’:
term.c:23: warning: incompatible implicit declaration of built-in function ‘exit’
/tmp/cc8BMzwx.o: In function `main':
term.c:(.text+0x82): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
This doesn't make any sense to me, because the header includes pthread.h, which should have the pthread_create function. Any ideas what's going wrong?
For Linux the correct command is:
gcc -pthread -o term term.c
In general, libraries should follow sources and objects on command line, and -lpthread is not an "option", it's a library specification. On a system with only libpthread.a installed,
gcc -lpthread ...
will fail to link.
Read this or this detailed explanation.
For Linux the correct command is:
gcc -o term term.c -lpthread
you have to put -lpthread just after the compile command,this command will tell to the compiler to execute program with pthread.h library.
gcc -l links with a library file.Link -l with library name without the lib prefix.
in eclipse
properties->c/c++Build->setting->GCC C++ linker->libraries in top part add "pthread"
Running from the Linux terminal, what worked for me was compiling using the following command (suppose the c file I want to compile is called test.c):
gcc -o test test.c -pthread
Hope it helps somebody!
If you are using cmake, you can use:
add_compile_options(-pthread)
Or
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
I believe the proper way of adding pthread in CMake is with the following
find_package (Threads REQUIRED)
target_link_libraries(helloworld
${CMAKE_THREAD_LIBS_INIT}
)
Acutally, it gives several examples of compile commands used for pthreads codes are listed in the table below, if you continue reading the following tutorial:
https://computing.llnl.gov/tutorials/pthreads/#Compiling
Compile it like this : gcc demo.c -o demo -pthread
In Visual Studio 2019 specify -pthread in the property pages for the project under:
Linker -> Command Line -> Additional Options
Type in -pthread in the textbox.
You need to use the option -lpthread with gcc.
you need only Add "pthread" in proprieties=>C/C++ build=>GCC C++ Linker=>Libraries=> top part "Libraries(-l)".
thats it
check man page and you will get.
Compile and link with -pthread.
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
....
Since none of the answers exactly covered my need (using MSVS Code), I add here my experience with this IDE and CMAKE build tools too.
Step 1: Make sure in your .cpp, (or .hpp if needed) you have included:
#include <functional>
Step 2 For MSVSCode IDE users:
Add this line to your c_cpp_properties.json file:
"compilerArgs": ["-pthread"],
Step 2 For CMAKE build tools users:
Add this line to your CMakeLists.txt
set(CMAKE_CXX_FLAGS "-pthread")
Note: Adding flag -lpthread (instead of -pthread) results in failed linking.
From man gcc,
-pthread
Define additional macros required for using the POSIX threads library.
You should use this option consistently for both compilation and linking.
This option is supported on GNU/Linux targets,
most other Unix derivatives,
and also on x86 Cygwin and MinGW targets.
It is correct that -pthread is an option and the best way to handle this.
There are statements in some answers that it generates different compiled code. This is misleading.
If you wish to duplicate -pthread, you could use -lpthread -D_REENTRANT=1. So there are two things going on with the -pthread option.
Indeed it links with the pthread library as many answers express. Also, the order of the pthread library is important because it may override some weak symbols. So a correct version using -lpthread may need to have it multiple times on the command line.
The other important part is the _REENTRANT define. Note, that this is in the implementation namespace. Some people may care for portability and other not. However, it is very important that it is defined as the first thing in the compilation unit. This symbol will alter the way that many system headers files are parsed.
You can include #define _REENTRANT 1 at the top of every source file, but it is much easier to have it on the command line. Again, the -pthread is the best way to achieve this. Also, gcc may change the way this is implemented in the future. However, I think it is important for programmers to understand what is going on.
term.c: In function ‘main’: term.c:23: warning: incompatible implicit
declaration of built-in function ‘exit’
You never included <stdlib.h>, where exit() is declared. Also, I think newer versions of gcc have removed the need for _REENTRANT.
Why features.h?
Example on godbolt, without -pthread.
So, it is NOT generating different code. Ie, the backend of the compiler is NOT different. It is only conditional compilation and linking to different libraries. It does not generate 'lock free' code or add appropriate machine barriers because you have used this option.
In Anjuta, go to the Build menu, then Configure Project.
In the Configure Options box, add:
LDFLAGS='-lpthread'
Hope it'll help somebody too...
Sometimes, if you use multiple library, check the library dependency.
(e.g. -lpthread -lSDL... <==> ... -lSDL -lpthread)

Clang returns different compiler errors for system include files

main.cpp:
#include "test.h"
void main () {narrowingConversion ();}
include/test.h:
void narrowingConversion () {int i = 1; char a[1] = {i};}
Clang compiles the above code successfuly when including the include folder as a system folder:
clang++ -std=c++0x -isystem./include main.cpp
But clang fails when the folder is included normally:
clang++ -std=c++0x -I./include main.cpp
./include/test.h:1:54: error: non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list [-Wc++11-narrowing]
Question: Why does clang behaves differently for system and non system files?
Clang suppresses warnings for system headers by default. It seems to deem C++11 narrowing a non-fatal error and to suppress diagnostics about that in this context.
As per the manual, to see this when the header was #included from a directory deemed to be a system one (which -Isystem specifies), you'd need to enable this option:
-Wsystem-headers
Enable warnings from system headers.
This flag is probably inherited from GCC, to which it was added in 2000. The rationale for that was:
The header files declaring interfaces to the operating system and runtime libraries often cannot be written in strictly conforming C. Therefore, GCC gives code found in system headers special treatment. All warnings, other than those generated by ‘#warning’ (see Diagnostics), are suppressed while GCC is processing a system header. Macros defined in a system header are immune to a few warnings wherever they are expanded. […]
m7913d found the equivalent section of the Clang documentation, which doesn't give as much exposition as GCC did:
More information can be found here: Controlling Diagnostics in System Headers
But the core result is the same:
Warnings are suppressed when they occur in system headers.
And, as we've seen, Clang seems to consider C++11 narrowing not to be a hard error, and to suppress it for system headers in the absence of -Wsystem-headers.

Error during make

I am trying to compile my file using make, however, it shows the following error
/usr/bin/gcc -march=i586 -m32 -fno-builtin -fno-stack-protector -nostdlib -c -Wall -O0 -DBSDURG -DVERSION=\""`cat version`"\" -I../include -o binaries/farm.o ../system/farm.c
Loading object files to produce GRUB bootable xinu
binaries/farm.o: In function `initialize':
farm.c:(.text+0x2c): undefined reference to `malloc'
After some searching, people have mentioned that not include "stdlib.h" may be the cause, however, I have included it
/* farm.c - definition of farmer and vegetarian lab */
#include <xinu.h>
#include "farm.h"
#include <stdio.h>
#include <stdlib.h>
Anyone some idea what are the possible causes?
Many Thanks!
-nostdlib flag means "don't link with standard C library". malloc is libc function. Either you link with libc (by removing -nostdlib), or, if that's a requirement, - implement another malloc (or don't use this function).
Include files are for compilation time resolution of functions not link time resolution of symbols.
That is a link time issue.
Your problem is most likely caused by the -nostdlib since you have told gcc not to include any of the normal standard library functions during linking. (It might be -fono-builtin but I don't think so.)
You either need to provide your own implementation of whatever standard functions you need (in this case malloc) or manually link with whatever library includes malloc (-lgcc perhaps?) or drop -nostdlib from your compilation and linking line.

How to compile for a freestanding environment with GCC?

The code I'm working on is supposed to be possible to build for both hosted and freestanding environments, providing private implementations for some stdlib functions for the latter case.
Can I reliably test this with just GCC on a normal workstation/build server? Compile for freestanding environment with GCC
The "-ffreestanding" option looked promising, but it seems that it "only" disables built-ins and sets the STDC_HOSTED macro properly, it still provides all system headers.
The option "-nostdinc" is too restrictive; I still want to use the headers required for a freestanding implementation (in particular stddef.h and limits.h).
What am I missing here?
Oh, and I'm using GCC 4.4.3 for the moment, will upgrade to 4.5.0 "soon".
Well, since no answer is given yet I'd might as well describe how I made this work. It's pretty simple although depending on the target system it can be tedious.
Using "-nostdinc" means that the standard system include paths will be skipped; other include-paths given with "-I" will of course still be searched for headers.
So, for the freestanding build target I create a folder 'include-freestanding-c89' and link the relevant system headers -- float.h, iso646.h, limits.h, stdarg.h and stddef.h -- there. Other headers might be included in these, depending on your platform, so you might have to do some research and set up more links (hence the tediousness if you need to do this for several target platforms).
The C89 directory can then be used as base for 'include-freestanding-c99', the extra headers to link are stdbool.h and stdint.h
The command-line to use is then
gcc -std=c89 -nostdinc -nostdlib -ffreestanding -I include-freestanding-c89
or
gcc -std=c99 -nostdinc -nostdlib -ffreestanding -I include-freestanding-c99
This Xen Makefile uses gcc -print-search-dirs to get the directory with stddef.h and similar, adds it with -isystem, then uses -nostdinc to build:
https://github.com/mirage/xen/blob/2676bc915157ab474ee478d929b0928cf696b385/stubdom/Makefile#L35

Resources