2016-05-16 46 views
4

这是一个make文件,我写的目标是将目录中的所有C++文件转换为目标文件。我的问题是,它总是首先执行g ++,然后执行其他任何命令。使执行顺序的问题

CC=g++ 
CPPFLAGS=`pkg-config --cflags --libs gtkmm-3.0` 
SRCS=$(wildcard classes/source/*.cc) 
PROGS=$(patsubst %.cc,%,$(SRCS)) 
CLASS_HEADERS=classes/ 
all: $(PROGS) 
    mkdir -p build/release/objs 
%: %.cc 
    $(CC) -I$(CLASS_HEADERS) -c $< -o build/release/objs/$(@F).o $(CPPFLAGS) 

结果:

g++ -Iclasses/ -c classes/source/helloworld.cc -o build/release/objs/helloworld.o `pkg-config --cflags --libs gtkmm-3.0` 
mkdir -p build/release/objs 

感谢

+1

为'build/release/objs'提供另一个依赖目标,并放在'$(PROGS)'之前。 –

+1

“全部”的规则说:确保所有'$(PROGS)'都是最新的;当完成后,运行'mkdir'将完成创建'all'的工作。你需要更多的东西像'all:objdir $(PROGS)',其中'objdir'的规则可能是:'objdir:; mkdir -p build/release/objs'(你可以使用换行符和制表符代替分号,尽管显示的符号实际上可以在单行上起作用)。这只是@πάνταῥεῖ所说的更长版本。 –

+0

Jonathan Leffler你已经解决了我的问题,并提供了一个很好的解释来帮助我更好地理解如何制作作品。 – Russeree

回答

1

食谱都是经过任何先决条件执行,因此在制作all时,在运行mkdir之前,将会通过$(PROGS)

build/release/objs应该是目标文件的先决条件,因为除非目录存在,否则无法创建目标文件。该目录也应该是order-only prerequisite,因为如果dir时间戳发生更改,则不需要重新制作每个对象文件。

您的模式规则也是broken(请参阅2),并且您使用的是错误的flag variables。您也可以回收利用built-in implicit rule for compiling

CXXFLAGS := $(shell pkg-config --cflags --libs gtkmm-3.0) 
CPPFLAGS := -Iclasses/ 
SRCS  := $(wildcard classes/source/*.cc) 
OBJS  := $(SRCS:classes/source/%.cc=build/release/objs/%.o) 

.PHONY: all 
all: $(OBJS) 

$(OBJS): build/release/objs/%.o: classes/source/%.cc | build/release/objs 
    $(COMPILE.cc) $(OUTPUT_OPTION) $< 

build/release/objs: ; mkdir -p [email protected] 

旁注:因为你只编译-libs gtkmm-3.0可能不应该在标志,您在连接时提供的库。

+0

非常感谢。 – Russeree

+0

@Russeree如果回答您的问题,请接受答案。 – user657267

+0

非常感谢,完成。 – Russeree

3

最简单的解决方法是使用目标目录之前,总是发出mkdir。如果使用-p选项,那么冗余执行此命令确实没有什么坏处。

%: %.cc 
    mkdir -p build/release/objs 
    $(CC) -I$(CLASS_HEADERS) -c $< -o build/release/objs/$(@F).o $(CPPFLAGS) 

正如我的回答注意到GNU make's -j option:虽然有时工作,这是不正确的只需在您现有的all依赖性列表中添加mkdir目标作为初始依赖。原则上,这些可以以任何顺序执行(所以mkdir不一定是第一个)。如果你想采用基于依赖关系的方法,你必须开始做更复杂的事情。例如使用make递归:

all: do_mkdir 
    $(MAKE) $(progs) 

do_mkdir: 
    mkdir -p build/release/objs 
1

可能的解决方案可以为对象目录中创建目标和构建目标之前将其放置:

为目标
...... 
OBJ_DIR := build/release/objs 

all: create_obj_dir $(PROGS) 

create_obj_dir: 
    mkdir -p $(OBJ_DIR) 

%: %.cc 
    $(CC) -I$(CLASS_HEADERS) -c $< -o $(OBJ_DIR)/$(@F).o $(CPPFLAGS) 
+1

如果您使用-j运行多个生成线程,则不一定有效 –

+0

@ChrisDodd true ... –