Reputation: 783
I have the following makefile
# See gcc/clang manual to understand all flags
CFLAGS += -std=c99 # Define which version of the C standard to use
CFLAGS += -Wall # Enable the 'all' set of warnings
CFLAGS += -Werror # Treat all warnings as error
CFLAGS += -Wshadow # Warn when shadowing variables
CFLAGS += -Wextra # Enable additional warnings
CFLAGS += -O2 -D_FORTIFY_SOURCE=2 # Add canary code, i.e. detect buffer overflows
CFLAGS += -fstack-protector-all # Add canary code to detect stack smashing
# We have no libraries to link against except libc, but we want to keep
# the symbols for debugging
LDFLAGS = -rdynamic
# external libs
# par défaut les chemins classiques
LDFLAGS += -I$(HOME)/local/include
LDFLAGS += -L$(HOME)/local/lib
# Default compiler
CC=gcc
# folders
SOURCE_FOLDER=src
TESTS_FOLDER=tests
PAQUET_FOLDER=paquet
SEND_RECEIVE_DATA_FOLDER=sendAndReceiveData
CLIENT_FOLDER=client
SERVER_FOLDER=server
# folder of sources
PAQUET_FULL_PATH=$(SOURCE_FOLDER)/$(PAQUET_FOLDER)
SEND_RECEIVE_DATA_FULL_PATH=$(SOURCE_FOLDER)/$(SEND_RECEIVE_DATA_FOLDER)
CLIENT_FULL_PATH=$(SOURCE_FOLDER)/$(CLIENT_FOLDER)
SERVER_FULL_PATH=$(SOURCE_FOLDER)/$(SERVER_FOLDER)
# sources files
# On prend tout
PACKET_SOURCES = $(wildcard $(PAQUET_FULL_PATH)/*.c)
SEND_RECEIVE_DATA_SOURCES = $(wildcard $(SEND_RECEIVE_DATA_FULL_PATH)/*.c)
CLIENT_SOURCES = $(wildcard $(CLIENT_FULL_PATH)/*.c)
SERVER_SOURCES = $(wildcard $(SERVER_FULL_PATH)/*.c)
# objects
PACKET_OBJECTS=$(PACKET_SOURCES:.c=.o)
SEND_RECEIVE_DATA_OBJECTS=$(SEND_RECEIVE_DATA_SOURCES:.c=.o)
CLIENT_OBJECTS=$(CLIENT_SOURCES:.c=.o)
SERVER_OBJECTS=$(SERVER_SOURCES:.c=.o)
# another things
# Default target
all: clean server client
client: $(CLIENT_OBJECTS) $(PACKET_OBJECTS); \
$(CC) $(CFLAGS) $(CLIENT_OBJECTS) $(LDFLAGS);
server: $(SERVER_OBJECTS) $(PACKET_OBJECTS); \
$(CC) $(CFLAGS) $(SERVER_OBJECTS) $(LDFLAGS);
$(PACKET_OBJECTS): $(PACKET_OBJECTS); \
$(CC) $(CFLAGS) -lz $(PACKET_OBJECT) $(LDFLAGS);
tests: $(PACKET_OBJECTS) $(TESTS_OBJECTS); \
$(CC) $(CFLAGS) -lcunit $(LDFLAGS);
.PHONY: clean
clean:
@rm -f *.o
I got this message :
make: Circular src/paquet/packet_implem.o <- src/paquet/packet_implem.o dependency dropped. \ gcc -std=c99 -Wall -Werror -Wshadow -Wextra -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all -lz -rdynamic -I/home/jy95/local/include -L/home/jy95/local/lib; /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function
_start': (.text+0x20): undefined reference to
main' collect2: error: ld returned 1 exit status Makefile:71: recipe for target 'src/paquet/packet_implem.o' failed make: *** [src/paquet/packet_implem.o] Error 1
What I want :
1) Build the dependancies (PACKET_SOURCES) and (SEND_RECEIVE_DATA_SOURCES)
2) Build the client and the server with the dependancies from step 1
3) The executable "client" will be at the root of the folder.
How can I correct my errors ?
Upvotes: 0
Views: 1529
Reputation: 181244
The problem occurs in this rule:
$(PACKET_OBJECTS): $(PACKET_OBJECTS); \
$(CC) $(CFLAGS) -lz $(PACKET_OBJECT) $(LDFLAGS);
That says that every target in the expansion of $(PACKET_OBJECTS)
depends on every target in the expansion of $(PACKET_OBJECTS)
. That gives a great many dependency cycles, and in particular it gives you one-element cycles of object files depending on themselves.
In fact, this rule is problematic in several other ways:
a.out
).$(PACKET_OBJECT)
. I suppose that this is probably a misspelling of $(PACKET_OBJECTS)
. If instead you mean current target among those given in $(PACKET_OBJECTS)
, then that would be spelled $@
.-lz
), and probably should not do so.Chances are reasonably good that you could simply delete that rule altogether and thereby be better off. You might want to add -lz
to your LDFLAGS
; otherwise it would just be lost.
Additionally,
You probably want to move the -I$(HOME)/local/include
option: it does not belong in LDFLAGS, and will not serve its purpose there. If you need it, then put it instead in your CPPFLAGS
, or maybe in CFLAGS
or even INCLUDES
.
Your various rules that build executable targets should provide options that specify the name of the target to build. You can spell that as "-o $@
",
It is unconventional to include your clean
target as a prerequisite of all
. It will always rebuild everything from scratch if you run make
without specifying a target. Most people prefer to do that only on demand.
Your all
target does not build a target named "all", so it, too, should be declared .PHONY
.
Very likely there's more, but I'll leave that for you to sort out.
Upvotes: 1
Reputation: 3688
Use -c to generate objects without trying to make an executable, that way you don't need a main
$(PACKET_OBJECTS): $(PACKET_OBJECTS); \
$(CC) -c $(CFLAGS) -lz $(PACKET_OBJECT) $(LDFLAGS);
I think you might also need a rule like this for your SERVER_OBJECTS
.c.o:
$(CC) -c $(CFLAGS) -lz $< -o $@
Upvotes: 1