为什么 make 不在我的源文件中迭代? [英] Why make doesn't iterate in my sources files?

查看:65
本文介绍了为什么 make 不在我的源文件中迭代?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为我的项目制作了一个 makefile,但 make 不会遍历我的源文件.我不知道我能做些什么来解决这个问题.

I made a makefile fo my project but make doesn't iterate through my source files. I can't figure out what I could do to solve this.

我的目录 atm 中有 2 个源文件

I have 2 source files in my directory atm

生成文件:

LIBNAME=hazelicious
FLIBNAME=lib$(LIBNAME).so
VERSION=
CC=g++
CXXFLAGS=-W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/
LDFLAGS=-shared -Wl,-soname,$(FLIBNAME)
DSRC=src/
DTGT=
DOBJ=$(DTGT)obj/
DOUT=$(DTGT)bin/
EXEC=$(DOUT)$(APPNAME)
SRC= $(wildcard $(DSRC)**/*.cpp)
OBJ= $(subst $(DSRC), $(DOBJ), $(patsubst %.cpp, %.o, $(SRC)))

all: $(FLIBNAME)

install: 
    @sudo cp $(DOUT)$(FLIBNAME) /usr/local/lib/
    @sudo cp $(DSRC)Hazelicious.h /usr/local/include/
    @echo "Library and header files copied!"

$(FLIBNAME): $(OBJ)
    @mkdir -p $(DOUT)
    @$(CC) -o $(DOUT)$@ $^ $(LDFLAGS)

$(OBJ): $(SRC)
    mkdir -p $(DOBJ)
    mkdir -p $(@D)
    $(CC) -o $@ -c $< $(CXXFLAGS)

checkvar:
    @echo $(SRC)
    @echo $(OBJ)

clean:
    @rm -rf $(DOBJ)
    @rm -rf $(EXEC)

run:
    @./$(EXEC)

输出:

g++ -o obj/Hazelicious/Log.o -c src/Hazelicious/Log.cpp -W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/
g++ -o obj/Hazelicious/Application.o -c src/Hazelicious/Log.cpp -W -Wall -O2 -std=c++17 -fPIC -I./vendor/spdlog/include/

如您所见,第二行采用相同的 Log.cpp 文件

As you can see the second line takes the same Log.cpp file

我的目录结构:

/src
  /Hazelicious
    Application.cpp
    Log.cpp
    ...
/obj
  /Hazelicicous
/bin

推荐答案

如果你期待这个:

SRC= $(wildcard $(DSRC)**/*.cpp)

要在$(DSRC) 的所有子目录中查找所有.cpp 文件,您会感到失望.** 特殊通配符序列是非标准的,仅受某些 shell 支持(如 zsh 或 bash,如果您启用了特殊选项).它不是 POSIX 标准通配符的一部分,也不受 GNU make 的 wildcard 函数的支持.您必须使用标准实现,例如:

to find all .cpp files in all subdirectories of $(DSRC), you'll be disappointed. The ** special globbing sequence is non-standard and only supported by some shells (like zsh, or bash if you enable a special option). It's not part of POSIX standard globbing and is not supported by GNU make's wildcard function. You'll have to use a standard implementation such as:

SRC := $(shell find $(DSRC) -name \*.cpp)

(这里使用简单的变量赋值(:=),而不是递归变量赋值(=)以提高效率.

(use simple variable assignment (:=) here, not recursive variable assignment (=) for a big efficiency improvement).

还有这个:

OBJ= $(subst $(DSRC), $(DOBJ), $(patsubst %.cpp, %.o, $(SRC)))

可能会给您带来麻烦,因为 subst 会替换所有 实例,即使在单词中间,即使一个单词中有多个实例也是如此.更好(也更简单)就是:

can get you into trouble because subst substitutes all instances, even in the middle of words, even if there is more than one instance in a word. Much better (and simpler) is just:

OBJ := $(patsubst $(DSRC)/%.cpp,$(DOBJ)/%.o,$(SRC))

您看到相同源文件的原因是您的配方有误:

The reason you see the same source file is that your recipe is wrong:

$(OBJ): $(SRC)
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

假设 SRC 解析为 src/foo.cpp src/bar.cpp src/biz.cpp.然后OBJ 解析为obj/foo.o obj/bar.o obj/biz.o.所以,在扩展上述规则的目标和先决条件后,make 将得到:

Suppose SRC resolves to src/foo.cpp src/bar.cpp src/biz.cpp. Then OBJ resolves to obj/foo.o obj/bar.o obj/biz.o. So, after expanding the target and prerequisite of the above rule, make will get this:

obj/foo.o obj/bar.o obj/biz.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

当 make 在显式规则中看到多个目标时,它会将其视为多个显式规则,每个目标一个,如下所示:

When make sees multiple targets in an explicit rule, it treats that as multiple explicit rules, one for each target, like this:

obj/foo.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)
obj/bar.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)
obj/biz.o : src/foo.cpp src/bar.cpp src/biz.cpp
        mkdir -p $(DOBJ)
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

您可以看到,在您的所有规则中,第一个先决条件(即 $< 扩展为)将是 src/foo.cpp,这正是你观察到的行为.

You can see that in all your rules, the first prerequisite (which is what $< expands to) will be src/foo.cpp, and that's exactly the behavior you observe.

Make 不会以某种方式神奇地遍历所有目标和先决条件并为您匹配它们.

Make doesn't somehow magically loop through all the targets and prerequisites and match them up for you.

在 make 中,您总是编写一个规则来构建单个目标,从该目标的先决条件列表中.在您的情况下,您可能想像这样编写模式规则:

In make you always write a rule that builds a single target, from a list of that target's prerequisites. In your case, you probably want to write a pattern rule like this:

$(DOBJ)/%.o : $(DSRC)/%.cpp
        mkdir -p $(@D)
        $(CC) -o $@ -c $< $(CXXFLAGS)

而不是上面的显式规则.这为 make 提供了一个模式,它可以用来构建任何与其匹配的目标,并列出相关 .cpp 文件的先决条件.

instead of the explicit rule above. This provides make with a pattern it can use to build any target that matches it, and lists a prerequisite of the associated .cpp file.

这篇关于为什么 make 不在我的源文件中迭代?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