Start erlang with user defined variable (using rebar)? - erlang

I'd like to be able to use the following macro in my modules:
-ifdef(debug).
My startup script looks something like the following:
#!/bin/sh
PWD="$(pwd)"
#NAME="$(basename $PWD)"
erl -pa "$PWD/ebin" deps/*/ebin -boot start_sasl \
-name foo#127.0.0.1 \
-debug 1 \
-s $NAME \
+K true \
+P 65536
What else would need to be added so that debug is defined in my module? I need this to be dynamic so I don't have to modify source code for deployment into production. Using different startup scripts per dev/qa/prod environments is fine, but modifying source code shouldn't be necessary.
With erlc this can be done with -Ddebug. I use rebar however, and am not sure how to do it with that. I've tried adding the following to my rebar.config:
{erl_opts, [{D, "debug"}]}.
This gives the following error:
{error,
{1,
erl_parse,
"bad term"}}

The define for the compiler in rebar.config should look like this:
{erl_opts, [{d, debug}]}.
Note: the syntax is exactly the same as the compiler module's syntax: http://www.erlang.org/doc/man/compile.html
Current version of rebar (rebar version: 2 date: 20111205_155958 vcs: git 54259c5) does support compiler defines, as well.
rebar -D <defines> compile
See rebar --help for more rebar options.

ifdef is a preprocessor macro, it gets evaluated and removed at compile time -- you would have to re-compile your module with something like erlc -Ddebug module.erl to change it. add the "-P" flag if you want to see the output from the preprocessor in module.P.
to get access to the "-debug 1" argument at runtime, you can use init:get_argument(debug).
# erl -debug 1
...
1> init:get_argument(debug).
{ok,[["1"]]}
2> init:get_argument(foo).
error

Related

undefined function mochiweb_html:parse/1

I'm trying to use mochiweb in a module, but can't find a way to make the module 'aware' of mochiweb.
mochiweb_html:parse("<XML>").
This works fine in erl, but I keep getting undefined function when I use it inside a module.
if i understand your question, it sounds like a code path problem. as long as mochiweb_html.beam is in your code path, you can use any exported function.
running it from the erlang shell (erl) may have worked because the beam file was in your cwd.
for example:
# cd /home/blah/src/mochiweb/ebin; erl
1> code:where_is_file("mochiweb_html.beam").
"./mochiweb_html.beam"
# cd /tmp; erl
1> code:where_is_file("mochiweb_html.beam").
non_existing
make sure that the directory containing mochiweb_html.beam is in your code path.
to add it to your code path, use command lind args (-pa, -pz):
# erl -pa /home/blah/src/mochiweb/ebin
1> code:where_is_file("mochiweb_html.beam").
"/home/blah/src/mochiweb/ebin/mochiweb_html.beam"
or using the code module (code:add_patha, code:add_pathz):
# erl
1> code:where_is_file("mochiweb_html.beam").
non_existing
2> code:add_patha("/home/blah/src/mochiweb/ebin/").
true
3> code:where_is_file("mochiweb_html.beam").
"/home/blah/src/mochiweb/ebin/mochiweb_html.beam"

run eunit test from console using erl -noshell

I wanted to run the following eunit test command from console
eunit:test([test_module, [verbose]).
I tried this, but seems not working
erl -noshell -pa ./ebin -s eunit test test_module verbose -init stop
~/uid_server$erl -noshell -pa ./ebin -s eunit test test_module verbose -init stop
undefined
*** test module not found ***
::test_module
=======================================================
Failed: 0. Skipped: 0. Passed: 0.
One or more tests were cancelled.
Do you know how to pass not a simple arguments properly from console?
Your parameters look wrong. This should work:
erl -noshell -pa ebin -eval "eunit:test(test_module, [verbose])" -s init stop
-s can only run functions without arguments by specifying the module and function name (for example init and stop to execute init:stop()).
You can also pass one list to a function of arity 1 like this:
-s foo bar a b c
would call
foo:bar([a,b,c])
All the parameters are passed as a list of atoms only (even when you try to use some other characters, such as numbers, they are converted to atoms).
So since you want to pass two params and not only atoms if you want to run eunit:test/2 you'd have to use -eval which takes a string containing Erlang code as an argument. All -eval and -s functions are executed sequentially in the order they are defined.
Also, make sure you have your test code in ./ebin as well (otherwise write -pa ebin test_ebin where test_ebin is where your test code is).
You can also use rebar...
Get rebar by cd'ing to your project directory and typing the following:
curl http://cloud.github.com/downloads/basho/rebar/rebar -o rebar
chmod u+x rebar
Add the following to your module under test, right after last export:
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
Next, add your tests at the bottom of your module, wrapped in an ifdef like so:
-ifdef(TEST).
simple_test() ->
?assertNot(true).
-endif.
Lastly, run rebar from your shell like so:
./rebar compile eunit
you can try quote parameters instead of listing.
erl -noshell -pa ./ebin -s eunit test "test_module verbose" -init stop
More than eight years passed since the question, but there's still a nice solution not mentioned in the previous answers.
Once you are using EUnit, you can leverage from some of it's "automagic" features. One of them is an automatic export of the test/0 function, containing all the tests for the module.
So, if you are writing your tests alongside with the source code in the same module, all you have to do is:
$ erl -noshell -run your_module test -run init stop
If you are writing the tests in a separated, dependent module (as you should), you have to point to that module:
$ erl -noshell -run your_module_tests test -run init stop
All this will work fine, but the test won't be run in verbose mode as the OP required, but this is simple to solve with the EUNIT environment variable set to verbose.
Final version:
$ EUNIT=verbose erl -noshell -run your_module_tests test -run init stop
Have fun with Erlang and EUnit!
I use this script: https://github.com/lafka/dotconfig/blob/master/bin/eunit-module to run eunit on specific modules.
Example:
eunit-module <module> src ebin -I deps
That will do a couple of things:
Arg #2 is the directory where .erl resides
Arg #3 is the directory to output the compiled .beam
Arg #4++ is all the additional paths to add to your code path
Using -I specifies additional code paths AND where to look for files referenced with -include_lib

Forcing erl -make to recompile files when macros are changed

I tried to do something similar to How to make two different source directories in a Makefile output to one bin directory?, so I have these files (relative to my project root):
Emakefile:
% EMakefile
% -*- mode: erlang -*-
{["src/*", "src/*/*", "src/*/*/*"],
[{i, "include"}, {outdir, "ebin"}, debug_info]}.
test/Emakefile:
% EMakefile
% -*- mode: erlang -*-
{["../src/*", "../src/*/*", "../src/*/*/*"],
[{i, "../include"}, {outdir, "../ebin"}, debug_info, {d, 'TEST'}]}.
Makefile:
EPATH=-pa ebin
all: before_compile
erl -make
all_test: before_compile
cd test
erl -make
cd ..
before_compile: mk_ebin copy_sqlite create_db copy_config copy_dot_app
test: all_test
erl -noshell $(EPATH) \
-s tests run \
-s init stop
rm -f ct.db
clean:
rm -fv ebin/*
... dependencies of before_compile
The problem is that running make test doesn't recompile any modules which are already compiled with make. It seems erl -make doesn't care that they were compiled without TEST defined, it just checks that the modules themselves are older than beam-files. How do I force it to recompile (and avoid recompilation when it isn't needed)?
UPDATE: Strangely, when running make all_test immediately after make clean, it appears that ./Emakefile is used instead of test/Emakefile: I am getting
Recompile: src/tests
Recompile: src/server_protocol_client
etc. and no tests instead of
Recompile: ../src/tests
Recompile: ../src/server_protocol_client
which I get by doing cd test; erl -make manually. Any idea why? Anyway, I've fixed this problem by removing test/Emakefile and replacing all_test in Makefile:
all_test: before_compile
erl -noshell -eval "make:all([{d, 'TEST'}])." -s init stop
all_test: before_compile
cd test
erl -make
cd ..
This is incorrect. Each line produces its own process. Do such:
all_test: before_compile
cd test; \
erl -make

How do I install LFE on Ubuntu Karmic?

Erlang was already installed:
$dpkg -l|grep erlang
ii erlang 1:13.b.3-dfsg-2ubuntu2 Concurrent, real-time, distributed function
ii erlang-appmon 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application monitor
ii erlang-asn1 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP modules for ASN.1 support
ii erlang-base 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP virtual machine and base applica
ii erlang-common-test 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application for automated testin
ii erlang-debugger 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application for debugging and te
ii erlang-dev 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP development libraries and header
[... many more]
Erlang seems to work:
$ erl
Erlang R13B03 (erts-5.7.4) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.4 (abort with ^G)
1>
I downloaded lfe from github and checked out 0.5.2:
git clone http://github.com/rvirding/lfe.git
cd lfe
git checkout -b local0.5.2 e207eb2cad
$ configure
configure: command not found
$ make
mkdir -p ebin
erlc -I include -o ebin -W0 -Ddebug +debug_info src/*.erl
#erl -I -pa ebin -noshell -eval -noshell -run edoc file src/leex.erl -run init stop
#erl -I -pa ebin -noshell -eval -noshell -run edoc_run application "'Leex'" '"."' '[no_packages]'
#mv src/*.html doc/
Must be something stupid i missed :o
$ sudo make install
make: *** No rule to make target `install'. Stop.
$ erl -noshell -noinput -s lfe_boot start
{"init terminating in do_boot",{undef,[{lfe_boot,start,[]},{init,start_it,1},{init,start_em,1}]}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
Is there an example how I would create a hello world source file and compile and run it?
No, there is nothing you missed. The Makefile in LFE is "less than perfect" and should be ignored, it will be improved upon in the next release. To compensate all the needed files have already compiled and the .beam files are in the ebin directory. As it is not part of OTP I don't think it should ever install there.
The easiest way to handle this to create a private erlang library directory and point the environment variable ERL_LIBS to it. Then just drop the whole LFE directory there. When erlang starts the code server will automatically add the lfe/ebin directories into the path and the .beam files there will automagically be found and loaded. This will work with any package that contains an ebin directory. This also works on Windows. So:
Make an libs directory, say ~/erlang/lib
Set the environment variable ERL_LIBS, export ERL_LIBS=~/erlang/lib
Put the whole LFE directory there
When you start erlang you will then see /Users/rv/erlang/lib/lfe/ebin (or wherever you have it) in the code path (code:get_path()). You will then also be able to start the LFE shell directly with
erl -noshell -noinput -s lfe_boot start
There will be an lfe and an lfe.bat which does this included as well in the future.
As with erlang any text editor will work to edit LFE. For emacs there is an LFE mode which is still rather basic but works. You cannot yet run LFE in a window. Soon. The best way to include this is to put the following in your .emacs file:
;; LFE mode.
(setq load-path (cons "/Users/rv/erlang/lib/lfe/emacs" load-path))
(require 'lfe-start)
There are some example files in lfe/examples, all should work. In lfe/test/visual there is a bunch of my test files which have been included as example files. To compile an LFE file from the normal erlang shell do
lfe_comp:file("foo").
l(foo). %No autloload here, do this to ensure loading
while from the LFE shell do:
(c '"foo") ;This will autoload
There is a bunch of documentation in lfe/docs which is quite accurate but the user_guide.txt needs to be extended. There is also a Google group for LFE at
http://groups.google.se/group/lisp-flavoured-erlang
which contains some interesting discussions and people have written quite a lot in the github LFE wiki.
That's about it I think. contact me if/when you have more questions.

Erlang emakefile explain

I have an Emakefile that looks like:
%% --
%%
%% --
{'/Users/user/projects/custom_test/trunk/*',
[debug_info,
{outdir, "/Users/user/projects/custom_test/trunk/ebin"},
{i, "/Users/user/projects/custom_test/trunk/include/."}
]
}.
What is an explanation in layman's terms for what each item does in the list?
How do I run the emakefile so that I am able to compile it?
After compilation, how do I run that generated BEAM file?
1/ {"source files globbed", Options}
Here the options are :
debug_info add debug info for the debugger
{outdir, "/Users/user/projects/custom_test/trunk/ebin"} where should the output be written (the .beam files)
{i, "/Users/user/projects/custom_test/trunk/include/."} where to find the .hrl header files.
2/ erl -make
3/ erl -pa /Users/user/projects/custom_test/trunk/ebin starts a shell.
Find the module serving as an entry point in your application and call the functions :
module:start().
You can also run the code non interactively :
erl -noinput -noshell -pa /Users/user/projects/custom_test/trunk/ebin -s module start
For the Emakefile synax visit the man page
In the directory where the Emakefile is run erl -make to compile using the Emakefile
Simplest way to run would be to simply start an erlang shell in the same directory as the beam files with the command erl. Then run the code with module_name:function_name(). (including the dot).

Resources