GNU make:在Makefile中将参数提取到-j

时间:2011-03-14 19:40:06

标签: gnu-make

我一直在寻找一个小时,这些信息似乎无处可寻......

我希望能够提取(并且可能使用)通过-j选项传递的请求make“jobs”的数量,或者在Makefile中通过Make子本身来实现。

到目前为止我见过的最有希望的是$(MAKEFLAGS)变量,但在我的系统上(如果我这样做,比如make -j2),这个变量的内容只是“--jobserver-fds = 3,4 -j“。有没有办法用-j传递实际的作业数?

3 个答案:

答案 0 :(得分:13)

我很抱歉,但无法识别并行作业的数量 - 无需编写扫描进程列表的应用程序或脚本来识别调用参数。

检查http://cvs.savannah.gnu.org/viewvc/make/main.c?revision=1.246&root=make&view=markup处的源代码。搜索job_slots > 1

更新:如果您可以控制操作范围,可以使用自己的程序/脚本包装make应用程序,解析参数,设置专用环境变量并在之后调用原始make。

答案 1 :(得分:11)

实际上有一种方法可以在* nix上的makefile中完全实现。

MAKE_PID := $(shell echo $$PPID)
JOB_FLAG := $(filter -j%, $(subst -j ,-j,$(shell ps T | grep "^\s*$(MAKE_PID).*$(MAKE)")))
JOBS     := $(subst -j,,$(JOB_FLAG))

ps,grep也需要安装,但它几乎是给定的。它可以进一步改进以处理 - 工作也

答案 2 :(得分:1)

哟,

我想出了一种不同的方法,我更喜欢按照已接受的答案中的建议解析命令行。我遇到的主要问题是它不能在递归调用的 makefile 中工作,因为作业参数是通过那里的 env 传递的,然后它代表作业服务器,它不告诉你它将提供多少作业令牌

所以我决定真正接受 jobserver 的事情,并制作一个小的 python 代码,它消耗来自 jobserver 的所有令牌,对它们进行计数,然后将它们放回去。

这是一个巧妙的想法,似乎非常容易实现,而且对我来说似乎非常有效。

关于如何使用它有多个注意事项:

  1. 必须在配方中使用 + 前缀调用脚本,因为这样可以启用“submake”功能,该功能复制子进程的作业服务器描述符,以便能够“生成工作人员”
  2. 为了给出正确的作业计数,配方中包含此脚本的规则应该成为所有目标的通用订单伪先决条件,以便它由 make 在其他任何事情之前运行,并且永远不会与其他事情并行, 因为然后计数将关闭

python 脚本:


import argparse, os

def safe_int(s):
    try:
        return int(s)
    except:
        return -1

class JobserverArgs:
    known_names = ["jobserver-fds","jobserver-auth"]
    def __init__(self):
        self.fds = "-1,-1"

    @staticmethod
    def from_argv():
        ja = JobserverArgs()
        parser = argparse.ArgumentParser()
        for name in JobserverArgs.known_names:
            parser.add_argument('--'+name, dest="fds")
        parser.parse_known_args(namespace=ja)
        return ja

    def get_fds(self):
        return tuple([safe_int(fd) for fd in (self.fds+",").split(",")][:2])


fd_in, fd_out = JobserverArgs.from_argv().get_fds()

if fd_in == -1 or fd_out == -1:
    print(1)
else:
    os.set_blocking(fd_in, False)

    tokens = os.read(fd_in, 1024)
    os.write(fd_out, tokens)

    print(len(tokens)+1)

示例生成文件:

TARGETS := a b c d e

.PHONY: $(TARGETS)
$(TARGETS):
    @for i in 1 2; do echo "$@$$i"; sleep 1; done

.PHONY: all
all: $(TARGETS)
    @echo done all

$(TARGETS): | common

.PHONY: common
common:
    +$(eval JOBS:=$$(shell python jobs.py $(MAKEFLAGS)))
    @echo JOBS=$(JOBS)

运行:

projects/make-fun » make all -j100
JOBS=100
a1
b1
c1
d1
e1
a2
b2
c2
d2
e2
done all