我正在开发一个结构如下的 C++ 项目:
/root
--/Client
----/build
----/include
----/src
--/Common
----/include
----/src
--/Server
----/build
----/include
----/src
--Makefile
理想情况下,我想从单个 makefile 编译和构建服务器和客户端。 .o 文件将在 /build 文件夹中生成,而可执行文件将在 /root 中 makefile 必须从目标 和 /Common 文件
编译文件所以我想出了这个(抱歉搞砸了):
CC := g++
CFLAGS := -Wall -Wextra -I./Common/include -I./Server/include -I./Client/include
LDFLAGS := -lws2_32
CLIENT_SRC_DIR := ./Client/src
CLIENT_BUILD_DIR := ./Client/build
CLIENT_BIN_DIR := ./Client/bin
CLIENT_EXE := ./Client/bin/client.exe
SERVER_SRC_DIR := ./Server/src
SERVER_BUILD_DIR := ./Server/build
SERVER_BIN_DIR := ./Server/bin
SERVER_EXE := ./Server/bin/server.exe
COMMON_SRC_DIR := ./Common/src
COMMON_BUILD_DIR := ./Common/build
CLIENT_SRCS := $(wildcard $(CLIENT_SRC_DIR)/*.cpp)
CLIENT_OBJS := $(patsubst $(CLIENT_SRC_DIR)/%.cpp,$(CLIENT_BUILD_DIR)/%.o,$(CLIENT_SRCS))
SERVER_SRCS := $(wildcard $(SERVER_SRC_DIR)/*.cpp)
SERVER_OBJS := $(patsubst $(SERVER_SRC_DIR)/%.cpp,$(SERVER_BUILD_DIR)/%.o,$(SERVER_SRCS))
COMMON_SRCS := $(wildcard $(COMMON_SRC_DIR)/*.cpp)
.PHONY: all clean fclean dirs
all: client server
client: $(CLIENT_EXE)
server: $(SERVER_EXE)
$(CLIENT_EXE): $(CLIENT_OBJS)
$(CC) $(CFLAGS) -o $@ $(CLIENT_OBJS) $(LDFLAGS);
$(SERVER_EXE): $(SERVER_OBJS) | $(SERVER_BIN_DIR)
$(CC) $(CFLAGS) -o $@ $(SERVER_OBJS) $(LDFLAGS);
$(CLIENT_BUILD_DIR)/%.o: $(CLIENT_SRC_DIR)/%.cpp $(COMMON_SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $^ -o $@;
$(SERVER_BUILD_DIR)/%.o: $(SERVER_SRC_DIR)/%.cpp $(COMMON_SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $^ -o $@;
dirs:
mkdir "$(CLIENT_BUILD_DIR)";
mkdir "$(CLIENT_BIN_DIR)";
mkdir "$(SERVER_BUILD_DIR)";
mkdir "$(SERVER_BIN_DIR)";
clean:
rm -r $(CLIENT_BUILD_DIR) $(SERVER_BUILD_DIR);
fclean: clean
rm -r $(CLIENT_BIN_DIR) $(SERVER_BIN_DIR);
re: fclean all
不幸的是,我收到的消息是:
make: *** No rule to make target 'Client/build/main.o', needed by 'Client/bin/client.exe'. Stop.
我知道当文件丢失时会出现此消息,但由于我使用 % 通配符,它不会工作吗?
我真的很难弄清楚这个问题,谢谢所有帮助我的人!
你的规则试图同时做太多事情。 看看下面的规则:
$(CLIENT_BUILD_DIR)/%.o: $(CLIENT_SRC_DIR)/%.cpp $(COMMON_SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $^ -o $@;
我们正在尝试构建
$(CLIENT_BUILD_DIR)/main.o
,因此%
部分是main
。
将其代入规则:
$(CLIENT_BUILD_DIR)/main.o: $(CLIENT_SRC_DIR)/main.cpp $(COMMON_SRC_DIR)/main.cpp
$(CC) $(CFLAGS) $^ -o $@;
哎呀:你依赖的
$(COMMON_SRC_DIR)/main.cpp
不存在。
我想您编写此规则的目的是说“.cpp 文件可以来自 either 目录”。在这种情况下,您只需编写两个规则,每个规则对应一个可能的来源:
$(CLIENT_BUILD_DIR)/%.o: $(CLIENT_SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $^ -o $@;
$(CLIENT_BUILD_DIR)/%.o: $(COMMON_SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $^ -o $@;
$(SERVER_BUILD_DIR)/%.o: $(SERVER_SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $^ -o $@;
$(SERVER_BUILD_DIR)/%.o: $(COMMON_SRC_DIR)/%.cpp
$(CC) $(CFLAGS) $^ -o $@;
顺便说一句:编译 C++ 代码时应该使用
$(CXX)
和 $(CXXFLAGS)
。