【问题标题】:How can I run a pattern rule within another rule in a makefile?如何在生成文件的另一个规则中运行模式规则?
【发布时间】:2016-08-22 12:14:56
【问题描述】:

我希望编写一个 makefile 来自动编译我正在处理的项目,其中文件可能会或可能不会更改数量。我还需要能够快速告诉 make 将文件编译为调试版本或发布版本(由命令行定义区分)。经过一番研究,我发现了模式规则并制作了一个。这是我到目前为止的代码:

# Our folders
# ODIR -    The .o file directory
# CDIR -    The .cpp file directory
# HDIR -    The .hpp file directory
ODIR = obj
CDIR = src
HDIR = inc

# Get our compiler and compiler commands out of the way
# CC -  Our compiler
# CFNO - Our compiler flags for when we don't have an output file
# CF -  Our compiler flags. This should be appended to any compile and should
#           have the name of the output file at the end of it.
# OF -  Object flags. This should be appended to any line that is generating
#           a .o file. 
CC = g++
CFNO = -std=c++11 -wall -Wno-write-strings -Wno-sign-compare -lpaho-mqtt3c -pthread -O2 -I$(HDIR)
CF = $(CFNO) -o
OF = -c

# Our project/output name
NAME = tls_test

# Set out Debug and Release settings, as well as any defines we will use to identify which mode we are in
# NOTE: '-D[NAME OF DEFINE]' is how you create a define through the compile commands
DEBUG = -DDEBUG -g
RELEASE = -DRELEASE

# Our two compile modes
# eval allows us to create variables mid-rule
debug:
    $(eval DR = $(DEBUG))

release:
    $(eval DR = $(RELEASE))

# Our compiling commands
all: 
    $(CC) $(CF) $(NAME) $(ODIR)/*.o

# NOTE: $@ is the end product being created and $< is the first of the prerequisite
$(ODIR)/%.o: $(CDIR)/%.c
    echo "$(CC) $(DR) $(OF) $(CF) $@ $<"

我遇到的问题是我需要运行的东西的顺序。命令行调用应该告诉 make 使用 debug 或 release,它设置一个 make 变量,然后调用 all。 all 应该在运行当前在 all 规则中的行之前运行底部的模式规则。那么,如何使模式规则成为依赖项,以及如何从另一个规则中调用规则?

【问题讨论】:

  • 您希望 Make 编译 src/ 中的所有源文件(带有适合构建的标志),然后将所有生成的目标文件链接到可执行文件中,对吗?

标签: makefile gnu-make


【解决方案1】:

使用特定于目标的变量

虽然不是绝对必要,但分离标志对管理构建选项大有帮助,然后您可以使用 target-specific variable 附加来切换标志。当您使用它时,您不妨使用内置变量名称。

我还添加了依赖项生成 (-MMD -MP),因为它总是有用的。

ODIR := obj
CDIR := src
HDIR := inc

SRCS := $(wildcard $(CDIR)/*.cpp)
OBJS := $(SRCS:$(CDIR)/%.cpp=$(ODIR)/%.o)
DEPS := $(OBJS:%.o=%.d)

CPPFLAGS := -I$(HDIR) -MMD -MP
CXXFLAGS := -std=c++11 -Wall -Wno-write-strings -Wno-sign-compare -pthread -O2
LDFLAGS  := -pthread
LDLIBS   := -lpaho-mqtt3c

NAME := tls_test

.PHONY: debug release clean

debug: CPPFLAGS+=-DDEBUG
debug: CXXFLAGS+=-g

release: CPPFLAGS+=-DRELEASE

debug release: $(NAME)

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

$(OBJS): $(ODIR)/%.o: $(CDIR)/%.cpp
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(OUTPUT_OPTION) $<

clean: ; $(RM) $(NAME) $(OBJS) $(DEPS)    

-include $(DEPS)

【讨论】:

  • 我可以猜到你想要OUTPUT_OPTION 是什么,但你应该把它拼出来。
  • @Beta 为什么,让它默认为-o $@
  • 我的立场是正确的。我不知道这个变量,但现在我知道了,我不认为它使这个 makefile 更容易理解或维护。
  • @Beta 也许不是,但这就是内置规则使用的内容,所以我认为最好将其保留在那里,尽管我从未使用过不支持-o 的编译器。
  • 如果 OP 连续运行 make debugmake release,这不会重新编译对象(除非 gcc 依赖项生成比我认为的更智能)。
猜你喜欢
  • 1970-01-01
  • 2012-09-28
  • 2018-04-23
  • 2019-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多