I'm learning C by rehashing some Project Euler problems, as I did for Python. In Python, I created a file of general mathematical utilities such as prime number checking, which I pulled functions out of as and when I needed them. I was wondering if there was a way to simply do a similar thing with C, other than compiling alongside the utilities file each time?
I'm running Linux and using gcc as my compiler, if that helps.
It looks like you need some basic knowledge about separate compilation and libraries(archives and shared libraries). You can read about it in chapter "2.3 Writing and Using Libraries" of
Advanced Linux Programming, 1st Edition by CodeSourcery LLC, Mark L. Mitchell, Alex Samuel, Jeffrey Oldham.
This book is also available as a PDF from http://www.advancedlinuxprogramming.com/ (although the site is down at the moment). Perhaps you can search for other places to legally download the PDF.
A crash course:
You create a number of object (*.o) files via
gcc name.c -o name.o
Each file has a header that declares the functions in the source file. You might have several source files using a single header if the functions are related. The source files such as name.c include that header. Your code that uses those functions also includes that header.
You create a static library (archive) with ar
ar ruv libXYZ.a name1.o name2.o ... nameN.o
The prefix lib is important.
You link to the library with
gcc prog.o -lXYZ -o prog
This command will create an executable named prog from the object file prog.o and from object files, extracted from libXYZ.a, which are required to satisfy symbol references from prog.o.
Related
This question already has an answer here:
How to Include external C library on windows
(1 answer)
Closed 4 years ago.
I've seen plenty of online tutorials explaining how to use GLFW and libcurl, but where do I actually place the files I downloaded?
For example I downloaded this file for GLFW -
And these are the contents The C+ file wasn't in there I put that there :p
So how would I add the library to any of my .c files?
I've looked everywhere, I might just not be using the right keywords.
And second, how can I have multiple libraries at the same time?
And lastly, what do I put in the <> in the include?
I'm using windows 10 and am using GCC as my compiler. I really should get the Intel one shoudn't I?
This is what the SRC looks like.
In C, a library comes in two parts:
One (or more) header files
The actual library implementation, under Linux either a shared object (.so) or a static library (.a), under Windows I guess it would be a DLL file
You need to include the header file in each C source file of yours where you want to use functionality from the library:
In your source, add a line
#include <library-header.h>
for each header you want to include.
for all header files the library is delivered with.
You will have to tell your compiler where to find the header files. For gcc, you would have to enter something like that on the command line.
gcc -I /path/to/library/directory/include -c my_source.c -o my_source.o
Then, you need to link your program with the actual library. This again, depends on your tool chain, e.g. the compiler you use. For gcc again, the command line would look something like
gcc -lname_of_the_libray -L/path/to/library/directory/ my_source.o -o my_exe
However, libraries are often distributed in source code, which means you would have to compile the library beforehand.
I'm trying to write a simple syntax checker for C code using the frontend available in libclang. Due to deployment concerns, I need to be able to statically link all the libraries in libclang, and not pass around the .so file that has all the libraries.
I'm building clang/llvm from source, and in llvm/Release+Asserts/lib I have a bunch of .a files that I think I should be able to use, but it never seems to work (the linker spews out thousands of errors about missing symbols). However, when I compile it using the libclang.so also present in that directory as follows:
clang main.c -o bin/dlc -I../llvm/tools/clang/include -L../llvm/Release+Asserts/lib/ -lclang
Everything seems to work well.
What is the minimum set of .a files I need to include to make this work? I've tried including absolutely all of the .a files in the build output directory, with them provided to clang/gcc in different orders, without any success. I only need the functions mentioned in libclang's Index.h, but there don't seem to be any resources or documentation on what the various libclang*.a files are for. It would be very helpful to know which files libclang.so pulls in.
The following is supposed to work, as long the whole project has all static libraries (I counted 116 in my Release/lib directory).
clang main.c -o bin/dlc -I../llvm/tools/clang/include ../llvm/Release/lib/*.a
[edit: clang main.c -o bin/dlc -I../llvm/tools/clang/include ../llvm/Release/lib/libclang.a ../llvm/Release/lib/*.a]
Note that the output binary is not static, so you don't need any -static flag for gcc or ld, if you're using this syntax.
If that doesn't work you might need to list the libraries in order: if some library requires a function available in another library, then it may be necessary to list it first in the command line. See comments about link order at:
http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Link-Options.html#Link-Options
Hello Stack Overflow Community,
i am working on a c project to interleave multiple c programs into one binary, which can run the interleaved programs as treads or forks for benchmarking purposes.
Therefore i run make in each program folder of the desired programs and prelink all .o files with "ld -r" to one new .o file. After that i add a specific named function to each of these "big" .o files, which does nothing but run the main() of each program and providing the argc and argv. Then i use objcopy to localize every global Symbol except the unknown ones and the one of my specific function which shall run the main(). At last i link these manipulated .o files together with my program which runs the specific named functions as threads, or forks or after another.
Now to my Question/Problem:
I ran into a problem with static libs. I was using ffmpeg for testing, and it builds static libs such as libavcodc and libavutil and so on. Unfortunately, "ld -r" does not link .a files. So i tried to extract these libs with ar -x and then link the extracted .o files in the way mentioned above to the "big" new .o file. But i did not work because libavcodec and libavutil both include the file ff_inverse.o. That is obviously not a problem when i just build ffmpeg, which will link these static libraries. But still, both libraries include it, so there must be a machanism which makes the choice, which ff_inverse.o to use and to link. So my Question: How does this work? Where is the difference?
The way ld does it with normal linking is to prioritize the libraries. Libraries listed first in the command line are linked in first, and only if symbols still are unresolved does it move on to the next library. When linking static libraries, it ignores the name of each .o file, because the name is unnecessary, only the exported symbols are necessary. You may want to emulate that behavior, by extracting libraries in a sorted order.
got a nasm project and i'm calling a c function from it
I put the name of the function in "extern"
and when linking i put all the links together but i can an error of "undefined reference to"
here is my compile/link command
gcc -o Project4 Project4.o array1c.c readdouble.o writedouble.o readarray.o printarray.o addarray.o invertarray.o invertarray2.o invertarray3.o averagearray.o quicksort.c
I would first compile all of your .c files using the "gcc -c" command into object files, then link those resulting .o files (such as "array1c.o" and "quicksort.o") together with your other pre-existing object files and see if that still gives you an undefined reference. That may be an unnecessary step, but I've never combined raw .c files and .o files in a single call to gcc.
You may also have to add an underscore to the beginning of any c-functions called ... I know this an be a platform dependent thing (i.e., Linux typically doesn't need underscores on c-functions whereas OSX and some other UNIX platforms do).
Lastly you could try, using ld, to just link all the object files together at once rather than linking some of the object files together into Project4.o, and then linking that to what you had assembled using nasm (at least that's what I'm assuming you're doing, i.e., you're making a Project4.o, and then calling functions from that in your assembly code).
Hope this helps,
Jason
A third party provided me a static lib (.a) to link with on solaris station.
I tried to compile with sunpro, and failed at link step.
I suppose the issue is coming from the compiler I use (gcc instead?) or simply its version (as the std lib provided by the compiler could change from the version expected by the library AFAIK it could leads to errors at link step).
How could I know which compiler was used to generate this lib? Is there some tools doing that? Some option in sunpro/gcc or whatever?
As an hint: I've read some time ago that compilers use different mangling conventions when generating object files (true?). Still, "nm --demangle" command line prints me well all function names from debug symbols in this static lib. How does it work ? If my assumption is ok, nm does have a way to resolve which convention is in use in a static library, isn't it? Or is it simply meaning that lib was generated by GNU gcc, as nm is a part of GNU binutils?
I am not close to my workstation so I can't copy & paste error output from the linker (not for the moment but I could copy them in a further edit)
Extract the object files from the archive then run the strings command on some of them (first on the smaller ones since there'd be less noise to sift through). Many compilers insert ASCII signatures in the object files.
For example, the following meaningless source file, foo.c:
extern void blah();
when compiled on my Fedora 10 machine into foo.o via gcc -c -o foo.o foo.c results in a 647 byte foo.o object file. Running strings on foo.o results in
GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)
.symtab
.strtab
.shstrtab
.text
.data
.bss
.comment
.note.GNU-stack
foo.c
which makes it clear the compiler was GCC. Even if I'd compiled it with -fno-ident, the .GNU-stack note ELF section would have still been present.
You can extract the object files using the ar utility, or using Midnight Commander (which integrates ar), or you can simply run strings on the archive (which might give you more noise and be less relevant, but would still help.)
I tend to use the strings program (with the '-a' option, or my own variant where the '-a' behaviour is standard) and look for the tell-tale signs. For example, in one of my own libraries, I find:
/work1/gcc/v4.2.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.2.3/include
/work1/gcc/v4.3.0/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.0/include
/work1/gcc/v4.3.1/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.1/include
/work1/gcc/v4.3.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.3/include
That suggests that the code in the library has been compiled with a variety of versions of GCC over a period of years (actually, I'm quite startled to find so many versions in a single library).
Another library contains:
cg: Sun Compiler Common 11 Patch 120760-06 2006/05/26
acomp: Sun C 5.8 Patch 121015-02 2006/03/29
iropt: Sun Compiler Common 11 Patch 120760-06 2006/05/26
/compilers/v11/SUNWspro/prod/bin/cc -O -v -Xa -xarch=v9 ...
So, there are usually fingerprints in the object files indicating which compiler was used. But you have to know how to look for them.
Is the library supposed to be a C or C++ library?
If it is a C library then name mangling can not be the problem, as there is none in C. It could be however in a wrong format. Unices used to have libraries in the a.out format but almost all newer versions switched to more powerful formats like ELF.
If it is a C++ library then name mangling can be an issue. Most compilers embed some symbols that are compiler specific into the code, so if you have a tool like nm to list the symbols you can hopefully deduce from what compiler it came.
For example g++ creates a symbol
__gxx_personality_v0
in it's libraries
You can try the unix utility file:
file foo.a