You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在GNU Make 3.81的Makefile中切换至相对父目录?

解决GNU Make中cd到父目录不生效的问题

嘿,这个坑我踩过!在GNU Make里直接写cd '..'没效果,核心原因是Make的每条命令都是在独立的Shell进程中执行的——你cd到父目录的那个进程跑完就终止了,下一条命令又回到了Make初始的工作目录,相当于白cd了😅。

要解决这个问题,关键是要基于当前Makefile文件的实际路径来切换目录(而不是依赖执行make命令时的工作目录),同时让cd和后续命令在同一个Shell进程里生效。下面给你两种实用的解决方法:

方法1:获取Makefile的绝对路径,统一在父目录执行命令

首先,先定义一个变量来获取当前Makefile所在的绝对目录(不管你在哪个目录执行make,这个路径都是准确的):

# 获取当前Makefile的绝对目录
MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
# 基于上面的路径,得到父目录的绝对路径
PARENT_DIR := $(abspath $(MAKEFILE_DIR)/..)

然后,你可以用两种方式在父目录执行命令:

方式A:把cd和命令放在同一行(同Shell进程)

把cd和要执行的命令用&&连接,这样它们会在同一个Shell进程里运行,cd的效果会保留:

# 示例:在父目录打印当前路径
print-parent-dir:
    cd $(PARENT_DIR) && echo "当前工作目录:$$PWD"

如果要执行多条命令,可以用Shell的大括号把命令包起来,注意每行末尾加反斜杠\(表示命令未结束):

# 示例:在父目录执行多个操作
parent-operations:
    cd $(PARENT_DIR) && { \
        echo "列出父目录内容:"; \
        ls -l; \
        echo "创建临时文件:"; \
        touch temp_demo.txt; \
    }

方式B:用make -C直接切换目录执行目标

如果父目录也有Makefile,你可以直接用make-C选项(切换到指定目录后再执行目标),这是更简洁的写法:

# 示例:调用父目录Makefile的build目标
build-parent-project:
    $(MAKE) -C $(PARENT_DIR) build

方法2:全局切换Make的工作目录(适合整个Makefile都在父目录工作)

如果你的整个Makefile逻辑都需要在父目录运行,可以在Makefile开头就切换工作目录,比如:

MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
# 切换到父目录,后续所有命令都在该目录执行
$(shell cd $(MAKEFILE_DIR)/..)
# 或者更稳妥的,重新设置CURDIR变量
CURDIR := $(abspath $(MAKEFILE_DIR)/..)

不过这种方式要注意,后续所有依赖路径都要基于父目录来写,避免混淆。

为什么直接cd '..'不行?

举个反例,你写这样的代码:

bad-example:
    cd '..'
    pwd

这两条命令是在两个完全独立的Shell进程里执行的:第一条进程cd到父目录后就退出了,第二条进程还是在你执行make时的原始目录,所以pwd输出的还是原来的路径,看起来cd没生效。

内容的提问来源于stack exchange,提问作者kenorb

火山引擎 最新活动