简体   繁体   中英

Getting undefined references when linking against a static library

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. Ac Bc and Dc 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 DI 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.

ie, 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.

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'

ie 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 eg

-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

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

也许您应该使用ranlib或适当的ar选项为.a文件提供索引。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM