How i compile and run erlang program? - erlang

i have
freebsd 10
folder /usr/home/ec2-user/ezmq with files from https://github.com/zeromq/ezmq
installed erlang
then i:
in command line run - erl
in erl
c("/usr/home/ec2-user/ezmq/examples/hwclient.erl").
c("/usr/home/ec2-user/ezmq/examples/hwserver.erl").
hwserver:main().
hwclient:main().
and have error
exception error: undefined function ezmq:start/1
in function hwserver:main/0 (/usr/home/ec2-user/ezmq/examples/hwserver.erl, line 14)
and have error
exception error: undefined function ezmq:start/1 in function hwclient:main/0 (/usr/home/ec2-user/ezmq/examples/hwclient.erl, line 14)
how i compile and run
this https://github.com/zeromq/ezmq/blob/master/examples/hwclient.erl + hwserver.erl
examples?
and i have error
** exception exit: {{undef,[{gen_listener_tcp,start_link,
[ezmq_tcp_socket,
[<0.49.0>,<<>>,5555,
[binary,inet,
{active,false},
{send_timeout,5000},
{backlog,10},
{nodelay,true},
{packet,raw},
{reuseaddr,true}]],
[]],
[]},
{ezmq,handle_call,3,[{file,"src/ezmq.erl"},{line,238}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,585}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,239}]}]},
{gen_server,call,[<0.49.0>,{bind,tcp,5555,[]}]}}
in function gen_server:call/2 (gen_server.erl, line 180)
in call from hwserver:main/0 (/usr/home/ec2-user/ezmq/examples/hwserver.erl, line 15)

This project uses rebar, so try this:
Download it from here: https://github.com/rebar/rebar/wiki/rebar
Make it executable
Compile: ./rebar compile
Open two terminals
In terminal 1, run: erl -pa ebin -pa /deps/gen_listener_tcp/ebin
The -pa option tells the vm where to load beam files from.
In the erlang shell, run:
c("examples/hwserver")
hwserver:main().
In terminal 2, run: erl -pa ebin -pa /deps/gen_listener_tcp/ebin
In the erlang shell, run:
c("examples/hwclient")
hwclient:main().
You should see a bunch of output.
The make file seems to require putting rebar in your path. Once you do that, you can try the make targets.

Related

Debugging an Erlang code with eunit in IntelliJ

IDE: IntelliJ IDEA 2022.2.2
I set a breakpoint in my Erlang code which has eunit testcases.
In order to debug it, I clicked on "Run --> Debug". I got an error "Test suite was cancelled". What could be the reason?
"C:\Program Files\Erlang OTP\bin\erl.exe" -pa C:\Users\bhu\AppData\Local\Temp\intellij_erlang_debugger_7789 -pa C:/Users/bhu/AppData/Local/Temp/eunit_teamcity9 -pa F:/1TB/P/workspace-IntelliJ-Erlang1/out/test/workspace-IntelliJ-Erlang1 -pa F:/1TB/P/workspace-IntelliJ-Erlang1 -run debugnode main 50067 -noshell -s init stop
Testing started at 20:59 ...
** Invalid beam file or no abstract code: "F:\\1TB\\P\\workspace-IntelliJ-Erlang1\\src\\my_sort.erl"
Test suite was cancelled. Reason: {abort,{module_not_found,my_sort}}
The error means that the module my_sort was not loaded into the VM. You can find the function here. I think this is because the search path to your module my_sort is not added to the code path using the flag -pa /mypath/my_sort.erl.
Could you try to add to the code path using -pa ..?

Using Elixir module from Erlang fails

