makefile - Makefile - 根据条件分配变量
问题描述
我正在尝试将GNU make的官方文档中的示例改编为我的用例: GNU make - Example of a Conditional
libs_for_gcc = -lgnu
normal_libs =
ifeq ($(CC),gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif
foo: $(objects)
$(CC) -o foo $(objects) $(libs)
所以,我创建了这个原型:
libs_for_gcc="gcc libs"
normal_libs="normal libs"
libs=
all: do_nothing
@echo "all: done."
do_nothing:
@echo "do_nothing: done."
example:
@echo "example: go ..."
@echo "example - cc: '$(CC)'"
@echo "libs_for_gcc: $(libs_for_gcc)"
@echo "normal_libs: $(normal_libs)"
@echo "libs: $(libs)"
ifeq ($(CC),gcc)
libs=$(libs_for_gcc) && echo "libs: '$$libs'"
@echo "example - libs: '$(libs)'"
else
libs=$(normal_libs) && echo "libs: '$$libs'"
@echo example - libs: $(libs)
endif
@echo "example - libs: '$(libs)'"
@echo "example: done."
test: libs += " -Ddebug"
test: example foo
bar:
@echo "bar: go ..."
ifeq (${libs}, "")
@echo "bar - libs: empty"
@echo "assigning libs"
libs=$(libs_for_gcc)
else
@echo "bar - libs: not empty"
@echo "bar - libs: '${libs}'"
endif
@echo "bar - libs: '${libs}'"
@echo "bar: done."
foo:
@echo "foo: go ..."
ifneq ("$(libs)", "")
@echo "foo - libs: not empty"
@echo "foo - libs: '$(libs)'"
else
@echo "foo - libs: empty"
endif
@echo "foo: done."
现在,当我使用它运行默认目标时,$ make
它只会产生:
$ make
example: go ...
example - cc: 'cc'
libs_for_gcc: gcc libs
normal_libs: normal libs
libs:
libs="normal libs"
example - libs:
example - libs: ''
example: done.
我看到 的值libs
没有按预期更改。
当我运行make bar
目标时,它会产生:
$ make bar
bar: go ...
bar - libs: not empty
bar - libs: ''
bar - libs: ''
bar: done.
这里libs
不是空的,但里面什么都没有。
当我运行make foo
目标时,它会产生:
$ make foo
foo: go ...
foo - libs: empty
foo: done.
这里libs
理解为空
如我所见,libs
没有正确更改,我尝试将语法更改为:
example:
# [...]
ifeq ($(CC),gcc)
libs := $(libs_for_gcc)
@echo "example - libs: '$(libs)'"
else
libs := $(normal_libs)
@echo example - libs: $(libs)
endif
但后来我得到了GNU make错误:
$ make
example: go ...
example - cc: 'cc'
libs_for_gcc: gcc libs
normal_libs: normal libs
libs:
libs := "normal libs"
/bin/sh: 1: libs: not found
Makefile:7: recipe for target 'example' failed
make: *** [example] Error 127
我找不到任何关于这种行为的文档,所以我很感激任何建议。
编辑:
- 添加
all
和test
目标。
背景:
GNU make命令是用于打包和部署软件的工具链的重要组成部分,因此在系统管理员和 DevOps 工程师的日常工作中非常重要。
- Debian和RPM打包使用GNU make来打包软件。
Makefile Driven Packaging
它运行
./configure && make && make install
命令序列。 - Travis CI工作流程使用GNU make来运行测试套件。
C 语言自动测试
它运行
./configure && make && make test
序列。
所有完全不同的用例都由同一个 Makefile管理。现在,对于我的具体用例,我正在设置Travis CI工作流序列,以便为我的静态链接源代码库启用自动化测试。因此,与打包序列相反,自动化测试序列需要调试功能和高级输出评估来生成有意义的测试。我希望测试检查错误报告和内存使用报告,以提醒我任何隐藏的错误。
使用关于在目标声明行设置变量的建议,我能够更改libs
,和目标。我还看到了关于Bash变量的重要提示,它只在同一行有效:test
example
foo
libs
$ make
do_nothing: done.
all: done.
$ make test
example: go ...
example - cc: 'cc'
libs_for_gcc: gcc libs
normal_libs: normal libs
libs: -Ddebug
libs="normal libs" && echo "libs: '$libs'" ;
libs: 'normal libs'
example - libs: -Ddebug
example - libs: ' -Ddebug'
example: done.
foo: go ...
foo - libs: empty
foo - libs: ' -Ddebug'
foo: done.
配方libs=$(libs_for_gcc) && echo "libs: '$$libs'"
显示创建了一个新的Bash变量libs
,它不会影响GNU make变量。
条件仍然ifneq ($(libs),)
无法检测到libs
已经为test
目标设置的内容。
解决方案
您的示例与 GNU make 手册中的示例之间的区别在于,在 GNU make 手册中,他们设置了一个名为的make变量libs
(他们在任何配方之外分配变量)。
在您的使用中,您分配了一个名为的shell变量libs
(您在配方中分配它,用 TAB 缩进)。
这就是为什么您在尝试使用时会收到错误的原因:=
,因为这是一个make赋值,而不是一个有效的shell赋值。
然后在您的echo
打印中打印根本没有设置的make变量。$(libs)
此外,配方的每个逻辑行都在它自己的 shell 中运行。所以你正在运行相当于:
/bin/sh -c 'libs="gcc libs"'
/bin/sh -c 'echo '
因此,即使您确实更改了 echo 命令以打印 shell 变量(通过$$libs
),它也会为空,因为设置它的前一个 shell 已经退出。
您想使用与示例中相同的语法:将配方的变量 OUT 赋值并设置 make 变量:
libs_for_gcc = gcc libs
normal_libs = normal libs
ifeq ($(CC),gcc)
libs = $(libs_for_gcc)
else
libs = $(normal_libs)
endif
example:
@echo "example: go ..."
@echo "example - cc: '$(CC)'"
@echo "libs_for_gcc: $(libs_for_gcc)"
@echo "normal_libs: $(normal_libs)"
@echo "libs: $(libs)"
@echo "example - libs: '$(libs)'"
@echo "example: done."
推荐阅读
- python-3.x - max() arg 是 max(listname) 中的一个空序列
- ruby-on-rails - 使用 -d(守护进程)运行 Rails(Puma)时的 Nginx 502
- python-3.x - 运行 python 抓取代码后显示 TypeError(o'reilly 示例代码)
- flutter - 如何处理流控制器 Flutter
- reactjs - 反应中未显示图像预览
- ffmpeg - 使用 FFmpeg 录制屏幕
- log4j2 - 如何将 log4j.property 设置为 .jar 位置
- model-view-controller - stimulsoft mvc core如何动态报告图像大小
- c - 传递给函数的值已更改
- javascript - 将数组前一个对象分配给下一个元素并更新最后一个