简体   繁体   English

如何在 makefile 条件中使用自动变量?

[英]How do I use automatic variables in makefile conditionals?

Summarize the problem总结问题
I would like to change the compilation for a single source file, like so:我想更改单个源文件的编译,如下所示:

%.exe: %.c
ifeq($@, cannon.exe)
    $(CC) $(CFLAGS) -o $(patsubst %.exe,%,$@) $^ $(inc_flags) $(LDLIBS)
else
    $(CC) $(CFLAGS) -o $(patsubst %.exe,%,$@) $^
endif

but it doesn't work!但它不起作用!

Describe what you've tried描述你尝试过的东西
I have tried getting bash conditionals involved, but I couldn't figure it out and I shouldn't have to mix bash and make.我曾尝试让 bash 条件涉及,但我无法弄清楚,我不应该混合 bash 和 make。

Here's the full Makefile:这是完整的 Makefile:

CC := gcc
CFLAGS := -g -Wall -Wextra
LDLIBS := -lm
inc_dirs := math.h stdio.h
inc_flags := $(addprefix -I,$(inc_dirs))

executable:=cannon.exe
source:=$(executable:%.exe=%.cpp)

.DELETE_ON_ERROR:
all: $(executable)

%.exe: %.c
ifeq($@, cannon.exe)
    $(CC) $(CFLAGS) -o $(patsubst %.exe,%,$@) $^ $(inc_flags) $(LDLIBS)
else
    $(CC) $(CFLAGS) -o $(patsubst %.exe,%,$@) $^
endif

clean:
    rm -f $(executable:%.exe=%)

It turns out that if you want to do a special case for a certain source file, you can just define its recipe explicitly!事实证明,如果你想为某个源文件做一个特殊情况,你可以明确定义它的配方! Make will take explicit over implicit rules. Make 将显式接管隐式规则。 Full working code below.下面的完整工作代码。

CC := gcc
CFLAGS := -g -Wall -Wextra
LDLIBS := -lm
inc_dirs := math.h stdio.h
inc_flags := $(addprefix -I,$(inc_dirs))

executable:=cannon.exe
source:=$(executable:%.exe=%.cpp)
# no deps so no objs

.DELETE_ON_ERROR:
all: $(executable)

%.exe: %.c
    $(CC) $(CFLAGS) -o $(patsubst %.exe,%,$@) $^

cannon.exe: cannon.c
    $(CC) $(CFLAGS) -o $(patsubst %.exe,%,$@) $^ $(inc_flags) $(LDLIBS)

clean:
    rm -f $(executable:%.exe=%)

A better / more make-ish solution is to use constructed variable names , like this:一个更好/更完美的解决方案是使用构造变量名称,如下所示:

CC := gcc
CFLAGS := -g -Wall -Wextra
LDLIBS := -lm

inc_dirs := math.h stdio.h    
cannon_CFLAGS := $(addprefix -I,$(inc_dirs))

executable := cannon.exe
source := $(executable:%.exe=%.cpp)
# no deps so no objs

.DELETE_ON_ERROR:
all: $(executable)

%.exe: %.c
        $(CC) $(CFLAGS) $($*_CFLAGS) -o $@ $^

clean:
        rm -f $(executable:%.exe=%)

Notes:笔记:

Your rules should always create the same name as the target in the makefile.您的规则应始终创建与 makefile 中的目标相同的名称。 It's not right for the target to be named foo.exe but the build command creates a file named foo .将目标命名为foo.exe是不对的,但是 build 命令会创建一个名为foo的文件。 If you want to create a file named foo , then the makefile target should be named foo .如果要创建一个名为foo的文件,则 makefile 目标应命名为foo Basically you should always create the file contained in the make variable $@ .基本上,您应该始终创建包含在 make 变量$@中的文件。

Is it really the case that the directories you have are named math.h and stdio.h ?您拥有的目录是否真的被命名为math.hstdio.h That's.... bizarre.这……很奇怪。 And very likely to cause serious problems.而且极有可能造成严重的问题。 If math.h and stdio.h are files, then you should not add them with -I because -I takes directory names, in which to search file files.如果math.hstdio.h是文件,则不应将它们与-I添加,因为-I采用目录名称,在其中搜索文件文件。 It doesn't take filenames.它不需要文件名。

If you really did create local files named math.h and stdio.h , that's also a very bad idea: those are standard header file names and you shouldn't redeclare them yourself unless you really know what you're doing.如果您确实创建了名为math.hstdio.h的本地文件,那也是一个非常糟糕的主意:这些是标准头文件名,除非您真的知道自己在做什么,否则您不应该自己重新声明它们。

If you didn't create these files and you're just trying to include the standard headers math.h and stdio.h in your file, then you definitely don't need to add any flags to your compile line.如果您没有创建这些文件,而只是尝试在文件中包含标准头文件math.hstdio.h ,那么您绝对不需要在编译行中添加任何标志。 Just include them.只需包括它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM