Getting undefined references when linking against a static library - c

I made a static library with GCC. Building of the library was OK.
When I use it the linker throws undefined reference errors on some functions. But nm says the functions are defined and exported in the static library (marked with T). I know about the linking order that I need to put the libraries after that module that needs them so this can not be a problem.
The static library was built from 3 C files. A.c B.c and D.c The D module depend on A and B (includes their headers).
No problem when I use functions from A and B but when I try to use any function from D I get undefined reference errors on them.
If I move these functions in A or B it works. But not if they are in the D module.
I'm completely run out of ideas what's going on or what is I'm overlooked.
I'm using Code::Blocks and working with plain C files.

An old trick that many times works: List each static library twice in the linking phase.
i.e., in your makefile (or whatever you're using), put:
gcc -o <outfile> <liba> <libb> <libc> <liba> <libb> <libc>
Anyway, I hope you get the idea.

I found out that I added A .cpp file to my project and I just renamed it to .c. I chose C language instead of C++ when I created the project. I did't think this could cause problems
I thought the file extension decides when the IDE chooses between gcc and g++. But not. In Code::Blocks if you add a file with a .cpp extension it will use g++. If you add a file with a .c extension it will use gcc. But if you rename the file it will use the same compiler. You have to change it explicitly in the project options.
That D module was built using g++ instead of gcc.
I realized this when I set the IDE to show me the entire command line when building not just "Compiling foo.c".

In the master make file I wrote to simplify my application/library builds, the solution I used was to run the link step twice. Using the -u linker option to specify undefined symbols on the second link.
In my make file I have a target like this:
undefined.txt:
#$(generate-undefined-syms)
which calls this macro... the first attempt at linking...
define generate-undefined-syms
$(PRINTF) "$(this_makefile): Generating undefined symbols ... \n"
$(CC) -o rubbish $(LDFLAGS) $(objects) $(LDLIBS) 2>&1 | $(GREP) 'undefined reference' > tmp.txt; \
$(SED) 's/^.*`/-Wl,-u/g' < tmp.txt > undefined.txt; \
rm -f tmp.txt rubbish
endef
As my sed/regexp skills aren't good (and I wrote this stuff in a rush) I end up with undefined.txt containing:
-uSomeSym'
-uSomeOtherSym'
i.e. with a trailing '
I then use this make syntax to strip the 's, and remove duplicates
undefined_references = $(filter-out follow, $(sort $(subst ',,$(shell cat undefined.txt))))
The 'follow' filter is because if an undefined symbol is referenced many times, a message "more references to XXX follow" appears in the output, which leads to a spurious 'follow' in the undefined.txt file e.g.
-Wl, uXXXX' follow
Finally I link the second time (note the dependency on undefined.txt)
$(application): $(library_dependencies) $(objects) undefined.txt
$(CC) -o $# $(LDFLAGS) $(undefined_references) $(objects) $(LDLIBS)
I'd totally recommed the following book by the way, as I was able to write from scratch a simple build system in a couple of days.
Managing Projects with GNU Make, Third Edition
By: Robert Mecklenburg

Perhaps you should use ranlib or the approriate ar option to provide an index to your .a file.

Related

C - Staticaly link GLFW in Makefile MinGW32 - Windows10

It is my first time trying to link external libraries to a C file. I read that I can use a Makefile and this is what I have:
all: src/main.c
gcc src/main.c -o main.exe -IC:\src\C\GameTry\dependencies\include -LC:\src\C\GameTry\dependencies\lib -lglfw3 -lgdi32 -lglew32s
clean:
rm *.o
The reason I included -lgdi32 is beacuse the official glfw documentation states that:
When using MinGW to link an application with the static version of GLFW, you must also explicitly link with gdi32
This makefile works but OpenGL throws the warning corrupt .drectve at end of def file repeatedly many times and it throws undefined reference to '__security_cookie' error may times aswell which causes the program to not compile.
I have looked all arround the internet and haven't been able to find an answer. I believe these errors have something to do with the default MSVN libraries but I'm not sure
If you have libglfw3.a that matches your compiler and platform (make sure to not mix win32 and win64), then a .def file should not be needed.
Somehow the linker is picking up a .def file anyway.
If there is a .def for glfw3, can you try to remove or rename it and try again?

find duplicate declared functions in c library (single files)

I'm working on an embedded project and I am duplicating a sample project.
Not taking the linking order of the object files into account, I just put the c files in a random order in my Makefile.
Compiling and linking yields an executable.elf of 1.9Mb.
No errors were generated but the executable didn't work.
After a long search with no solution I finally duplicated the project exactly, including the order of the c files (120 of them) and behold I got an executable.elf of 2.2Mb and no errors. AND the executable worked.
Nothing changed in compile-options and/or linking-options. Just changed the order in which the c files are listed in the makefile, and therefore the order of the object files at link time.
I suspect that there are multiple duplicate function implementations with different bodies/sizes. My hypothesis is that link time the linker, with no memory of previous link actions, just picks the first one it encounters without raising an error.
However I would like to get a hold on this provided library (all single c files, no lib *.a file) and find the duplicate function implementations. So I know in which order I should provide the c files and more importantly, why.
Two questions:
Is the description above, indeed a potential cause of the issues?
Are there other possibilities?
How to find the duplicate function implementations?
Unfortunately, the code being compiled is proprietary and details cannot be shared at this time.
Compiler is:
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496]
Target is:
cortex-m3
Your help is appreciated.
--- EDIT ---
There are two files:
is the list with all the source code (source.mk):
C_FILES_SRC = $(SDK_DIR)/file001.c
C_FILES_SRC += $(SDK_DIR)/file002.c
C_FILES_SRC += $(SDK_DIR)/ .....
|
C_FILES_SRC += $(APPL_DIR)/file121.c
C_FILES_SRC += $(APPL_DIR)/file122.c
is the Makefile (short version):
include source.mk
CFLAGS = xxxxx
# create objects
%.o: %.c
$(GCC) $(CFLAGS) -MMD -MP -MF($(#:%.o=%.d) -o $# -c $<
# link it all together
executable.elf
$(GCC) $(MAIN_CFLAGS) $(LINK_SCRIPTS) -Xlinker --gc-sections $(LIBS_DIR) $(EXTRA_LINK_FLAGS) $(SPECS) -o $# $(OBJS) $(LIBS)
$(SIZE) --format=berkeley $#
In the Makefile I change nothing. Only changed the order of files in source.mk
Only static libraries (.a or .lib) exhibit "first match resolution" such that link order was critical. Since all object files are explicitly linked, you'd get a link error if there were duplicate symbols. So only the order the the .a/.lib files are presented to the linker could have that effect.
Perhaps you have two different versions of a library and are linking both in a different order?
The GNU toolchain's binutils includes the nm tool for examining symbols in object and archive (library) files.
An alternative possibility is that the executable entry point is sensitive to link order on your platform; in which case it may just be the link order of crt0 (or other run-time start-up code).

Makefile for a system

I'm trying to build an application where there are two different systems interacting with each other and most of their functionalities are common. So I'm planning a directory structure like this.
Xxx
|_sys1
|
|_sys2
|
|_common
Each have a separate include and src directories.
Learned from a little browsing that keeping the compilation of common as libcmn.so will be efficient and can be linked for compiling xxx and yyy.
Though I understand how to create a .so, using them in a makefile with variables and linking header files are new to me.
Can someone guide me on how the Makefile for each should be and how linking should be done for a proper build?
In a make(1) control file, sequencing is important. Here is the general rule:
Targets placed on the same prerequisites line may be build concurrently. Order is preserved between different <code>Makefile</code> targets. So something like this:
all:: a b
a:: a.o lib/libfoo.so
${CC} ${LDFLAGS} -o $# a.o -Llib -rpath=lib -lfoo.so ${LDLIBS}
b:: b.o lib/libfoo.so
${CC} ${LDFLAGS} -o $# b.o -Llib -rpath=lib -lfoo.so ${LDLIBS}
lib/libfoo.so:
${MAKE} -C lib all
Now, on a big server you can do this:
$ make -j10 all
and everything will be built in the right order. Just be sure there is a Makefile in the lib directory that knows how to build the library.
Unless libfoo.so is significantly large, I'd make it a static libary, then you would not have to pre-program where to find it later at runtime.
To compile xxx and yyy that use your libcmn.so, they just need to include the library interface header.
To link with the library just add a -lcmn and -Lpath/to/your/lib to your LDFLAGS
To be noted that using this method, you will need to :
Add the library path to LD_LIBRARY_PATH
or add the library path to ldconfig
or move the library to a place where ldconfig looks already (/usr/lib for example)
You can also use the dlopen and dlsym functions to map your libcmn functions to function pointers at runtime. This will allow you to specify the path and name of the library to load at runtime and avoid the LD_LIBRARY_PATH problem.
You will need to add the -ldl flag to compile using this technique

Using Makefile to link multiple files

I'm kind of lost in the Makefile business and I'm trying to come to terms with it. I would love if someone could make it clear on an example I'm currently programming.
I have these files:
my-bit-vector.h -> a header file included in eratost.c, ppm.c
ppm.c -> a .c file which includes my-bit-vector.h and error.h
error.h -> a header file included in eratost.c, ppm.c
error.c -> a .c file which includes error.h and defines the functions in it
erato.c -> a .c file which includes my-bit-vector.h and error.h
I need to link these together into one executable file. How would I go about doing that via Makefile? I hope I didn't forget something. Could you please help?
The contents of a Makefile, when put simple, is one or more targets (the things you want built). Each target has dependencies (if any dependencies don't exist yet, they must be built, and if they do exist but they're newer than their target, the target must be rebuilt), and rules (the commands to build the target, presumably from the dependencies).
In your case, lets say your final output is a program called program. You've identified the sources to build it, but you don't build an executable directly from sources, you do it from object files. You could start your makefile like this:
program: ppm.o error.o erato.o
cc -o program ppm.o error.o erato.o
WARNING The spacing on rule lines (the cc command line shown above) requires a TAB, not just spaces!
That's enough to start but not enough to be right. You'll notice that there's no target:dependency/rules for the .o's yet, but it still works because Make has some built-in rules.
With this makefile, if you type "make" twice, the first time you'll see everything gets built and the second time it won't -- nothing changed so no rebuild is needed. Unfortunately if you edit your .h's now, the .c's still won't rebuild, so lets fix that:
program: ppm.o error.o erato.o
cc -o program ppm.o error.o erato.o
ppm.o: ppm.c my-bit-vector.h error.h
error.o: error.c error.h
erato.o: erato.c my-bit-vector.h error.h
Now you've got your dependencies set to cause make to rebuild sources that must be rebuilt when headers change. There's no rules on those source builds because the built-in rule here is (often) sufficient. You can override the built-in if necessary, of course.
Here, when you type "make", the tool will find the first target (program) and inspect its dependencies. It will then make sure each of its dependencies are up to date (based on their target:dependency / rule definitions), recursively as long as there are targets needing to be considered for being built. Finally it will apply the rules for this target to complete its build.
There's much more that can be done with makefiles, this is just a brief intro.
program: ppm.o error.o erato.o
gcc ppm.o error.o erato.o -o program
ppm.o: ppm.c
gcc -c ppm.c -o ppm.o
error.o: error.c
gcc -c error.c -o error.o
erato.o: erato.c
gcc -c erato.c -o erato.o
stuff before the ":" is the target. stuff after ":" are the required targets for this target.
So if you "make program" make is looking for a target named "all". The target all requires ppm.o which is also defined as target in the makefile. So it executes this target first. the target ppm.o requires ppm.c which has no target defined in the makefile, so it is probably a file. I hope this explains the basic functionality to you.
http://mrbook.org/tutorials/make/
is a really good tutorial for beginners, with some basic makefile examples.

Compiling Small Gcc Project on Windows Using MinGW

so I've been programming in C++ for almost 2 years now, and the whole while I've had the pleasure of using an IDE (VS) with lovely project settings and automatic linking and the like. I've always stayed away from any external libraries which required me to compile via makefiles, or at least the ones which were meant for linux environments/other compilers.
Anyways I now want to use a super handy utility (Bob Jenkins Perfect Minimal Hash) but it requires me to compile via makefiles, not only that but using the g++ compiler.
I went ahead and got the mingW32-make utility and am now trying to get it to work. Where I'm at now:
Succesfully installed minGW
Succesfully called the make utility
Failed to succesfully make the project.
The error I get is:
C:\gen_progs\ph>mingw32-make
mingw32-make: *** No rule to make
target lookupa.c', needed by lookupa.o'. Stop.
And the makefile itself:
CFLAGS = -O
.cc.o:
gcc $(CFLAGS) -c $<
O = lookupa.o recycle.o perfhex.o perfect.o
const64 : $(O)
gcc -o perfect $(O) -lm
# DEPENDENCIES
lookupa.o : lookupa.c standard.h lookupa.h
recycle.o : recycle.c standard.h recycle.h
perfhex.o : perfhex.c standard.h lookupa.h recycle.h perfect.h
perfect.o : perfect.c standard.h lookupa.h recycle.h perfect.h
Now the error seems reasonable, at least from my minimal understanding of makefiles, I have all the referenced .c, .h files, however I have none of the .o files and there doesn't appear to be any instructions on how to make these. So my question/s are:
am I calling the make utility wrong? Or do I need to compile the object files first? Or... do I need to add something to the make file?
Again I have all the referenced .c and .h files.
Edit: Sorry about that I was actually missing that specific file it seems to have disapeared somewhere along the line. However, adding it back in this is the error I now get:
c:\gen_progs\ph>mingw32-make
cc -O -c -o lookupa.o lookupa.c
process_begin: CreateProcess(NULL, cc -O -c -o lookupa.o lookupa.c, ...) failed.
make (e=2): The system cannot find the file specified.
mingw32-make: *** [lookupa.o] Error 2
Regarding your error "process_begin: CreateProcess(NULL, cc -O -c -o lookupa.o lookupa.c, ...) failed."
This is because the make utility wants to use the "cc" compiler to compile your program, but that compiler is not part of the Mingw-package.
Solution: Change the ".cc.o:" to ".c.o:". This changes the implicit rule which tells Make what compiler to use (gcc on the next line) when compiling .c files (the original line tells it how to compile .cc files).
Saying either make -DCC=gcc at the command line or adding the line CC=gcc to the top of the Makefile would cure the issue as well. Make's built in rules for handling C source code all name the C compiler with the variable CC, which defaults to "cc" for reasons of backward compatibility even in Gnu Make.
It looks like the original Makefile author tried to work around that problem by supplying a custom rule for compiling .cc files, but since there are no .cc files in the project that rule was not actually used.
Specifying the correct value for CC is superior to fixing the explicit rule to name .c files IMHO because Makefiles are generally easier to use and maintain and are the most portable when the least possible information is specified.
I don't think not having .o files is the problem. Make will make them from the source files (the files to the right of the colon).
Your immediate problem seems to be that make can't file the file "lookupa.c". From the rules you posted, it looks to me like that file should be sitting in the same directory as the makefile, but it isn't. You need to figure out where that file is, and how to get it there.
(For some reason I have a mental image of Wile E. Coyote sitting at his computer, seeing that file name, looking up, and getting plastered with an anvil).

Resources