gcc static link - gcc

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.

Related

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)

Why is it possible to override symbols from some static libraries but not others?

I'm working on a tool that links against Clang, and I need to implement a small number of changes to some operations. To improve development times, instead of rebuilding Clang, I decided to redefine the symbols of interest in my program code, and let the linker take care of the rest: in most cases, the program version of a symbol that is defined in both program code and a static library takes precedence at link-time without a fuss. (The linked answer relates to Linux, but I found that to work on macOS too–usually.)
This worked great when I was using the stock Clang build for macOS that can be downloaded from the LLVM website. However, I am currently trying to switch to my company's customized Clang (which I built once from source, and hoped to further modify in the same way), and now I get duplicate symbol errors.
I don't know what is causing this issue. My project's linker flags have remained unchanged (save for one new static library): importantly, they do not contain -all_load or its -force_load cousin, which tell the linker to try to include every symbol defined in static libraries. The symbols that I'm trying to override look defined the same way when I check them with nm in the stock archive and in the custom archive. The difference has to be with how I built LLVM, but just knowing that doesn't really help me figure out what I need to change.
For instance, say that I want to redefine clang::Qualifiers::getAsString() const. I could do that just fine using the stock LLVM libraries, but now I would get a duplicate symbol error:
duplicate symbol __ZNK5clang10Qualifiers11getAsStringEv in:
.../Objects-normal/x86_64/TypePrinter.o
clang+llvm-internal/lib/libclangAST.a(TypePrinter.cpp.o)
Using nm -f darwin to inspect both archives, I would get very similar results for __ZNK5clang10Qualifiers11getAsStringEv:
# clang+llvm-6.0.0/lib/libclangAST.a
(undefined) external __ZNK5clang10Qualifiers11getAsStringEv
0000000000000bb0 (__TEXT,__text) external __ZNK5clang10Qualifiers11getAsStringEv
# clang+llvm-internal/lib/libclangAST.a
(undefined) external __ZNK5clang10Qualifiers11getAsStringEv
0000000000000d00 (__TEXT,__text) external __ZNK5clang10Qualifiers11getAsStringEv
So, assuming more or less identical symbol definitions, and identical linker flags, why was I able to override static library symbols this way before, and why am I no longer able to?
This part of the premise isn't quite correct:
In most cases, the program version of a symbol that is defined in both program code and a static library takes precedence at link-time without a fuss. (The linked answer relates to Linux, but I found that to work on macOS too–usually.)
The linked answer appears correct, but I originally misunderstood it. The actual behavior, as evidenced by passing -Wl,-why_load to Clang (or -why_load to the linker), goes as follow:
if a symbol is referenced, try to find its definition in the program code.
if it is defined in the program code, you're done; do not search static libraries.
if it is not defined in the program code, look up the .__SYMDEF file in the static library to know which object file has it.
use all the definitions from that object file.
The issue was that switching to the custom Clang, I accidentally pulled in references to symbols that were defined in the same object file as symbols that I am redefining, causing the linker to see both definitions. I was able to solve the problem by using the -why_load argument to the linker, and then looking for which symbol caused the problem object file to be loaded. I then duplicated the definition of that symbol to my program, and now the linker doesn't complain anymore.
The morale of the story is that this technique isn't as reliable on macOS as it is on Linux, and that if you do it, you kind of have to go all in. It's better to take the entire source file and copy it to your project than to try to pick symbols piecewise.
Actually this behavior is the same for Linux, see this reproducer:
First case: build library where symbols are in different object files:
//val.cpp - contains needed symbol
int val=42;
//wrong_main.cpp - contains duplicate symbol
int main(){
return 21;
}
>>> g++ -c val.cpp -o val.o
>>> g++ -c wrong_main.cpp -o wrong.o
>>> ar rcs libsingle.a val.o wrong.o
Linking against this library works, no multiple definition of main-error is issued, because no symbols at all are used from the object file wrong_main.o at all:
//main.cpp
extern int val;
int main(){
return val;
}
>>> g++ main.cpp -L. -lsingle -o works
Second case: both symbols are in the same object file:
//together.cpp - contains both, needed and duplicate, symbols
#include "val.cpp"
#include "wrong_main.cpp"
>>> g++ -c together.cpp -o together.o
>>> ar rcs libtogether.a all.o
Linking against libtogether.a doesn't work:
>>> g++ main.cpp -L. -ltogether -o doesntwork
./libtogether.a(all.o): In function `main':
all.cpp:(.text+0x0): multiple definition of `main'
/tmp/cc38isDb.o:main.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
The linker takes either the whole object file from a static library or nothing. In this case val is needed and so the object file together.o will be taken, but it also contains the duplicate symbol main and thus the linker issues an error.
A great description how the linker works on Linux (and very very similar on MacOS) is this article.

gcc 5.40 doesn't include standard include files?

