0

我正在使用递归 Makefile 运行 make (GNU Make 3.82)。
我正在运行make -j2以仅并行生成 2 个进程。
内部 Makefile 用 $(MAKE) 调用。

但是,看起来内部 Makefile(由主 Makefile 启动)无限生成进程,就好像它是给定的-j,而不是-j2.

为了验证这一点,我转储了孩子“make”的环境变量:

# pgrep -a make
17218 make -j2
17227 make -C obj_dir/ -f Vf1_package.mk ...

# strings /proc/17227/environ
...
MAKEFLAGS= --jobserver-fds=3,4 -j
...

MAKEFLAGS没有在任何地方显式设置,并且-j只在命令行中提供,并且不会出现在 makefile 的任何地方。因此,似乎“make”本身决定在为孩子“make”-j编写时从论点中去除“2”。MAKEFLAGS

知道什么可能导致“make”设置MAKEFLAGS-j而不是-j2


更新 1

我已经确定了问题,但我仍然不明白为什么会发生以及如何解决。

问题是当子制作在SCL上下文下运行时,作业服务器无法正常工作。
这是必需的,因为我需要子制作才能使用特定的 gcc 工具链。

SCL      = scl enable devtoolset-8
...
sub_make:
    $(SCL) "$(MAKE) -C $(SUB_MAKE_DIR) ... "

像这样运行时,子制作会产生无限数量的作业。删除 SCL 后,它会按预期工作。

  • 为什么 SCL 会干扰 make 的作业服务器?
  • 我该如何解决这个问题?我知道我可以在运行外部 Makefile 之前启用 SCL,但我想从 Makefile 中控制工具集。

更新 2

这似乎与SCL更改PATH环境变量的事实有关。在 newPATH上,“make”是较新的(“GNU Make 4.2.1”)。

因此,如果顶级 make 正在运行旧的 GNU Make 3.82 并且子 make 正在运行更新的 4.2.1 make,那么 make 作业服务器似乎会失败,也许这些版本之间在 make 与子 make 通信的方式上发生了一些变化。

4

2 回答 2

1

这里没有错。顶级品牌知道总共有多少工作,并安排所有子品牌通过工作服务器共享这些工作(这就是--jobserver-fds进入的MAKEFLAGS目的)。子制作不需要知道总共有多少工作,他们只需要知道如何询问他们是否可以开始新工作。

在您使用的非常旧版本的 GNU make 中,无法从子 make 中知道-j此构建的具体编号。

从 GNU make 4.2 开始,make 将添加特定-j值以MAKEFLAGS供参考,即使它仍未使用。

编辑

我对它的工作原理一无所知scl。但是,GNU make jobserver 通过在所有子 make 之间共享文件描述符来工作。如果此scl工具对此进行了干扰,例如强制关闭所有文件描述符,或者在显然无法访问这些共享文件描述符的 docker 映像中运行 sub-make 或类似的事情,那么它显然无法工作使用 jobserver 功能,您必须在 scl 中运行整个 make。

一种选择是不要将 ,-j放在外部 make 上,而是使用-j, inside运行单个内部 make scl

于 2021-05-18T13:11:47.190 回答
0

您可以运行make --print-data-base 并检查是否获得正确的-j.

可以执行一个简单的测试示例,如下所示,您可以在其中测试以检查 gnu make 是否能够并行编译多个文件以生成目标文件并给出正确的 -j 值:

# .SILENT:
.PHONY:compile objs
TARGET = program.exe
CC=gcc

SOURCES = file_1.c file_2.c file_3.c
OBJ_FILES:= $(SOURCES:.c=.o)


objs: $(OBJ_FILES)

%.o: %.c
    $(CC) $(FLAGS) -c $< -o $@

all: test 

# Enable parallel compilation
compile:
    make -j ${NUMBER_OF_PROCESSORS} objs

link : compile $(TARGET)

$(TARGET): $(OBJ_FILES)
    $(CC) $(FLAGS) $(OBJ_FILES) -o $@

test: link 
    # Execute test script
    echo "Executing test script"

执行命令:make test
这将帮助您调试并检查是否存在 gnu-make 问题或某些内部错误或 make 无法并行运行,因为它没有找到任何东西。我曾经使用${NUMBER_OF_PROCESSORS}过所有可用的处理器,您可以根据需要更改它的值并测试不同的运行。

编辑
不幸的是我不知道sc1。如果scl是确定的根本原因,那么选项将在sc1内运行整个make。或者通过在 sc1 中显式传递 -j2 来测试一次可能会很好,因为全局标志可能没有传递给 SC1。

于 2021-05-18T14:21:21.383 回答