[英]Makefile - wildcard and recipe build
I have the following makefile 我有以下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. make:循环src / paquet / packet_implem.o <-src / paquet / packet_implem.o依赖项已删除。 \\ 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; \\ 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 /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:在函数_start': (.text+0x20): undefined reference to
main的_start': (.text+0x20): undefined reference to
'collect2:错误:ld返回1退出状态Makefile:71:目标'src / paquet / packet_implem.o'的配方失败:*** [src / paquet / packet_implem.o]错误1
What I want : 我想要的是 :
1) Build the dependancies (PACKET_SOURCES) and (SEND_RECEIVE_DATA_SOURCES) 1)建立依存关系(PACKET_SOURCES)和(SEND_RECEIVE_DATA_SOURCES)
2) Build the client and the server with the dependancies from step 1 2)使用步骤1中的依赖关系构建客户端和服务器
3) The executable "client" will be at the root of the folder. 3)可执行文件“客户端”将位于文件夹的根目录。
How can I correct my errors ? 我该如何纠正错误?
Use -c to generate objects without trying to make an executable, that way you don't need a main 使用-c生成对象而不尝试创建可执行文件,这样您就不需要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 我认为您可能还需要SERVER_OBJECTS这样的规则
.c.o:
$(CC) -c $(CFLAGS) -lz $< -o $@
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)
. 这表示,在扩大每个目标$(PACKET_OBJECTS)
依赖于每一个目标的扩展$(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
). 相反,它尝试将目标文件(请参阅下文) 链接到一个可执行文件中,为结果分配默认名称(也许是a.out
)。 $(PACKET_OBJECT)
. 配方引用未定义的变量$(PACKET_OBJECT)
。 I suppose that this is probably a misspelling of $(PACKET_OBJECTS)
. 我想这可能是$(PACKET_OBJECTS)
的拼写错误。 If instead you mean current target among those given in $(PACKET_OBJECTS)
, then that would be spelled $@
. 相反,如果您的意思是$(PACKET_OBJECTS)
指定的当前目标,则将其拼写为$@
。 -lz
), and probably should not do so. 如果确实要使用此规则来构建目标文件,则该配方不需要指定要链接的库(例如-lz
),并且可能不应该这样做。 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
; 您可能需要将-lz
添加到您的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. 您可能想移动-I$(HOME)/local/include
选项:它不属于LDFLAGS,因此在此不起作用。 If you need it, then put it instead in your CPPFLAGS
, or maybe in CFLAGS
or even INCLUDES
. 如果需要,则将其放到CPPFLAGS
,或者放到CFLAGS
甚至是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 $@
", 您可以将其拼写为“ -o $@
”,
It is unconventional to include your clean
target as a prerequisite of all
. 把clean
目标作为all
的前提是不寻常的。 It will always rebuild everything from scratch if you run make
without specifying a target. 如果运行make
而不指定目标,它将始终从头开始重建所有内容。 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
. 您的all
目标不会构建名为“ all”的目标,因此也应将其声明为.PHONY
。
Very likely there's more, but I'll leave that for you to sort out. 很可能还有更多,但我会留给您整理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.