【问题标题】:Why does EUnit compile .beam files into .eunit/ebin?为什么 EUnit 将 .beam 文件编译成 .eunit/ebin?
【发布时间】:2012-05-26 12:28:34
【问题描述】:

免责声明:这个问题的作者主要是 Erlang/OTP 的理论知识。

我有一个小型 OTP 应用程序,它通过 open_port()myapp/ebin 目录中调用一些非 Erlang 可执行文件。当我运行应用程序本身时,一切顺利,可执行文件的端口已成功打开。

但是当我尝试为应用程序运行单元测试时,依赖于open_port() 的单元测试失败,因为当以EUnit 启动时,应用程序试图在myapp/.eunit/ebin 下找到可执行文件。

如何在不更改应用程序本身代码的情况下更改该行为?如何使用与运行应用程序本身相同的当前目录运行 EUnit 测试? (我的意思是更改提供可执行文件路径的代码只是为了能够运行 EUnit 并不是一个好主意)。

编辑:我遵循了 Erlang mailing list 中的建议,但 code:priv_dir(myapp_name) 返回 {error, bad_name}

编辑:我可以看到.eunit/ 包含modulename.beam 文件,ebin/ 包含modulename.beam 文件和modulename_tests.beam 文件。现在我完全迷失了。当我运行make test 时,rebar 运行eunit 命令,该命令调用ebin/ 目录中的每个modulename_tests.beam 文件,该文件调用.eunit/ 目录中相应的modulename.beam 文件(filename:absname("") 清楚地表明modulename.beam 文件在测试期间从.eunit/ 执行)。为什么会这样?为什么我们需要从.eunit/ 目录而不是ebin/ 运行modulename.beam 文件?

为什么我们实际上需要在myapp/ebinmyapp/.eunit/ebin 中拥有完全相同的.beam 文件?

附:我已阅读official documentation 并没有找到解决方案。

【问题讨论】:

    标签: erlang erlang-otp eunit erlang-ports


    【解决方案1】:

    EUnit 自己不会这样做 - .eunit 目录是 Rebar 使用的约定。

    【讨论】:

    【解决方案2】:

    使用erlang启动脚本“.erlang”,它可以解决你的问题。

    在 .erlang 文件中,使用code:add_pathz/N 添加你需要的路径。

    在阅读couchdb 源代码之前,有一个如何使用priv 目录的示例。也许解决方案对您有帮助。它用start_port函数包裹open_port,并在start_port函数中设置目录。

    在文件couch_os_daemon.erl

    start_port(Command) ->
        PrivDir = couch_util:priv_dir(),
        Spawnkiller = filename:join(PrivDir, "couchspawnkillable"),
        Port = open_port({spawn, Spawnkiller ++ " " ++ Command}, ?PORT_OPTIONS),
        {ok, Port}.
    
    
    stop_port(#daemon{port=Port, kill=undefined}=D) ->
        ?LOG_ERROR("Stopping daemon without a kill command: ~p", [D#daemon.name]),
        catch port_close(Port);
    stop_port(#daemon{port=Port}=D) ->
        ?LOG_DEBUG("Stopping daemon: ~p", [D#daemon.name]),
        os:cmd(D#daemon.kill),
        catch port_close(Port).
    

    在文件 couch_util.erl 中

    priv_dir() ->
        case code:priv_dir(couch) of
            {error, bad_name} ->
                % small hack, in dev mode "app" is couchdb. Fixing requires
                % renaming src/couch to src/couch. Not really worth the hassle.
                % -Damien
                code:priv_dir(couchdb);
            Dir -> Dir
        end.
    
    start_driver(LibDir) ->
        case erl_ddll:load_driver(LibDir, "couch_icu_driver") of
        ok ->
            ok;
        {error, already_loaded} ->
            ok = erl_ddll:reload_driver(LibDir, "couch_icu_driver");
        {error, Error} ->
            exit(erl_ddll:format_error(Error))
        end.
    

    你可以greppriv,可以找到很多例子。

    【讨论】:

    • 亲爱的陈,有没有办法动态添加这个路径?在另一台机器上使用代码时,使用 code:add_pathsz() 添加硬编码值将无济于事。
    猜你喜欢
    • 2013-01-03
    • 2012-05-24
    • 1970-01-01
    • 2016-07-14
    • 2019-05-20
    • 2016-06-03
    • 2012-04-06
    • 1970-01-01
    • 2013-08-04
    相关资源
    最近更新 更多