我可以使用SCons显示构建的进度吗?

时间:2013-05-15 15:06:26

标签: scons

我有一个简单的构建系统,用于我使用SCons整理的项目。该项目有很多源文件,我认为随着构建的进展,显示某种进度信息对用户友好。 SCons提供了CXXCOMSTR之类的构造变量,我可以覆盖它来控制在每个构建步骤中显示给终端的内容。例如,而不是看到像:

gcc file.c -o file.o

如果有这样的话会很好:

[1/10] Compiling file.c: `gcc file.c -o file.o`

[1/10]指定这是此构建期间正在更新的十个目标中的第一个。有没有办法访问这些信息,以便我可以生成这样的消息?看起来我需要知道正在更新的目标总数(这是基于SCons所做的依赖性扫描)和一些枚举每个目标的方法。我知道类似的行为类似于其他构建系统,如CMake和waf,但在SCons(扩展)文档中没有遇到过任何内容。

2 个答案:

答案 0 :(得分:5)

可以使用Progress() SCons功能完成此操作。

SCons man page中有更多示例,只搜索“进度”。

您可以提供要调用的函数,将定期显示的字符串,或者将以旋转方式显示的字符串列表。您可以访问正在构建的当前目标,但我认为不可能知道完成的百分比。

答案 1 :(得分:4)

我能够提出一个相当不错的解决方法,允许您以百分比显示构建进度。基本上下面的代码是如何工作的:

  • 如果之前从未构建过目标,则会在每个目标旁边显示[??%]
  • 在第一次构建时,它会缓存.scons_progress
  • 中为该目标处理的总节点
  • 下次运行构建时,它将在启动时从文件中读取,并从上次获取该目标的总节点,并使用它来显示百分比(即[50%])。
  • 如果节点数量超过缓存总数,则会恢复为[??%]并更新.scons_progress
  • 随着时间的推移,您的SConstruct"稳定" (即您不是一直在进行更改),这些缓存值应该越来越准确。
  • 更新缓存会降低构建速度(每个节点略有增加),因此您可能希望将interval设置为5,以便它每5个节点仅更新一次缓存

以下是代码:

custom_utils.py下的site_scons/

PROGRESS = {
    "env": None,
    "nodes": 0,
    "interval": 1,
    "total": 0,
    "cache": {},
    "cache_key": "_",
    "cache_name": ".scons_progress",
    "cache_update": False
}

def get_progress_total():
    return PROGRESS["cache"].get(PROGRESS["cache_key"], 0)

def update_progress_cache():
    PROGRESS["cache"][PROGRESS["cache_key"]] = PROGRESS["nodes"]
    with open(PROGRESS["cache_name"], "w") as f:
        f.write(json.dumps(PROGRESS["cache"]))

def load_progress_cache():
    try:
        with open(PROGRESS["cache_name"]) as f:
            PROGRESS["cache"] = json.load(f)

            cache_key = "_".join(COMMAND_LINE_TARGETS)
            if cache_key:
                PROGRESS["cache_key"] = cache_key
    except IOError as e:
        pass

def progress_function(node):
    PROGRESS["nodes"] += PROGRESS["interval"]

    #Only update cached environment if it is not None
    if node.env:
        PROGRESS["env"] = node.env
        PROGRESS["env"].Replace(PROGRESS = "[??%]")

    #Update display message
    if PROGRESS["nodes"] <= PROGRESS["total"]:
        PROGRESS["env"].Replace(PROGRESS = "[%d%%]" % (100*PROGRESS["nodes"]/PROGRESS["total"]))
    #If current node is more than total, we need to update the cache
    elif not PROGRESS["cache_update"]:
        PROGRESS["cache_update"] = True
        PROGRESS["env"].Replace(PROGRESS = "[??%]")
    #If cache flag is on, update cache file
    else:
        update_progress_cache()

def progress_settings(env, interval):
    load_progress_cache()
    PROGRESS["interval"] = interval
    PROGRESS["env"]      = env
    PROGRESS["total"]    = get_progress_total()
    Progress(progress_function, interval=PROGRESS["interval"])

SConstruct

if GetOption("progress"):
    custom_utils.progress_settings(env, 5)

示例输出:

user@linuxbox:~/project1$ scons -j4 --progress
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
[??%] Compiling (shared): src/ExpressRuntimeException.os
[??%] Compiling (shared): src/Application.os
[??%] Compiling (shared): src/Callback.os
[??%] Compiling (shared): src/Response.os
[??%] Compiling (shared): src/Router.os
[??%] Compiling (shared): src/Route.os
[??%] Compiling (shared): src/Regex.os
[??%] Compiling (shared): src/tools.os
[??%] Linking   (shared): libexpresscpp.so
scons: done building targets.

user@linuxbox:~/project1$ scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed src/ExpressRuntimeException.os
Removed src/Application.os
Removed src/Callback.os
Removed src/Response.os
Removed src/Router.os
Removed src/Route.os
Removed src/Regex.os
Removed src/tools.os
Removed libexpresscpp.so
scons: done cleaning targets.

user@linuxbox:~/project1$ scons -j4 --progress
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
[14%] Compiling (shared): src/ExpressRuntimeException.os
[51%] Compiling (shared): src/Application.os
[59%] Compiling (shared): src/Callback.os
[66%] Compiling (shared): src/Response.os
[74%] Compiling (shared): src/Router.os
[81%] Compiling (shared): src/Route.os
[88%] Compiling (shared): src/Regex.os
[96%] Compiling (shared): src/tools.os
[100%] Linking   (shared): libexpresscpp.so
scons: done building targets.