How to link my main.c file with my library .a file? - c

I am trying to make a static library that belongs to me. Suppose there are two files: stack.h stores the declarations which I want to store it in the ./include document, and stack.c implements the definition, and main.c call the functions in the stack.h.
Make stack.a file which I want to store it in ./libwith those instructions:
>> gcc -c stack.c
>> ar -cq libstack.a stack.o
>> mv stack.h include
>> mv libstack.a lib
If I want to link the main.c with my libstack.a, what I am going to do with gcc? Do I need to put this lib into the PATH? If so, how to do it?
If next step, I want to do my dynamic library .so file, can anyone give some advice?

C Libraries
In general, libraries are created from many library source files and are either built as archive files (libmine.a) that are statically linked into executables that use them, or as shared object files (libmine.so) that are dynamically linked into executables that use them. To link in libraries of these types, use the gcc command line options -L for the path to the library files and -lto link in a library (a .so or a .a):
-L{path to file containing library} -l${library name}
For example, if I have a library named libmine.so in /home/newhall/lib/ then I'd do the following to link it into my program:
$ gcc -o myprog myprog.c -L/home/newhall/lib -lmine
You may also need to specify and include path so the compiler can find the library header file: -I /home/newhall/include
If you create your own shared object files and do not install them in /usr/lib, then you need to set your LD_LIBRARY_PATH environment variable so that the runtime linker can find them and load them at run time.
For example, if I put my .so files in a directory named lib in my home directory, I'd set my LD_LIBRARY_PATH enviroment to the following:
# if running bash:
>> export LD_LIBRARY_PATH=/home/newhall/lib:$LD_LIBRARY_PATH
# if running tcsh:
>> setenv LD_LIBRARY_PATH /home/newhall/lib:$LD_LIBRARY_PATH
USING AND LINKING LIBRARY CODE
To use a Library that is not linked into your program automatically by
the compiler, you need to
include the library's header file in your C source file (test.c in the example below)
tell the compiler to link in the code from the library .o file into your executable file:
step 1: Add an include line (#include "somelib.h") in a program
source file (e.g., test.c).
step 2: Link the program's .c file with the library object file
(i.e. specify the somelib.o file as a command line argument to gcc):
>> gcc -o myprog test.c somelib.o
The resulting executable file (myprog) will contain machine code for all
the functions defined in test.c plus any mylib library functions that are called by.
CREATING AND USING YOUR OWN LIBRARY CODE
To create a Library of code you need to do the following:
(1) Create an INTERFACE to your library: mylib.h
(2) Create an IMPLEMENTATION of your library: mylib.c
(3) Create a LIBRARY OBJECT FILE (.o) that can be linked with programs that use your library
3a. or create a SHARED OBJECT FILE (.so) from many .o files that can be dynamically linked with programs that use your library
3b. or create an ARCHIVE FILE (.a) from many .o files that can be statically linked with programs that use your library
(4) USE the library in other C code: (a) #include "mylib.h" (b) link in the libary code into a.out file
(5) Set LD_LIBRARY_PATH environment variable for finding shared objects in non-standard locations at runtime
Details:
(1) INTERFACE: the header file to your library should contain definitions for everything exported by your library:
function prototypes with comments for users of your library functions
definitions for types and global variables exported by your library
You should have "boiler plate" code (#ifndef ... #endif) around the header file's contents, to ensures that the preprocessor only includes the mylib.h file one time.
Here is what an example .h file might look like:
#ifndef MYLIB_H_ // _MYLIB_H_ is not allowed.
#define MYLIB_H_
// a constant definition exported by library:
#define MAX_FOO 20
// a type definition exported by library:
struct foo_struct {
int x;
float y;
};
typedef struct foo_struct foo_struct;
// a global variable exported by library
// "extern" means that this is not a variable declaration, it
// just defines that a variable named total_foo of type int
// exits and you can use it (its declaration is in some library source file)
extern int total_foo;
// a function prototype for a function exported by library:
extern int foo(float y, float z); // a very bad function name
#endif
(2) IMPLEMENTATION: create a mylib.c file that #includes "mylib.h" and contains the implementation of every function in your library.
#include "mylib.h"
...
int total_foo;
int foo(float y, float z) {
...
}
(3) create a LIBRARY OBJECT FILE that can be linked into other programs that use your library (use the -c option to gcc to tell it just to create an object file (a .o file) rather than an executable:
>> gcc -o mylib.o -c mylib.c
you can then use the mylib.o file as the "library file" and statically link it into other programs that use it, or...
(3a) alternately, you can create a SHARED OBJECT FILE from one or more .o files that can be linked into other programs that use your library A shared object file is the Unix name for a dynamically linked library whose code is loaded into the a.out file at runtime. To create a .so file use the -shared flag to gcc. Here is what an example build might look like:
>> gcc -shared -o libmylib.so mylib.o blah.o grr.o -lm
(3b) you could also build an ARCHIVE FILE (a statically linked library, libmylib.a) from one or more .o files. If you link with a static library, its code is copied into the a.out file at runtime.
See gcc documentation for more information on how to build .a and .so files.
(4) USE the library in other programs:
step 1: Add an include line (#include "mylib.h") in all program source files that use library definitions (e.g., test.c).
step 2: Link the program's .c file with the library object file
(i.e. specify the mylib.o file as a command line argument to gcc):
gcc test.c mylib.o
OR to link in libmylib.so (or libmylib.a):
gcc test.c -lmylib
OR to link with a library not in the standard path:
gcc test.c -L/home/newhall/lib -lmylib
The resulting a.out out will contain machine code for all the functions
defined in test.c plus any mylib library functions that are called by
the test.c code.
(5) RUNNING an executable linked with a shared object file:
If the shared object file in not in /usr/lib, then you need to set your
LD_LIBRARY_PATH environment variable so that the runtime linker can find
and load your .so file into the executable at runtime:
in bash:
>> export LD_LIBRARY_PATH=/home/newhall/lib:$LD_LIBRARY_PATH
in tcsh:
>> setenv LD_LIBRARY_PATH /home/newhall/lib:$LD_LIBRARY_PATH

there is another useful link: demo for making libraries

Related

Is the GCC link option truly necessary when linking to a static library?

I've been playing around with GCC lately and have been experimenting with the linking options. I'm somewhat confused why the link option -l is necessary when statically linking to an archive file. It seems like you can just toss the .a file as if it were an ordinary object file.
For example, take the following make file:
test1 : main.c libfunc.a
gcc main.c -L. -lfunc -o main.out
test2 : main.c libfunc.a
gcc main.c libfunc.a -o main.out
libfunc.a : func1.c func2.c
gcc func1.c -c
gcc func2.c -c
ar cr libfunc.a func1.o func2.o
Make target test1 uses GCC's linking options to link to the archive file. Target test2 instead just includes the archive file direct. Building and running each output seem to result in the same executable.
There are several ways you can tell gcc what file(s) to use. An argument of the form -lname (or the two arguments -l name) says “Search for a library named name”. Per the GCC documentation, this argument is passed to the linker (typically the ld command). The linker looks for a file with a name like libname.extension, where extension is one of the known library files extensions such as .a or .so, and it looks for files with those names in a list of library directories it has. You can add directories to search with the -L switch.
When the linker finds the library, it uses it just as if you had specified the path, so the end result is the same whether you specify the library with -l or with its path.
By using the path, you can specify libraries that are not in the known library directories or that have unusual names.
Note that the linker does not process libraries the same way as object files. When the linker processes an object file, it incorporates everything in the object file into the output file being constructed. When the linker processes a library file, it incorporates only those modules within the library that provide a symbol definition for a symbol referenced by a prior module and not yet resolved. For example, if you write a program that uses sqrt but does not use sin, then, when the linker processes libm.a after reading your object module, it will take the sqrt module from the library but not the sin module.

How to Export User Defined Library in C

I've created a rather large library:
DataStructures.h :
Stack.h :
Stack.c
LinkedList.h :
LinkedList.c
HashTable.h :
HashTable.c
etc...
How would I export this library so others can use them? Would they have to link the .c together with their main?
You need to compile your .c files into a library and distribute the library and headers together.
There are two types of library; dynamic (ending in .so on Linux) and static (ending in .a on Linux).
I believe static libs end in .lib on Windows and dynamic libs end in .dll over there, but I'm not a windows dev.
Macs can have both .so and .dylib files, depending on your tool chain.
On Linux, the general way to make a static lib is with the tools ar and ranlib. Assuming your Makefile has a list of object files called OBJS,
mylibrary.a: $(OBJS)
ar -ru $# $(OBJS)
ranlib $#
Creating a shared library is similar, but instead of ar and ranlib, you usually use gcc -shared, and you must compile the object files for "position independent code", ie add -fPIC to your CFLAGS.
Once you have the library and the header files, place the headers in a directory called "include" and the library in a directory called "lib". Archive these two directories up (eg with tar or zip) and send them to whoever is using them.
Note that they will need the same kind of computer, operating system version, compiler, etc as you. This is why C library code is most frequently shared in source code format.

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.

GCC: undefined reference to xxx

I know that have been already asked a lot of time but I can't really solve it...
so I have a src folder where my main.c source is, an srclib where my lib.c file is stored and an include directory where my lib.h file is stored. now the makefile compiles the lib correctly and put the lib.a file in lib folder. the main.cincludes the lib like this:
#include "lib.h"
and it's compiled with -I ../include option, but when i compile it I get the undefined reference to xxx error for every function in the library
so what am I missing?
Nope. -I is for including the header files. You also need to link with the library using -l option.
Note: You may need to provide the path-to-library using -L option.
To quote the online gcc manual
-llibrary
Search the library named library when linking...... The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
EDIT:
To quote the remaining part of the same manual
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.
So, you need to put the -l<libanme> at the last of your compilation statement, as s_echo.c uses functions defined in that particular library.

Link .a library to .o object so only .o needs to be included when building

I'm using a pre-built library called 'libdscud-6.02.a', which includes a lot of low level I/O calls for some specific hardware. From this, I created some wrapper functions which I compiled into an object file called 'io.o'.
Now, I have a few programs which I'm compiling with these I/O functions and instead of having to do this:
gcc libdscud-6.02a io.o -o test test.c
I would like to just have this:
gcc io.o -o test test.c
Is there any way to link the .a file into the .o file so I only need to include the .o file when compiling binaries?
You could do the opposite and add the io.o file to the .a file using ar:
ar q libdscud-6.02.a io.o
One solution would be simply to use a make variable:
IO_STUFF = libdscud-6.02a io.o
...
$(CC) $(IO_STUFF) ...
AFAIK it is not possible to link .a library and .o file to create another intermediate file i.e. file which is not linked like .o file.
The solution provided by Burton Samograd look like a very good option; but in case you are not allowed to modify .a library file then you can follow suggestion provided by DarkDust in case you are building using make.
However you can create a shared library .so file, from a .a library file and .o file (I think that is what Michael Burr is trying to convey). You can use only the shared library instead of both .a & .o file to generate your executable as follows:
Generate shared library gcc io.o libdscud-6.02.a -shared -o io.so (Please note that the order of files passed for linking is important)
Build your source with gcc io.so -o test test.c . To execute your executable path of io.so should be in the look up path of loader (ld) i.e. LD_LIBRARY_PATH.
The right way to work with shared object would be to create a libio.so which is the naming convention and not io.so and build code as gcc test.c -o test -L<path_to_libio.so> -lio and path to libio.so should be in ld's look up path for executing the output executable.
I know creating shared library just to avoid addition of another file for compilation does not seem to be what you want to do ...but it is just for your info in case you didn't already know :)

Resources