gcc 5.4.0
cygwin 2.8.0
Win10
I've been been knocking my head around this problem.When I compile a simple program, see below, I get an error in one of the gcc include files. I checked the cygwin mailing list and no one has reported an error in the gcc download so I think it's a misunderstanding on my part but I can't figure what I did wrong. Prior to this point all the gcc include fileswere included automatically. Oh, and the compile is correct for other libraries.
The code is:
gcc -std=c++11 test.cpp or gcc test.cpp
include iostream
using namespace std;
int main(int argc, char** argv) { }
and the error message is:
/tmp/ccfBvaqg.o:test.cpp:(.text+0x44): undefined reference to std::ios_base::Init::Init()'
/tmp/ccfBvaqg.o:test.cpp:(.text+0x44): relocation truncated to fit: R_X86_64_PC32 against undefined symbolstd::ios_base::Init::Init()'
/tmp/ccfBvaqg.o:test.cpp:(.rdata$.refptr._ZNSt8ios_base4InitD1Ev[.refptr._ZNSt8ios_base4InitD1Ev]+0x0): undefined reference to `std::ios_base::Init::~Init()'
gcc is the C compiler driver. The compiler automatically detects the language based on the file name; that is why the compilation succeeded. However, the linker is not affected by the names of the source files. By default, the C compiler driver does not link with the C++ standard library.
Since you used the standard library (<iostream> is a bit atypical header file in such a way that merely including it causes a standard library function to be called at the start of the program), but did not link it, the linker fails. The solution is to link with the C++ standard library. The simplest way to do that is to use the C++ compiler driver (g++) which links the standard library by default.

Migrating g++ to 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++?

linker woes - undefined reference

I'm having a problem with my compiler telling me there is an 'undefined reference to' a function I want to use in a library. Let me share some info on the problem:
I'm cross compiling with gcc for C.
I am calling a library function which is accessed through an included header which includes another header, which contains the prototype.
I have included the headers directory using -I and i'm sure it's being found.
I'm first creating the .o files then linking them in a separate command.
So my thought is it might be the order in which I include the library files, but i'm not sure what is the correct way to order them. I tried with including the headers folder both before and after the .o file.
Some suggests would be great, and maybe and explanation of how the linker does its thing.
Thanks!
Response to answers
there is no .a library file, just .h and .c in the library, so -l isn't appropriate
my understanding of a library file is that it is just a collection of header and source files, but maybe it's a collection of .o files created from the source?!
there is no library object file being created, maybe there should be?? Yes seems I don't understand the difference between includes and libraries...i'll work on that :-)
Thanks for all the responses! I learned a lot about libraries. I'd like to put all the responses as the accepted answer :-)
Headers provide function declarations and function definitions. To allow the linker find the function's implementation (and get rid of the undefined reference) you need to ask the compiler driver (gcc) to link the specific library where the function resides using the -l flag. For instance, -lm will link the math library. A function's manual page typically specifies what library, if any, must be specified to find the function.
If the linker can't find a specified library you can add a library search path using the -L switch (for example, -L/usr/local/lib). You can also permanently affect the library path through the LIBRARY_PATH environment variable.
Here are some additional details to help you debug your problem. By convention the names of library files are prefixed with lib and (in their static form) have a .a extension. Thus, the statically linked version of the system's default math library (the one you link with -lm) typically resides in /usr/lib/libm.a. To see what symbols a given library defines you can run nm --defined-only on the library file. On my system, running the command on libm.a gives me output like the following.
e_atan2.o:
00000000 T atan2
e_asinf.o:
00000000 T asinf
e_asin.o:
00000000 T asin
To see the library path that your compiler uses and which libraries it loads by default you can invoke gcc with the -v option. Again on my system this gives the following output.
GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd)
using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o
It sounds like you are not compiling the .c file in the library to produce a .o file. The linker would look for the prototype's implementation in the .o file produced by compiling the library
Does your build process compile the library .c file?
Why do you call it a "library" if it's actually just source code?
I fear you mixed the library and header concepts.
Let's say you have a library libmylib.a that contains the function myfunc() and a corresponding header mylib.h that defines its prototype. In your source file myapp.c you include the header, either directly or including another header that includes it. For example:
/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...
your source file looks like:
/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");
Now you can compile it to obtain myapp.o:
gcc -c -I../mylib/includes myapp.c
Note that the -I just tells gcc where the headers files are, they have nothing to do with the library itself!
Now you can link your application with the real library:
gcc -o myapp -L../mylib/libs myapp.o -lmylib
Note that the -L switch tells gcc where the library is, and the -l tells it to link your code to the library.
If you don't do this last step, you may encounter the problem you described.
There might be other more complex cases but from your question, I hope this would be enough to solve your problem.
Post your makefile, and the library function you are trying to call. Even simple gcc makefiles usually have a line like this:
LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared
In this case, it means link the standard C library, among others
I guess you have to add the path where the linker can find the libraray. In gcc/ld you can do this with -L and libraray with -l.
-Ldir, --library-path=dir
Search directory dir before standard
search directories (this option must
precede the -l option that searches
that directory).
-larch, --library=archive
Include the archive file arch in the
list of files to link.
Response to answers - there is no .a library file, just .h and .c in the library, so -l isn't approriate
Then you may have to create the libraray first?
gcc -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
I have encountered this problem when building a program with a new version of gcc. The problem was fixed by calling gcc with the -std=gnu89 option. Apparently this was due to inline function declarations. I have found this solution at https://gcc.gnu.org/gcc-5/porting_to.html

Resources