如何在 GNU Make 中更改当前目录

ruv*_*vim 9 makefile guile gnu-make

我想将带有源的目录与带有目标的目录分开。似乎从 Makefile 更改当前工作目录应该是最简单的解决方案。

由于以下缺点,明确的目标路径是不够的:

  1. Makefile 中的冗余代码,因为对目标的每个引用都应以变量为前缀。
  2. 更复杂的命令行来构建特定的中间目标(更糟糕的调试)。

另请参阅Pauls 的规则 #3

如果目标构建在当前工作目录中,那么生活是最简单的。

关于 VPATH——我也同意要求开发人员“在运行 make 之前切换到目标目录是一种痛苦”。

Mik*_*han 8

在单独的目录中构建目标是一种常见的make做法,GNUmake方便地支持它,而无需更改目录或调用辅助工具。这是一个例行的说明:

生成文件

srcs := main.c foo.c
blddir := bld
objs := $(addprefix $(blddir)/,$(srcs:.c=.o))
exe := $(blddir)/prog

.PHONY: all clean

all: $(exe)

$(blddir):
    mkdir -p $@

$(blddir)/%.o: %.c | $(blddir)
    $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<

$(exe) : $(objs)
    $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)

clean:
    rm -fr $(blddir)
Run Code Online (Sandbox Code Playgroud)

它运行如下:

$ make
mkdir -p bld
cc   -c -o bld/main.o main.c
cc   -c -o bld/foo.o foo.c
cc -o bld/prog bld/main.o bld/foo.o
Run Code Online (Sandbox Code Playgroud)

婴儿床:-

make更改其工作目录可能有充分的理由,但仅仅将构建产品放在单独的目录中不是一个理由。


use*_*111 6

在 GNU Make 程序中,我使用的是为 mingw64 (windows) 构建的,

GNU Make 4.2.1 专为 x86_64-w64-mingw32 构建

我可以通过这个命令使用这个目标,

debug:
    cd $(PREFIX) && $(GDB) kiwigb.exe
Run Code Online (Sandbox Code Playgroud)

结果是目录更改是暂时的,但一切正常。


ruv*_*vim 5

已知方法概述

\n\n

Paul D. Smith 在“ Multi-Architecture Builds ”论文中对如何分离源目录和目标目录的各种方法进行了出色的研究。描述了以下方法(及其缺点):

\n\n
    \n
  • 源副本
  • \n
  • 显式路径(对每个目标的引用都以路径名为前缀)
  • \n
  • VPATH(从目标目录调用构建)
  • \n
  • 高级VPATH(自动递归调用)
  • \n
\n\n

还有一种方法

\n\n

然而,我发现了更简单的解决方案 \xe2\x80\x94 ,它具有较小的样板,并且没有递归调用make. 如果 GNU Make支持 Guile,我们可以使用 Guilechdir函数从 Makefile 更改当前工作目录。\n我们也可以mkdir在此之前通过创建目录。

\n\n
data ?= ./data/\n\n# Create $(data) directory if it is not exist (just for example)\n$(guile (if (not (access? "$(data)" F_OK)) (mkdir "$(data)") ))\n\n# Set the new correct value of CURDIR (before changing directory)\nCURDIR := $(abspath $(data))\n\n# Change the current directory to $(data)\n$(guile (chdir "$(data)"))\n\n# Another way of updating CURDIR\n#  \xe2\x80\x94 via sub-shell call after changing directory\n# CURDIR := $(shell pwd)\n\n\n# Don\'t try to recreate Makefile file\n# that is disappeared now from the current directory\nMakefile : ;\n\n$(info     CURDIR = $(CURDIR)     )\n$(info        PWD = $(shell pwd)  )\n
Run Code Online (Sandbox Code Playgroud)\n\n

更改当前目录的最终样板

\n\n

假设:data变量在上下文中可用并且$(data)目录的父目录可访问,路径可以是相对的。

\n\n
srcdir := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))\nifeq (,$(filter guile,$(.FEATURES)))\n  $(warning Guile is required to change the current directory.)\n  $(error Your Make version $(MAKE_VERSION) is not built with support for Guile)\nendif\n$(MAKEFILE_LIST): ;\n$(guile (if (not (file-exists? "$(data)")) (mkdir "$(data)") ))\nORIGCURDIR  := $(CURDIR)\nCURDIR      := $(realpath $(data))\n$(guile (chdir "$(data)"))\nifneq ($(CURDIR),$(realpath .))\n  $(error Cannot change the current directory)\nendif\n$(warning CURDIR is changed to "$(data)")\n
Run Code Online (Sandbox Code Playgroud)\n\n

请记住,指令中的相对路径include默认是从当前目录计算的,因此它取决于位置 \xe2\x80\x94 是在此样板之前还是之后使用。

\n\n

注意$(data)不应在规则中使用;$(srcdir)可用于指定相对于此 Makefile 文件位置的文件。

\n\n

发现问题

\n\n

该方法在GNU Make 4.0和4.2.1中进行了测试

\n\n

观察到一个小问题。abspath更改当前目录 \xe2\x80\x94 后,函数无法正常工作,它会继续根据旧目录解析相对路径CURDIRrealpath工作正常。

\n\n

此外,该方法可能还有其他未知的缺点。

\n

  • 主要缺点是它要求您拥有一个带有 Guile 支持的 GNU make 版本,该版本直到 GNU make 4.0 才出现,并且仍然是可选的,因此并非所有构建都可能有它。 (2认同)