我有以下Makefile来构建我的erlang项目:
.SUFFIXES: .erl .beam .yrl
ERL_SRC := $(wildcard src/*.erl)
ERL_OBJ := $(patsubst src/%.erl,ebin/%.beam,${ERL_SRC})
all: main
main: ${ERL_OBJ}
ebin/%.beam: src/%.erl
erlc +debug_info -W -o ebin $<
clean:
rm -fr ebin/*.beam
我正在尝试更新它以在test / eunit文件夹中构建我的eunit测试,并让输出转到与src相同的ebin文件夹,如下所示:
.SUFFIXES: .erl .beam .yrl
ERL_SRC := $(wildcard src/*.erl)
ERL_OBJ := $(patsubst src/%.erl,ebin/%.beam,${ERL_SRC})
EUNIT_SRC := $(wildcard test/eunit/*.erl)
EUNIT_OBJ := $(patsubst test/eunit/%.erl,ebin/%.beam,${EUNIT_SRC})
all: main
main: ${ERL_OBJ}
ebin/%.beam: src/%.erl test/eunit/%.erl
erlc +debug_info -W -o ebin $<
clean:
rm -fr ebin/*.beam
eunit: ${EUNIT_OBJ}
test: main eunit
使主要工作正常,但如果我尝试进行测试,它会失败:
make: *** No rule to make target `ebin/data_eunit.beam', needed by `eunit'. Stop.
测试模块data_eunit.erl位于test / eunit中。问题似乎与ebin /%。beam target有关。如果我将src /%。erl与test / eunit /%。erl交换,那么我可以构建测试而不是src。如何从两个源文件夹进行构建并将输出转到一个输出文件夹?
答案 0 :(得分:5)
您可以在Makefile中使用vpath / VPATH
.SUFFIXES: .erl .beam .yrl
# use vpath to tell make where to search for %.erl files
vpath %.erl src eunit
# or use VPATH to tell make where to search for any prerequisite
# VPATH=src:eunit
ERL_OBJ = $(patsubst src/%.erl,ebin/%.beam, $(wildcard src/*erl))
ERL_OBJ += $(patsubst eunit/%.erl,ebin/%.beam, $(wildcard eunit/*erl))
all: main
main: ${ERL_OBJ}
ebin/%.beam: %.erl
erlc +debug_info -W -o ebin $<
clean:
rm -fr ebin/*.beam
答案 1 :(得分:4)
也许你应该大大简化你的构建。我的erlang构建系统只是使用如下所示的Emakefile调用erl -make
:
{"src/*", [debug_info, {outdir, "ebin"}, {i, "include"}]}.
当然,您可以拥有多个src loc,但只需混合测试和常规代码 - 您已经将它们混合在ebin中。不要让自己变得比它需要的更难。
答案 2 :(得分:2)
这不会真正回答你的问题,但我不喜欢冒着使用支持测试的代码污染我的ebin /的风险。所以这就是我组织我的toplevel Makefile的方式:
all:
(cd src && erl -make)
test:
(cd test && erl -make && \
erl -noinput -eval 'eunit:test({dir, "."}, [verbose]), init:stop()')
然后我将以下内容放入src/Emakefile
:
{['*'],
[{outdir,"../ebin"}]}.
进入test/Emakefile
我放
{['../src/*'],
[debug_info, {d, 'TEST'}]}.
{['*'],
[debug_info, {d, 'TEST'}]}.
所以如果我运行make all
然后src / * .erl被编译成ebin /,但是如果我运行make test
我将src / *。erl和test / * .erl编译成test /和使用单元测试运行所有梁文件。
在编译测试时,启用了TEST宏,以便在使用ifdef作为eunit指南建议时禁用单元测试:
-ifdef(TEST).
test_code_() -> ...
-endif.
这是我非常满意的设置。
答案 3 :(得分:0)
你应该创建另一个目标,将该树编译成ebin,使其依赖于原始构建目标。
答案 4 :(得分:0)
这就是我想要的:
.SUFFIXES: .erl .beam .yrl
ERL_SRC := $(wildcard src/*.erl)
ERL_OBJ := $(patsubst src/%.erl,ebin/%.beam,${ERL_SRC})
EUNIT_SRC := $(wildcard test/eunit/*.erl)
EUNIT_OBJ := $(patsubst test/eunit/%.erl,ebin/%.beam,${EUNIT_SRC})
all: main
main: ${ERL_OBJ}
${ERL_OBJ}: ${ERL_SRC}
erlc +debug_info -W -o ebin $<
clean:
rm -fr ebin/*.beam
${EUNIT_OBJ}: ${EUNIT_SRC}
erlc +debug_info -W -o ebin $<
eunit: ${EUNIT_OBJ}
test: main eunit
我可以通过其他方式改进这个吗?也许将$ {ERL_OBJ}和$ {EUNIT_OBJ}中的类似编译行移动到变量。
答案 5 :(得分:0)
而不是“ebin /%。beam:src /%。erl test / eunit /%。erl”你试过了:
%。beam:%。erl