如何在GNU Make中更改当前目录 [英] How to change current directory in GNU Make

查看:178
本文介绍了如何在GNU Make中更改当前目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to separate the directory with sources from the directory with targets. And it seems that changing the current working directory from Makefile should be the simplest solution.

到目标的显式路径不足,因为存在以下缺点:

Explicit path to targets is not sufficient because of the following drawbacks:

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

另请参见保罗的规则#3 :

See also Pauls's rule #3:

如果目标是在当前工作环境中构建的,则生活最简单 目录.

Life is simplest if the targets are built in the current working directory.

关于VPATH -我也同意要求开发人员在运行make之前先切换到目标目录是一件痛苦的事".

Regarding VPATH — I also agree that requiring developers "to change to the target directory before running make is a pain".

推荐答案

已知方法概述

Paul D. Smith在"

Known methods overview

The excellent research of various methods how to separate the source and target directories was made by Paul D. Smith in "Multi-Architecture Builds" paper. The following methods are described (with their drawbacks):

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

但是,我找到了更简单的解决方案-使用更小的样板并且无需递归调用make.如果使用 Guile支持的GNU Make,我们可以只需使用Guile chdir函数即可从Makefile更改当前工作目录. 我们也可以通过 mkdir 之前.

However I found the simpler solution — with smaller boilerplate and without recursive invocation of make. In case of GNU Make with Guile support we can just use Guile chdir function to change the current working directory from Makefile. Also we can create directory via mkdir before that.

data ?= ./data/

# Create $(data) directory if it is not exist (just for example)
$(guile (if (not (access? "$(data)" F_OK)) (mkdir "$(data)") ))

# Set the new correct value of CURDIR (before changing directory)
CURDIR := $(abspath $(data))

# Change the current directory to $(data)
$(guile (chdir "$(data)"))

# Another way of updating CURDIR
#  — via sub-shell call after changing directory
# CURDIR := $(shell pwd)


# Don't try to recreate Makefile file
# that is disappeared now from the current directory
Makefile : ;

$(info     CURDIR = $(CURDIR)     )
$(info        PWD = $(shell pwd)  )

最终样板更改当前目录

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

Final boilerplate to change the current directory

The assumptions: data variable is available in the context and the parent of $(data) directory is accessible, the path can be relative.

srcdir := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
ifeq (,$(filter guile,$(.FEATURES)))
  $(warning Guile is required to change the current directory.)
  $(error Your Make version $(MAKE_VERSION) is not built with support for Guile)
endif
$(MAKEFILE_LIST): ;
$(guile (if (not (file-exists? "$(data)")) (mkdir "$(data)") ))
ORIGCURDIR  := $(CURDIR)
CURDIR      := $(realpath $(data))
$(guile (chdir "$(data)"))
ifneq ($(CURDIR),$(realpath .))
  $(error Cannot change the current directory)
endif
$(warning CURDIR is changed to "$(data)")

请记住,默认情况下,include指令中的相对路径是从当前目录计算得出的,因此,它取决于位置-是在此样板之前还是之后使用.

Remember that relative path in include directive is calculated from the current directory by default, hence it depends on the location — is it used before this boilerplate or after.

NB :规则中不应使用$(data)$(srcdir)可用于指定相对于该Makefile文件位置的文件.

NB: $(data) should not be used in the rules; $(srcdir) can be used to specify a file relative to this Makefile file location.

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

This method was tested in GNU Make 4.0 and 4.2.1

观察到一个小问题. abspath 函数更改当前目录后无法正常工作-根据旧的CURDIR继续解析相对路径; realpath 可行正确.

One minor issue was observed. abspath function works incorrectly after changing the current directory — it continues resolving relative paths according to the old CURDIR; realpath works correctly.

这种方法可能还有其他未知的缺点.

Also this method may have other yet unknown drawbacks.

这篇关于如何在GNU Make中更改当前目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