Migrating g++ to gcc - gcc

I have a mixture of c and c++ files compiling under g++. As explained in:
What is the difference between g++ and gcc?
The c files are being compiled as c++ with the g++ command line. Not huge problem but migrating over to gcc will allow th c files to compile as c files and the c++ file to compile as c++.
What -I includes or -L libraries do I need to add to the gcc command line, that the g++ command line is including by default?

You shouldn't need to add any includes or libraries beyond what you already have.
Whatch out for C functions being called from C++ code - you need to tell the C++ compiler those are C functions so the program is linked correctly and works.
The standard practice is to add the following directives to all your C headers being included in C++ files:
#ifdef __cplusplus
extern "C" {
#endif
... C header contents go here ...
#ifdef __cplusplus
}
#endif
More info here: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html

You shouldn't need to add any. If it's using C++ it should automatically bring in C++ libraries.
If not, you'll want -lstdc++ (and if you're still getting undefined references, -lc for the libc). Don't forget -lm if you use math functions.

GCC can determine which language a file is in based on the file extension. However, GCC does not automatically link in run time support for any language other than C. In practice that means you can compile C++ programs using gcc instead of g++ but you'll need to add the -lstdc++ directive:
#include <iostream>
int main()
{
std::cout << "Hello world\n";
}
g++ hello.cc
gcc hello.cc -lstdc++
More accurately, you will need to specify -lstdc++ if you you use the standard library, exceptions, operator new, or RTTI. For instance, try compiling the following without -lstdc++:
int main()
{
try {
throw 1;
}
catch (int i)
{
return i;
}
}
Please note that STL containers (including std::strings) use operator new by default. Strictly speaking you should be able to use the algorithms (std::min, std::find_first_of, etc.) binders and a few other things in the standard library without -lstdc++ but for the most part you might as well include it (the linker will ignore any libraries that you don't actually link to).

Why not compile the c objects with gcc and the c++ with g++ and then when you link, link using the g++?

Related

Undocumented ABI changes of std::function between GCC-4 and GCC-5/6/7/8/9, how to make a .so working with devtoolset-4/6/7/8/9?

with _GLIBCXX_USE_CXX11_ABI=0
std::function of GCC-4 is different of GCC-5 and follwing versions.
The following code show you the fact:
==> lib.cc <==
#include <functional>
std::function<int(const void*p)> holder;
int run_holder(const void *p)
{
return holder(p);
}
==> main.cc <==
#include <stdio.h>
#include <functional>
extern int run_holder(const void*p);
extern std::function<int(const void*p)> holder;
int foo(const void* p)
{
printf("p=%p\n", p);
return 0;
}
int main()
{
holder = foo;
foo((void*)0x12345678);
holder((void*)0x12345678);
run_holder((void*)0x12345678);
}
==> make.sh <==
#!/bin/bash
GCC4=/usr/bin/g++
GCCN="scl enable devtoolset-5 -- g++"
$GCC4 -std=c++11 -c -g lib.cc -shared -o libfoo.so &&
$GCCN -std=c++11 -L. -lfoo -g main.cc -o a.out &&
LD_LIBRARY_PATH=. ./a.out
expected result, something like:
p=0x12345678
p=0x12345678
p=0x12345678
actual result:
p=0x12345678
./make.sh: line 6: 973 Segmentation fault LD_LIBRARY_PATH=. ./a.out
The reason is the implementation of std::function changes without document.
gcc4: /usr/include/c++/4.8.2/functional:2430
typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);
gcc5: /opt/rh/devtoolset-4/root/usr/include/c++/5.3.1/functional:2226
gcc8: /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/std_function.h:609
using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
So I can not write a .so using std::function compiled by gcc4 and used by gcc5/6/7/8. There is no macro like _GLIBCXX_USE_CXX11_ABI can control the behavior.
So I can not write a .so using std::function compiled by gcc4 and used by gcc5/6/7/8.
Correct. Neither Red Hat nor the GCC project has ever claimed that's possible, quite the opposite. C++11 support in GCC 4.x was incomplete and unstable, and subject to ABI changes and API changes. What you're trying to do was never supported.
I've explained this in more detail at https://stackoverflow.com/a/49119902/981959
The Developer Toolset documentation covers it too (emphasis mine):
"A compiler in C++11 or C++14 mode is only guaranteed to be compatible with another compiler in C++11 or C++14 mode if they are from the same release series (for example from Red Hat Developer Toolset 6.x).
...
"Using the C++14 language version is supported in Red Hat Developer Toolset when all C++ objects compiled with the respective flag have been built using Red Hat Developer Toolset 6 or later. Objects compiled by the system GCC in its default mode of C++98 are also compatible, but objects compiled with the system GCC in C++11 or C++14 mode are not compatible."
There is no macro like _GLIBCXX_USE_CXX11_ABI can control the behavior.
We do not provide macros to control things that are unsupported and cannot work.
If you want to use C++11 with a mix of GCC versions you need to use a release that has stable, non-experimental support for C++11. So not GCC 4.x.

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 OS X Lion, cannot find cstdint

