许多文件夹项目 Makefile
Many folders project Makefile
我有以下项目结构:
common
|-- foo.cpp
|-- foo.h
exercise_1
|-- main.cpp
|-- bar_1.cpp
|-- bar_1.h
exercise_2
|-- main.cpp
|-- bar_2.cpp
|-- bar_2.h
...
如何组织 Makefile
从主目录构建这样的项目,例如:
make exercise_10
因此该命令将在 common
目录和 exercise_10
文件夹中构建目标文件,并且 link 它们都可以在 exercise_10
中执行。我从以下内容开始:
COMPILER = g++
INCLUDE = -I common/
DEPS = common/*.o
OBJECTS := $(patsubst common/%.cpp, common/%.o, $(wildcard common/*.cpp))
common: $(OBJECTS)
exercise_%:
$(COMPILER) $@/main.cpp $(INCLUDE) -o $@/main $(DEPS)
但它不起作用,我不知道下一步该怎么做。
谢谢!
如果您使用 GNU make,您可以定义一个宏来构建您的任何练习。类似于以下内容:
EXERCISES := $(wildcard exercise_*)
MAINS := $(addsuffix /main,$(EXERCISES))
.PHONY: all
all: $(MAINS)
common-objs := $(patsubst %.cpp,%.o,$(wildcard common/*.cpp))
common-headers := $(wildcard common/*.h)
%.o: %.cpp $(common-headers)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Icommon -c $< -o $@
# $(1): exercise directory
define BUILD_EXERCISE
.PHONY: $(1)
$(1): $(1)/main
$(1)-objs := $$(patsubst %.cpp,%.o,$$(wildcard $(1)/*.cpp))
OBJS += $$($(1)-objs)
$(1)-headers := $$(wildcard $(1)/*.h)
$$($(1)-objs): $$($(1)-headers)
$(1)/main: $$($(1)-objs) $$(common-objs)
$$(CXX) $$(CXXFLAGS) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS)
endef
$(foreach e,$(EXERCISES),$(eval $(call BUILD_EXERCISE,$(e))))
.PHONY: clean
clean:
rm -f $(MAINS) $(OBJS) $(common-objs)
看起来有点复杂,其实不然。唯一的技巧是 BUILD_EXERCISE
宏中的 $$
。它是必需的,因为宏被 make 扩展了两次。其他一切都很简单:
CXX
、CPPFLAGS
、CXXFLAGS
、LDFLAGS
和 LDLIBS
是 Variables Used by Implicit Rules。
$@
、$<
和 $^
是 Automatic Variables。
wildcard
、addsuffix
、patsubst
、foreach
、eval
和 call
是 make functions.
- Phony targets 被声明为
.PHONY
特殊目标的先决条件。
- The
foreach-eval-call
construct 是一种以编程方式实例化 make 语句的方法。
%.o: %.cpp...
是 pattern rule.
我有以下项目结构:
common
|-- foo.cpp
|-- foo.h
exercise_1
|-- main.cpp
|-- bar_1.cpp
|-- bar_1.h
exercise_2
|-- main.cpp
|-- bar_2.cpp
|-- bar_2.h
...
如何组织 Makefile
从主目录构建这样的项目,例如:
make exercise_10
因此该命令将在 common
目录和 exercise_10
文件夹中构建目标文件,并且 link 它们都可以在 exercise_10
中执行。我从以下内容开始:
COMPILER = g++
INCLUDE = -I common/
DEPS = common/*.o
OBJECTS := $(patsubst common/%.cpp, common/%.o, $(wildcard common/*.cpp))
common: $(OBJECTS)
exercise_%:
$(COMPILER) $@/main.cpp $(INCLUDE) -o $@/main $(DEPS)
但它不起作用,我不知道下一步该怎么做。
谢谢!
如果您使用 GNU make,您可以定义一个宏来构建您的任何练习。类似于以下内容:
EXERCISES := $(wildcard exercise_*)
MAINS := $(addsuffix /main,$(EXERCISES))
.PHONY: all
all: $(MAINS)
common-objs := $(patsubst %.cpp,%.o,$(wildcard common/*.cpp))
common-headers := $(wildcard common/*.h)
%.o: %.cpp $(common-headers)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Icommon -c $< -o $@
# $(1): exercise directory
define BUILD_EXERCISE
.PHONY: $(1)
$(1): $(1)/main
$(1)-objs := $$(patsubst %.cpp,%.o,$$(wildcard $(1)/*.cpp))
OBJS += $$($(1)-objs)
$(1)-headers := $$(wildcard $(1)/*.h)
$$($(1)-objs): $$($(1)-headers)
$(1)/main: $$($(1)-objs) $$(common-objs)
$$(CXX) $$(CXXFLAGS) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS)
endef
$(foreach e,$(EXERCISES),$(eval $(call BUILD_EXERCISE,$(e))))
.PHONY: clean
clean:
rm -f $(MAINS) $(OBJS) $(common-objs)
看起来有点复杂,其实不然。唯一的技巧是 BUILD_EXERCISE
宏中的 $$
。它是必需的,因为宏被 make 扩展了两次。其他一切都很简单:
CXX
、CPPFLAGS
、CXXFLAGS
、LDFLAGS
和LDLIBS
是 Variables Used by Implicit Rules。$@
、$<
和$^
是 Automatic Variables。wildcard
、addsuffix
、patsubst
、foreach
、eval
和call
是 make functions.- Phony targets 被声明为
.PHONY
特殊目标的先决条件。 - The
foreach-eval-call
construct 是一种以编程方式实例化 make 语句的方法。 %.o: %.cpp...
是 pattern rule.