Use one c source code file in multiple projects - c

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>

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 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"

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.

Compiling a source file that has dependencies on multiple source code trees

How can I compile a C source file that #include's header files from each of two independent source trees? Each source tree has its own set of makefiles, and the source trees are completely independent of each other.
I'm writing a Wireshark plugin which interprets packets of a particular network protocol. In order to compile the plugin, the compiler needs to resolve symbols against the Wireshark source tree. However, in order for the plugin to actually interpret the network packet contents when Wireshark gives it a byte array, the plugin must also include definitions of data structures and RPC XDR routines from an entirely separate source tree. So the compiler also needs to resolve symbols against both Wireshark and a completely separate source tree containing these files.
Is there an easy way to do this? Any suggestions at all would be very much appreciated.
Make sure you don't confuse compile with link. Not saying you are, but just pointing out there are two distinct steps.
To compile against tree1 and tree2, use the -I include directive to gcc. gcc -c -I/some/include/for/tree1 -I/some/include/for/tree2 input.c -o output.o
to link against two trees, create .so or .la files (static or dynamic libraries ) from each tree. Call them tree1.la tree2.la. put them in /path/to/tree1/libs and /path/to/tree2/libs
then link
gcc -o prog -ltree1 -ltree2 -L/path/to/tree1/libs -L/path/to/tree2/libs
If the trees are sufficiently large, they should end up creating static or dynamic libraries of object code. Then you just point to their headers to compile and point to their libs to link.
If you are using gcc / g++
Use -I flags to include the required header files for compiling.
eg:
g++ -I<includepath1> -I<includepath2> ... -c somefile.cpp -o somefile.o
Use -L flag to link against the libraries.
eg:
g++ -o pluginname.so somefile.o somefile2.o somefile3.o -L <libpath1> -l<libname1> -L <libpath2> -l <libname2> <fullpath to .a file for statically linking>
In windows the approach is similar only nomenclature is different, .dll file instead of .so and .lib files instead of .a files.

Header Files in Multiple Directories: Best Practices

I'm a C Newb
I write lots of code in dynamic languages (javascript, python, haskell, etc.), but I'm now learning C for graduate school and I have no idea what I'm doing.
The Problem
Originally I was building all my source in one directory using a makefile, which has worked rather well. However, my project is growing and I would like to split the source into multiple directories (unit tests, utils, core, etc.). For example, my directory tree might look like the following:
.
|-- src
| |-- foo.c
| |-- foo.h
| `-- main.c
`-- test
`-- test_foo.c
test/test_foo.c uses both src/foo.c and src/foo.h. Using makefiles, what is the best/standard way to build this? Preferably, there would be one rule for building the project and one for building the tests.
Note
I know that there are other ways of doing this, including autoconf and other automatic solutions. However, I would like to understand what is happening and be able to write the makefiles from scratch despite its possible impracticality.
Any guidance or tips would be appreciated. Thanks!
[Edit]
So the three solutions given so far are as follows:
Place globally used header files in a parallel include directory
use the path in the #include satement as in #include "../src/foo.h"
use the -I switch to inform the compiler of include locations
So far I like the -I switch solution because it doesn't involve changing source code when directory structure changes.
For test_foo.c you simply need to tell the compiler where the header files can be found. E.g.
gcc -I../src -c test_foo.c
Then the compiler will also look into this directory to find the header files. In test_foo.c you write then:
#include "foo.h"
EDIT:
To link against foo.c, actually against foo.o, you need to mention it in the object file list. I assume you have already the object files, then do after that:
gcc test_foo.o ../src/foo.o -o test
I also rarely use the GNU autotools. Instead, I'll put a single hand-crafted makefile in the root directory.
To get all headers in the source directory, use something like this:
get_headers = $(wildcard $(1)/*.h)
headers := $(call get_headers,src)
Then, you can use the following to make the object-files in the test directory depend on these headers:
test/%.o : test/%.c $(headers)
gcc -std=c99 -pedantic -Wall -Wextra -Werror $(flags) -Isrc -g -c -o $# $<
As you can see, I'm no fan of built-in directives. Also note the -I switch.
Getting a list of object-files for a directory is slightly more complicated:
get_objects = $(patsubst %.c,%.o,$(wildcard $(1)/*.c))
test_objects = $(call get_objects,test)
The following rule would make the objects for your tests:
test : $(test_objects)
The test rule shouldn't just make the object files, but the executables. How to write the rule depends on the structure of your tests: Eg you could create an executable for each .c file or just a single one which tests all.
A common way of doing this is for header files used by a single C file to be named the same as that C file and in the same directory, and for header files used by many C files (especially those used by the whole project) to be in a directory include that is parallel to the C source directory.
Your test file should just include the header files directly using relative paths, like this:
#include "../src/foo.h"

Resources