Including header files into static library - c

Since every time when we link against a static library we also need to include the header files, I am wondering if it is possible to archive into the static library, when creating it, those heads?
Say I have two object files foo1.o and foo2.o generated by
gcc foo1.c -I foo1.h -c -o foo1.o
gcc foo2.c -I foo2.h -c -o foo2.o
Gcc tutorials tell us we can generate libfoo.a using
ar libfoo.a foo1.o foo2.o
This must sound silly, but is it possible to put those header files inside libfoo.a when archiving? In this way, when linking against libfoo.a, people no more need to spend hours in order to find and include foo1.h and foo2.h, so there seems to be some benefits in doing so, right?
Thanks for your ideas.

First, the header is required to compile your source, not to link it. You do not need the header to link your objects with static libraries.
Second, no, there is no standard or common way to generate an archive with both the library and it's header. Probably there is no way to do this with common C compilers.
You could declare the library's prototypes inside your source, and than ignore the header. But this would be unsafe, since there will be no guarantee that both library and you source where compiled with compatible prototypes.
Following Paul Griffiths comments. If you just want to not have to include a path for every library, you should install those headers and those libraries and set the path in you environment.
Example:
export C_INCLUDE_PATH=$HOME/install/include
export LIBRARY_PATH=$HOME/install/lib
You must export this every time you open an new shell, or you can define it in you .bashrc

You can compile everything you want into a static library, but the counterpart is that you won't be able to call the functions from outside (ie by linking) because if you want to do so, you'll always need their prototypes

Related

How to write common functions for reusing in C

I was trying to write a common function for other files could reuse it, the example as following, I have three files:
The first file: cat test1.h
void say();
The second file: cat test1.c
void say(){
printf("This is c example!");
}
The third file: cat test2.c
include "test1.h"
void main(){
say();
}
but when I ran: gcc -g -o test2 test2.c
it threw error as:
undefined reference to `say'
Additionally: I knew this would work:gcc -g -o test2 test1.c test2.c
but I don't wanna do this, because the other team would use the server, and I hope them directly use my binary code not source code. I hope that just like we use printf() function, we just need include .
You can build yourself a library from the object files containing your useful functions, and store the header(s) that describe them in a convenient location. You and your colleagues then compile with the headers and link that library with any executables that use any of those functions. That's very much the same general mechanism that the C compiler uses to include the standard headers and automatically link with the standard C library.
The mechanics vary a bit depending on platform (Windows vs Unix being the primary distinction, though there are differences between Unix platforms too), and also on the type of library (static archive vs dynamic linked / loaded libraries — also known as shared objects or shared libraries).
In broad outline, for a Unix system with a static library, you'd:
Compile library object files libfile1.o, libfile2.o, … using (for example) gcc -c libfile1.c libfile2.c.
Create an archive from the object files — using for example ar r libname.a libfile1.o libfile2.o.
Copy the headers to a standard location such as /usr/local/include.
Copy the library to a standard location such as /usr/local/lib.
You'd compile any code that uses the library functions with -I/usr/local/include (if that is not already a standard compilation option).
You'd link the programs with -L/usr/local/lib -lname (you might not need to specify -L… but you would need to specify -lname).
Including a header file does not make a function available. It simply informs the compiler that the function will be provided at a later time.
You should compile the file with the function into a shareable object file (or a library if there is more than one function that you want to share). Mind the switch -c which tells gcc not to build an executable file:
gcc -o test1.o test1.c -c
Similarly, compile the main function into its own object file. Now you or anyone else can link the object file with their main program:
gcc -o test2 test2.o test1.o
The process can be automated using make.
Other programmers can use compiled object files (`*.o') in their programs. They need only to have a header file with function prototypes, extern data declarations and type definitions.
You can also wrap many object files into the library.
On many systems you can also create the dynamic linked libraries which do not have to be linked into the executable.
you also need to compile test1:
gcc -g -o test2 test1.c test2.c.

how do I import a c library?

