0
votes

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 tomain' 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 ?

2
there will not be any symbols for debugging unless the CFLAGS includes the parameter g. and if using the gdb debugger, then instead of g use ggdbuser3629249
regarding: CC=gcc 1) use := rather that = so the macro is only evaluated once rather than every time it is referenced. 2) the idea of using macros for shell functions is to specify exactly which instance of the program name to use. I.E use: CC := /usr/bin/gccuser3629249
this statement: LDFLAGS += -I$(HOME)/local/include is something you want at the end of the gcc` command in the 'compile' recipe. NOT in the link recipe. Suggest: INCLUDE += -I$(HOME)/local/includeuser3629249
before the all target, there should be the line: .PHONY : alluser3629249
You (normally) do not want to be running the 'clean' target when trying to build. so this line: all: clean server client would be better written as: all: server clientuser3629249

2 Answers

1
votes

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:

  • the recipe does not, in fact, create any of the rule's designated targets
  • instead, it attempts to link the object files (see next) together into an executable, assigning the default name to the result (perhaps a.out).
  • The recipe references an undefined variable $(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 $@.
  • not only do the object files certainly not each have themselves as prerequisites, they also do not have each other as prerequisites. The dependencies for each object should be their corresponding sources.
  • If you indeed mean for this rule to be used to build your object files then the recipe does not need to specify libraries to link in (e.g. -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.

1
votes

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 $@