5

I created my first Erlang project. It's a simple secret code game. I'm trying to avoid OTP at all costs because it seems REALLY confusing and my mentor thought it wasn't necessary to use it this go- around.

I have three folders: ebin src test

I use a makefile to compile all code and run tests.

Life is good until tonight...

To mock my input (and outputs?) for the game, it was recommended that I use Meck but I am having a really hard time integrating it into my project.

I tried manually installing. I did a git clone of Meck. I can "cd" into the eBin folder in the Meck directory and compile, run all the system tests, and perform a basic command "meck:new(dog)". Awesome!

Now I need to get Meck working with my project...I read this line in the Github Meck readme: "If you want to install your own built version of meck add the ebin directory to your Erlang code path or move the meck folder into your release folder and make sure that folder is in your ERL_LIBS environment variable."

But I can't figure out how to add the ebin directory to my Erland code path, I don't have a release folder (this is a rebar thing I think?) and I don't know how to add a ERL_LIBS environment variable. So I'm stuck.

Here's what I've tried: To add the ebin directory to my code path, I did this in my makefile (I have the meck directory sitting on my Desktop right now):

    erlc -pa ~/Desktop/meck/ebin/

And I added the ERL_LIBS to my .bash_profile like so:

    export ERL_LIBS='~/Desktop/meck/ebin/'

I also tried installing Agner and get errors when I install:

    ERROR: compile failed while processing /private/tmp/agner.0r04Vm: {'EXIT',
        {undef,
            [{rebar,get_jobs,
                 [{config,"/private/tmp/agner.0r04Vm",
                      [{require_otp_vsn,"R14|R15"},
                       {lib_dirs,["deps"]},
                       {escript_incl_apps,
                           [getopt,gproc,rebar,plists,gen_fsm2,jsx]},
                       {erl_opts,[{i,"deps"}]},
                       {plugins,[agner_rebar_plugin]},
                       local]}],
                 []},
             {rebar_base_compiler,run,4,
                 [{file,"src/rebar_base_compiler.erl"},{line,49}]},
             {rebar_erlc_compiler,doterl_compile,3,
                 [{file,"src/rebar_erlc_compiler.erl"},{line,157}]},
             {rebar_core,run_modules,4,[{file,"src/rebar_core.erl"},{line,420}]},
             {rebar_core,execute,4,[{file,"src/rebar_core.erl"},{line,354}]},
             {rebar_core,process_dir0,6,[{file,"src/rebar_core.erl"},{line,217}]},
             {rebar_core,process_dir,4,[{file,"src/rebar_core.erl"},{line,128}]},
             {rebar_core,process_commands,2,
                 [{file,"src/rebar_core.erl"},{line,83}]}]}}
    make: *** [compile] Error 1

Can anyone help? I feel like there were several option for me to try and none of them are working.

Update:

Here's what my make file looks like after reading @d11wtq's solution:

    .SUFFIXES: .erl .beam .yrl        

    .erl.beam:
        erlc -W $<        

    .yrl.erl:
        erlc -W $<        

    ERL = erl -boot start_clean        

    MODS = console_io feedback mastermind secret_code meck        

    all:    compile path run_test        

    compile:
        erlc -o ebin/ src/*.erl
        erlc -o ebin/ test/*.erl        

    path:
        erlc -pa ebin/
        -env ERL_LIBS deps/        

    run_test:
        erl -noshell -pa ebin \
        -eval 'eunit:test("ebin").' \
        -eval 'mastermind:start_game().' \
        -s init stop        

    clean:
        rm -rf ebin/*.beam
        rm -rf erl_crash.dump

Final Update:

Based on the tips, here is my final makefile that now works.

    all:    compile run_test run_game

    compile:
        erlc -o ebin/ src/*.erl
        erlc -o ebin/ test/*.erl

    run_test:
        erl -pa ebin \
        -env ERL_LIBS deps/ \
        -eval 'eunit:test("ebin").' \
        -s init stop

    run_game:
        erl -pa ebin \
        -env ERL_LIBS deps/ \
        -eval "mastermind:start_game()." \
        -s init stop

    clean:
        rm -rf ebin/*.beam
        rm -rf erl_crash.dump
Kelly
  • 619
  • 8
  • 18

2 Answers2

4

Just put meck (and all its subdirectories) in a subdirectory of your project; say, deps/.

So now you'll have:

src/
ebin/
deps/
  meck/
    src/
    ebin/

Because libs in Erlang are packaged up the same way as applications, there is the environment variable ERL_LIBS that will tell the VM where to find libraries your app uses. Meck is one of those libs, and it is at the path "deps/".

erl -pa ebin/ -env ERL_LIBS deps/

Now meck should be visible to the Erlang VM.

d11wtq
  • 34,788
  • 19
  • 120
  • 195
  • Thank you so much for your help! I added the deps/meck folder and added the ERL_LIBS line to my makefile. I think I still need to add something to my MODS line above? There are 4 files in the src folder: meck.app.src, meck.erl, meck_abstract.hrl and meck_mod.erl. Do I add these to the MODS line? Also, when I run this currently, I get this error: env: ERL_LIBS: No such file or directory make: [path] Error 127 (ignored) – Kelly May 12 '13 at 13:17
  • Don't confuse `erlc` with `erl`. The `-env` flag is used by the Erlang VM, but not by the compiler. Libs don't need to be linked in at compile time, so even if your code references modules that don't exist, the compiler won't tell you about it. You'll find out at runtime. Now, since you're using rebar, why don't you just install meck by adding it to your rebar.config and using `rebar get-deps` and `rebar compile`? https://github.com/basho/rebar/wiki/Dependency-management. – d11wtq May 12 '13 at 13:34
  • Thank you so much for the tip on erl vs. erlc! I realized after reading your note that I really didn't know what those lines in my makefile were doing. I went back and read the documentation and this time I understood the documentation so much more easily after reading your tips above. I udpated my question with a final version of my makefile that now works with meck. Thanks again! (Also, I was trying to avoid rebar at this stage of the game. I'm still just learning Erlang and my assignment is due tomorrow, so I wasn't ready to start learning about rebar.) – Kelly May 12 '13 at 17:14
3

Quoting meck's README:

Meck is best used via rebar. Add the following dependency t your rebar.config in your project root:

{deps, [
    {meck, ".*", {git, "https://github.com/eproxus/meck.git"}}
]}.

And then run rebar get-deps and rebar compile.

legoscia
  • 39,593
  • 22
  • 116
  • 167
  • You were totally right about this. Thank you for that. When my mentor when to run the game, it wouldn't work because we didn't have this set up. Thanks for sharing!! – Kelly May 15 '13 at 19:47