makefile 符号 $@ 和 $< 有何作用?意思是?

发布于 2024-09-08 22:27:47 字数 332 浏览 3 评论 0 原文

CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
    $(CC) $(CFLAGS) $< -o $@

$@$< 到底是做什么的?

CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
    $(CC) $(CFLAGS) 
lt; -o $@

What do the $@ and $< do exactly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

小帐篷 2024-09-15 22:27:47

$@ 是正在生成的目标的名称,$< 是第一个先决条件(通常是源文件)。您可以在 GNU制作手册

例如,考虑以下声明:

all: library.cpp main.cpp

在本例中:

  • $@ 计算结果为 all
  • $< 计算结果为 library.cpp< /code>
  • $^ 计算结果为 library.cpp main.cpp

$@ is the name of the target being generated, and $< the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.

For example, consider the following declaration:

all: library.cpp main.cpp

In this case:

  • $@ evaluates to all
  • $< evaluates to library.cpp
  • $^ evaluates to library.cpp main.cpp
她如夕阳 2024-09-15 22:27:47

来自 使用 GNU Make 管理项目,第三版,第 14 页16(它遵循 GNU 自由文档许可证):

自动变量是在规则匹配后由make设置的。他们
提供对目标和先决条件列表中的元素的访问,以便
您不必显式指定任何文件名。他们非常
对于避免代码重复很有用,但在定义时至关重要
更通用的模式规则。

有七个“核心”自动变量:

  • $@:代表目标的文件名。

  • $%:存档成员规范的文件名元素。

  • $<:第一个先决条件的文件名。

  • $?:比目标更新的所有先决条件的名称,
    用空格分隔。

  • $^:所有先决条件的文件名,以空格分隔。这
    列表已删除重复的文件名,因为对于大多数用途,例如
    编译、复制等,不需要重复。

  • $+:与$^类似,这是分隔的所有先决条件的名称
    由空格组成,但 $+ 包含重复项。这个变量是
    为特定情况创建,例如链接器的参数,其中
    重复的值有意义。

  • $*:目标文件名的主干。词干通常是文件名
    没有它的后缀。它在模式规则之外的使用是
    气馁。