I'm new to programming and am taking the cs50 online course, the course provides an online container with an IDE but in order to do the problem sets offline i downloaded the library files but haven been able to reference them on my code, the library import statement is declared as not used and the function from that library is marked as non existent, could anyone lend a helping hand? print from the issue
Download all the files, I suppose they are cs50.h and cs50.c.
Put both files in the same directory of your main file, and use include statement for cs50.h like this:
#include "cs50.h"
When we use a library that is not in the standard library folder, we must include it with "" instead of <>
Note by editor
The above statement is stricken because it's misleading. You can in fact use <> to include your own headers, provided you pass the directory in which those headers reside as one of the search paths to your compiler.
Let's say you want to compile foo.c that uses a header file called bar.h residing in /where/bar/lives/include/ directory, and a library called libbar.a in /where/bar/lives/lib/ directory, then in majority of C compilers you can use -I flag and -L flags to make it possible to include and link the right bits into your project:
To compile your program foo.c you would:
cc -I/where/bar/lives/include -o foo.o -c foo.c
To link you would:
cc -o foo foo.o -L/where/bar/lives/lib -lbar
These two steps would produce your program binary foo
Interestingly you can use -I. and -L. to include present working directories and use <> to your heart's content.
First off, the mechanism is called include in C, as the code itself suggests.
Then, your issue is in the #include statement. Using <...> tells the compiler (specifically the preprocessor) to look for libraries installed in your system. To include local libraries you should use "...". When using this, also pay attention to the path because it's relative.
So, considering your folder structure, the include statement should be
#include "src/cs50.h"

Why the order of object files is important for static libraries?

I create some files:
file1.c
file2.c
file3.c
I compile them using gcc -c file1.c and i did the same for other files, and i get object files. Later i used ar tool to create static library.
Everythink works correctly, but ar has option
ar -m -a file.o lib.a filetomove.o
to move object files in library, why order of object files is important? Please, show me example where object files must be in correct order.
This is less and less of a problem as time goes on, but for a long time linkers were single pass. That means if a symbol was defined in a.o and referenced in b.o, the linker had to "see" b.o before a.o or it would never find a definition for the reference.
In other circumstances, sometimes a "default" function is provided in a library that is linked last. This is a popular technique in embedded systems development. You can provide an override function by linking it in a static library or object module, but if you don't, the last library will provide a symbol that satisfies the linker.

Link static library with static library

I have a Makefile.am with two noinst_LIBRARIES, and one of them needs to link with the other.
Adding it to the CFLAGS throws a compiler warning, but as far as I know, automake likes to freak out about using LDADD with libraries, since they are not complete programs.
How can I do this, assuming libb.a needs to pull in liba.a?
You can't do it. Actually, what you are trying to do doesn't really make sense. Static libraries are just archives containing object files and a table of contents. Put simply, you can think of a static library as a .zip containing .o files.
The linking phase only takes place when compiling a shared object or executable. When your program is linked against liba.a, you also need to specify -static -lb or similar and that's it.

object file from .a not included in .so

I have created a .c file which is being converted to a .o file along with around 300 other .c files and included in a .a static library. This library, along with many others is being used to create a .so dynamic library. On analyzing both the .a and the .so file with nm, I found that for some reason the symbols defined in the .c file are present in the .a file but not in the .so file. I can think of no reason this should happen. Can somebody please help me out here? The steps used to create the two binaries are:
gcc -fvisibility=hidden -c foo.c -o foo.c.o
ar cr libbar.a foo.c.o ...
gcc -fvisibility=hidden -fPIC -o libfinal.so libbar.a x.o y.a ...
The reason I have specified visibility hidden here is that I want to expose only a few selected symbols. To expose the symbols from foo.c I have specified the visibility attribute so that the functions signatures in the header foo.h look like:
extern int _____attribute_____ ((visibility ("default"))) func();
EDIT: The command nm libbar.a | grep Ctx gives:
000023c5 T CtxAcquireBitmap
000026e9 T CtxAcquireArray
00001e77 T CtxCallMethod
However, nm libfinal.so | grep Ctx does not show anything.
UPDATE: Found another post which discusses the uses of the --whole-archive option. Also, stumbled across the --export-dynamicoption which apparently tells the linker to retain unreferenced symbols. Investigating further.
Try using --whole-archive linker option to include all objects into your shared library when linking
gcc -o libfinal.so -Wl,--whole-archive libbar.a x.o y.a -Wl,--no-whole-archive
From man ld:
--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the
link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared
library, forcing every object to be included in the resulting shared library. This option may be used more than once.
Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use -Wl,-whole-archive.
Second, don't forget to use -Wl,-no-whole-archive after your list of archives, because gcc will add its own list of archives to your
link and you may not want this flag to affect those as well.
As far as I know, when compiling against a .a, gcc will only pull out the objects that are referenced by the other modules. If your intent is to include the whole content of the .a in the .so, a plain "compile/link x.c into libfinal.so using content in libbar.a" is not what you want.
Creating a dummy reference for the required symbols in my main file did not solve the problem. The referenced symbols appeared in the binary dump (obtained using nm) with a U (= undefined) marker. I managed to solve the problem by linking the object file directly when creating the .so file instead of including it in the .a library first. As these functions were marked extern they were included in the .so even though they were not being referenced within the library. Had they not been marked extern, they would not have been included just like sylvainulg said.
Thanks to Dmitry for pointing out the --whole-archive option. I did not know that such an option exists.

Resources