Create library from several .c files and use it for linkin - gcc

I'm having problems creating a lib and using it to link a .c-file with a main-function.
I have e.g.
cfile1.c
cfile2.c
cfile3.c
program.c (with main-function)
I want to create a library from all the .c-files and use it to link the
program.c
What is the best way to do that?

I assume your program.c (which is main) need those *.c files(support) to make a new library. If is that so, may be you should compile all of them because your program.c need that (if there is a function on *.c files called on program.c files)
I think, you can take a look on this link below:
Including one C source file in another?
Hope it helps, CMIIW

Related

How do I create a C++ program with each class in a different file

I want to create a class say PEN in one one c++ file and inherit it in another class that is in a separate file and finally run the program from a C++ file that has only the main function. I know this is a basic thing but I am new to C++. The program is a console program.
There's a few things here.
. Referencing
. Compling
. Linking
Referencing
You put your classes and main function in separate .cpp files.
Each file that references a class in another file needs to #include class.h where class.h is the headers that include the class declarations. You can have a single shared header for all the files, or a separate one for each. Usually there is a .h for each .cpp with the same name by convention.
Compiling
Then when you complie, you need to decide if you want a single binary blob (for you, this is my recommendation) or a library to link to.
Not sure exactly the cpp compile options but it will be something like: path/to/cpp-compiler main.cpp class.cpp
Order is important here, the classes main.cpp needs must be specified AFTER main.cpp on the command line.
Linking
If you chose to compile a separate library, you will need to do:
path/to/cpp-compiler
-c class.cpp
path/to/cpp-compiler -c main.cpp
separately, then do:
path/to/cpp-compiler -o a.out main.cpp class.o
to link.
You can also pack multiple .o files into a .so or dll if you like and link to that.
Linking can become quite complex and has many quirks so I think stick with compiling all you sources together for now until you get more familiar with it.
This is a good answer here: Using G++ to compile multiple .cpp and .h files
I suggest you do a little more research as there are bound to be heaps of other answers to this question.

Specific "cannot open shared object file" error

I'm a first year computer science student following a course on (amongst others) Makefiles. For our first assignment, we had to create a shared library and link against it.
I have the following setup:
A folder hw1 containing the folders app and lib.
Inside lib is a file called libmine.so, the library I want to link against.
Inside app, there are two files: test.cpp and a Makefile. The former uses the libmine library.
The Makefile is as follows (in the file itself, indentation etc. is correct):
all: test
test: test.cpp
g++ -Wall -o test -L../lib -I../lib/include test.cpp -lmine
However, when running test, I get the infamous `libmine.so: cannot open shared object file' error.
I believe this has something to do with exporting LD_LIBRARY_PATH. I have tried doing so (export LD_LIBRARY_PATH=$[very long relative path to the lib folder]), but I want to do this in my Makefile. Additionally, I don't want the path to be relative, as my teachter should be able to open the file when I send it to him (so I think it should be something like ../lib/libmine.so).
I looked at various StackOverflow posts, such as this one, but none seemed to answer this specific question (either it was a different setup or the solution simply didn't work). By the way: putting the line export LD_LIBRARY_PATH=../lib right under test: test.cpp and before the g++ command did not do anything.
Any help is much appreciated :)
when running test, I get the infamous `libmine.so: cannot open shared object file' error.
This is happening because the -L../lib argument tells the static linker where to find the library, but it doesn't tell anything to the dynamic linker (aka loader), and the problem is that the latter can't find this library.
To solve this, you can use LD_LIBRARY_PATH, but this is usually ill-advised.
What you want is something called RPATH or RUNPATH (assuming you are on a Linux or similar system):
g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath=../lib -lmine
Additionally, I don't want the path to be relative, as my teachter should be able to open the file when I send it to him
Is your teacher going to run your binary on the same system, or on a different one? If the former, you could do this:
g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath=/full/path/to/hw1/lib -lmine
If the latter, /full/path/to/hw1/lib may or may not be available on your teacher's machine, and you need to think about what exactly you are going to send to him.
The usual way to solve this is to package both the application and the library into a tar file:
tar cvf to-send.tar app/test lib/libmine.so
The teacher can then extract the parts of your tar file into arbitrary directory, and try to run it. To make this work, you need RPATH that is relative to the application, regardless of where the application ends up. To achieve that, you want:
g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath='$ORIGIN/../lib' -lmine

