Why does rebar use my erl_opts to compile my deps? - erlang

I have a structure similar to the following:
rebar.config
deps/
apps/A/rebar.config
My top-level rebar.config file looks like the following:
{sub_dirs, ["apps/A"]}.
{lib_dirs, ["deps"]}.
A/rebar.config looks like the following:
{deps, [
%% deps
]}.
{erl_opts, [debug_info, warn_missing_spec, warnings_as_errors]}.
Now, one of my dependencies doesn't provide -spec for all of its functions, so the warnings_as_errors causes the compile to fail.
I was expecting the erl_opts to only affect my code, and for the dependencies to have their own options. Why does rebar do this?

It turns out that one of my dependencies doesn't have a rebar.config, so rebar is compiling it using my options.
What's confusing is that erl_opts is not set in the top-level rebar.config, but in a local rebar.config file. This is the file that has the deps clause.
It seems that the options are inherited "sideways" in this case.

I cannot reproduce this using the following version of rebar:
rebar 2.1.0-pre R15B03 20131210_073701 git 2.1.0-pre
On my local setup, using your same config (goldrush is my dependency):
...
==> goldrush (compile)
DEBUG: Matched required ERTS version: 5.9.3.1 -> .*
DEBUG: Matched required OTP release: R15B03 -> .*
DEBUG: Min OTP version unconfigured
DEBUG: erl_opts [debug_info,warn_export_all]
...
==> myapp (compile)
DEBUG: Matched required ERTS version: 5.9.3.1 -> .*
DEBUG: Matched required OTP release: R15B03 -> .*
DEBUG: Min OTP version unconfigured
DEBUG: erl_opts [debug_info,debug_info,warn_missing_spec,warnings_as_errors]
...
As you can see, the two applications receive two different sets of options.
Could you enable debugging and post the relevant output?
./rebar -vvv clean compile
What version of rebar/Erlang are you running?

Related

Fetch dependencies from hex.pm with Rebar3 for Erlang

I have added poison library to rebar.config file:
{
deps, [
poison
]
}.
But when I run rebar3 compile, it shows me an error:
===> Package <<"poison">> not found. Fetching registry updates and trying again...
...
===> Package not found in registry: <<"poison">>.
How do I make it work?

Rebar eunit runs non native (non Hipe) code

I have compiled my Erlang module using
rebar compile
using the following option in rebar.config
{erl_opts, [native, {hipe, [verbose]}, warnings_as_errors, debug_info]}.
{eunit_compile_opts, [native, {hipe, [verbose]}, warnings_as_errors, debug_info]}.
I see that the code is indeed compiled to native since I see Hipe messages during compilation and the .beam file size are also larger than non-native compilation.
However when I run
rebar eunit
which tests my module I always get false for
code:is_module_native(?MODULE)
within my module under test.
Why does rebar not run my eunit test as native code?
I have additionally added this line to the reltool.config file,
{app, hipe, [{incl_cond, include}]},
rebar 2.1.0-pre 17 20140421_192321 git 2.1.0-pre-166-ged88055
Your code is recompiled when you run "rebar eunit" using the compile options defined by
{erl_opts, [native, {hipe, [verbose]}, warnings_as_errors, debug_info]}.
and modified by the compile options defined by
{eunit_compile_opts, [???]}.
Did you check these options?

How do you setup an Erlang NIF project with rebar?

I looked through the questions here on StackOverflow and Googled around for an example of setting up a Basic NIF project in rebar for wrapping a C++ library.
I used to library project on GitHub as a guide:
https://github.com/tuncer/re2
My project is here:
https://github.com/project-z/emutton/
When I do a rebar compile && rebar eunit, I get a failure in the eunit test because it cannot find emtn.so:
$ rebar compile && rebar eunit
==> emutton (compile)
==> emutton (eunit)
undefined
*** test module not found ***
**emtn
=ERROR REPORT==== 25-Jun-2013::12:21:55 ===
The on_load function for module emtn returned {error,
{load_failed,
"Failed to load NIF library: 'dlopen(/.../source/emutton/priv/emtn.so, 2): image not found'"}}
=======================================================
Failed: 0. Skipped: 0. Passed: 0.
One or more tests were cancelled.
ERROR: One or more eunit tests failed.
ERROR: eunit failed while processing /.../source/emutton: rebar_abort
When I call rebar compile, it is only producing a single driver file, emtn_drv.so and no emtn.so:
$ tree priv
priv
└── emtn_drv.so
0 directories, 1 file
I have an echo statement in c_src/build_deps.sh that I don't see output when I call rebar clean. It seems to behave as though my pre_hook and post_hook in rebar.config are completely ignored:
{pre_hooks, [{compile, "c_src/build_deps.sh"}]}.
{post_hooks, [{clean, "c_src/build_deps.sh clean"}]}.
Examples of no output shown from rebar:
$ rebar compile
==> emutton (compile)
$ rebar clean
==> emutton (clean)
Because I have cloned tuncer's RE2 bindings project and when I do a rebar compile see output from his build_deps.sh script. The permissions on mine match those on his:
-rwxr-xr-x 1 ajl staff 891B Jun 25 12:30 c_src/build_deps.sh
Any idea what I'm missing here? I believe that rebar is configured correctly to call out to the script and do the compilation.
Your problem is that the line in your rebar.config
https://github.com/project-z/emutton/blob/master/rebar.config%20#L1
Doesn't match what you attempt to load
https://github.com/project-z/emutton/blob/master/src/emtn.erl#L25
You should either change the rebar.config to
{port_specs, [{"priv/emtn.so",["c_src/emtn_nif.c"]}]}.
and change emtn.erl to
erlang:load_nif(filename:join(PrivDir, "emtn"), 0). % ?MODULE is an atom, I believe you need a string
Or change emtn.erl to
erlang:load_nif(filename:join(PrivDir, "emtn_drv"), 0).

