0

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 ?

14
  • 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 ggdb Commented Oct 13, 2017 at 4:57
  • 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/gcc Commented Oct 13, 2017 at 5:06
  • 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/include Commented Oct 13, 2017 at 5:10
  • before the all target, there should be the line: .PHONY : all Commented Oct 13, 2017 at 5:10
  • 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 client Commented Oct 13, 2017 at 5:12

2 Answers 2

1

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.

5
  • thanks for your explanation. The problem is that without this rule: I got this (src/paquet/packet_implem.c:6:26: fatal error: zlib.h: No such file or directory #include <zlib.h> //crc32)
    – jy95
    Commented Oct 12, 2017 at 19:47
  • @jacquesy, the rule in question was not doing anything useful for you. Without it, make is trying to actually build the object files, which you need it to do and which previously it would not have done. That uncovers an unrelated error. If libz and its development components are not already installed then you need to install them. If zlib.h is not in the default include file search path, then you need to add another -I option to tell the compiler where to find it. Commented Oct 12, 2017 at 19:55
  • It is already the case and I used now : INCLUDES += -I$(HOME)/local/include INCLUDES += -L$(HOME)/local/lib and LDFLAGS += -lz LDFLAGS += -lcunit . Doesn't understand why it blocks ?
    – jy95
    Commented Oct 12, 2017 at 19:58
  • @jacquesy, make will print each command it executes. Check the one that fails to make sure that all the options you need are included. You can even take that line and try running variations of it directly from the command line. I'm afraid I can't tell you exactly what you need because it depends on where things are installed on your machine. Commented Oct 12, 2017 at 20:04
  • No problemo : It works on another machine ^^. I think I will destroy my xubuntu and Bash Linux for Windows after XD. Just Cunit is the complexe one
    – jy95
    Commented Oct 12, 2017 at 21:08
1

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 $@
3
  • thanks. Do you have any idea about the circular dependency dropped and the way to correct this?
    – jy95
    Commented Oct 12, 2017 at 18:23
  • You're PACKET_OBJECTS rule has a dependency on itself. Maybe you don't need this rule at all if you use the .c.o rule.
    – cleblanc
    Commented Oct 12, 2017 at 18:25
  • Never heard of the rule .c.o . I was testing wildcards and I already regret XD
    – jy95
    Commented Oct 12, 2017 at 18:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.