I'm trying to compile an application that utilizes cstdint. Since Apple deprecated the gcc, I wanted to try compiling it with clang, but i get the error:
fatal error: 'cstdint' file not found
I know that the gcc 4.6.2 version has the option for -std=c++0x, to include the library, but since the os x version is 4.2 that's not much of an option here. Any suggestions on how I can move forward? I have tried to install 4.6.2, but ran into a variety of issues when compiling some of the needed libraries before building gcc.
Presumably, you have the source code to this application, so you can modify the headers to include the correct cstdint header, as Clang 3.0 (which Lion's tools come with) does have the header.
Quick Solution
The header is under the tr1 directory, so you will want to do either of these includes:
#include <tr1/cstdint>
Or
#include <stdint.h> // which will use the C99 header
Longer, boring explanation
After doing some additional reading since I remember you can do this without the tr1 directory:
By default, you are going to be including C++ headers from /usr/include/c++/4.2.1, which are the GNU GCC headers. /usr/include/c++/4.2.1/tr1 includes the TR1 header files, like cstdint.
The alternative method is to compile using the Clang++ frontend and passing the -stdlib=libc++ flag, which will use the headers from /usr/include/c++/v1, which are Clang's C++ header implementations. It has cstdint.
Example:
// file called example.cxx
#include <tr1/cstdint>
int main() {
// whatever...
}
Compile this with:
g++ example.cxx
or
clang++ example.cxx
And it will do what you want.
If you don't want to use the tr1 version (which is roughly the same, if not exactly):
// file called example.cxx
#include <cstdint>
int main() {
// stuff
}
This is compiled like this:
clang++ -stdlib=libc++ example.cxx
Though if you use -stdlib=libc++, it means you're linking to Clang's C++ library libc++, rather than GCC's libstdc++.

gcc static link

I want to static link libray which I included (such as stdio) with gcc, so I use the -static options.
My environment is ubuntu 10.10.
gcc version is 4.4.5.
the compile command I used is : gcc -static -o output.out input.c
the following is my source code.
include
int main(){
printf("hello world");
return 0;
}
After I compile it and use the -static option, I objdump the executable file.
and I found out that the printf is actually called _IO_printf.
And I write another program, the following is the souce code.
include
int main(){
return 0;
}
I compile this source code with the same option and objdump the new executable file.
However, I can't find the _IO_printf.
My question is why I can't fine _IO_printf in the second case. I have static linked the libray which I included.
Can someone plz help me solve this problem, thx.
A linker doesn't just put object files and libraries together. It creates links between the different parts. So if there is an unresolved symbol (e.g. function or variable) in one unit, it looks for it in other units and makes the connection.
Since the second program doesn't call printf, the linker does not need to resolve that symbol. So there is no point adding that function to the executable (it'll just sit there and take space). The linker can see what's missing, and should (normally) add only what's missing down to some practical granularity.

Shared Library Constructor is not executed

I have the following problem. I write a shared library
#include <stdio.h>
#include <stdlib.h>
static void __attribute__ ((constructor)) test_init(void);
static void __attribute__ ((destructor)) test_clean(void);
/* Initialization */
static void test_init(void){
fprintf(stderr,"initialized\n");
fflush(stderr);
}
/* CleanUp */
static void test_clean(void){
fprintf(stderr,"cleaned up\n");
fflush(stderr);
}
double test (double x){
return 2.0*x;
}
And compile it using
gcc -c -fPIC testlib.c -o testlib.o
ld -shared -o libtest.so testlib.o
Then I include it into a test program
#include <stdio.h>
#include <stdlib.h>
extern double test(double x);
void main(void){
printf("%.10e\n",test(10.0));
}
which I compile and start using
gcc testprog.c -o testprog -L. -ltest
LD_LIBRARY_PATH=. ./testprog
Then the output is given by
2.0000000000e+01
which means that the constructor/destructor are not executed. On the other hand, if I compile
ar rvs testlib.a testlib.o
gcc testprog.c testlib.a -o testprog
the output of the program is given by
testprog
initialized
2.0000000000e+01
cleaned up
Why are the constructors not executed if the library is linked dynamically?
I use the following versions
GNU ld (GNU Binutils; openSUSE 11.3) 2.20.0.20100122-6
gcc version 4.5.0 20100604 [gcc-4_5-branch revision 160292] (SUSE Linux)
Thank you in advance for your help!
Edited: 2011-04-13, 11:05
Thank you very much luxifer,
the document helped indirectly! The magic hint was that one should involve the linker through the compiler...
gcc -fPIC testlib.c -shared
-Wl,-soname,libtest.so -o libtest.so
works!!!
Gcc's constructor handling is not the same thing as the ELF constructor handling, rather, it sits on top of it. To work, you need to link in the glue code that is provided in gcc's startup files.
The easiest way to do that is to link using gcc:
gcc -shared -o testlib.so testlib.o
This text is meant for reference, but I'm coming over to your office for convenience :)
I'm not an expert on that field but a quick Google search gave me this. Reading just the beginning of the document and if I get it right the problem is this:
Linked statically your program is self-contained at execution time... it has the whole library in it and it's completely loaded into memory when you run it.
Linked dynamically when the library function is called from your program at execution time the linker tries to resolve all unresolved references on functions by looking if it has an implementation in some library. If so it loads this implementation, i.e. just the functions code.
So if I get this right and the dynamic linker just loads portions of libraries, i.e. needed functions, and not the whole library then this would explain why your constructor isn't called when your library is linked dynamically.

Resources