How to Export User Defined Library in C - 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.

Related

Is there a way to automatically find which files are compiled into a library using cmake/make?

I have a C library which I am using in a project. It consists of .c and .h files in src and include directories. I wrote a CMakeLists.txt file that generates a Makefile which compiles library.so.
The thing is, the library also includes .c files for tests, compatibility headers for other operating systems, and other files which I don't actually use. I would like to determine which src/header files are actually compiled into the .so library. Is there a way to do so automatically, based on CMakeLists.txt or Makefile, without going through and examining each file?
If you are using gccthen you can trick the compiler into telling you which source files it used by generating the dependency information for the next make run. If I am right, the necessary flags are:
-MT $# -MMD -MP -MF $(AUTODEP_DIR)$(notdir $#).d
This should produce for foo.cpp a file foo.o.d which contains target-prerequisites lines like:
foo.o : foo.cpp bar.hpp baz.hpp
foo.cpp :
bar.hpp :
baz.hpp :
where the line with the object file as target (the file before the :) displays what got used as C/C++ source in the compile run (all files after the :). Starting with the list of .o files which are in the libary, this should give you the exact list of files that you are looking for. It requires a bit of scripting but doesn't look too complicated.
clang and other compilers of course have their own, maybe differing set of flags but it shouldn't be too hard to pick them.

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

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

Including header files into static library

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

Use one c source code file in multiple projects

I've written several c text processing functions that I've placed in a the files: string_functions.c and string_functions.h.
I was using these functions for one project and that worked out well. Now I want to use these same functions in a completely different project at the same time. I'm using gcc in Debian.
Is there a good way to use the same c source code in multiple projects at the same time. The projects are in different sub-directories with the same parent directory.
How do I structure the make files to do this?
Or do I just place a copy of the string_functions.c(h) in both projects. This seems like it would make it harder to maintain the source code.
Best way to do this is to build your C files (.h and .c) into a shared library.
There are many tutorials available on how to do this with gcc; one is at this link
Once the shared library is built, you can then link it into many other projects.
Briefly, these are the steps.
Ensure your string_functions.c includes string_functions.h and builds, of course.
Then compile position independent (that's what -fPIC is for)
$gcc -Wall -fPIC -c string_functions.c
Finally build your shared library like this
$gcc -shared -o my_stringfunctions.so string_functions.o
To link to your new shared library from some other program, ensure that whatever directory
you put it in is in your LD_LIBRARY_PATH.
Then you may link using something like
$gcc my_otherprogram.c -L/path/to/my/lib -lmy_stringfunctions
As pointed out, one should put include files (.h) used by a shared library in some directory path, and add the location to the include search path using the -I option:
$gcc my_otherprogram.c -I/path/to/include/files -L/path/to/my/lib -lmy_stringfunctions
If this is how your directory looks:
/parent
/project1
...
string_functions.h
string_functions.c
/project2
...
string_functions.h
string_functions.c
Then all you have to do is store it in a common location, and then point to that location when building your code. This is the standard way of doing it for custom installed libraries in /opt/, for example.
Hence, one suggestion is to do your directory structure like this:
/parent
/include
string_functions.h
string_functions.c
/project1
...
/project2
...
And when building your respective projects, you include that search path when compiling (using the -I flag):
gcc mainfile.c -I/parent/include <other options>

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