I am trying to use in Erlang module a beam-file compiled from Elixir source. It raises error when I run Erlang node but I can use the code directly from Elixir.
Elixir module:
defmodule Recursion do
def print_multiple_times(msg, n) when n <= 1 do
IO.puts msg
end
def print_multiple_times(msg, n) do
IO.puts msg
print_multiple_times(msg, n - 1)
end
end
Erlang module:
-module(use_recur).
-define(elixir__recursion, 'Elixir.Recursion').
-export([hey/0]).
hey() ->
?elixir__recursion:print_multiple_times("Hello!", 3).
Compile both:
$ rm -f *.beam
$ elixirc recursion.ex
$ erlc use_recur.erl
Run Erlang:
$ erl -run use_recur hey -run init stop -noshell {"init terminating in do_boot",{undef,[{'Elixir.IO',puts,["Hello!"],[]},{'Elixir.Recursion',print_multiple_times,2,[{file,"recursion.ex"},{line,7}]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({undef,[{Elixir.IO,puts,Hello!,[]},{Elixir.Recursion,print_multiple_times,2,[{},{}]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
Elixir script:
Recursion.print_multiple_times "Hello!", 3
Runs successfully:
$ elixir elx_recur.exs
Hello!
Hello!
Hello!
Why does it happen? I'd say Erlang's output should be the same.
The error means that Erlang could not find a module named 'Elixir.IO'. This module is part of core Elixir. You'll need to add the ebin folder of your Elixir installation to Erlang's load path using -pa (or other similar flags like -pz) to make Erlang load Elixir's core libraries, as that folder contains the compiled .beam files of Elixir core, including Elixir.IO.beam.
erl -pa /path/to/elixir/ebin ...

Erlang ct:run_test dependencies

I try to run common test suites from erl shell with command:
> ct:run_test([{spec,"test/spec"}]).
Test suite fails with an error:
undefined function eredis:start_link/3
But if I type in the shell this:
> eredis:module_info().
I can see that dependent module eredis was loaded:
[{exports,[{start_link,0},
{start_link,2},
...
{start_link,6},
...
Why ct:run_test does not see dependent modules and how to run it correctly from erl shell?
I found that the problem is not in dependencies.
I wrote sample code that reproduces the problem.
One should always set absolute path to ebin directory (with -pa option) when running ct:run_test/1 from erlang shell.
Otherwise common tests started from erlang shell with the command:
$ ./rebar3.1 compile && erl -pa _build/default/lib/ct_fail/ebin/
> ct:run_test([{spec,"test/spec"}]).
will fail with the error:
=== ERROR! init_per_testcase crashed!
Location: [{ct_fail,start_link},
{fail_SUITE,init_per_testcase,16},
{test_server,do_init_per_testcase,1191},
{test_server,run_test_case_eval1,955},
{test_server,run_test_case_eval,926}]
Reason: {undef,[{ct_fail,start_link,[1,2],[]},
{fail_SUITE,init_per_testcase,2,
[{file,"fail_SUITE.erl"},{line,16}]},
{test_server,do_init_per_testcase,2,
[{file,"test_server.erl"},{line,1191}]},
{test_server,run_test_case_eval1,6,
[{file,"test_server.erl"},{line,955}]},
{test_server,run_test_case_eval,9,
[{file,"test_server.erl"},{line,926}]}]}
The most interesting part is that when module_info command is executed before test running:
$ ./rebar3.1 compile && erl -pa _build/default/lib/ct_fail/ebin/
> ct_fail:module_info().
ct_fail:module_info().
[{module,ct_fail},
{exports,[{start_link,0},
{start_link,1},
{start_link,2},
{start_link,3},
{start_link,4},
{init,1},
...
> ct:run_test([{spec,"test/spec"}]).
then tests will succeed!
By the way when test fails:
$ ./rebar3.1 compile && erl -pa _build/default/lib/ct_fail/ebin/
> ct:run_test([{spec,"test/spec"}]).
...
function call that caused test failure disappears from module exports list:
> ct_fail:module_info().
[{module,ct_fail},
{exports,[{start_link,0},
{start_link,1},
{start_link,3},
{start_link,4},
{init,1},
...
ct_fail:start_link/2 is not exported anymore!

What's the difference between code:add_path and using -pa on the command line?

This is my .erlang file:
code:add_path("/home/root/projects/myapp/ebin").
code:add_path("/home/root/projects/esmtp/ebin").
application:load(esmtp),
application:set_env(esmtp, smarthost, {"localhost",25}),
application:set_env(esmtp, default_from, "<stuff>"),
application:start(esmtp).
When I run:
erl -boot myapp
it fails:
{"init terminating in do_boot",{'cannot get bootfile','myapp.boot'}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
But if I run:
erl -boot myapp -pa /home/root/projects/myapp/ebin
It works fine. That leads me to believe that -pa on the command line is treated differently than code:add_path() in the .erlang file. I know the .erlang file is in effect, because esmtp loads and runs correctly. What's the difference between -pa and code:add_path()?
The .erlang file is read and executed after the boot file is loaded, so the path has not been added when erlang is looking for the boot file.
The -pa on the other hand is added before the vm starts to look for the boot file so then it is found.

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