Erlang deps loading - erlang

I'm trying to write erlang first app. It has
https://github.com/emedia-project/erlffmpeg in deps, I have almost the
same Makefile.
When I run erlang shell in erlffmpeg dir and eval README
example, all ok. But When I do it from my project's dir, I get error
like: ucp detect undef. So, my erl shell see the fns from ffmpeg
module, but when i try to eval this fns it seems like shell doesn't know
about inheritant deps of ffmpeg.
I run erl shell with make dev command. In short, it does erl -pa ebin
deps/*/ebin
Seems like i'm missing some knowledge about module loading.
What should I do with this and what you advice me to read?
Thank you!

So, the answer is to use rebar and set the deps like:
{deps, [
{ffmpeg, ".*", {git, "https://github.com/emedia-project/erlffmpeg", "master"}}
]}.
In this case rebar will automatically download all iner dependencies in root deps folder, so the shell with command erl -pa ebin deps/*/ebin will hook up all .beam files.
Big thanks to friendly #erlang members.

Related

Rebar shell - passing config file

I'm sure this will be so simple I will kick myself my asking but how do I pass erl args, like -config {file} to erl when calling rebar shell? I thought it would simply passthrough anything that didn't match it's own switches but not so.
rebar shell doesn't appear to allow arguments, but it's basically the equivalent of the following command line:
erl -pa deps/*/ebin -pa ebin
If your project has no dependencies, you don't need the -pa deps/*/ebin part.
If you need extra arguments, just add them to this command.
Another alternative is to use the ERL_FLAGS environment variable to specify extra arguments:
ERL_FLAGS='-config my_config_file.config' rebar shell
rebar3 supports this directly now:
rebar3 shell --config something.config, or
Add {shell, [{config, "something.config}]}. to your rebar.config
It's not elegant modify everytime your rebar.config but you can use the tuple {sys_config, FilePath}.
{sys_config, "config/sys.config"}.
When you run the command "rebar3 shell", they will load the configuration placed in "config/sys.config"

How run an Erlang application inside the Erlang shell

I have an Erlang application and I can compile it easily and run it by using basho rebar which makes an stand-alone escript executable file. I run it from command line like: ./myapp myconfig.config
My questio is that how can I run it inside Erlang shell. This application has four other applications as dependency. Rebar compile all of the easily. But I need to run this application from inside the shell like:
erl -noshell -name node1#machine -run test start parameter1 -s init stop;
But I don't know in which path I should run it. When I try it in "ebin" folder (where beam files are located), dependencies are not accessible. As I see each dependency applications has it own "ebin" folder.
So how can I run my application by "erl -noshell" command (consider dependency applications)?
Rebar handles all these things automatically.
A typical directory structure for a Rebar-powered OTP application is something like this:
/
src/
ebin/
deps/
dep1/
src/
ebin/
dep2/
src/
ebin/
So, if you're in the root directory of your project, you can point erl to the right place with the -pa argument. To tell it where to find both your application's and its dependencies' BEAM files, try the following:
erl [...] -pa ebin -pa deps/*/ebin

Wildcards in erlc's -I option?

Is it possible to use wildcards in the Erlang compiler's -I option?
For example, I want to do something like this:
erlc -I deps/*/include -I deps src/foo.erl
I know that other solutions exist (like using rebar or make) but in this case, I am looking explicitly at erlc.
In Linux (and other unixoid systems) wildcards are never resolved by the invoked program.
The shell you use (e.g. bash) resolves all wildcards.
So erlc won't see the the asterix at all.
(If you read the documentation of find(1) you may find that my previous explanation is somewhat oversimplified.)
If you don't want to use an extra tool (I'd recommend looking at rebar oder make, though), you could try:
erlc $(find deps -name include -exec echo '-I {}' ';') -I deps src/foo.erl
(Weak substitute, I know.)

Add Path to Erlang Search Path?

I recently installed Erlang RFC4627 (JSON-RPC) with the debian package. I ran the test server using:
sudo erl -pa ebin
and then at the prompt:
test_jsonrpc:start_httpd().
returned
ok
I tested with http://:5671/ and got the success messages.
When I try to run rabbitmq-http2 however, I get the errors that the readme says are caused by rfc4627's code not being on the erlang search path. How do I put it on the path. I saw something on Dave Thomas's blog which suggested putting the path in the file:
~/.erlang
This didn't seem to work for me (maybe I did it wrong?).
The code module is how you manipulate the path within an application.
The flags -pa that you used in starting the Erlang shell actually refer to a function in this module:
add_patha(Dir) -> true | {error, What}
You are right about the .erlang file in your home directory - it is run at start-up time of the shell and you can add in handy paths.
For an application you can start the shell with a batch file that calls something like this:
erl -pa ./ebin ../../lib/some/path/ebin
The flags behaviour of erl is described here.
For more sophisticated path management you need to get familiar with how OTP release management is done (but I suspect that is a while away for you yet).

erlang - startup script

To start my program I do the next sequence:
$ erl
> c(module1).
> c(module2).
> c(modulen).
modulen:start().
Is there any possibility to create script that allow me to launch my program ?
You could use a loader script that takes care of starting your application in an OTP fashion:
-module(XYZ_app).
-export([start/0]).
start() ->
application:start(inets),
application:start(XYZ).
You launch that script through a shell script. Beware of using escript if you plan on building daemons running at the OS boot time as they are tricky.
#!/bin/bash
erl -boot start_sasl -s XYZ_app start
Of course you need your XYZ.app file (just an example):
{application, tinycouch,
[{description, "tinycouch"},
{vsn, "0.1"},
{modules, [
tinycouch, tinycouch_app, tinycouch_sup,
tinycouch_server, tinycouch_logger_h, tinycouch_utils,
tinycouch_db, mod_tinycouch
]},
{registered, [tinycouch
,tinycouch_server
,tinycouch_sup
]},
{applications, [kernel, stdlib, sasl, inets]},
{env, []},
%% Application Start point
{mod, {tinycouch_sup, []}}]}.
... and all your .erl files must have been compiled.
Note that if you intend to distribute your application (e.g. Debian repository etc), you probably should consider having a make file to compile and install your app.
As a final note: you could also go with a boot file (the ultimate OTP way) but I find those very constraining: a boot file ties your application to specific version release of Erlang (and other dependent applications). Your application might be able to run in various Erlang releases but you will need to have a separate build/release process for each "platform release" you intend to ship for.
You can compile the modules with erlc
erlc module1 module2 module3
You can also create a script to run you program
#!/usr/bin/escript
main(_) ->
modulen:start().
Then in the console:
chmod +x start.erl
./start.erl
Two ways
precompile your code
$ erlc module1.erl
$ erl -s module1 funcname arg1 arg2 ....
Or use escript
#!/usr/bin/env escript
main() ->
module1:fun(...)
escript is a scripting interface to Erlang
You can use erl -make directly, as it assumes all *.erl files should be compiled to *.beam, and skip it if they haven't been changed since last compile. Check out the make module for what you can put in your Emakefile to change certain behavior.
Using plain Makefile to invoke this compile strategy also gives other users a familiar build-procedure.
Having a bootstrap start function as jldupont suggests is a nice way to start up your development environment. It is even sufficiently fine for using in production to some point.
The next step is to use full OTP (*.rel) release files and generate boot scripts that starts all the applications in the order the *.app specify dependencies on each other.
In the home directory, create file
.erlang
in that file write
compile:file(/path-to/module1).
compile:file(/path-to/module2).
compile:file(/edit-real-path-to/modulen). % etcetera; do not use c(module) inside this file!
then, if you need add (inside .erlang):
module1:start(). % etc
When you run erl (in the shell), the content of the .erlang (provided this file is in the home dir) will be executed at start (of the interpreter-erlang-VM you launch).
You can create .erlang file in some other (some 'current') directory, then, if you run erl (erlang interpreter) in that directory, that another .erlang will override the content of that .erlang in the home dir (of that which is like /home/your-user-name/.erlang ).
It is good idea to write inside of .erlang some reminder, like
io:format(".erlang loaded-compiled module1!\n"). %etc
(as not to forget about that code which otherwise will be executed silently !)
(also, you can check, for this case, that e.g. module1 is indeed compiled and loaded after start, this or some similar way:
AllLoaded = code:all_loaded().
lists:filter(fun({Module,_})-> Module =:= module1 end, AllLoaded).
the answer should be like:
[{module1,"/home/your-user-name/(path-to-your-code)/module1.beam"}]
)
Check out Sinan and Faxien: http://www.erlware.org

Resources