首页 > 解决方案 > 如何从测试脚本中运行 WAF 编译的 C++ 程序?

问题描述

尊敬的 WAF 构建系统专家,

假设您使用 WAF 构建系统来构建一个库fooLib和一个程序fooProg。然后,您想fooProg通过 Python 脚本fooProgTest检查程序,该脚本检查fooProg.

这是fooLiband的最小示例fooProg

$ cat fooLib/fooLib.cpp 
int foo()
{
    return 42;
}
$ cat fooProg/fooProg.cpp 
#include <iostream>

extern int foo();

int main()
{
    std::cout << foo() << std::endl;
    return 0;
}

在这个例子中,我的目标是有一个 Python 脚本来检查fooProg输出 42。这是我不太干净的解决方案:

import os
from waflib.Tools import waf_unit_test


def options(opt):
    opt.load("compiler_cxx waf_unit_test python")


def configure(cnf):
    cnf.load("compiler_cxx waf_unit_test python")

def build(bld):
    bld.add_post_fun(waf_unit_test.summary)
    bld.options.clear_failed_tests= True

    bld(features= "cxx cxxshlib",
        target= "fooLib",
        source= "fooLib/fooLib.cpp")

    bld(features= "cxx cxxprogram",
        target= "fooProg/fooProg",
        source= "fooProg/fooProg.cpp",
        use= "fooLib")

    testEnv= os.environ.copy()
    testEnv["FOO_EXE"]= bld.path.find_or_declare("fooProg/fooProg").abspath()
    bld(features= "test_scripts",
        test_scripts_source= "fooProgTest/fooProgTest.py",
        test_scripts_template= "${PYTHON} ${SRC[0].abspath()}",
        test_scripts_paths= {
            "LD_LIBRARY_PATH": bld.bldnode.abspath()
        },
        test_scripts_env= testEnv
       ) 
cat fooProgTest/fooProgTest.py 
#!/usr/bin/env python

import os
import subprocess

assert subprocess.check_output("{}".format(
        os.environ["FOO_EXE"])).startswith("42")

我的问题如下:

非常感谢!

标签: pythonc++testingwaf

解决方案


你们中有人知道如何避免手动设置 LD_LIBRARY_PATH 吗?

您可以为可执行文件指定运行时搜索路径。假设文件fooLib.so与 位于同一目录中fooProg,对 wscript 进行以下更改就足够了:


    bld(features= "cxx cxxprogram",
        target= "fooProg/fooProg",
        source= "fooProg/fooProg.cpp",
        use= "fooLib",
        rpath= "$ORIGIN")

这使得 LD 在搜索共享对象时也会考虑存储可执行文件的目录。

如何避免通过环境变量“FOO_EXE”设置 fooProg 的路径?

subprocess.check_output你可以传递多个参数。IE


    subprocess.check_output([
        "your_executable_to_launch",
        "arg1",
        "arg2"
    ])

在您的测试脚本中,您必须使用sys.argv或读取参数argparse


额外

启动解释器来启动您的应用程序似乎有点 hacky。相反,定义一个自定义任务(实现waflib.Task.Task),然后运行subprocess.check_output​​1


1 AFAIK waf 为您提供了一种启动进程的便捷方法,尽管我不记得它的名称。


推荐阅读