此外,上述每个变量都有两个变体
与其他品牌的兼容性。一种变体仅返回目录
值的一部分。这通过在后面附加“D”来表示
符号、$(@D)$( 等。另一个变体仅返回文件
值的一部分。这通过在后面附加“F”来表示
符号、$(@F)$( 等。请注意,这些变体名称超过
一个字符长,因此必须用括号括起来。 GNU 使
为 dir 和 notdir 提供了更具可读性的替代方案
功能。


From Managing Projects with GNU Make, 3rd Edition, p. 16 (it's under GNU Free Documentation License):

Automatic variables are set by make after a rule is matched. They
provide access to elements from the target and prerequisite lists so
you don’t have to explicitly specify any filenames. They are very
useful for avoiding code duplication, but are critical when defining
more general pattern rules.

There are seven “core” automatic variables:

  • $@: The filename representing the target.

  • $%: The filename element of an archive member specification.

  • $<: The filename of the first prerequisite.

  • $?: The names of all prerequisites that are newer than the target,
    separated by spaces.

  • $^: The filenames of all the prerequisites, separated by spaces. This
    list has duplicate filenames removed since for most uses, such as
    compiling, copying, etc., duplicates are not wanted.

  • $+: Similar to $^, this is the names of all the prerequisites separated
    by spaces, except that $+ includes duplicates. This variable was
    created for specific situations such as arguments to linkers where
    duplicate values have meaning.

  • $*: The stem of the target filename. A stem is typically a filename
    without its suffix. Its use outside of pattern rules is
    discouraged.

In addition, each of the above variables has two variants for
compatibility with other makes. One variant returns only the directory
portion of the value. This is indicated by appending a “D” to the
symbol, $(@D), $(<D), etc. The other variant returns only the file
portion of the value. This is indicated by appending an “F” to the
symbol, $(@F), $(<F), etc. Note that these variant names are more than
one character long and so must be enclosed in parentheses. GNU make
provides a more readable alternative with the dir and notdir
functions.

抱猫软卧 2024-09-15 22:27:47

$@$< 称为自动变量。变量 $@ 表示目标的名称,$< 表示创建输出文件所需的第一个先决条件。
例如:

hello.o: hello.c hello.h
         gcc -c 
lt; -o $@

这里,hello.o 是输出文件。这就是 $@ 扩展的内容。第一个依赖项是 hello.c。这就是 $< 扩展的结果。

-c 标志生成 .o 文件;请参阅 man gcc 了解更详细的解释。 -o 指定要创建的输出文件。

有关更多详细信息,您可以阅读这篇有关 linicide 的 Linux Makefile 的文章

另外,您可以检查 GNU make手册。它将使制作 Makefile 和调试它们变得更容易。

如果运行此命令,它将输出 makefile 数据库:

make -p 

The $@ and $< are called automatic variables. The variable $@ represents the name of the target and $< represents the first prerequisite required to create the output file.
For example:

hello.o: hello.c hello.h
         gcc -c 
lt; -o $@

Here, hello.o is the output file. This is what $@ expands to. The first dependency is hello.c. That's what $< expands to.

The -c flag generates the .o file; see man gcc for a more detailed explanation. The -o specifies the output file to create.

For further details, you can read this article on linoxide about Linux Makefiles.

Also, you can check the GNU make manuals. It will make it easier to make Makefiles and to debug them.

If you run this command, it will output the makefile database:

make -p 
南风几经秋 2024-09-15 22:27:47

$@$< 是特殊宏。

其中:

$@ 是目标的文件名。

$< 是第一个依赖项的名称。

The $@ and $< are special macros.

Where:

$@ is the file name of the target.

$< is the name of the first dependency.

慕烟庭风 2024-09-15 22:27:47

如果 main.cpphello.cppfactorial.cpp 中的任何一个发生更改,Makefile 将构建 hello 可执行文件。实现该规范的最小 Makefile 可能是:

hello: main.cpp hello.cpp factorial.cpp
    g++ -o hello main.cpp hello.cpp factorial.cpp
  • 优点:非常容易阅读
  • 缺点:维护噩梦,C++ 依赖项重复
  • 缺点:效率问题,我们重新编译所有 C++,即使只更改了一个

为了改进上述内容,我们只编译那些已编辑过的 C++ 文件。然后,我们将生成的目标文件链接在一起。

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

main.o: main.cpp
    g++ -c main.cpp

hello.o: hello.cpp
    g++ -c hello.cpp

factorial.o: factorial.cpp
    g++ -c factorial.cpp
  • 优点:修复了效率问题
  • 缺点:新的维护噩梦,对象文件规则上可能存在拼写错误

为了改进这一点,我们可以用单个 .cpp.o 规则替换所有对象文件规则:

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

.cpp.o:
    g++ -c 
lt; -o $@
  • 优点:回到具有一个简短的 makefile,有点容易阅读

这里的 .cpp.o 规则定义了如何从 anyfile.cpp 构建 anyfile.o

  • $< 匹配第一个依赖项,在本例中为 anyfile.cpp
  • $@ 与目标匹配,在本例中为 anyfile .o

Makefile 中的其他更改包括:

  • 更轻松地将编译器从 g++ 更改为任何 C++ 编译器。
  • 使更改编译器选项变得更加容易。
  • 使更改链接器选项变得更加容易。
  • 使更改 C++ 源文件和输出变得更加容易。
  • 添加了默认规则“all”,该规则充当快速检查,以确保在尝试构建应用程序之前所有源文件都存在。

The Makefile builds the hello executable if any one of main.cpp, hello.cpp, factorial.cpp changed. The smallest possible Makefile to achieve that specification could have been:

hello: main.cpp hello.cpp factorial.cpp
    g++ -o hello main.cpp hello.cpp factorial.cpp
  • pro: very easy to read
  • con: maintenance nightmare, duplication of the C++ dependencies
  • con: efficiency problem, we recompile all C++ even if only one was changed

To improve on the above, we only compile those C++ files that were edited. Then, we just link the resultant object files together.

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

main.o: main.cpp
    g++ -c main.cpp

hello.o: hello.cpp
    g++ -c hello.cpp

factorial.o: factorial.cpp
    g++ -c factorial.cpp
  • pro: fixes efficiency issue
  • con: new maintenance nightmare, potential typo on object files rules

To improve on this, we can replace all object file rules with a single .cpp.o rule:

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

.cpp.o:
    g++ -c 
lt; -o $@
  • pro: back to having a short makefile, somewhat easy to read

Here the .cpp.o rule defines how to build anyfile.o from anyfile.cpp.

  • $< matches to first dependency, in this case, anyfile.cpp
  • $@ matches the target, in this case, anyfile.o.

The other changes present in the Makefile are:

  • Making it easier to changes compilers from g++ to any C++ compiler.
  • Making it easier to change the compiler options.
  • Making it easier to change the linker options.
  • Making it easier to change the C++ source files and output.
  • Added a default rule 'all' which acts as a quick check to ensure all your source files are present before an attempt to build your application is made.
过期以后 2024-09-15 22:27:47

例如,如果您想编译源代码但在不同的目录中有对象:

您需要执行以下操作:

gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...

但对于大多数宏,结果将是所有对象后跟所有源,例如:

gcc -c -o <all OBJ path> <all SRC path>

所以这不会编译任何内容^^,您将无法将对象文件放在不同的目录中:(

解决方案是使用这些特殊宏,

$@ 
lt;

这将为 SRC (src/file.c) 中的每个 .c 文件生成一个 .o 文件 (obj/file.o)

$(OBJ):$(SRC)
   gcc -c -o $@ 
lt; $(HEADERS) $(FLAGS)

这意味着:

    $@ = $(OBJ)
    
lt; = $(SRC)

但是逐行代替 OBJ 的所有行,后面跟着 SRC 的所有行

in exemple if you want to compile sources but have objects in an different directory :

You need to do :

gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...

but with most of macros the result will be all objects followed by all sources, like :

gcc -c -o <all OBJ path> <all SRC path>

so this will not compile anything ^^ and you will not be able to put your objects files in a different dir :(

the solution is to use these special macros

$@ 
lt;

this will generate a .o file (obj/file.o) for each .c file in SRC (src/file.c)

$(OBJ):$(SRC)
   gcc -c -o $@ 
lt; $(HEADERS) $(FLAGS)

it means :

    $@ = $(OBJ)
    
lt; = $(SRC)

but lines by lines INSTEAD of all lines of OBJ followed by all lines of SRC

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文