I am trying to compile a C language library as a shared object on my new install of Fedora 22. The project compiled fine on my old install of Fedora 20. But now, when I run my makefile:
CC=gcc
vpath %.c src
vpath %.h inc
CFLAGS = -fPIC
INCLUDE = -Iinc -I/usr/include -I/usr/local/include
LIBPATH = -L/usr/lib -L/lib64
LIBS = -lportaudio -lm -lpthread -ldl
OBJ_PATH = ./objs
SRCS = my_code1.c my_code2.c # etc.
OBJS = $(SRCS:.c=.o)
.PHONY: libmylib.so
all: libmylib.so
debug: $(CFLAGS) += -DDEBUG -O0 -g3 -DPD
debug: all
release: $(CFLAGS) += -DTESTING -O2 -DPD -funroll-loops -fomit-frame-pointer
release: all
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDE) $(LIBPATH) $(LIBS) -c -o $# $^
libmylib.so: $(OBJS)
$(CC) -shared -Wl,-soname,libmylib.so \
-Wl,--no-undefined $(OBJS) -lc -lportaudio -ldl -lm -lpthread
mv libmylib.so ./bin
mv *.o $(OBJ_PATH)
clean:
rm $(OBJ_PATH)/*.o
rm bin/libmylib.so
I get very many undefined reference errors:
my_code1.o: In function `func_in_my_code1':
my_code1.c:(.text+0x1b8): undefined reference to `func_from_my_code2'
my_code2.o: In function `func_in_my_code2':
my_code2.c:(.text+0x310): undefined reference to `func_from_my_func1'
The functions in question are most certainly defined in the code. Presumably these are compiled into .o files in the compile stage.
The exact same build environment worked on my previous fedora installation. I am at a loss as to why I should get these errors.
Also, if I compile without the -Wl,--no-undefined flag, it compiles fine, but when I try to load the library from another application, it tosses the same set of undefined errors.
This may have nothing to do with the new version of Fedora. It is possible that there are some environment variables or something that didn't make through to my new install, but I have no idea what they could be.
Apparently I now need to insert the extern keyword into these functions. The code compiled and ran perfectly well before... I would like to reiterate, for posterity's sake, that I did post the entire makefile in my question.
Related
I have problem with linking libevent into my c project on ubuntu 14.04 LTS Server. Everything works fine on ArchLinux and Centos7 (both ubuntu and centos I run on virtual machine).
These is my Makefile:
TARGET: opoznienia
CFLAGS = -Wall -O2 --std=c11 -D DEBUG=1 $(shell pkg-config --cflags libevent_pthreads) -pthread -Wextra
LFLAGS = -Wall $(shell pkg-config --libs libevent_pthreads) -pthread -Wextra
OFILES = main.o err.o dropnobody.o ... <-- tl;tr
opoznienia: $(OFILES)
$(CC) $(LFLAGS) $^ -o $#
.PHONY: clean TARGET
clean:
rm -f opoznienia *.o *~ *.bak
On ubuntu I get error:
telnet_server.c:(.text+0xfc): undefined reference to `event_new'
GNU linker parses the object files arguments (.o .a .so) from left to right trying to match all the undefined symbols. And the order of object files is really important here, because GNU linker 'forgets' any symbols if they were not used by any object file passed in the argument list before the current object file.
In your case try changing the linkage order form:
$(CC) $(LFLAGS) $^ -o $#
To:
$(CC) $^ $(LFLAGS) -o $#
Let us know if this helps.
A static library is linked fine in the command line, but not through makefile. Compiling part accessing include files seems ok, but ld process must be wrong in the makefile.
Thanks for your help in advance!
Here is my command line:
gcc -o quadEq.exe quadEq.c -I../include -L../lib -lnowic
Here is my Makefile:
CFLAGS = -Wall -g -c
INCLUDE = -I../include
LDFLAGS = -L../lib
LDLIBS = -lnowic
SOURCES = quadEq.c
OBJECTS = $(SOURCES:.c=.o)
EXE = quadEq
all: $(SOURCES) $(EXE)
$(EXE): $(OBJECTS)
gcc $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $#
.c.o:
gcc $(CFLAGS) $(INCLUDE) $< -o $#
Here is my screen capture that ran Makefile and the command line.
Static libraries care in which order you link them. If libA.a depends on libB.a, then you have to do -lB -lA.
If a libA.a symbol depends on libB.a that depends on a libA.a symbol, you have to cyclically link: -lB -lA -lB. I've seen some cycles get to about 3 or 4 loops, but generally 2 is enough in my experience.
This is different from dynamic library linking which not only doesn't care what order you link them, but you don't need to also link dependent libraries since the .so specifies them.
Based on Aggieboy's suggestions, I rewrote the makefile and made it work.;
CC = gcc
CFLAGS = -x c -Wall -g
INCPATH = -I../include
LIBPATH = -L../lib
LLIBS = -lnowic
%: %.c
$(CC) -o $# $(CFLAGS) $(INCPATH) $< $(LIBPATH) $(LLIBS)
By the way, this accepts a filename to make from the command line argument.
Thank you Aggieboy again!
I'm experiencing some compilation issues with my dynamic library. It should be linked to main.c but for all references to it I receive "undefined reference to function_name".
The contents of main.c isn't really that important; I include my library:
#include "matrix.h"
Then I have a simple Makefile to link the two.
#Variables
LIB = matrix
# Usual compilation flags
CFLAGS = -std=c99 -Wall -Wextra -g
CPPFLAGS = -I../include -DDEBUG
LDFLAGS = -lm
# Special rules and targets
.PHONY: all clean help
all: $(LIB).o libmatrix.so main
$(LIB).o: $(LIB).c $(LIB).h
$(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c -o $# $<
libmatrix.so: $(LIB).o
$(CC) $(CFLAGS) -fPIC -shared -o $# $< $(LDFLAGS)
main: main.o libmatrix.so
$(CC) $(CFLAGS) -o $# $< -L -lmatrix
Can anyone direct me to where I might be going wrong? Many thanks in advance.
You probably want -L. not -L in your last line, so:
main: main.o libmatrix.so
$(CC) $(CFLAGS) -o $# $< -L. -lmatrix
You should read Program Library HOWTO and Drepper's paper: How to Write Shared Libraries; you might want to set some -rpath at link time (maybe using -Wl,-rpath,. ...), and you might want to link with -rdynamic ....
Alternatively, set your LD_LIBRARY_PATH environment variable to contain . (I don't recommend that), or install your shared library in /usr/local/lib/ (and add it to /etc/ld.so.conf then run ldconfig). See also dlopen(3), environ(7), ld.so(8), ldconfig(8)
It seems I'm having issues with the pthread when I try compiling with a Makefile:
/csapp.c:462: undefined reference to `pthread_create'
I think it might have something to do with the -lpthread?
Here is my Makefile (yes they are tabbed once):
CC = gcc
CFLAGS = -Wall -g
LDFLAGS = -lpthread
OBJS = proxy.o csapp.o
all: proxy
proxy: $(OBJS)
csapp.o: csapp.c
$(CC) $(CFLAGS) -c csapp.c
proxy.o: proxy.c
$(CC) $(CFLAGS) -c proxy.c
clean:
rm -f *~ *.o proxy
I believe your problem is with LDFLAGS.
From 10.3 Variables Used by Implicit Rules:
LDFLAGS Extra flags to give to compilers when they are supposed to invoke the linker, ld, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable instead.
LDLIBS Library flags or names given to compilers when they are supposed to invoke the linker, ld. LOADLIBES is a deprecated (but still supported) alternative to LDLIBS. Non-library linker flags, such as -L, should go in the LDFLAGS variable.
So try:
LDLIBS = -lpthread
I have this simple structure:
.
test.c
plugins/a.c
plugins/b.c
plugins/c.c
And I'm compiling this with a bash script:
gcc -o test test.c -std=gnu99 -ldl -Wl,--export-dynamic
gcc -c plugins/a.c -o plugins/a.o -pedantic -g -Wall -std=c99 -fpic -I.
gcc plugins/a.o -o plugins/a.so -shared
...same for b and c...
Anyways, I want to port that to a Makefile. Here's what I have:
CC = gcc
PLUGIN_DIR = plugins
PLUGINS_C = $(wildcard $(PLUGIN_DIR)/*.c)
PLUGINS_O = $(patsubst %.c,%.o, $(PLUGINS_C))
new: clean all
all: test plugins
test: test.o
$(CC) -o $# $^ -std=gnu99 -ldl -Wl,--export-dynamic
plugins:
???
$(PLUGIN_DIR)/*.c:
$(CC) -c $(PLUGIN_DIR)/$# $^ -pedantic -g -Wall -std=c99 -fpic -I.
$(PLUGIN_DIR)/*.o:
$(CC) $# $^ -shared
clean:
rm -rf test *.o *.a plugins/*.o plugins/*.so
But this won't work as the plugins rule is empty and I really can't find out what should I write in there to make it compile all the plugins inside the plugins folder.
Also, I'm not sure if I messed up things with $# and $^.
There are a number of problems with your makefile before we get to your question.
The wildcard character in a rule target is % not * (in lines like your $(PLUGIN_DIR)/*.c:).
Rules specify how the files named by the target/target pattern are built. So your %.c rule is telling make how to build .c files (which I trust you'll agree) isn't exactly what you meant. (Similarly your %.o rule is telling make how to build .o files).
You don't have any prerequisites (right-hand side of : in a target line) listed for your build rules so make cannot intelligently rebuild targets as their prerequisites are changed (and will never rebuild them instead).
To get to your question, you likely don't want anything in the body of the plugins target. Instead you want to list the desired plugins output files (the .so files) as the prerequisites of the plugins target. (You will also want to include .PHONY: plugins in your makefile to tell make that plugins is not a real file but instead a phony target.)
Your %.so rule wants to be more like:
$(PLUGINS_DIR)/%.so: $(PLUGINS_DIR)/%.o
$(CC) $^ -o $# -shared
and your %.o rule wants to be more like:
$(PLUGINS_DIR)/%.o: $(PLUGINS_DIR)/%.c
$(CC) -c $< -o $# -pedantic -g -Wall -std=c99 -fpic -I.