49

我试图通过使用一个通用的 makefile 来整合一些构建信息。我的问题是我想使用来自不同子目录级别的 makefile,这使得工作目录值 ( pwd) 不可预测。例如:

# Makefile.common
TOP := $(shell pwd)
COMPONENT_DIR := $(TOP)/component
COMPONENT_INC := $(COMPONENT_DIR)/include
COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a

如果我Makefile.common从子目录中包含,像这样,$(TOP)目录不正确,其他一切都遵循:

# other_component/Makefile
include ../Makefile.common
# $(COMPONENT_LIB) is incorrectly other_component/component

Makefile.common使用自己的目录路径而不是更善变的最佳方法是什么pwd

4

5 回答 5

71

您应该能够使用MAKEFILE_LIST 变量,如下所示:

# This must be the first line in Makefile.common
TOP := $(dir $(firstword $(MAKEFILE_LIST)))

从文档中:

当 make 读取各种 makefile 时,包括从 MAKEFILES 变量、命令行、默认文件或包含指令获得的任何文件,它们的名称将自动附加到 MAKEFILE_LIST 变量中。它们是在 make 开始解析它们之前添加的。这意味着如果 makefile 所做的第一件事是检查此变量中的最后一个单词,它将是当前 makefile 的名称。但是,一旦当前的 makefile 使用了 include,最后一个单词将是刚刚包含的 makefile。

于 2008-11-27T23:05:22.703 回答
10

这不是好的风格,因为它添加了另一个依赖项(即 realpath 二进制文件)。根据您的用例,这可能是可以接受的。

ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

如果您没有安装 realpath:

$ sudo apt-get install realpath # on debian and derivatives

编辑:一定要使用:=,而不是=因为后者会导致make使用后期绑定,并且MAKEFILE_LIST可能由于后期包含而改变。

于 2010-03-30T19:13:43.983 回答
2

您是否尝试过这样做:

# Makefile.common
TOP ?= $(shell pwd)
COMPONENT_DIR := $(TOP)/component
COMPONENT_INC := $(COMPONENT_DIR)/include
COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a

# other_component/Makefile
TOP ?= ..
include ../Makefile.common

使用 ?= 构造将防止 TOP 被重新定义(如果已设置)。您可以在调用 make 时根据您在树中的位置将其设置为适当的值。我承认我使用 GNU make 已经有一段时间了,所以这可能不起作用或可能需要一些调整。

于 2008-11-27T04:44:26.623 回答
2

把常用的东西写进去common.mk。然后将 common.mk 放在 Make 在遇到 include 语句时查找的默认目录中。请参阅Make 查找的常用目录的手册

您也可以将 common.mk 放在自定义目录中,然后键入 make -I customdir.

在每个子文件夹的 Makefile 中,您可以

include common.mk

就这些。无需担心路径和移动东西。

于 2012-04-22T04:23:40.633 回答
2

我的解决方案:

cwd  :=  $(shell readlink -en $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))) 

这也适用于make -f /opt/some/dir/Makefile whenn your in 之类的调用/opt/other/path/subdir

于 2015-01-29T08:12:13.770 回答