首页 > 解决方案 > 关于“复杂”树结构的 C++ Makefile

问题描述

我发现了很多相关的问题,但我仍然无法制作自己的 Makefile。这个makefile在Windows上使用Mingw64,我希望它在*nix上运行,目前是Debian,但我希望它也能在Alpine上运行,因为它在Docker容器中使用。

项目树结构类似于:

./
  src/
    main.cpp
    Server.cpp <- use asio and Utils/Split.h
    Server.h   <- use asio
    Utils/
      Split.h
  lib/
    asio/include/ <- asio library (without boost, header only)
  Makefile <- That is what I am trying to do right now
  Dockerfile

我尝试了多种方法,这是我最新的 Makefile(显然,它不起作用):

NAME        := GameServer
CXX         := g++
CXXFLAGS    := -std=c++2a -DASIO_STANDALONE

SRC_DIR     := ./src
LIBS        := -I lib/asio-1.18.1/include \
               -I lib/rapidjson-1.1.0/include \
               -I src

rwildcard   = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

SRCS        := $(call rwildcard,$(SRC_DIR),*.cpp)
OBJS        := $(SRCS:%.cpp=%.o)

.PHONY: all

all: $(NAME)

$(NAME): $(OBJS)
    $(CXX) -o $@ $^

$(OBJS): $(SRCS)
    $(CXX) $(CXXFLAGS) -c -o $@ $< $(LIBS)

注意:代码 (.cpp, .h) 是有效的,它来自一个已经运行的项目,但构建在 Visual Studio 上(使用 MSVC 编译)。

这是我的 mingw32-make 完成的两个功能:

g++ -c -o src/Server.o src/main.cpp -I lib/asio/include -I src
g++ -o Server src/main.o src/Server.o

第一行:它应该从 .cpp 构建 .o 并将包含添加到 asio。我添加-I src了添加 src/Utils,但我想这不是这样做的方式吗?
第二行:它应该(链接?)两个 .o 在一个文件中:可执行文件。

我使用这个makefile得到的错误是:

所以这是我的问题:

  1. 我究竟做错了什么 ?
  2. 有没有更好的方法来尝试在 Windows 上创建开发环境,并且仍然能够将项目复制到 Docker 容器中(然后使用 gcc 映像编译它)以使用相同的 Makefile 构建它?

抱歉,如果我忘了提及一些细节,我是 Mingw 及其环境的新手。

谢谢

编辑:更正版本:

NAME        := GameServer
CXX         := g++
CXXFLAGS    := -std=c++1z

SRC_DIR     := ./src
LIBS        := -lwsock32 -lws2_32 \
               -I lib/asio-1.18.1/include \
               -I lib/rapidjson-1.1.0/include \
               -I src

rwildcard   = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

SRCS        := $(call rwildcard,$(SRC_DIR),*.cpp)
OBJS        := $(SRCS:%.cpp=%.o)

.PHONY: all

all: $(NAME)

$(NAME): $(OBJS)
    $(CXX) -o $@ $^ $(LIBS)

$(OBJS): $(SRC_DIR)/%.o: $(SRC_DIR)/%.cpp
    $(CXX) $(CXXFLAGS) -c -o $@ $< $(LIBS)

标签: c++makefile

解决方案


考虑规则...

$(OBJS): $(SRCS)
    $(CXX) $(CXXFLAGS) -c -o $@ $< $(LIBS)

make表明 中的所有项目都$(OBJS)依赖于 中的所有项目$(SRCS)。但是命令...

$(CXX) $(CXXFLAGS) -c -o $@ $< $(LIBS)

...总是编译由 . 标识的第一个依赖项$<。碰巧在您的情况下$<src/main.cpp.

相反,您可能应该使用模式规则,例如...

$(SRC_DIR)/%.o: $(SRC_DIR)/%.cpp
    $(CXX) $(CXXFLAGS) -c -o $@ $< $(LIBS)

您还可以将该规则的范围限制为仅$(OBJS)使用完整静态模式规则指定的那些目标...

$(OBJS): $(SRC_DIR)/%.o: $(SRC_DIR)/%.cpp
    $(CXX) $(CXXFLAGS) -c -o $@ $< $(LIBS)

推荐阅读