Purpose of nested archives

ar can create an .a file which includes another .a file, such that the output of ar -t whatever.a looks like:
someotherarchive.a
foo.o
bar.o
However, if this archive is then linked, the symbols from an .o in someotherarchive.a will not be accessible by foo.o. This can be resolved by flattening with the T switch to ar when creating, but that also creates a thin archive. Since there does not seem to be a flatten-but-don't-thin option, it's necessary to extract from someotherarchive.a first and then link the .os independently to create something that contains:
otherarchivememberA.o
otherarchivememberB.o
foo.o
bar.o
Raising the question, if putting one .a inside another .a makes it inaccessible, what's the purpose of doing so?
Presumably this is because ar was historically a general purpose archiving tool, like tar.
In other words, there is no purpose to inaccessibly nesting archives if you are creating static libraries.

What are the different types of files generated by the GCC compiler for?

When running make on one of my C projects I'm playing around with, I notice that gcc produces different file types at stages. I'm curious as to what these are, as I'm not too familiar with gcc.
The extensions I noticed are:
.o (I understand that these are compiled libraries)
.o.lst
.d
.a
I hope this is not a silly question, but I'm just trying to understand these files, and what they're used for.
.o is object file ie machine dependent output code
use gcc -c
.a is static library ... collection of several o files
ar -r
.d file is the dependency file that contain the dependency
.lst -If you want to see the C code together with the assembly it was converted to, use a command l
gcc -c -g -Wa,-a,-ad [other GCC options] foo.c > foo.lst

moving from make to cmake: how to use build target with wildcards

I'm trying to convert an makefile-build to cmake (to avoid the current state of being forced to take care for the windows-build env based on make/msdev and the linux based on make/gcc).
In this project, I've found a directory full of sourcecode files that get, based on a naming convention, compiled to libraries. (e.g. c1223.c => c1223.dll (or .sl) )
The current makefile consists of some directives using wildcards, e.g.:
LIB_NO = $(basename $(subst s,,$#))
OBJ = $(OBJ_PATH)/s$(LIB_NO).o $(OBJ_PATH)/c$(LIB_NO).o\
$(OBJ_PATH)/b$(LIB_NO).o
$(OBJ_PATH)/%.o : %.c
-$(CC) $(CFLAGS) -I$(PWD) -c $< -o $#
-(chmod a+w $#;true)
I've searched for a while but can't find anything that seems to work. Is it even possible with cmake to let it generate a wildcard based build?
Any comments, hints and suggestions are very welcome :)
cheers
Markus
You can use fairly primitive globbing (there's no regular expression syntax that I can see).
file(GLOB TESTSRCS "test/src/*.cpp")
# Compile the test sources.
add_executable(Tests ${TESTSRCS})
target_link_libraries(Tests ${LIB} gtest gtest_main)
The actual makefiles do not seem to contain wildcard searches inside them. If you add new files you will need to re-run cmake.
What I don't know is how you would manage to wrap up the library creation in a single macro if you have many different library files to generate.
You might be able to do something like this if there's only one c file per library:
file(GLOB libfiles "path/to/libs/c*.c")
foreach(libfile ${libfiles})
GET_FILENAME_COMPONENT(libname ${libfile} NAME) # remove the '.c' part (untested, hopefully this will work)
add_library(${libname} ${libfile})
endforeach(libfile)
If anybody else has a better solution, I would also like to learn it.
CMake does not generate makefiles that have wildcard-based rules in them. It generates specific rules for the files that it knows about.
In your example, you are explicitly listing the .o files that comprise your library. In CMake, you would instead explicitly list the source files that contribute to your library, and then let CMake take care of the rest.
Do you need makefiles that have wildcard-based rules in them for some reason?
Couldn't you simply construct a list of the source files, and then, for each element in the list, do an "add_library" call with the source file and a library name constructed from the source file name?

Resources