Always got undef error of lager_transform when using lager log framework

I want to use lager as my log utility and I have orgnazied my proj as below:
proj\
|
|--lager\
| |--src\
| |--ebin\
| |--...
|
|--logserver\
| |--src\
| |--ebin\
| |--rebar.config
| |--...
|
|--rebar
|
However, when I try to compile logserver, I always got the following error:
D:\proj\logserver>..\rebar compile
==> logserver (compile)
src/logserver_app.erl:none: error in parse transform 'lager_transform': {undef,
[{lager_transform,
parse_transform,
[[{attribute,1,file,
{"src/logserver_app.erl",1}},
...
Can anyone know the reason? Thanks!
These is some additional information:
I am using Windows OS and using latest version of Erlang and rebar
and lager.
lager itself has already been compiled. We can find the D:\proj\logserver>dir ..\lager\ebin\lager_transform.beam (This will
succeed)
rebar's config file(D:\proj\logserver\rebar.config):
...
{erl_opts, [{parse_transform, lager_transform}, debug_info,{d,'TEST'}, {i, "include"}, {src_dirs, ["src"]}]}.
{lib_dirs, ["..\lager\ebin"]}.
...
If you already have lager in your deps then make sure that you move lager dependency first in rebar.config so that way it will compile first. Like so:
{deps,[
lager,
..
]}.
Did you add lager as a dependency in your rebar.config? I guess lager is not in the path.
From the rebar wiki:
To use lager in your application, you need to define it as a rebar dep
or have some other way of including it in erlang’s path. You can then
add the following option to the erlang compiler flags:
{parse_transform, lager_transform}
You can add 'lager' as a dependency by editing your rebar.config:
%% == Dependencies ==
%% Where to put any downloaded dependencies. Default is "deps"
{deps_dir, "deps"}.
%% What dependencies we have, dependencies can be of 3 forms, an application
%% name as an atom, eg. mochiweb, a name and a version (from the .app file), or
%% an application name, a version and the SCM details on how to fetch it (SCM
%% type, location and revision). Rebar currently supports git, hg, bzr and svn.
{deps, [application_name,
{application_name, "1.0.*"},
{application_name, "1.0.*",
{git, "git://github.com/basho/rebar.git", {branch, "master"}}}]}.
In your case, that should be something like:
{deps, [{lager, ".*", {git, "git://github.com/basho/lager.git", "HEAD"}}]}.
More info about the rebar dependency manager here:
https://github.com/basho/rebar/wiki/Dependency-management

Command 'generate' not understood or not applicable

I am trying to run rebar generate to generate a release for an erlang rebar project and getting the following error. Any ideas what I am doing wrong?
./rebar generate
Command 'generate' not understood or not applicable
I am on OSX with erlang version Erlang R14B03 and below is my rebar.conf
{lib_dirs, ["deps"]}.
{sub_dirs, ["rel"]}.
{deps, [
{folsom, ".*", {git, "git://github.com/boundary/folsom", "master"}}
]}.
{require_otp_vsn, "R14|R15"}.
{erl_opts, [
fail_on_warning,
debug_info,
warn_missing_spec
]}.
{clean_files, ["*.eunit", "ebin/*.beam", "rel/graphsom"]}.
{cover_enabled, true}.
{eunit_opts, [verbose, {report, {eunit_surefire, [{dir, "."}]}}]}.
You are getting this error because rebar is unable to find a release. You should check if you have reltool.config somewhere and rebar knows about it.
If no release exists, you can create a new one:
mkdir rel
cd rel
../rebar create-node nodeid=YOUR_NODE_ID
Lastly, you need to tell rebar about the release. In your case, you already have the following added to rebar.config:
{sub_dirs, ["rel"]}.
This should allow the generate command to build a new release.

Resources