I'm very new to Erlang and using Rebar but we are doing a project that needs to connect to a Riak server, for this I'm trying to use the Riak Erlang client (riakc_pb_socket etc).
The problem is that the shell that is started from my start up script (generated by Rebar and reltool) does not include the dependencies I've specefied in my rebar.config (they download just fine when I do rebar get-deps however). I know that I can include them to my path when I start the shell myself (erl -pa PATH) but since this needs to be done automatically I wonder how I achive that, can I specify such behavior with Rebar or do I need to do code loading from inside the application?
Thanks to the link provided by Roberto Aloi I was able to figure out how the reltool works and after some working I found that all I had to do was add this line
{app, riakc, [{mod_cond, app}, {incl_cond, include}]},
To my reltool.config and now it works, so thanks a lot :)
Related
I am trying to integrate rebar3 into my project, but for some reason, I can't make it find and resolve dependencies when running the app.
Dependencies are downloaded and put in the respective folders in the project and the app compiles without errors, but then functions from dependencies are undefined if I call them from inside the project app or from the Erlang REPL.
I think I am missing some small point, but can't figure out what exactly.
My rebar.config is as simple as this:
{erl_opts, [debug_info]}.
{
deps, [
{jsx}
]
}.
{cover_enabled, true}.
The project repo is here.
Can you please share a link to a simple example project where dependencies are present in the rebar.config and are successfully used in the app code?
but then functions from dependencies are undefined if I call them from inside the project app or from the Erlang REPL
In order to load all the dependencies in the REPL, you need to start the REPL using rebar3 shell. rebar3 shell invokes erl with the correct arguments so that the paths of all of the project's dependencies are added to Erlang's Code Path. The command also accepts many flags and arguments; you can see the full list and description by running rebar3 help shell.
So assuming that i have an rebar app structure and in deps folder i have a number of dependencies, some are library applications and some are applications that need to be started. I usually do it like this:
start(_Type, _Args) ->
code:add_path("../deps/depapp/ebin"),
{ok, _} = application:ensure_all_started(depapp),
Is this the correct way to do it in an development environment ? How about in production ?
What you used is not necessarily a wrong way but could exposes some problems. For instance this way you have no choices for starting dependent applications which must be started before your application.
So there are other alternatives for loading or starting dependent OTP applications or libraries.
1) Using erl command line flags:
erl -pa ebin deps/*/ebing -s your_dep_app start -s your_app start
2) Using package manger for handling it:
As an example Rebar as a package manager can handle it for you. What you need is specifying your application dependencies in rebar.config and then issue rebar get-deps for Rebar2 or rebar3 compile for Rebar3. Following is a snippet of a sample config file for Rebar3:
{deps,[
%% Packages
rebar,
{rebar,"1.0.0"},
{rebar, {pkg, rebar_fork}}, % rebar app under a different pkg name
{rebar, "1.0.0", {pkg, rebar_fork}},
%% Source Dependencies
{rebar, {git, "git://github.com/erlang/rebar3.git"}},
{rebar, {git, "http://github.com/erlang/rebar3.git"}}]}.
For more information about Rebar dependency manager take a look at this link.
Also for starting or loading them using Rebar you can make a release and let Rebar start or load them. Following is a snippet of a sample Rebar config file for making a release:
{relx, [
{release,
{your_app, "0.1.0"},
[your_dep_app_1,
{your_dep_app_2, load}]}]}.
This config loads and starts your_dep_app_1 but just loads your_dep_app_2. For more information about Rebar release manager take a look at this link.
I am new to rebar and erlang in general and read that we can use other modules by specifying them as deps in rebar.config file. I am able to compile them properly but not sure how to use them in my module. If I try to use them, I get an error that the function is not available.
How can I use the functions from the modules that are in deps in my modules.
Thanks!
You have to tell code server where to find compiled code. I usually have in MakeFile something like:
run:
erl -pa ebin -pa deps/*/ebin
You usually need to specify application:start(appname) or similar in your application file before using them (to get some application to start up) and try to define them in the app.src file also, after that you should be able to use them
I would like to build and deploy an application which has Django as frontend, YAWS (appmods) or Mochiweb/Webmachine as a backend and CouchDB as a datastore. Furthermore, I plan to extensively use CouchDB's ability to replicate in order to provide high fault tolerance for the whole application.
I tend to think that in order to achieve this, I must create a single OTP release which has YAWS and CouchDB as Erlang/OTP applications.
Does this approach seem to be correct? How can I organize YAWS and CouchDB in terms of OTP applications in order to create a solid production setup? Are there any best practices for doing that?
Erlang releases are a good way to package software, because they include all of the dependent libraries. This way, different erlang applications can run different versions of their required libraries without conflicting with each other.
A popular way of dealing with the complicated release process Erlang has is to let Rebar do it for you. They have a quick start guide to get you on the right path. I don't know if you're currently using Rebar to manage your project, but it makes things a lot easier. It is definitely worth looking into if you aren't using it yet.
However, rebar won't include your dependencies right out of the box. In order to do that, you should modify the reltool.config file and all your required applications.
First step is to add the directory where all your dependencies are located, e.g.:
{sys, [
...
{lib_dirs, ["../deps"]},
...
}.
Then, add your dependencies as applications to include in the release:
{sys, [
...
{app, jiffy, [{incl_cond, include}]},
{app, cowboy, [{incl_cond, include}]},
...
}.
Now, when you run the rebar generate command, your applications should be in the target directory under lib:
find brawl_server -type d -maxdepth 2
brawl_server
brawl_server/bin
brawl_server/erts-5.9.1
brawl_server/erts-5.9.1/bin
brawl_server/lib
brawl_server/lib/brawl_server-1.1
brawl_server/lib/cowboy-0.6.0
brawl_server/lib/jiffy-0.6.1
brawl_server/lib/kernel-2.15.1
brawl_server/lib/sasl-2.2.1
brawl_server/lib/stdlib-1.18.1
brawl_server/log
brawl_server/log/sasl
brawl_server/releases
brawl_server/releases/1
You also need to make sure your own OTP application knows it needs to start the applications it depends on. If you have a generated Rebar project, modify your <appname>.app.src file to include them:
{application, app, [
...
{applications, [
jiffy,
cowboy,
kernel,
stdlib
]},
...
}.
You should be able to compile and generate the release and run it with the included scripts, as laid out in the Rebar release handling article.
At this point, though, there's an added wrinkle, because apparently vanilla CouchDB isn't OTP compliant, and you can't include it this way. There is another distribution you may be able to use, instead: rcouch. I haven't tried it myself, hopefully it will work for you.
Further reading:
Learn you some erlang for great good: Releases
I used my own project, brawl-online, as an example
I would recommend to create DEB/RPM/you-name-it package or packages. CheckInstall is the simplest solution for this.
I'm attempting to understand how to build a multiple-application Erlang OTP release using Rebar.
My applications include Webmachine, Riak, and a few applications of my own devising. So far, I have been running Rebar successfully in the application root directory. But the Rebar bootstrap program suggests that there may be a better way. E.g.:
"You now have a self-contained script called "rebar" in
your current working directory. Place this script anywhere in your path
and you can use rebar to build OTP-compliant apps."
I can think of several ways to do this. But I'm wondering:
Is there is a preferred convention: e.g., placing Rebar in an .erlang file, /usr/local/bin, etc., etc.?
Many thanks,
LRP
I keep a copy in /usr/local/bin, which I use when creating new apps. For example:
$ rebar create-app appid=myapp
All of my projects are built with rebar by placing the binary in the root directory of my project and referencing it locally in my Makefile as seen here. As of this writing, this seems to be the convention the community has adopted. For example, nitrogen, mochiweb, ibrowse, and erlydtl are all built this way.
Personally, I'm not a big fan of including the rebar binary with every project but I don't see a good alternative. It makes life easier for people that either don't have rebar in their path, or don't have an updated version in their path.
I suspect this is a temporary situation. Eventually the rebar project will start to have fewer commits, and we'll all agree to keep a copy in our path. At that point we can all stop including it. Of course, if your projects are only going to be used by you, this is a non-issue.