Update master with mainline rebar (v2)

This PR uses the latest software provided by the upstream Rebar (v2) repo.

The most significant change allows this version of Rebar to work with
compilers which do not support the -m64 flag, as reported in #892
amongst others.

The latest code base also contains @davisp's Properly skip apps with a
.app.src.script file patch which CouchDB has been carrying for a while
now.
diff --git a/.travis.yml b/.travis.yml
index 9494ca9..8be6814 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,8 +9,29 @@
   - R14B04
   - R14B03
   - 17.0
+  - 18.0
+  - 19.1
+  - 20.0.5
+  - 20.1.5
+env: MAKE_TARGET=ci
 before_script:
   - hostname -f
   - cc -v
   - ld -v
-script: "make travis"
+  - find .rebar
+after_script:
+  - find .rebar
+matrix:
+  include:
+    - otp_release: 20.1.5
+      env: MAKE_TARGET=ci-dialyze
+  allow_failures:
+    - otp_release: 20.1.5
+      env: MAKE_TARGET=ci-dialyze
+script: make $MAKE_TARGET
+cache:
+  directories:
+    - .rebar
+before_cache:
+  - rm -fv .rebar/erlcinfo
+  - rm -fv $HOME/.cache/.rebar/erlcinfo
diff --git a/Makefile b/Makefile
index d0d16f8..106e289 100644
--- a/Makefile
+++ b/Makefile
@@ -22,11 +22,11 @@
 xref:
 	@./rebar xref
 
-build_plt:
-	@./rebar build-plt
+maybe_build_plt:
+	@./rebar -vv check-plt || ./rebar -vv build-plt
 
-dialyzer:
-	@./rebar dialyze
+dialyze: maybe_build_plt
+	@./rebar -vv dialyze
 
 binary: VSN = $(shell ./rebar -V)
 binary: clean all
@@ -45,4 +45,6 @@
 test_inttest: all deps
 	@$(RETEST) -l $(LOG_LEVEL) $(RT_TARGETS)
 
-travis: clean debug xref clean all deps test
+ci: clean debug xref clean all deps test
+
+ci-dialyze: clean debug dialyze
diff --git a/README.md b/README.md
index ec65693..54e6ad1 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
+**rebar is deprecated and will receive only bug fixes. We encourage you to move to [rebar3](https://github.com/erlang/rebar3).**
+
+----
+
 rebar
 =====
 
@@ -5,6 +9,7 @@
 applications, port drivers and releases.
 
 [![Build Status](https://secure.travis-ci.org/rebar/rebar.png?branch=master)](http://travis-ci.org/rebar/rebar)
+[![Build status](https://ci.appveyor.com/api/projects/status/4c48dw0cbu265cvt?svg=true)](https://ci.appveyor.com/project/rebar-win-ci/rebar-t0g71)
 
 rebar is a self-contained Erlang script, so it's easy to distribute or even
 embed directly in a project. Where possible, rebar uses standard Erlang/OTP
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index aa69555..dbb5402 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -1,3 +1,64 @@
+# 2.6.4
+
+* rebar/619: [Fix cdb processing when a file is skipped](https://github.com/rebar/rebar/pull/619)
+
+# 2.6.3
+
+* rebar/610: [qc: lift experimental notice](https://github.com/rebar/rebar/pull/610)
+* rebar/611: [port_compiler: consistently format default_env/0](https://github.com/rebar/rebar/pull/611)
+* rebar/612: [Introduce and use compat random number module](https://github.com/rebar/rebar/pull/612)
+* rebar/614: [Add an additional check for the existence of a 'rebar.beam' file](https://github.com/rebar/rebar/pull/614)
+* rebar/615: [port_compiler: generate clang compilation db](https://github.com/rebar/rebar/pull/615)
+* rebar/616: [port_compiler: clean up compile_each()](https://github.com/rebar/rebar/pull/616)
+* rebar/617: [port_compiler: auto-select C++ specific link template](https://github.com/rebar/rebar/pull/617)
+
+# 2.6.2
+
+* rebar/532: [Automatically clean neotoma-generated erl files, regression test](https://github.com/rebar/rebar/pull/532)
+* rebar/549: [Add Windows continuous integration through AppVeyor](https://github.com/rebar/rebar/pull/549)
+* rebar/551: [fprof: document Cachegrind support](https://github.com/rebar/rebar/pull/551)
+* rebar/556: [fprof: further document Cachegrind support](https://github.com/rebar/rebar/pull/556)
+* rebar/557: [Fix windows eunit tests](https://github.com/rebar/rebar/pull/557)
+* rebar/558: [Add qualified name tests docs (see pr #119)](https://github.com/rebar/rebar/pull/558)
+* rebar/560: [Lock retest dependency](https://github.com/rebar/rebar/pull/560)
+* rebar/562: [Add support for Windows integration testing](https://github.com/rebar/rebar/pull/562)
+* rebar/567: [Allow windows release to use etc conf dir](https://github.com/rebar/rebar/pull/567)
+* rebar/570: [xref: fix dialyzer warning introduced in 69802f63120](https://github.com/rebar/rebar/pull/570)
+* rebar/573: [Provide additional debug logging on relup generation](https://github.com/rebar/rebar/pull/573)
+* rebar/578: [Add the latest OTP 18 version to the Travis build](https://github.com/rebar/rebar/pull/578)
+* rebar/580: [Additional Common Test regression tests](https://github.com/rebar/rebar/pull/580)
+* rebar/581: [Update retest dependency url](https://github.com/rebar/rebar/pull/581)
+* rebar/586: [Ensure ebin created for dia compiler](https://github.com/rebar/rebar/pull/586)
+* rebar/587: [rebar_require_vsn: Update regexp to account for newer OTP versions](https://github.com/rebar/rebar/pull/587)
+* rebar/588: [Look for ct .spec files in the ct_dir that was specified](https://github.com/rebar/rebar/pull/588)
+* rebar/589: [Introduce REBAR_DEPS_PREFER_LIBS env variable to alter search behaviour](https://github.com/rebar/rebar/pull/589)
+* rebar/590: [Treat port env vars as expandable only if they self reference](https://github.com/rebar/rebar/pull/590)
+* rebar/591: [Fix/eunit tests surefire crash](https://github.com/rebar/rebar/pull/591)
+* rebar/594: [Introduce REBAR_VSN_CACHE_FILE env variable to load/save vsn cache](https://github.com/rebar/rebar/pull/594)
+* rebar/599: [Fix bug when running gcc in cross_sizeof](https://github.com/rebar/rebar/pull/599)
+* rebar/602: [Support full-source rebar3-style deps (deps without Version Regexes)](https://github.com/rebar/rebar/pull/602)
+* rebar/603: [add deprecated message](https://github.com/rebar/rebar/pull/603)
+* rebar/605: [Add necessary OSX flags for port driver linking](https://github.com/rebar/rebar/pull/605)
+* rebar/606: [Revert 'Treat port env vars as expandable only if they self reference'](https://github.com/rebar/rebar/pull/606)
+
+# 2.6.1
+
+* rebar/514: [Add license to relnotes tool per reviewer request](https://github.com/rebar/rebar/pull/514)
+* rebar/518: [Generate reserved file for erlc regression test](https://github.com/rebar/rebar/pull/518)
+* rebar/520: [Fixed version of #451](https://github.com/rebar/rebar/pull/520)
+* rebar/521: [rebar_utils: fix comment](https://github.com/rebar/rebar/pull/521)
+* rebar/522: [Fixed version of #395](https://github.com/rebar/rebar/pull/522)
+* rebar/524: [completion: add libid= to bash and zsh scripts](https://github.com/rebar/rebar/pull/524)
+* rebar/530: [Allow behaviors defined inside xref_extra_path](https://github.com/rebar/rebar/pull/530)
+* rebar/535: [Add regression test for covered common test](https://github.com/rebar/rebar/pull/535)
+* rebar/537: [Fix eunit test on OTP18](https://github.com/rebar/rebar/pull/537)
+* rebar/538: [Fix #536](https://github.com/rebar/rebar/pull/538)
+* rebar/539: [Add erl_first_files in eunit_first_files and qc_first_files](https://github.com/rebar/rebar/pull/539)
+* rebar/540: [Complete port compiler help string](https://github.com/rebar/rebar/pull/540)
+* rebar/543: [rmemo: use a better R13 check (Reported-by: Stavros Aronis)](https://github.com/rebar/rebar/pull/543)
+* rebar/545: [Fix #544](https://github.com/rebar/rebar/pull/545)
+* rebar/546: [Added report and verbose options for LFE compile.](https://github.com/rebar/rebar/pull/546)
+
 # 2.6.0
 
 * rebar/203: [Pluggable proto compilers gpb](https://github.com/rebar/rebar/pull/203)
diff --git a/THANKS b/THANKS
index 042bb30..943ad94 100644
--- a/THANKS
+++ b/THANKS
@@ -142,3 +142,12 @@
 Danil Onishchenko
 Stavros Aronis
 James Fish
+Tony Rogvall
+Andrey Teplyashin
+Duncan McGreggor
+Sebastien Serre
+John Daily
+Yury Gargay
+Frank Hunleth
+Matwey Kornilov
+Julius Andrikonis
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..59b9570
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,24 @@
+version: 2.6.1.{build}
+clone_depth: 1
+build_script:
+- cmd: >-
+    bootstrap.bat
+
+    set REBAR_EXTRA_DEPS=1
+
+    .\rebar get-deps
+
+    copy rebar deps\retest
+
+    copy rebar.cmd deps\retest
+
+    cd deps\retest & .\rebar compile escriptize
+test_script:
+- cmd: >-
+    rebar eunit
+
+    "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
+
+    cd deps\retest & retest -l debug -t 120000 ..\..\inttest
+artifacts:
+- path: rebar
diff --git a/bootstrap b/bootstrap
index f02ccd3..d65ccee 100755
--- a/bootstrap
+++ b/bootstrap
@@ -24,7 +24,10 @@
         true ->
             rm("ebin/*.beam");
         false ->
-            rm("ebin/rebar.beam")
+            case filelib:is_file("ebin/rebar.beam") of
+               true -> rm("ebin/rebar.beam");
+               false -> io:fwrite("No beam files found.~n")
+            end
     end,
 
     %% Add check for debug flag
diff --git a/ebin/rebar.app b/ebin/rebar.app
index 152829d..9449e1e 100644
--- a/ebin/rebar.app
+++ b/ebin/rebar.app
@@ -3,7 +3,7 @@
 
 {application, rebar,
  [{description, "Rebar: Erlang Build Tool"},
-  {vsn, "2.6.0"},
+  {vsn, "2.6.4"},
   {modules, [ rebar,
               rebar_abnfc_compiler,
               rebar_app_utils,
@@ -46,7 +46,8 @@
               rebar_metacmds,
               rebar_getopt,
               rebar_mustache,
-              rmemo ]},
+              rmemo,
+              rebar_rand_compat ]},
   {registered, []},
   {applications,
    [
@@ -68,6 +69,9 @@
          %% Default log level
          {log_level, warn},
 
+         %% Log colored
+         {log_colored, uncolored},
+
          %% any_dir processing modules
          {any_dir_modules, [
                             rebar_require_vsn,
diff --git a/inttest/app_src/app_src.erl b/inttest/app_src/app_src.erl
index dec7307..a6c53d1 100644
--- a/inttest/app_src/app_src.erl
+++ b/inttest/app_src/app_src.erl
@@ -1,6 +1,6 @@
 -module(app_src).
 
--compile(export_all).
+-export([test/0]).
 
 test() ->
     ok.
diff --git a/inttest/app_src/app_src_rt.erl b/inttest/app_src/app_src_rt.erl
index d71f03e..c8240d2 100644
--- a/inttest/app_src/app_src_rt.erl
+++ b/inttest/app_src/app_src_rt.erl
@@ -26,13 +26,18 @@
 %% -------------------------------------------------------------------
 -module(app_src_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
-     {create, "src/app_src.app.src", app(app_src)}].
+    [
+     {create, "src/app_src.app.src", app(app_src)}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
diff --git a/inttest/app_src_script/app_src_script.erl b/inttest/app_src_script/app_src_script.erl
index 6372c92..3f2a19b 100644
--- a/inttest/app_src_script/app_src_script.erl
+++ b/inttest/app_src_script/app_src_script.erl
@@ -1,6 +1,6 @@
 -module(app_src_script).
 
--compile(export_all).
+-export([test/0]).
 
 test() ->
     ok.
diff --git a/inttest/app_src_script/app_src_script_rt.erl b/inttest/app_src_script/app_src_script_rt.erl
index 4c00ec8..377f929 100644
--- a/inttest/app_src_script/app_src_script_rt.erl
+++ b/inttest/app_src_script/app_src_script_rt.erl
@@ -26,13 +26,18 @@
 %% -------------------------------------------------------------------
 -module(app_src_script_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
-     {create, "src/app_src_script.app.src.script", app_script(app_src_script)}].
+    [
+     {create, "src/app_src_script.app.src.script", app_script(app_src_script)}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
diff --git a/inttest/app_src_script_2/app_src_script_2.erl b/inttest/app_src_script_2/app_src_script_2.erl
index 26b8364..88eee51 100644
--- a/inttest/app_src_script_2/app_src_script_2.erl
+++ b/inttest/app_src_script_2/app_src_script_2.erl
@@ -1,6 +1,6 @@
 -module(app_src_script_2).
 
--compile(export_all).
+-export([test/0]).
 
 test() ->
     ok.
diff --git a/inttest/app_src_script_2/app_src_script_2_rt.erl b/inttest/app_src_script_2/app_src_script_2_rt.erl
index 1bf59d1..78cd761 100644
--- a/inttest/app_src_script_2/app_src_script_2_rt.erl
+++ b/inttest/app_src_script_2/app_src_script_2_rt.erl
@@ -26,14 +26,19 @@
 %% -------------------------------------------------------------------
 -module(app_src_script_2_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
+    [
      {create, "src/app_src_script_2.app.src.script", app_script(app_src_script_2)},
-     {create, "src/app_src_script_2.app.src", app(app_src_script_2)}].
+     {create, "src/app_src_script_2.app.src", app(app_src_script_2)}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
diff --git a/inttest/appup_src/appup_src_rt.erl b/inttest/appup_src/appup_src_rt.erl
index 2ca6788..0131972 100644
--- a/inttest/appup_src/appup_src_rt.erl
+++ b/inttest/appup_src/appup_src_rt.erl
@@ -26,13 +26,18 @@
 %% -------------------------------------------------------------------
 -module(appup_src_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
-     {copy, "src", "src"}].
+    [
+     {copy, "src", "src"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
diff --git a/inttest/appup_src/src/appup_src.erl b/inttest/appup_src/src/appup_src.erl
index 6f4d0d7..26b1812 100644
--- a/inttest/appup_src/src/appup_src.erl
+++ b/inttest/appup_src/src/appup_src.erl
@@ -1,6 +1,6 @@
 -module(appup_src).
 
--compile(export_all).
+-export([test/0]).
 
 test() ->
     ok.
diff --git a/inttest/appup_src_2/appup_src_2_rt.erl b/inttest/appup_src_2/appup_src_2_rt.erl
index 09d2503..4b621b1 100644
--- a/inttest/appup_src_2/appup_src_2_rt.erl
+++ b/inttest/appup_src_2/appup_src_2_rt.erl
@@ -26,13 +26,18 @@
 %% -------------------------------------------------------------------
 -module(appup_src_2_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
-     {copy, "src", "src"}].
+    [
+     {copy, "src", "src"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
diff --git a/inttest/appup_src_2/appup_src_rt_2.erl b/inttest/appup_src_2/appup_src_rt_2.erl
index d662183..e855a96 100644
--- a/inttest/appup_src_2/appup_src_rt_2.erl
+++ b/inttest/appup_src_2/appup_src_rt_2.erl
@@ -26,13 +26,17 @@
 %% -------------------------------------------------------------------
 -module(appup_src_rt_2).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
-     {copy, "src", "src"}].
+    [{copy, "src", "src"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
diff --git a/inttest/appup_src_2/src/appup_src.erl b/inttest/appup_src_2/src/appup_src.erl
index 6f4d0d7..26b1812 100644
--- a/inttest/appup_src_2/src/appup_src.erl
+++ b/inttest/appup_src_2/src/appup_src.erl
@@ -1,6 +1,6 @@
 -module(appup_src).
 
--compile(export_all).
+-export([test/0]).
 
 test() ->
     ok.
diff --git a/inttest/appup_src_script/appup_src_script_rt.erl b/inttest/appup_src_script/appup_src_script_rt.erl
index c98e54e..5dab165 100644
--- a/inttest/appup_src_script/appup_src_script_rt.erl
+++ b/inttest/appup_src_script/appup_src_script_rt.erl
@@ -26,13 +26,18 @@
 %% -------------------------------------------------------------------
 -module(appup_src_script_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
-     {copy, "src", "src"}].
+    [
+     {copy, "src", "src"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
diff --git a/inttest/appup_src_script/src/appup_src.erl b/inttest/appup_src_script/src/appup_src.erl
index 6f4d0d7..26b1812 100644
--- a/inttest/appup_src_script/src/appup_src.erl
+++ b/inttest/appup_src_script/src/appup_src.erl
@@ -1,6 +1,6 @@
 -module(appup_src).
 
--compile(export_all).
+-export([test/0]).
 
 test() ->
     ok.
diff --git a/inttest/bug_5_rt.erl b/inttest/bug_5_rt.erl
index 8894cb5..7f00e4a 100644
--- a/inttest/bug_5_rt.erl
+++ b/inttest/bug_5_rt.erl
@@ -2,22 +2,23 @@
 %% ex: ts=4 sw=4 et
 -module(bug_5_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 files() ->
     [{create, "ebin/a1.app", app(a1)},
      {create, "deps/d1/src/d1.app.src", app(d1)},
      {create, "rebar.config",
-      <<"{deps, [{d1, \"1\", {hg, \"http://example.com\", \"tip\"}}]}.\n">>},
-     {copy, "../rebar", "rebar"}].
+      <<"{deps, [{d1, \"1\", {hg, \"http://example.com\", \"tip\"}}]}.\n">>}
+    ] ++ inttest_utils:rebar_setup("..").
 
 run(_Dir) ->
     {ok, _} = retest:sh("./rebar compile"),
     ok.
 
-
-
 %%
 %% Generate the contents of a simple .app file
 %%
diff --git a/inttest/code_path_no_recurse/code_path_no_recurse_rt.erl b/inttest/code_path_no_recurse/code_path_no_recurse_rt.erl
index 74d035e..a2ca980 100644
--- a/inttest/code_path_no_recurse/code_path_no_recurse_rt.erl
+++ b/inttest/code_path_no_recurse/code_path_no_recurse_rt.erl
@@ -28,14 +28,17 @@
 -export([files/0,
          run/1]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "src", "src"},
      {copy, "test", "test"},
      {copy, "deps", "deps"}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     retest:log(info, "Compile project~n"),
diff --git a/inttest/cover/cover_rt.erl b/inttest/cover/cover_rt.erl
index a9f3f08..3f5e485 100644
--- a/inttest/cover/cover_rt.erl
+++ b/inttest/cover/cover_rt.erl
@@ -30,13 +30,18 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{create, "ebin/foo.app", app(foo)},
-     {copy, "../../rebar","rebar"},
+    [
+     {create, "ebin/foo.app", app(foo)},
      {copy, "src", "src"},
      {copy,
       "rebar-cover_export_json.config",
-      "rebar-cover_export_json.config"}].
+      "rebar-cover_export_json.config"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     ifdef_test(),
diff --git a/inttest/cross1/c_src/test1.c b/inttest/cross1/c_src/test1.c
new file mode 100644
index 0000000..4073ed6
--- /dev/null
+++ b/inttest/cross1/c_src/test1.c
@@ -0,0 +1 @@
+#include "test1.h"
diff --git a/inttest/cross1/c_src/test1.h b/inttest/cross1/c_src/test1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/inttest/cross1/c_src/test1.h
diff --git a/inttest/cross1/cross1_rt.erl b/inttest/cross1/cross1_rt.erl
new file mode 100644
index 0000000..297f353
--- /dev/null
+++ b/inttest/cross1/cross1_rt.erl
@@ -0,0 +1,66 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+%% -------------------------------------------------------------------
+%%
+%% rebar: Erlang Build Tools
+%%
+%% Copyright (c) 2016 Luis Rascao
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+%% -------------------------------------------------------------------
+
+-module(cross1_rt).
+-export([files/0,
+         run/1]).
+
+-include_lib("eunit/include/eunit.hrl").
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
+files() ->
+    [
+     {copy, "c_src", "c_src"},
+     {create, "ebin/foo.app", app(foo, [])}
+    ] ++ inttest_utils:rebar_setup().
+
+run(_Dir) ->
+    %% we will now determine where gcc is located
+    %% create a symlink to it in the cwd and change the
+    %% rebar arch so that rebar is fooled into believing
+    %% it's doing cross compilation.
+    {ok, [_, GccLocation]} = retest_sh:run("which gcc", []),
+    {ok, _} = retest_sh:run(io_lib:format("ln -s ~s unknown-unknown-linux-gnu-gcc", [GccLocation]),
+                            []),
+    ?assertMatch({ok, _}, retest_sh:run("./rebar compile -vvv",
+                                        [{env, [{"PATH", "./:" ++ os:getenv("PATH")},
+                                                {"REBAR_TARGET_ARCH", "unknown-unknown-linux-gnu"}]}])).
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name, Modules) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, Modules},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/ct1/ct1_rt.erl b/inttest/ct1/ct1_rt.erl
index dc83095..97d77f9 100644
--- a/inttest/ct1/ct1_rt.erl
+++ b/inttest/ct1/ct1_rt.erl
@@ -2,23 +2,25 @@
 %% ex: ts=4 sw=4 et
 -module(ct1_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 files() ->
-    [{create, "ebin/a1.app", app(a1)},
-     {copy, "../../rebar", "rebar"},
+    [
+     {create, "ebin/a1.app", app(a1)},
      {copy, "rebar.config", "rebar.config"},
      {copy, "app.config", "app.config"},
-     {copy, "test_SUITE.erl", "itest/test_SUITE.erl"}].
+     {copy, "test_SUITE.erl", "itest/test_SUITE.erl"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     {ok, _} = retest:sh("./rebar compile ct"),
     {ok, _} = retest:sh("./rebar compile ct -v"),
     ok.
 
-
-
 %%
 %% Generate the contents of a simple .app file
 %%
diff --git a/inttest/ct1/test_SUITE.erl b/inttest/ct1/test_SUITE.erl
index e8a2bb8..3d86a6a 100644
--- a/inttest/ct1/test_SUITE.erl
+++ b/inttest/ct1/test_SUITE.erl
@@ -1,6 +1,6 @@
 -module(test_SUITE).
 
--compile(export_all).
+-export([all/0, simple_test/1, app_config_file_test/1]).
 
 -include_lib("ct.hrl").
 
diff --git a/inttest/ct2/ct2_rt.erl b/inttest/ct2/ct2_rt.erl
index f9d2b19..06d7abb 100644
--- a/inttest/ct2/ct2_rt.erl
+++ b/inttest/ct2/ct2_rt.erl
@@ -2,15 +2,19 @@
 %% ex: ts=4 sw=4 et
 -module(ct2_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 files() ->
-    [{create, "ebin/foo.app", app(foo)},
-     {copy, "../../rebar", "rebar"},
+    [
+     {create, "ebin/foo.app", app(foo)},
      {copy, "foo.test.spec", "foo.test.spec"},
      {copy, "deps/bar.test.spec", "deps/bar.test.spec"},
-     {copy, "foo_SUITE.erl", "test/foo_SUITE.erl"}].
+     {copy, "foo_SUITE.erl", "test/foo_SUITE.erl"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     Ref = retest:sh("./rebar compile ct -vvv", [async]),
diff --git a/inttest/ct2/foo_SUITE.erl b/inttest/ct2/foo_SUITE.erl
index d03aedf..be089c7 100644
--- a/inttest/ct2/foo_SUITE.erl
+++ b/inttest/ct2/foo_SUITE.erl
@@ -2,7 +2,7 @@
 
 -include_lib("common_test/include/ct.hrl").
 
--compile(export_all).
+-export([all/0, foo/1]).
 
 all() -> [foo].
 
diff --git a/inttest/ct3/ct3_rt.erl b/inttest/ct3/ct3_rt.erl
index a87cf21..32ded4c 100644
--- a/inttest/ct3/ct3_rt.erl
+++ b/inttest/ct3/ct3_rt.erl
@@ -26,21 +26,25 @@
 %% -------------------------------------------------------------------
 -module(ct3_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 files() ->
-    [{create, "ebin/a1.app", app(a1)},
-     {copy, "../../rebar", "rebar"},
+    [
+     {create, "ebin/a1.app", app(a1)},
      {copy, "rebar.config", "rebar.config"},
      {copy, "app.config", "itest/app.config"},
      {copy, "test_SUITE.erl", "itest/test_SUITE.erl"},
      {copy, "converted"},
-     {copy, "unconverted"}].
+     {copy, "unconverted"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     {ok, _} = retest:sh("./rebar compile ct -v",
-                        [{env, [{"ERL_FLAGS", "-name ct_rt3"}]}]),
+                        [{env, [{"ERL_FLAGS", "-name ct_rt3@localhost"}]}]),
     ok.
 
 %%
diff --git a/inttest/ct3/test_SUITE.erl b/inttest/ct3/test_SUITE.erl
index efd930d..610c14c 100644
--- a/inttest/ct3/test_SUITE.erl
+++ b/inttest/ct3/test_SUITE.erl
@@ -26,7 +26,7 @@
 %% -------------------------------------------------------------------
 -module(test_SUITE).
 
--compile(export_all).
+-export([all/0, simple_test/1, app_config_file_test/1, check_path/1]).
 
 -include_lib("ct.hrl").
 
diff --git a/inttest/ct4/ct4_rt.erl b/inttest/ct4/ct4_rt.erl
new file mode 100644
index 0000000..b393bc7
--- /dev/null
+++ b/inttest/ct4/ct4_rt.erl
@@ -0,0 +1,44 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(ct4_rt).
+
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
+files() ->
+    [
+     {create, "ebin/foo.app", app(foo)},
+     {copy, "rebar.config", "rebar.config"},
+     {copy, "foo.test.spec", "test/foo.test.spec"},
+     {copy, "deps/bar.test.spec", "deps/bar.test.spec"},
+     {copy, "deps/bar.test.spec", "baz.test.spec"},
+     {copy, "foo_SUITE.erl", "test/foo_SUITE.erl"}
+    ] ++ inttest_utils:rebar_setup().
+
+run(_Dir) ->
+    Ref = retest:sh("./rebar compile ct -vvv", [async]),
+    {ok, [[CTRunCmd]]} = retest:sh_expect(Ref, "^\"ct_run.*",
+                                  [global, {capture, first, binary}]),
+    {match, _} = re:run(CTRunCmd, "foo.test.spec", [global]),
+    %% deps/bar.test.spec should be ignored by rebar_ct:collect_glob/3
+    nomatch = re:run(CTRunCmd, "bar.test.spec", [global]),
+    %% baz.test.spec should be also ignored by rebar_ct:collect_glob/3
+    %% since we specified in rebar.config that we want to search for
+    %% ct specs from the test dir
+    nomatch = re:run(CTRunCmd, "baz.test.spec", [global]),
+    ok.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, []},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/ct4/deps/bar.test.spec b/inttest/ct4/deps/bar.test.spec
new file mode 100644
index 0000000..a16610c
--- /dev/null
+++ b/inttest/ct4/deps/bar.test.spec
@@ -0,0 +1 @@
+%% this test spec should be ignored
diff --git a/inttest/ct4/foo.test.spec b/inttest/ct4/foo.test.spec
new file mode 100644
index 0000000..1850410
--- /dev/null
+++ b/inttest/ct4/foo.test.spec
@@ -0,0 +1 @@
+{suites, "../", [foo_SUITE]}.
diff --git a/inttest/ct4/foo_SUITE.erl b/inttest/ct4/foo_SUITE.erl
new file mode 100644
index 0000000..931ca50
--- /dev/null
+++ b/inttest/ct4/foo_SUITE.erl
@@ -0,0 +1,11 @@
+-module(foo_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0, simple/1]).
+
+all() -> [simple].
+
+simple(Config) ->
+    io:format("Test: ~p\n", [Config]),
+    ok.
diff --git a/inttest/ct4/rebar.config b/inttest/ct4/rebar.config
new file mode 100644
index 0000000..387f8c3
--- /dev/null
+++ b/inttest/ct4/rebar.config
@@ -0,0 +1,2 @@
+{ct_dir, "test"}.
+{ct_search_specs_from_test_dir, true}.
diff --git a/inttest/ct_cover/app.config b/inttest/ct_cover/app.config
new file mode 100644
index 0000000..bb718b2
--- /dev/null
+++ b/inttest/ct_cover/app.config
@@ -0,0 +1,2 @@
+%% This file is an application config file, not a CT test config file
+[{a1, [{foo, bar}]}].
diff --git a/inttest/ct_cover/cover.spec b/inttest/ct_cover/cover.spec
new file mode 100644
index 0000000..353f322
--- /dev/null
+++ b/inttest/ct_cover/cover.spec
@@ -0,0 +1,3 @@
+%% Cover analysis level.
+%% Level = details | overview
+{level, details}.
diff --git a/inttest/ct_cover/ct_cover_rt.erl b/inttest/ct_cover/ct_cover_rt.erl
new file mode 100644
index 0000000..8bff9df
--- /dev/null
+++ b/inttest/ct_cover/ct_cover_rt.erl
@@ -0,0 +1,35 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(ct_cover_rt).
+
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
+files() ->
+    [
+     {create, "ebin/a1.app", app(a1)},
+     {copy, "rebar.config", "rebar.config"},
+     {copy, "app.config", "app.config"},
+     {copy, "cover.spec", "cover.spec"},
+     {copy, "test_SUITE.erl", "itest/test_SUITE.erl"},
+     {copy, "mock", "deps"}
+    ] ++ inttest_utils:rebar_setup().
+
+run(_Dir) ->
+    {ok, _} = retest:sh("./rebar compile ct"),
+    ok.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, []},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/ct_cover/mock/dummy/app.config b/inttest/ct_cover/mock/dummy/app.config
new file mode 100644
index 0000000..c471954
--- /dev/null
+++ b/inttest/ct_cover/mock/dummy/app.config
@@ -0,0 +1,2 @@
+%% This file is an application config file, not a CT test config file
+[{dummy, [{foo, bar}]}].
diff --git a/inttest/ct_cover/mock/dummy/cover.spec b/inttest/ct_cover/mock/dummy/cover.spec
new file mode 100644
index 0000000..353f322
--- /dev/null
+++ b/inttest/ct_cover/mock/dummy/cover.spec
@@ -0,0 +1,3 @@
+%% Cover analysis level.
+%% Level = details | overview
+{level, details}.
diff --git a/inttest/ct_cover/mock/dummy/ebin/dummy.app b/inttest/ct_cover/mock/dummy/ebin/dummy.app
new file mode 100644
index 0000000..3c89b1b
--- /dev/null
+++ b/inttest/ct_cover/mock/dummy/ebin/dummy.app
@@ -0,0 +1,6 @@
+{application,dummy,
+             [{description,"dummy"},
+              {vsn,"1"},
+              {modules,[]},
+              {registered,[]},
+              {applications,[kernel,stdlib]}]}.
diff --git a/inttest/ct_cover/mock/dummy/itest/test_SUITE.erl b/inttest/ct_cover/mock/dummy/itest/test_SUITE.erl
new file mode 100644
index 0000000..25dde6a
--- /dev/null
+++ b/inttest/ct_cover/mock/dummy/itest/test_SUITE.erl
@@ -0,0 +1,17 @@
+-module(test_SUITE).
+
+-export([all/0, simple_test/1, app_config_file_test/1]).
+
+-include_lib("ct.hrl").
+
+all() ->
+    [simple_test,
+     app_config_file_test].
+
+simple_test(Config) ->
+    io:format("Test: ~p\n", [Config]).
+
+app_config_file_test(_Config) ->
+    application:start(dummy),
+    {ok, bar} = application:get_env(dummy, foo),
+    application:stop(dummy).
diff --git a/inttest/ct_cover/mock/dummy/rebar.config b/inttest/ct_cover/mock/dummy/rebar.config
new file mode 100644
index 0000000..34b1c47
--- /dev/null
+++ b/inttest/ct_cover/mock/dummy/rebar.config
@@ -0,0 +1,4 @@
+{cover_enabled, true}.
+
+{ct_dir, "itest"}.
+{ct_extra_params, "-repeat 2 -erl_args -config app -cover cover.spec"}.
diff --git a/inttest/ct_cover/rebar.config b/inttest/ct_cover/rebar.config
new file mode 100644
index 0000000..2b14ab8
--- /dev/null
+++ b/inttest/ct_cover/rebar.config
@@ -0,0 +1,7 @@
+{cover_enabled, true}.
+
+{deps_dir, "deps"}.
+{deps,[{dummy, ".*"}]}.
+
+{ct_dir, "itest"}.
+{ct_extra_params, "-repeat 2 -erl_args -config app"}.
diff --git a/inttest/ct_cover/test_SUITE.erl b/inttest/ct_cover/test_SUITE.erl
new file mode 100644
index 0000000..3d86a6a
--- /dev/null
+++ b/inttest/ct_cover/test_SUITE.erl
@@ -0,0 +1,17 @@
+-module(test_SUITE).
+
+-export([all/0, simple_test/1, app_config_file_test/1]).
+
+-include_lib("ct.hrl").
+
+all() ->
+    [simple_test,
+     app_config_file_test].
+
+simple_test(Config) ->
+    io:format("Test: ~p\n", [Config]).
+
+app_config_file_test(_Config) ->
+    application:start(a1),
+    {ok, bar} = application:get_env(a1, foo),
+    application:stop(a1).
diff --git a/inttest/ct_make_fails/app.config b/inttest/ct_make_fails/app.config
new file mode 100644
index 0000000..bb718b2
--- /dev/null
+++ b/inttest/ct_make_fails/app.config
@@ -0,0 +1,2 @@
+%% This file is an application config file, not a CT test config file
+[{a1, [{foo, bar}]}].
diff --git a/inttest/ct_make_fails/ct_make_fails_rt.erl b/inttest/ct_make_fails/ct_make_fails_rt.erl
new file mode 100644
index 0000000..e2abb9a
--- /dev/null
+++ b/inttest/ct_make_fails/ct_make_fails_rt.erl
@@ -0,0 +1,31 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(ct_make_fails_rt).
+
+-export([files/0, run/1]).
+
+
+files() ->
+    [{create, "ebin/a1.app", app(a1)},
+     {copy, "../../rebar", "rebar"},
+     {copy, "rebar.config", "rebar.config"},
+     {copy, "app.config", "app.config"},
+     {copy, "test_SUITE.erl", "itest/test_SUITE.erl"}].
+
+run(_Dir) ->
+    ok = case catch retest:sh("./rebar compile ct -v") of
+                {error, {stopped, _}} -> ok;
+                _ -> expected_to_fail
+              end.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, []},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/ct_make_fails/rebar.config b/inttest/ct_make_fails/rebar.config
new file mode 100644
index 0000000..58047ba
--- /dev/null
+++ b/inttest/ct_make_fails/rebar.config
@@ -0,0 +1,2 @@
+{ct_dir, "itest"}.
+{ct_extra_params, "-repeat 2 -erl_args -config app"}.
diff --git a/inttest/ct_make_fails/test_SUITE.erl b/inttest/ct_make_fails/test_SUITE.erl
new file mode 100644
index 0000000..068e926
--- /dev/null
+++ b/inttest/ct_make_fails/test_SUITE.erl
@@ -0,0 +1,17 @@
+-module(test_SUITE).
+
+-export([all/0, simple_test/1, app_config_file_test/1]).
+
+-include_lib("ct.hrl").
+
+all() ->
+    [simple_test,
+     app_config_file_test].
+
+simple_test(Config) ->
+    io:format("Test: ~p\n" [Config]).
+
+app_config_file_test(_Config) ->
+    application:start(a1),
+    {ok, bar} = application:get_env(a1, foo),
+    application:stop(a1).
diff --git a/inttest/ct_test_fails/app.config b/inttest/ct_test_fails/app.config
new file mode 100644
index 0000000..bb718b2
--- /dev/null
+++ b/inttest/ct_test_fails/app.config
@@ -0,0 +1,2 @@
+%% This file is an application config file, not a CT test config file
+[{a1, [{foo, bar}]}].
diff --git a/inttest/ct_test_fails/ct_test_fails.test.spec b/inttest/ct_test_fails/ct_test_fails.test.spec
new file mode 100644
index 0000000..7bba687
--- /dev/null
+++ b/inttest/ct_test_fails/ct_test_fails.test.spec
@@ -0,0 +1 @@
+{suites,"../itest",[test_SUITE, test2_SUITE]}.
diff --git a/inttest/ct_test_fails/ct_test_fails_rt.erl b/inttest/ct_test_fails/ct_test_fails_rt.erl
new file mode 100644
index 0000000..69ee382
--- /dev/null
+++ b/inttest/ct_test_fails/ct_test_fails_rt.erl
@@ -0,0 +1,32 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(ct_test_fails_rt).
+
+-export([files/0, run/1]).
+
+files() ->
+    [{create, "ebin/a1.app", app(a1)},
+     {copy, "../../rebar", "rebar"},
+     {copy, "rebar.config", "rebar.config"},
+     {copy, "app.config", "app.config"},
+     {copy, "ct_test_fails.test.spec", "itest/ct_test_fails.test.spec"},
+     {copy, "test_SUITE.erl", "itest/test_SUITE.erl"},
+     {copy, "test2_SUITE.erl", "itest/test2_SUITE.erl"}].
+
+run(_Dir) ->
+    ok = case catch retest:sh("./rebar compile ct -v 3") of
+             {error, {stopped, _}} -> ok;
+             _ -> expected_to_fail
+         end.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, []},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/ct_test_fails/rebar.config b/inttest/ct_test_fails/rebar.config
new file mode 100644
index 0000000..84c23ef
--- /dev/null
+++ b/inttest/ct_test_fails/rebar.config
@@ -0,0 +1,13 @@
+{ct_dir, ["itest"]}.
+{ct_extra_params, "-erl_args -config app"}.
+
+%% http://erlang.org/doc/apps/common_test/run_test_chapter.html#id77160
+%%      Any relative paths specified in the test specification, will be relative to the
+%%      directory which contains the  test specification file, if ct_run -spec TestSpecFile ...
+%%      or ct:run:test([{spec,TestSpecFile},...]) executes the  test. The path will be
+%%      relative to the top level log directory, if ct:run:testspec(TestSpec) executes the test.
+%% however for versions older than R16  what counts is the project root path and not the path
+%% of the location of the test spec. This will cause the test to fail since R15/14 can't find the
+%% test.spec file. Since we can't change the file we have no choice but to bypass the test
+%% completely
+{require_min_otp_vsn, "R16B"}.
diff --git a/inttest/ct_test_fails/test2_SUITE.erl b/inttest/ct_test_fails/test2_SUITE.erl
new file mode 100644
index 0000000..7db1d22
--- /dev/null
+++ b/inttest/ct_test_fails/test2_SUITE.erl
@@ -0,0 +1,9 @@
+-module(test2_SUITE).
+
+-export([all/0, simple_test/1]).
+
+all() ->
+    [simple_test].
+
+simple_test(Config) ->
+    io:format("Test: ~p\n", [Config]).
diff --git a/inttest/ct_test_fails/test_SUITE.erl b/inttest/ct_test_fails/test_SUITE.erl
new file mode 100644
index 0000000..047631c
--- /dev/null
+++ b/inttest/ct_test_fails/test_SUITE.erl
@@ -0,0 +1,10 @@
+-module(test_SUITE).
+
+-export([all/0, simple_test/1]).
+
+all() ->
+    [simple_test].
+
+simple_test(Config) ->
+    io:format("Test: ~p\n", [Config]),
+    ok = not_ok.
diff --git a/inttest/depplugins/depplugins_rt.erl b/inttest/depplugins/depplugins_rt.erl
index 7bcfe86..c2cb76a 100644
--- a/inttest/depplugins/depplugins_rt.erl
+++ b/inttest/depplugins/depplugins_rt.erl
@@ -17,13 +17,16 @@
 %%% </ol>
 
 -module(depplugins_rt).
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "base_dir_cwd_plugin.erl", "base_dir_cwd_plugin.erl"},
      {create, "ebin/fish.app", app(fish, [])},
@@ -38,7 +41,7 @@
       "deps/testplugin/plugins/testplugin_mod.erl"},
      {copy, "dep_cwd_plugin.erl", "deps/testplugin/dep_cwd_plugin.erl"},
      {create, "deps/testplugin/ebin/testplugin.app", app(testplugin, [])}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
diff --git a/inttest/erlc/erlc_rt.erl b/inttest/erlc/erlc_rt.erl
index 7e0c5dc..3ac5956 100644
--- a/inttest/erlc/erlc_rt.erl
+++ b/inttest/erlc/erlc_rt.erl
@@ -54,9 +54,12 @@
          "foo_worker.beam",
          "SIMPLE-ASN.beam"]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "rebar-no_debug_info.config", "rebar-no_debug_info.config"},
      {copy, "include", "include"},
@@ -66,10 +69,14 @@
      {copy, "mibs", "mibs"},
      {copy, "asn1", "asn1"},
      {create, "ebin/foo.app", app(foo, ?MODULES)},
+     {create, "src/._do_not_compile.erl",
+              "syntax error\n"
+              "this file is here to verify that rebar does not try to compile\n"
+              "files like OS X resource forks and should not be processed at all\n"},
      %% deps
      {create, "deps/foobar/ebin/foobar.app", app(foobar, [foobar])},
      {copy, "foobar.erl", "deps/foobar/src/foobar.erl"}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
diff --git a/inttest/erlc/src/._do_not_compile.erl b/inttest/erlc/src/._do_not_compile.erl
deleted file mode 100644
index f26f987..0000000
--- a/inttest/erlc/src/._do_not_compile.erl
+++ /dev/null
@@ -1,4 +0,0 @@
-syntax error
-this file is here to verify that rebar does not try to
-compile files like OS X resource forks and should not be
-processed at all
diff --git a/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl b/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl
index 384ce87..72c6928 100644
--- a/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl
+++ b/inttest/erlc_dep_graph/erlc_dep_graph_rt.erl
@@ -30,39 +30,57 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
+    [
      {copy, "rebar.config", "rebar.config"},
      {copy, "src", "src"},
      {copy, "include", "include"},
-     {copy, "extra_include", "extra_include"}].
+     {copy, "extra_include", "extra_include"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
+    retest_log:log(debug, "compiling all...\n\n", []),
     compile_all(ok, ""),
+    retest_log:log(debug, "checking beams integrity...\n\n", []),
     check_beams_ok(),
     check_beams_untouched(filelib:wildcard("ebin/*.beam")),
+    retest_log:log(debug, "modifying lisp.erl and recompiling...\n\n", []),
     modify_and_recompile_ok("src/lisp.erl", "ebin/lisp.beam"),
 
+    retest_log:log(debug, "cleaning all...\n\n", []),
     clean_all_ok(),
+    retest_log:log(debug, "compiling all (expect fail)...\n\n", []),
     compile_all(error, "-C rebar.config.non-existing"),
+    retest_log:log(debug, "compiling all...\n\n", []),
     compile_all(ok, ""),
+    retest_log:log(debug, "modifying extra_include/extra.hrl and recompiling...\n\n", []),
     modify_and_recompile_ok("extra_include/extra.hrl", "ebin/java.beam"),
 
+    retest_log:log(debug, "rewriting src/java.erl...\n\n", []),
     Java = "src/java.erl",
     {ok, OrigContent} = file:read_file(Java),
     %% Remove header file inclusion
     {ok, _} = file:copy("src/java.erl.no_extra", Java),
     %% Ensure recompilation
     touch([Java]),
+    retest_log:log(debug, "compiling all...\n\n", []),
     compile_all(ok, ""),
     %% Modify that header file
+    retest_log:log(debug, "again modifying extra_include/extra.hrl and recompiling...\n\n", []),
     touch(["extra_include/extra.hrl"]),
     %% Ensure we don't have to recompile anything
+    retest_log:log(debug, "ensure ebin/java.beam was untouched...\n\n", []),
     check_beams_untouched(["ebin/java.beam"]),
     %% Clean up
+    retest_log:log(debug, "modifying src/java.erl...\n\n", []),
     ok = file:write_file(Java, OrigContent),
 
     %% Check that changes propagate deeply through the dependency tree
+    retest_log:log(debug, "modifying include/lambda.hrl...\n\n", []),
     modify_and_recompile_ok("include/lambda.hrl", "ebin/perl.beam"),
 
     ok.
@@ -82,7 +100,9 @@
     BeamsModifiedBefore = mtime_ns(Beams),
     compile_all(ok, ""),
     BeamsModifiedAfter = mtime_ns(Beams),
-    lists:zipwith(fun(Before, After) -> ?assert(Cmp(Before, After)) end,
+    lists:zipwith(fun(Before, After) ->
+                    ?assert(Cmp(Before, After))
+                  end,
                   BeamsModifiedBefore, BeamsModifiedAfter).
 
 with_erl_beams(F) ->
@@ -95,13 +115,13 @@
         filelib:wildcard("src/*.erl")).
 
 mtime_ns(Files) ->
-    [os:cmd("stat -c%y " ++ File) || File <- Files].
+    [calendar:datetime_to_gregorian_seconds(filelib:last_modified(File)) || File <- Files].
 
 touch(Files) ->
     %% Sleep one second so that filelib:last_modified/1 is guaranteed to notice
     %% that files have changed.
     ok = timer:sleep(1000),
-    [os:cmd("touch " ++ File) || File <- Files].
+    [file:change_time(File, calendar:local_time()) || File <- Files].
 
 compile_all(Result, Opts) ->
     ?assertMatch({Result, _},
diff --git a/inttest/eunit/eunit_rt.erl b/inttest/eunit/eunit_rt.erl
index 1d71404..bc24b26 100644
--- a/inttest/eunit/eunit_rt.erl
+++ b/inttest/eunit/eunit_rt.erl
@@ -5,14 +5,19 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{create, "ebin/foo.app", app(foo)},
-     {copy, "../../rebar", "rebar"},
+    [
+     {create, "ebin/foo.app", app(foo)},
      {copy, "src", "src"},
      {copy, "eunit_src", "eunit_src"},
      {copy,
       "rebar-eunit_compile_opts.config",
-      "rebar-eunit_compile_opts.config"}].
+      "rebar-eunit_compile_opts.config"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     ifdef_test(),
diff --git a/inttest/eunit_surefire/eunit_src/bar.erl b/inttest/eunit_surefire/eunit_src/bar.erl
new file mode 100644
index 0000000..6a80dac
--- /dev/null
+++ b/inttest/eunit_surefire/eunit_src/bar.erl
@@ -0,0 +1,6 @@
+-module(bar).
+
+-include_lib("eunit/include/eunit.hrl").
+
+bar_test() ->
+    ?assert(true).
diff --git a/inttest/eunit_surefire/eunit_surefire_rt.erl b/inttest/eunit_surefire/eunit_surefire_rt.erl
new file mode 100644
index 0000000..fd26d4b
--- /dev/null
+++ b/inttest/eunit_surefire/eunit_surefire_rt.erl
@@ -0,0 +1,40 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(eunit_surefire_rt).
+-export([files/0, run/1]).
+
+-include_lib("eunit/include/eunit.hrl").
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
+files() ->
+    [
+     {create, "ebin/foo.app", app(foo)},
+     {copy, "src", "src"},
+     {copy, "eunit_src", "eunit_src"},
+     {copy, "rebar.config"}
+    ] ++ inttest_utils:rebar_setup().
+
+run(_Dir) ->
+    {ok, Output} = retest:sh("./rebar -v eunit tests=bar"),
+    ?assert(check_output(Output, "bar_test")),
+    ok.
+
+check_output(Output, Target) ->
+    lists:any(fun(Line) ->
+                      string:str(Line, Target) > 0
+              end, Output).
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, []},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/eunit_surefire/rebar.config b/inttest/eunit_surefire/rebar.config
new file mode 100644
index 0000000..0172560
--- /dev/null
+++ b/inttest/eunit_surefire/rebar.config
@@ -0,0 +1,7 @@
+{eunit_compile_opts, [
+    {src_dirs, ["eunit_src"]}
+]}.
+
+{eunit_opts, [
+    {report, {eunit_surefire, [{dir, "."}]}}
+]}.
diff --git a/inttest/eunit_surefire/src/foo.erl b/inttest/eunit_surefire/src/foo.erl
new file mode 100644
index 0000000..a4c91ba
--- /dev/null
+++ b/inttest/eunit_surefire/src/foo.erl
@@ -0,0 +1,10 @@
+-module(foo).
+
+-ifdef(TEST).
+
+-include_lib("eunit/include/eunit.hrl").
+
+foo_test() ->
+    ?assert(true).
+
+-endif.
diff --git a/inttest/inttest_utils.erl b/inttest/inttest_utils.erl
new file mode 100644
index 0000000..addac5f
--- /dev/null
+++ b/inttest/inttest_utils.erl
@@ -0,0 +1,19 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(inttest_utils).
+
+-export([ rebar_setup/1
+        , rebar_setup/2
+        , rebar_setup/0
+        ]).
+
+rebar_setup({win32, nt}, Dir) ->
+    [{copy, filename:join(Dir, "rebar.cmd"), "rebar.cmd"}];
+rebar_setup({_, _}, _) -> [].
+
+rebar_setup(Dir) ->
+    [{copy,
+      filename:join(Dir, "rebar"), "rebar"}] ++ rebar_setup(os:type(), Dir).
+
+rebar_setup() ->
+    rebar_setup("../..").
diff --git a/inttest/logging/logging_rt.erl b/inttest/logging/logging_rt.erl
index d3e1c0f..f774376 100644
--- a/inttest/logging/logging_rt.erl
+++ b/inttest/logging/logging_rt.erl
@@ -30,35 +30,47 @@
 
 -define(APP_FILE, "ebin/logging.app").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {create, ?APP_FILE, app(invalid_name, [])}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     SharedExpected = "==> logging_rt \\(compile\\)",
+    {ERROR, WARN, INFO, DEBUG} = log_labels(),
     %% provoke ERROR due to an invalid app file
     retest:log(info, "Check 'compile' failure output~n"),
     ok = check_output("./rebar compile -q", should_fail,
-                      [SharedExpected, "ERROR: "],
-                      ["WARN: ", "INFO: ", "DEBUG: "]),
+                      [SharedExpected, ERROR],
+                      [WARN, INFO, DEBUG]),
     %% fix bad app file
     ok = file:write_file(?APP_FILE, app(logging, [])),
     retest:log(info, "Check 'compile' success output~n"),
     ok = check_output("./rebar compile", should_succeed,
                       [SharedExpected],
-                      ["ERROR: ", "WARN: ", "INFO: ", "DEBUG: "]),
+                      [ERROR, WARN, INFO, DEBUG]),
     retest:log(info, "Check 'compile -v' success output~n"),
     ok = check_output("./rebar compile -v", should_succeed,
                       [SharedExpected],
-                      ["ERROR: ", "INFO: ", "DEBUG: "]),
+                      [ERROR, INFO, DEBUG]),
     retest:log(info, "Check 'compile -vv' success output~n"),
     ok = check_output("./rebar compile -vv", should_succeed,
-                      [SharedExpected, "DEBUG: "],
-                      ["ERROR: ", "INFO: "]),
+                      [SharedExpected, DEBUG],
+                      [ERROR, INFO]),
     ok.
 
+log_labels() ->
+    {
+      "(\\e\\[1m\\e\\[31mERROR: \\e\\[0m|ERROR: )",
+      "(\\e\\[33mWARN: \\e\\[0m|WARN: )",
+      "(\\e\\[32mINFO: \\e\\[0m|INFO: )",
+      "(\\e\\[34mDEBUG: \\e\\[0m|DEBUG: )"
+    }.
+
 check_output(Cmd, FailureMode, Expected, Unexpected) ->
     case {retest:sh(Cmd), FailureMode} of
         {{error, _}=Error, should_succeed} ->
@@ -73,7 +85,7 @@
     end.
 
 check_output1(Cmd, Captured, Expected, Unexpected) ->
-    ReOpts = [{capture, all, list}],
+    ReOpts = [{capture, all, list}, unicode],
     ExMatches =
         lists:zf(
           fun(Pattern) ->
diff --git a/inttest/neotoma1/mock/neotoma/priv/peg_includes.hrl b/inttest/neotoma1/mock/neotoma/priv/peg_includes.hrl
new file mode 100644
index 0000000..183b98c
--- /dev/null
+++ b/inttest/neotoma1/mock/neotoma/priv/peg_includes.hrl
@@ -0,0 +1,253 @@
+-file("peg_includes.hrl", 1).
+-type index() :: {{line, pos_integer()}, {column, pos_integer()}}.
+-type input() :: binary().
+-type parse_failure() :: {fail, term()}.
+-type parse_success() :: {term(), input(), index()}.
+-type parse_result() :: parse_failure() | parse_success().
+-type parse_fun() :: fun((input(), index()) -> parse_result()).
+-type xform_fun() :: fun((input(), index()) -> term()).
+
+-spec p(input(), index(), atom(), parse_fun(), xform_fun()) -> parse_result().
+p(Inp, StartIndex, Name, ParseFun, TransformFun) ->
+  case get_memo(StartIndex, Name) of      % See if the current reduction is memoized
+    {ok, Memo} -> %Memo;                     % If it is, return the stored result
+      Memo;
+    _ ->                                        % If not, attempt to parse
+      Result = case ParseFun(Inp, StartIndex) of
+        {fail,_} = Failure ->                       % If it fails, memoize the failure
+          Failure;
+        {Match, InpRem, NewIndex} ->               % If it passes, transform and memoize the result.
+          Transformed = TransformFun(Match, StartIndex),
+          {Transformed, InpRem, NewIndex}
+      end,
+      memoize(StartIndex, Name, Result),
+      Result
+  end.
+
+-spec setup_memo() -> ets:tid().
+setup_memo() ->
+  put({parse_memo_table, ?MODULE}, ets:new(?MODULE, [set])).
+
+-spec release_memo() -> true.
+release_memo() ->
+  ets:delete(memo_table_name()).
+
+-spec memoize(index(), atom(), parse_result()) -> true.
+memoize(Index, Name, Result) ->
+  Memo = case ets:lookup(memo_table_name(), Index) of
+              [] -> [];
+              [{Index, Plist}] -> Plist
+         end,
+  ets:insert(memo_table_name(), {Index, [{Name, Result}|Memo]}).
+
+-spec get_memo(index(), atom()) -> {ok, term()} | {error, not_found}.
+get_memo(Index, Name) ->
+  case ets:lookup(memo_table_name(), Index) of
+    [] -> {error, not_found};
+    [{Index, Plist}] ->
+      case proplists:lookup(Name, Plist) of
+        {Name, Result}  -> {ok, Result};
+        _  -> {error, not_found}
+      end
+    end.
+
+-spec memo_table_name() -> ets:tid().
+memo_table_name() ->
+    get({parse_memo_table, ?MODULE}).
+
+-ifdef(p_eof).
+-spec p_eof() -> parse_fun().
+p_eof() ->
+  fun(<<>>, Index) -> {eof, [], Index};
+     (_, Index) -> {fail, {expected, eof, Index}} end.
+-endif.
+
+-ifdef(p_optional).
+-spec p_optional(parse_fun()) -> parse_fun().
+p_optional(P) ->
+  fun(Input, Index) ->
+      case P(Input, Index) of
+        {fail,_} -> {[], Input, Index};
+        {_, _, _} = Success -> Success
+      end
+  end.
+-endif.
+
+-ifdef(p_not).
+-spec p_not(parse_fun()) -> parse_fun().
+p_not(P) ->
+  fun(Input, Index)->
+      case P(Input,Index) of
+        {fail,_} ->
+          {[], Input, Index};
+        {Result, _, _} -> {fail, {expected, {no_match, Result},Index}}
+      end
+  end.
+-endif.
+
+-ifdef(p_assert).
+-spec p_assert(parse_fun()) -> parse_fun().
+p_assert(P) ->
+  fun(Input,Index) ->
+      case P(Input,Index) of
+        {fail,_} = Failure-> Failure;
+        _ -> {[], Input, Index}
+      end
+  end.
+-endif.
+
+-ifdef(p_seq).
+-spec p_seq([parse_fun()]) -> parse_fun().
+p_seq(P) ->
+  fun(Input, Index) ->
+      p_all(P, Input, Index, [])
+  end.
+
+-spec p_all([parse_fun()], input(), index(), [term()]) -> parse_result().
+p_all([], Inp, Index, Accum ) -> {lists:reverse( Accum ), Inp, Index};
+p_all([P|Parsers], Inp, Index, Accum) ->
+  case P(Inp, Index) of
+    {fail, _} = Failure -> Failure;
+    {Result, InpRem, NewIndex} -> p_all(Parsers, InpRem, NewIndex, [Result|Accum])
+  end.
+-endif.
+
+-ifdef(p_choose).
+-spec p_choose([parse_fun()]) -> parse_fun().
+p_choose(Parsers) ->
+  fun(Input, Index) ->
+      p_attempt(Parsers, Input, Index, none)
+  end.
+
+-spec p_attempt([parse_fun()], input(), index(), none | parse_failure()) -> parse_result().
+p_attempt([], _Input, _Index, Failure) -> Failure;
+p_attempt([P|Parsers], Input, Index, FirstFailure)->
+  case P(Input, Index) of
+    {fail, _} = Failure ->
+      case FirstFailure of
+        none -> p_attempt(Parsers, Input, Index, Failure);
+        _ -> p_attempt(Parsers, Input, Index, FirstFailure)
+      end;
+    Result -> Result
+  end.
+-endif.
+
+-ifdef(p_zero_or_more).
+-spec p_zero_or_more(parse_fun()) -> parse_fun().
+p_zero_or_more(P) ->
+  fun(Input, Index) ->
+      p_scan(P, Input, Index, [])
+  end.
+-endif.
+
+-ifdef(p_one_or_more).
+-spec p_one_or_more(parse_fun()) -> parse_fun().
+p_one_or_more(P) ->
+  fun(Input, Index)->
+      Result = p_scan(P, Input, Index, []),
+      case Result of
+        {[_|_], _, _} ->
+          Result;
+        _ ->
+          {fail, {expected, Failure, _}} = P(Input,Index),
+          {fail, {expected, {at_least_one, Failure}, Index}}
+      end
+  end.
+-endif.
+
+-ifdef(p_label).
+-spec p_label(atom(), parse_fun()) -> parse_fun().
+p_label(Tag, P) ->
+  fun(Input, Index) ->
+      case P(Input, Index) of
+        {fail,_} = Failure ->
+           Failure;
+        {Result, InpRem, NewIndex} ->
+          {{Tag, Result}, InpRem, NewIndex}
+      end
+  end.
+-endif.
+
+-ifdef(p_scan).
+-spec p_scan(parse_fun(), input(), index(), [term()]) -> {[term()], input(), index()}.
+p_scan(_, <<>>, Index, Accum) -> {lists:reverse(Accum), <<>>, Index};
+p_scan(P, Inp, Index, Accum) ->
+  case P(Inp, Index) of
+    {fail,_} -> {lists:reverse(Accum), Inp, Index};
+    {Result, InpRem, NewIndex} -> p_scan(P, InpRem, NewIndex, [Result | Accum])
+  end.
+-endif.
+
+-ifdef(p_string).
+-spec p_string(binary()) -> parse_fun().
+p_string(S) ->
+    Length = erlang:byte_size(S),
+    fun(Input, Index) ->
+      try
+          <<S:Length/binary, Rest/binary>> = Input,
+          {S, Rest, p_advance_index(S, Index)}
+      catch
+          error:{badmatch,_} -> {fail, {expected, {string, S}, Index}}
+      end
+    end.
+-endif.
+
+-ifdef(p_anything).
+-spec p_anything() -> parse_fun().
+p_anything() ->
+  fun(<<>>, Index) -> {fail, {expected, any_character, Index}};
+     (Input, Index) when is_binary(Input) ->
+          <<C/utf8, Rest/binary>> = Input,
+          {<<C/utf8>>, Rest, p_advance_index(<<C/utf8>>, Index)}
+  end.
+-endif.
+
+-ifdef(p_charclass).
+-spec p_charclass(string() | binary()) -> parse_fun().
+p_charclass(Class) ->
+    {ok, RE} = re:compile(Class, [unicode, dotall]),
+    fun(Inp, Index) ->
+            case re:run(Inp, RE, [anchored]) of
+                {match, [{0, Length}|_]} ->
+                    {Head, Tail} = erlang:split_binary(Inp, Length),
+                    {Head, Tail, p_advance_index(Head, Index)};
+                _ -> {fail, {expected, {character_class, binary_to_list(Class)}, Index}}
+            end
+    end.
+-endif.
+
+-ifdef(p_regexp).
+-spec p_regexp(binary()) -> parse_fun().
+p_regexp(Regexp) ->
+    {ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]),
+    fun(Inp, Index) ->
+        case re:run(Inp, RE) of
+            {match, [{0, Length}|_]} ->
+                {Head, Tail} = erlang:split_binary(Inp, Length),
+                {Head, Tail, p_advance_index(Head, Index)};
+            _ -> {fail, {expected, {regexp, binary_to_list(Regexp)}, Index}}
+        end
+    end.
+-endif.
+
+-ifdef(line).
+-spec line(index() | term()) -> pos_integer() | undefined.
+line({{line,L},_}) -> L;
+line(_) -> undefined.
+-endif.
+
+-ifdef(column).
+-spec column(index() | term()) -> pos_integer() | undefined.
+column({_,{column,C}}) -> C;
+column(_) -> undefined.
+-endif.
+
+-spec p_advance_index(input() | unicode:charlist() | pos_integer(), index()) -> index().
+p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput)-> % strings
+  lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput));
+p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters
+  {{line, Line}, {column, Col}} = Index,
+  case MatchedInput of
+    $\n -> {{line, Line+1}, {column, 1}};
+    _ -> {{line, Line}, {column, Col+1}}
+  end.
diff --git a/inttest/neotoma1/mock/neotoma/src/neotoma.app.src b/inttest/neotoma1/mock/neotoma/src/neotoma.app.src
new file mode 100644
index 0000000..dff6cef
--- /dev/null
+++ b/inttest/neotoma1/mock/neotoma/src/neotoma.app.src
@@ -0,0 +1,10 @@
+{application, neotoma,
+ [
+  {description, "PEG/Packrat toolkit and parser-generator."},
+  {vsn, "1.7.3"},
+  {applications, [kernel, stdlib]},
+  {contributors, ["Sean Cribbs"]},
+  {licenses, ["MIT"]},
+  {links, [{"Github", "https://github.com/seancribbs/neotoma"}]}
+ ]
+}.
diff --git a/inttest/neotoma1/mock/neotoma/src/neotoma.erl b/inttest/neotoma1/mock/neotoma/src/neotoma.erl
new file mode 100644
index 0000000..f4102f6
--- /dev/null
+++ b/inttest/neotoma1/mock/neotoma/src/neotoma.erl
@@ -0,0 +1,145 @@
+-module(neotoma).
+-author("Sean Cribbs <seancribbs@gmail.com>").
+-export([file/1, file/2, bootstrap/0]).
+-export([main/1]).
+
+-define(ALL_COMBINATORS, [p_eof, p_optional, p_not, p_assert, p_seq,
+        p_choose, p_zero_or_more, p_one_or_more, p_label, p_scan,
+        p_string, p_anything, p_charclass, p_regexp, line, column]).
+
+-type option() :: {module, atom()} | {output, file:filename()} |  {transform_module, atom()} |
+                  {neotoma_priv_dir, file:filename()}.
+
+%% @doc Handler function for escript.
+-spec main(list()) -> ok | no_return().
+main([]) ->
+    io:format("Usage: neotoma filename [-module output_module] [-output output_dir] [-transform_module transform_module]\n");
+main([Filename | Args]) ->
+    %% code:priv_dir is unreliable when called in escript context, but
+    %% escript:script_name does what we want.
+    PrivDir = filename:join([filename:dirname(escript:script_name()), "priv"]),
+    file(Filename, [{neotoma_priv_dir, PrivDir} | parse_options(Args)]).
+
+%% @doc Generates a parser from the specified file.
+%% @equiv file(Filename, [])
+-spec file(file:filename()) -> ok | {error, atom()}.
+file(InputGrammar) ->
+    file(InputGrammar, []).
+
+%% @doc Generates a parser from the specified file with the given options.
+-spec file(file:filename(), [option()]) -> ok | {error, atom()}.
+file(InputGrammar, Options) ->
+    Basename = filename:basename(InputGrammar, ".peg"),
+    InputDir = filename:dirname(InputGrammar),
+    ModuleName = proplists:get_value(module, Options, list_to_atom(Basename)),
+    OutputDir = proplists:get_value(output, Options, InputDir),
+    OutputFilename = filename:join(OutputDir, atom_to_list(ModuleName) ++ ".erl"),
+    TransformModule = proplists:get_value(transform_module, Options, false),
+    validate_params(filename:absname(InputGrammar),
+                    ModuleName,
+                    TransformModule,
+                    filename:absname(OutputFilename)),
+    Parsed = parse_grammar(InputGrammar),
+    Rules = proplists:get_value(rules, Parsed),
+    Root = proplists:get_value(root, Parsed),
+    Code = proplists:get_value(code, Parsed),
+    GenTransform = proplists:get_value(transform, Parsed),
+    Combinators = proplists:get_value(combinators, Parsed, ?ALL_COMBINATORS),
+    ModuleAttrs = generate_module_attrs(ModuleName, Combinators),
+    EntryFuns = generate_entry_functions(Root),
+    TransformFun = create_transform(TransformModule, OutputDir, GenTransform),
+    PrivDir = proplists:get_value(neotoma_priv_dir, Options, code:priv_dir(neotoma)),
+    {ok, PegIncludes} = file:read_file(filename:join([PrivDir, "peg_includes.hrl"])),
+    file:write_file(OutputFilename, [ModuleAttrs, "\n", Code, "\n", EntryFuns, "\n", Rules, "\n", TransformFun, "\n", PegIncludes]).
+
+-spec validate_params(file:filename(),atom(),atom(),file:filename()) -> 'ok'.
+validate_params(InputGrammar, _, _, OutputFile) when InputGrammar =:= OutputFile ->
+    throw({badarg, "Input and output file are the same!"});
+validate_params(_,_, false, _) -> ok;
+validate_params(_,_, TransformModule, _) when not is_atom(TransformModule) ->
+    throw({badarg, "transform_module option must be an atom"});
+validate_params(_,Basename, TransformModule, _) when Basename =:= TransformModule ->
+    throw({badarg, "Transform module named same as parser module!"});
+validate_params(_,_, TransformModule, OutputFile) ->
+    OutMod = list_to_atom(filename:basename(OutputFile, ".erl")),
+    case OutMod of
+        TransformModule -> throw({badarg, "Transform module file same as parser output file!"});
+        _ -> ok
+    end.
+
+-spec generate_module_attrs(atom(), [atom()]) -> iolist().
+generate_module_attrs(ModName, Combinators) ->
+    ["-module(", atom_to_list(ModName) ,").\n",
+     "-export([parse/1,file/1]).\n",
+     [ generate_combinator_macro(C) || Combinators /= undefined, C <- Combinators ],
+     "\n"
+     ].
+
+generate_combinator_macro(C) ->
+    ["-define(", atom_to_list(C), ",true).\n"].
+
+-spec generate_entry_functions({iodata(),_}) -> iolist().
+generate_entry_functions(Root) ->
+    {RootRule,_} = Root,
+     ["-spec file(file:name()) -> any().\n",
+     "file(Filename) -> case file:read_file(Filename) of {ok,Bin} -> parse(Bin); Err -> Err end.\n\n",
+     "-spec parse(binary() | list()) -> any().\n",
+     "parse(List) when is_list(List) -> parse(unicode:characters_to_binary(List));\n",
+     "parse(Input) when is_binary(Input) ->\n",
+     "  _ = setup_memo(),\n",
+     "  Result = case '",RootRule,"'(Input,{{line,1},{column,1}}) of\n",
+     "             {AST, <<>>, _Index} -> AST;\n",
+     "             Any -> Any\n"
+     "           end,\n",
+     "  release_memo(), Result.\n"].
+
+-spec parse_grammar(file:filename()) -> any().
+parse_grammar(InputFile) ->
+    case neotoma_parse:file(InputFile) of
+        {fail, Index} ->
+            throw({grammar_error, {fail, Index}});
+        {Parsed, Remainder, Index} ->
+            io:format("WARNING: Grammar parse ended unexpectedly at ~p, generated parser may be incorrect.~nRemainder:~n~p",
+                      [Index, Remainder]),
+            Parsed;
+        L when is_list(L) -> L;
+        _ -> throw({error, {unknown, grammar, InputFile}})
+    end.
+
+-spec create_transform(atom() | boolean(),file:filename(),_) -> iolist().
+create_transform(_,_,[]) -> [];
+create_transform(false,_,_) ->
+    "transform(_,Node,_Index) -> Node.";
+create_transform(ModName,Dir,_) when is_atom(ModName) ->
+    XfFile = filename:join(Dir, atom_to_list(ModName) ++ ".erl"),
+    case filelib:is_regular(XfFile) of
+        true -> io:format("'~s' already exists, skipping generation.~n", [XfFile]);
+        false -> generate_transform_stub(XfFile, ModName)
+    end,
+    ["transform(Symbol,Node,Index) -> ",atom_to_list(ModName),":transform(Symbol, Node, Index)."].
+
+-spec generate_transform_stub(file:filename(), atom()) -> 'ok' | {'error',atom()}.
+generate_transform_stub(XfFile,ModName) ->
+    Data = ["-module(",atom_to_list(ModName),").\n",
+            "-export([transform/3]).\n\n",
+            "%% Add clauses to this function to transform syntax nodes\n",
+            "%% from the parser into semantic output.\n",
+            "transform(Symbol, Node, _Index) when is_atom(Symbol) ->\n  Node."],
+    file:write_file(XfFile, Data).
+
+%% @doc Bootstraps the neotoma metagrammar.  Intended only for internal development!
+%% @equiv file("src/neotoma_parse.peg")
+-spec bootstrap() -> 'ok'.
+bootstrap() ->
+    file("priv/neotoma_parse.peg", [{output, "src/"}, {neotoma_priv_dir, "priv"}]).
+
+%% @doc Parses arguments passed to escript
+-spec parse_options(list()) -> list().
+parse_options(["-module", ModName | Rest]) ->
+    [{module, list_to_atom(ModName)} | parse_options(Rest)];
+parse_options(["-output", Dir | Rest]) ->
+    [{output, Dir} | parse_options(Rest)];
+parse_options(["-transform_module", ModName | Rest]) ->
+    [{transform_module, list_to_atom(ModName)} | parse_options(Rest)];
+parse_options([]) ->
+    [].
diff --git a/inttest/neotoma1/mock/neotoma/src/neotoma_parse.erl b/inttest/neotoma1/mock/neotoma/src/neotoma_parse.erl
new file mode 100644
index 0000000..1bffaf8
--- /dev/null
+++ b/inttest/neotoma1/mock/neotoma/src/neotoma_parse.erl
@@ -0,0 +1,625 @@
+-module(neotoma_parse).
+-export([parse/1,file/1]).
+-define(p_anything,true).
+-define(p_charclass,true).
+-define(p_choose,true).
+-define(p_label,true).
+-define(p_not,true).
+-define(p_one_or_more,true).
+-define(p_optional,true).
+-define(p_scan,true).
+-define(p_seq,true).
+-define(p_string,true).
+-define(p_zero_or_more,true).
+
+
+
+% insert escapes into a string
+-spec escape_string(string()) -> string().
+escape_string(String) -> escape_string(String, []).
+
+-spec escape_string(string(), string()) -> string().
+escape_string([], Output) ->
+  lists:reverse(Output);
+escape_string([H|T], Output) ->
+  escape_string(T,
+    case H of
+        $/  -> [$/,$\\|Output];
+        $\" -> [$\",$\\|Output];     % " comment inserted to help some editors with highlighting the generated parser
+        $\' -> [$\',$\\|Output];     % ' comment inserted to help some editors with highlighting the generated parser
+        $\b -> [$b,$\\|Output];
+        $\d -> [$d,$\\|Output];
+        $\e -> [$e,$\\|Output];
+        $\f -> [$f,$\\|Output];
+        $\n -> [$n,$\\|Output];
+        $\r -> [$r,$\\|Output];
+        $\s -> [$s,$\\|Output];
+        $\t -> [$t,$\\|Output];
+        $\v -> [$v,$\\|Output];
+        _   -> [H|Output]
+    end).
+
+-spec add_lhs(binary(), index()) -> true.
+add_lhs(Symbol, Index) ->
+  case ets:lookup(memo_table_name(), lhs) of
+    [] ->
+      ets:insert(memo_table_name(), {lhs, [{Symbol,Index}]});
+    [{lhs, L}] when is_list(L) ->
+      ets:insert(memo_table_name(), {lhs, [{Symbol,Index}|L]})
+  end.
+
+-spec add_nt(binary(), index()) -> true | ok.
+add_nt(Symbol, Index) ->
+  case ets:lookup(memo_table_name(), nts) of
+    [] ->
+      ets:insert(memo_table_name(), {nts, [{Symbol,Index}]});
+    [{nts, L}] when is_list(L) ->
+      case proplists:is_defined(Symbol, L) of
+        true ->
+          ok;
+        _ ->
+          ets:insert(memo_table_name(), {nts, [{Symbol,Index}|L]})
+      end
+  end.
+
+-spec verify_rules() -> ok | no_return().
+verify_rules() ->
+  [{lhs, LHS}] = ets:lookup(memo_table_name(), lhs),
+  [{nts, NTs}] = ets:lookup(memo_table_name(), nts),
+  [Root|NonRoots] = lists:reverse(LHS),
+  lists:foreach(fun({Sym,Idx}) ->
+                    case proplists:is_defined(Sym, NTs) of
+                      true ->
+                        ok;
+                      _ ->
+                        io:format("neotoma warning: rule '~s' is unused. ~p~n", [Sym,Idx])
+                    end
+                end, NonRoots),
+  lists:foreach(fun({S,I}) ->
+                    case proplists:is_defined(S, LHS) of
+                      true ->
+                        ok;
+                      _ ->
+                        io:format("neotoma error: nonterminal '~s' has no reduction. (found at ~p) No parser will be generated!~n", [S,I]),
+                        exit({neotoma, {no_reduction, list_to_atom(binary_to_list(S))}})
+                    end
+                end, NTs),
+    Root.
+
+-spec used_combinator(atom()) -> true.
+used_combinator(C) ->
+    case ets:lookup(memo_table_name(), combinators) of
+        [] ->
+            ets:insert(memo_table_name(), {combinators, ordsets:from_list([C])});
+        [{combinators, Cs}] ->
+            ets:insert(memo_table_name(), {combinators, ordsets:add_element(C, Cs)})
+    end.
+
+-spec used_transform_variables(binary()) -> [ 'Node' | 'Idx' ].
+used_transform_variables(Transform) ->
+  Code = unicode:characters_to_list(Transform),
+  {ok, Tokens, _} = erl_scan:string(Code),
+  used_transform_variables(Tokens, []).
+
+used_transform_variables([{var, _, Name}|Tokens], Acc) ->
+  used_transform_variables(Tokens, case Name of
+                                    'Node' -> [Name | Acc];
+                                    'Idx'  -> [Name | Acc];
+                                    _      -> Acc
+                                  end);
+used_transform_variables([_|Tokens], Acc) ->
+  used_transform_variables(Tokens, Acc);
+used_transform_variables([], Acc) ->
+  lists:usort(Acc).
+
+-spec file(file:name()) -> any().
+file(Filename) -> case file:read_file(Filename) of {ok,Bin} -> parse(Bin); Err -> Err end.
+
+-spec parse(binary() | list()) -> any().
+parse(List) when is_list(List) -> parse(unicode:characters_to_binary(List));
+parse(Input) when is_binary(Input) ->
+  _ = setup_memo(),
+  Result = case 'rules'(Input,{{line,1},{column,1}}) of
+             {AST, <<>>, _Index} -> AST;
+             Any -> Any
+           end,
+  release_memo(), Result.
+
+-spec 'rules'(input(), index()) -> parse_result().
+'rules'(Input, Index) ->
+  p(Input, Index, 'rules', fun(I,D) -> (p_seq([p_optional(fun 'space'/2), fun 'declaration_sequence'/2, p_optional(fun 'space'/2), p_optional(fun 'code_block'/2), p_optional(fun 'space'/2)]))(I,D) end, fun(Node, _Idx) ->
+  RootRule = verify_rules(),
+  Rules = unicode:characters_to_binary(lists:map(fun(R) -> [R, "\n\n"] end, lists:nth(2, Node))),
+  Code = case lists:nth(4, Node) of
+             {code, Block} -> Block;
+             _ -> []
+         end,
+  [{rules, Rules},
+   {code, Code},
+   {root, RootRule},
+   {transform, ets:lookup(memo_table_name(),gen_transform)},
+   {combinators, ets:lookup_element(memo_table_name(), combinators, 2)}]
+
+ end).
+
+-spec 'declaration_sequence'(input(), index()) -> parse_result().
+'declaration_sequence'(Input, Index) ->
+  p(Input, Index, 'declaration_sequence', fun(I,D) -> (p_seq([p_label('head', fun 'declaration'/2), p_label('tail', p_zero_or_more(p_seq([fun 'space'/2, fun 'declaration'/2])))]))(I,D) end, fun(Node, _Idx) ->
+  FirstRule = proplists:get_value(head, Node),
+  OtherRules =  [I || [_,I] <- proplists:get_value(tail, Node, [])],
+  [FirstRule|OtherRules]
+ end).
+
+-spec 'declaration'(input(), index()) -> parse_result().
+'declaration'(Input, Index) ->
+  p(Input, Index, 'declaration', fun(I,D) -> (p_seq([fun 'nonterminal'/2, p_zero_or_more(fun 'space'/2), p_string(<<"<-">>), p_zero_or_more(fun 'space'/2), fun 'parsing_expression'/2, p_optional(fun 'space'/2), p_optional(fun 'code_block'/2), p_optional(fun 'space'/2), p_string(<<";">>)]))(I,D) end, fun(Node, _Idx) ->
+  [{nonterminal,Symbol}|Tail] = Node,
+  add_lhs(Symbol, Index),
+  Transform = case lists:nth(6,Tail) of
+                  {code, CodeBlock} -> CodeBlock;
+                  _ ->
+                      ets:insert_new(memo_table_name(),{gen_transform, true}),
+                      ["transform('",Symbol,"', Node, Idx)"]
+                  end,
+  TransformArgs = case used_transform_variables(Transform) of
+    []              -> "_Node, _Idx";
+    ['Idx']         -> "_Node, Idx";
+    ['Node']        -> "Node, _Idx";
+    ['Idx', 'Node'] -> "Node, Idx"
+  end,
+  ["-spec '", Symbol, "'(input(), index()) -> parse_result().\n",
+   "'",Symbol,"'","(Input, Index) ->\n  ",
+        "p(Input, Index, '",Symbol,"', fun(I,D) -> (",
+        lists:nth(4, Tail),
+        ")(I,D) end, fun(", TransformArgs, ") ->",Transform," end)."]
+ end).
+
+-spec 'parsing_expression'(input(), index()) -> parse_result().
+'parsing_expression'(Input, Index) ->
+  p(Input, Index, 'parsing_expression', fun(I,D) -> (p_choose([fun 'choice'/2, fun 'sequence'/2, fun 'primary'/2]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'choice'(input(), index()) -> parse_result().
+'choice'(Input, Index) ->
+  p(Input, Index, 'choice', fun(I,D) -> (p_seq([p_label('head', fun 'alternative'/2), p_label('tail', p_one_or_more(p_seq([fun 'space'/2, p_string(<<"\/">>), fun 'space'/2, fun 'alternative'/2])))]))(I,D) end, fun(Node, _Idx) ->
+  Tail = [lists:last(S) || S <- proplists:get_value(tail, Node)],
+  Head = proplists:get_value(head, Node),
+  Statements = [[", ", TS] ||  TS <- Tail],
+  used_combinator(p_choose),
+  ["p_choose([", Head, Statements, "])"]
+ end).
+
+-spec 'alternative'(input(), index()) -> parse_result().
+'alternative'(Input, Index) ->
+  p(Input, Index, 'alternative', fun(I,D) -> (p_choose([fun 'sequence'/2, fun 'labeled_primary'/2]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'primary'(input(), index()) -> parse_result().
+'primary'(Input, Index) ->
+  p(Input, Index, 'primary', fun(I,D) -> (p_choose([p_seq([fun 'prefix'/2, fun 'atomic'/2]), p_seq([fun 'atomic'/2, fun 'suffix'/2]), fun 'atomic'/2]))(I,D) end, fun(Node, _Idx) ->
+case Node of
+  [Atomic, one_or_more] ->
+        used_combinator(p_one_or_more),
+        used_combinator(p_scan),
+        ["p_one_or_more(", Atomic, ")"];
+  [Atomic, zero_or_more] ->
+        used_combinator(p_zero_or_more),
+        used_combinator(p_scan),
+        ["p_zero_or_more(", Atomic, ")"];
+  [Atomic, optional] ->
+        used_combinator(p_optional),
+        ["p_optional(", Atomic, ")"];
+  [assert, Atomic] ->
+        used_combinator(p_assert),
+        ["p_assert(", Atomic, ")"];
+  [not_, Atomic] ->
+        used_combinator(p_not),
+        ["p_not(", Atomic, ")"];
+  _ -> Node
+end
+ end).
+
+-spec 'sequence'(input(), index()) -> parse_result().
+'sequence'(Input, Index) ->
+  p(Input, Index, 'sequence', fun(I,D) -> (p_seq([p_label('head', fun 'labeled_primary'/2), p_label('tail', p_one_or_more(p_seq([fun 'space'/2, fun 'labeled_primary'/2])))]))(I,D) end, fun(Node, _Idx) ->
+  Tail = [lists:nth(2, S) || S <- proplists:get_value(tail, Node)],
+  Head = proplists:get_value(head, Node),
+  Statements = [[", ", TS] || TS <- Tail],
+  used_combinator(p_seq),
+  ["p_seq([", Head, Statements, "])"]
+ end).
+
+-spec 'labeled_primary'(input(), index()) -> parse_result().
+'labeled_primary'(Input, Index) ->
+  p(Input, Index, 'labeled_primary', fun(I,D) -> (p_seq([p_optional(fun 'label'/2), fun 'primary'/2]))(I,D) end, fun(Node, _Idx) ->
+  case hd(Node) of
+    [] -> lists:nth(2, Node);
+    Label ->
+          used_combinator(p_label),
+          ["p_label('",  Label, "', ", lists:nth(2, Node), ")"]
+  end
+ end).
+
+-spec 'label'(input(), index()) -> parse_result().
+'label'(Input, Index) ->
+  p(Input, Index, 'label', fun(I,D) -> (p_seq([fun 'alpha_char'/2, p_zero_or_more(fun 'alphanumeric_char'/2), p_string(<<":">>)]))(I,D) end, fun(Node, _Idx) ->
+  lists:sublist(Node, length(Node)-1)
+ end).
+
+-spec 'suffix'(input(), index()) -> parse_result().
+'suffix'(Input, Index) ->
+  p(Input, Index, 'suffix', fun(I,D) -> (p_choose([fun 'repetition_suffix'/2, fun 'optional_suffix'/2]))(I,D) end, fun(Node, _Idx) ->
+  case Node of
+    <<"*">> -> zero_or_more;
+    <<"+">> -> one_or_more;
+    <<"?">> -> optional
+  end
+ end).
+
+-spec 'optional_suffix'(input(), index()) -> parse_result().
+'optional_suffix'(Input, Index) ->
+  p(Input, Index, 'optional_suffix', fun(I,D) -> (p_string(<<"?">>))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'repetition_suffix'(input(), index()) -> parse_result().
+'repetition_suffix'(Input, Index) ->
+  p(Input, Index, 'repetition_suffix', fun(I,D) -> (p_choose([p_string(<<"+">>), p_string(<<"*">>)]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'prefix'(input(), index()) -> parse_result().
+'prefix'(Input, Index) ->
+  p(Input, Index, 'prefix', fun(I,D) -> (p_choose([p_string(<<"&">>), p_string(<<"!">>)]))(I,D) end, fun(Node, _Idx) ->
+  case Node of
+    <<"&">> -> assert;
+    <<"!">> -> not_
+  end
+ end).
+
+-spec 'atomic'(input(), index()) -> parse_result().
+'atomic'(Input, Index) ->
+  p(Input, Index, 'atomic', fun(I,D) -> (p_choose([fun 'terminal'/2, fun 'nonterminal'/2, fun 'parenthesized_expression'/2]))(I,D) end, fun(Node, _Idx) ->
+case Node of
+  {nonterminal, Symbol} ->
+                [<<"fun '">>, Symbol, <<"'/2">>];
+  _ -> Node
+end
+ end).
+
+-spec 'parenthesized_expression'(input(), index()) -> parse_result().
+'parenthesized_expression'(Input, Index) ->
+  p(Input, Index, 'parenthesized_expression', fun(I,D) -> (p_seq([p_string(<<"(">>), p_optional(fun 'space'/2), fun 'parsing_expression'/2, p_optional(fun 'space'/2), p_string(<<")">>)]))(I,D) end, fun(Node, _Idx) ->lists:nth(3, Node) end).
+
+-spec 'nonterminal'(input(), index()) -> parse_result().
+'nonterminal'(Input, Index) ->
+  p(Input, Index, 'nonterminal', fun(I,D) -> (p_seq([fun 'alpha_char'/2, p_zero_or_more(fun 'alphanumeric_char'/2)]))(I,D) end, fun(Node, Idx) ->
+  Symbol = unicode:characters_to_binary(Node),
+  add_nt(Symbol, Idx),
+  {nonterminal, Symbol}
+ end).
+
+-spec 'terminal'(input(), index()) -> parse_result().
+'terminal'(Input, Index) ->
+  p(Input, Index, 'terminal', fun(I,D) -> (p_choose([fun 'regexp_string'/2, fun 'quoted_string'/2, fun 'character_class'/2, fun 'anything_symbol'/2]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'regexp_string'(input(), index()) -> parse_result().
+'regexp_string'(Input, Index) ->
+  p(Input, Index, 'regexp_string', fun(I,D) -> (p_seq([p_string(<<"#">>), p_label('string', p_one_or_more(p_seq([p_not(p_string(<<"#">>)), p_choose([p_string(<<"\\#">>), p_anything()])]))), p_string(<<"#">>)]))(I,D) end, fun(Node, _Idx) ->
+  used_combinator(p_regexp),
+  ["p_regexp(<<\"",
+	% Escape \ and " as they are used in erlang string. Other sumbol stay as is.
+	%  \ -> \\
+	%  " -> \"
+   re:replace(proplists:get_value(string, Node), "\"|\\\\", "\\\\&", [{return, binary}, global]),
+   "\">>)"]
+ end).
+
+-spec 'quoted_string'(input(), index()) -> parse_result().
+'quoted_string'(Input, Index) ->
+  p(Input, Index, 'quoted_string', fun(I,D) -> (p_choose([fun 'single_quoted_string'/2, fun 'double_quoted_string'/2]))(I,D) end, fun(Node, _Idx) ->
+  used_combinator(p_string),
+  lists:flatten(["p_string(<<\"",
+   escape_string(unicode:characters_to_list(proplists:get_value(string, Node))),
+   "\">>)"])
+ end).
+
+-spec 'double_quoted_string'(input(), index()) -> parse_result().
+'double_quoted_string'(Input, Index) ->
+  p(Input, Index, 'double_quoted_string', fun(I,D) -> (p_seq([p_string(<<"\"">>), p_label('string', p_zero_or_more(p_seq([p_not(p_string(<<"\"">>)), p_choose([p_string(<<"\\\\">>), p_string(<<"\\\"">>), p_anything()])]))), p_string(<<"\"">>)]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'single_quoted_string'(input(), index()) -> parse_result().
+'single_quoted_string'(Input, Index) ->
+  p(Input, Index, 'single_quoted_string', fun(I,D) -> (p_seq([p_string(<<"\'">>), p_label('string', p_zero_or_more(p_seq([p_not(p_string(<<"\'">>)), p_choose([p_string(<<"\\\\">>), p_string(<<"\\\'">>), p_anything()])]))), p_string(<<"\'">>)]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'character_class'(input(), index()) -> parse_result().
+'character_class'(Input, Index) ->
+  p(Input, Index, 'character_class', fun(I,D) -> (p_seq([p_string(<<"[">>), p_label('characters', p_one_or_more(p_seq([p_not(p_string(<<"]">>)), p_choose([p_seq([p_string(<<"\\\\">>), p_anything()]), p_seq([p_not(p_string(<<"\\\\">>)), p_anything()])])]))), p_string(<<"]">>)]))(I,D) end, fun(Node, _Idx) ->
+  used_combinator(p_charclass),
+  ["p_charclass(<<\"[",
+   escape_string(unicode:characters_to_list(proplists:get_value(characters, Node))),
+   "]\">>)"]
+ end).
+
+-spec 'anything_symbol'(input(), index()) -> parse_result().
+'anything_symbol'(Input, Index) ->
+  p(Input, Index, 'anything_symbol', fun(I,D) -> (p_string(<<".">>))(I,D) end, fun(_Node, _Idx) -> used_combinator(p_anything), <<"p_anything()">>  end).
+
+-spec 'alpha_char'(input(), index()) -> parse_result().
+'alpha_char'(Input, Index) ->
+  p(Input, Index, 'alpha_char', fun(I,D) -> (p_charclass(<<"[A-Za-z_]">>))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'alphanumeric_char'(input(), index()) -> parse_result().
+'alphanumeric_char'(Input, Index) ->
+  p(Input, Index, 'alphanumeric_char', fun(I,D) -> (p_choose([fun 'alpha_char'/2, p_charclass(<<"[0-9]">>)]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'space'(input(), index()) -> parse_result().
+'space'(Input, Index) ->
+  p(Input, Index, 'space', fun(I,D) -> (p_one_or_more(p_choose([fun 'white'/2, fun 'comment_to_eol'/2])))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'comment_to_eol'(input(), index()) -> parse_result().
+'comment_to_eol'(Input, Index) ->
+  p(Input, Index, 'comment_to_eol', fun(I,D) -> (p_seq([p_not(p_string(<<"%{">>)), p_string(<<"%">>), p_zero_or_more(p_seq([p_not(p_string(<<"\n">>)), p_anything()]))]))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'white'(input(), index()) -> parse_result().
+'white'(Input, Index) ->
+  p(Input, Index, 'white', fun(I,D) -> (p_charclass(<<"[\s\t\n\r]">>))(I,D) end, fun(Node, _Idx) ->Node end).
+
+-spec 'code_block'(input(), index()) -> parse_result().
+'code_block'(Input, Index) ->
+  p(Input, Index, 'code_block', fun(I,D) -> (p_choose([p_seq([p_string(<<"%{">>), p_label('code', p_one_or_more(p_choose([p_string(<<"\\%">>), p_string(<<"$%">>), p_seq([p_not(p_string(<<"%}">>)), p_anything()])]))), p_string(<<"%}">>)]), p_seq([p_string(<<"`">>), p_label('code', p_one_or_more(p_choose([p_string(<<"\\`">>), p_string(<<"$`">>), p_seq([p_not(p_string(<<"`">>)), p_anything()])]))), p_string(<<"`">>)]), p_string(<<"~">>)]))(I,D) end, fun(Node, _Idx) ->
+   case Node of
+       <<"~">> -> {code, <<"Node">>};
+       _   -> {code, proplists:get_value('code', Node)}
+   end
+ end).
+
+
+
+-file("peg_includes.hrl", 1).
+-type index() :: {{line, pos_integer()}, {column, pos_integer()}}.
+-type input() :: binary().
+-type parse_failure() :: {fail, term()}.
+-type parse_success() :: {term(), input(), index()}.
+-type parse_result() :: parse_failure() | parse_success().
+-type parse_fun() :: fun((input(), index()) -> parse_result()).
+-type xform_fun() :: fun((input(), index()) -> term()).
+
+-spec p(input(), index(), atom(), parse_fun(), xform_fun()) -> parse_result().
+p(Inp, StartIndex, Name, ParseFun, TransformFun) ->
+  case get_memo(StartIndex, Name) of      % See if the current reduction is memoized
+    {ok, Memo} -> %Memo;                     % If it is, return the stored result
+      Memo;
+    _ ->                                        % If not, attempt to parse
+      Result = case ParseFun(Inp, StartIndex) of
+        {fail,_} = Failure ->                       % If it fails, memoize the failure
+          Failure;
+        {Match, InpRem, NewIndex} ->               % If it passes, transform and memoize the result.
+          Transformed = TransformFun(Match, StartIndex),
+          {Transformed, InpRem, NewIndex}
+      end,
+      memoize(StartIndex, Name, Result),
+      Result
+  end.
+
+-spec setup_memo() -> ets:tid().
+setup_memo() ->
+  put({parse_memo_table, ?MODULE}, ets:new(?MODULE, [set])).
+
+-spec release_memo() -> true.
+release_memo() ->
+  ets:delete(memo_table_name()).
+
+-spec memoize(index(), atom(), parse_result()) -> true.
+memoize(Index, Name, Result) ->
+  Memo = case ets:lookup(memo_table_name(), Index) of
+              [] -> [];
+              [{Index, Plist}] -> Plist
+         end,
+  ets:insert(memo_table_name(), {Index, [{Name, Result}|Memo]}).
+
+-spec get_memo(index(), atom()) -> {ok, term()} | {error, not_found}.
+get_memo(Index, Name) ->
+  case ets:lookup(memo_table_name(), Index) of
+    [] -> {error, not_found};
+    [{Index, Plist}] ->
+      case proplists:lookup(Name, Plist) of
+        {Name, Result}  -> {ok, Result};
+        _  -> {error, not_found}
+      end
+    end.
+
+-spec memo_table_name() -> ets:tid().
+memo_table_name() ->
+    get({parse_memo_table, ?MODULE}).
+
+-ifdef(p_eof).
+-spec p_eof() -> parse_fun().
+p_eof() ->
+  fun(<<>>, Index) -> {eof, [], Index};
+     (_, Index) -> {fail, {expected, eof, Index}} end.
+-endif.
+
+-ifdef(p_optional).
+-spec p_optional(parse_fun()) -> parse_fun().
+p_optional(P) ->
+  fun(Input, Index) ->
+      case P(Input, Index) of
+        {fail,_} -> {[], Input, Index};
+        {_, _, _} = Success -> Success
+      end
+  end.
+-endif.
+
+-ifdef(p_not).
+-spec p_not(parse_fun()) -> parse_fun().
+p_not(P) ->
+  fun(Input, Index)->
+      case P(Input,Index) of
+        {fail,_} ->
+          {[], Input, Index};
+        {Result, _, _} -> {fail, {expected, {no_match, Result},Index}}
+      end
+  end.
+-endif.
+
+-ifdef(p_assert).
+-spec p_assert(parse_fun()) -> parse_fun().
+p_assert(P) ->
+  fun(Input,Index) ->
+      case P(Input,Index) of
+        {fail,_} = Failure-> Failure;
+        _ -> {[], Input, Index}
+      end
+  end.
+-endif.
+
+-ifdef(p_seq).
+-spec p_seq([parse_fun()]) -> parse_fun().
+p_seq(P) ->
+  fun(Input, Index) ->
+      p_all(P, Input, Index, [])
+  end.
+
+-spec p_all([parse_fun()], input(), index(), [term()]) -> parse_result().
+p_all([], Inp, Index, Accum ) -> {lists:reverse( Accum ), Inp, Index};
+p_all([P|Parsers], Inp, Index, Accum) ->
+  case P(Inp, Index) of
+    {fail, _} = Failure -> Failure;
+    {Result, InpRem, NewIndex} -> p_all(Parsers, InpRem, NewIndex, [Result|Accum])
+  end.
+-endif.
+
+-ifdef(p_choose).
+-spec p_choose([parse_fun()]) -> parse_fun().
+p_choose(Parsers) ->
+  fun(Input, Index) ->
+      p_attempt(Parsers, Input, Index, none)
+  end.
+
+-spec p_attempt([parse_fun()], input(), index(), none | parse_failure()) -> parse_result().
+p_attempt([], _Input, _Index, Failure) -> Failure;
+p_attempt([P|Parsers], Input, Index, FirstFailure)->
+  case P(Input, Index) of
+    {fail, _} = Failure ->
+      case FirstFailure of
+        none -> p_attempt(Parsers, Input, Index, Failure);
+        _ -> p_attempt(Parsers, Input, Index, FirstFailure)
+      end;
+    Result -> Result
+  end.
+-endif.
+
+-ifdef(p_zero_or_more).
+-spec p_zero_or_more(parse_fun()) -> parse_fun().
+p_zero_or_more(P) ->
+  fun(Input, Index) ->
+      p_scan(P, Input, Index, [])
+  end.
+-endif.
+
+-ifdef(p_one_or_more).
+-spec p_one_or_more(parse_fun()) -> parse_fun().
+p_one_or_more(P) ->
+  fun(Input, Index)->
+      Result = p_scan(P, Input, Index, []),
+      case Result of
+        {[_|_], _, _} ->
+          Result;
+        _ ->
+          {fail, {expected, Failure, _}} = P(Input,Index),
+          {fail, {expected, {at_least_one, Failure}, Index}}
+      end
+  end.
+-endif.
+
+-ifdef(p_label).
+-spec p_label(atom(), parse_fun()) -> parse_fun().
+p_label(Tag, P) ->
+  fun(Input, Index) ->
+      case P(Input, Index) of
+        {fail,_} = Failure ->
+           Failure;
+        {Result, InpRem, NewIndex} ->
+          {{Tag, Result}, InpRem, NewIndex}
+      end
+  end.
+-endif.
+
+-ifdef(p_scan).
+-spec p_scan(parse_fun(), input(), index(), [term()]) -> {[term()], input(), index()}.
+p_scan(_, <<>>, Index, Accum) -> {lists:reverse(Accum), <<>>, Index};
+p_scan(P, Inp, Index, Accum) ->
+  case P(Inp, Index) of
+    {fail,_} -> {lists:reverse(Accum), Inp, Index};
+    {Result, InpRem, NewIndex} -> p_scan(P, InpRem, NewIndex, [Result | Accum])
+  end.
+-endif.
+
+-ifdef(p_string).
+-spec p_string(binary()) -> parse_fun().
+p_string(S) ->
+    Length = erlang:byte_size(S),
+    fun(Input, Index) ->
+      try
+          <<S:Length/binary, Rest/binary>> = Input,
+          {S, Rest, p_advance_index(S, Index)}
+      catch
+          error:{badmatch,_} -> {fail, {expected, {string, S}, Index}}
+      end
+    end.
+-endif.
+
+-ifdef(p_anything).
+-spec p_anything() -> parse_fun().
+p_anything() ->
+  fun(<<>>, Index) -> {fail, {expected, any_character, Index}};
+     (Input, Index) when is_binary(Input) ->
+          <<C/utf8, Rest/binary>> = Input,
+          {<<C/utf8>>, Rest, p_advance_index(<<C/utf8>>, Index)}
+  end.
+-endif.
+
+-ifdef(p_charclass).
+-spec p_charclass(string() | binary()) -> parse_fun().
+p_charclass(Class) ->
+    {ok, RE} = re:compile(Class, [unicode, dotall]),
+    fun(Inp, Index) ->
+            case re:run(Inp, RE, [anchored]) of
+                {match, [{0, Length}|_]} ->
+                    {Head, Tail} = erlang:split_binary(Inp, Length),
+                    {Head, Tail, p_advance_index(Head, Index)};
+                _ -> {fail, {expected, {character_class, binary_to_list(Class)}, Index}}
+            end
+    end.
+-endif.
+
+-ifdef(p_regexp).
+-spec p_regexp(binary()) -> parse_fun().
+p_regexp(Regexp) ->
+    {ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]),
+    fun(Inp, Index) ->
+        case re:run(Inp, RE) of
+            {match, [{0, Length}|_]} ->
+                {Head, Tail} = erlang:split_binary(Inp, Length),
+                {Head, Tail, p_advance_index(Head, Index)};
+            _ -> {fail, {expected, {regexp, binary_to_list(Regexp)}, Index}}
+        end
+    end.
+-endif.
+
+-ifdef(line).
+-spec line(index() | term()) -> pos_integer() | undefined.
+line({{line,L},_}) -> L;
+line(_) -> undefined.
+-endif.
+
+-ifdef(column).
+-spec column(index() | term()) -> pos_integer() | undefined.
+column({_,{column,C}}) -> C;
+column(_) -> undefined.
+-endif.
+
+-spec p_advance_index(input() | unicode:charlist() | pos_integer(), index()) -> index().
+p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput)-> % strings
+  lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput));
+p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters
+  {{line, Line}, {column, Col}} = Index,
+  case MatchedInput of
+    $\n -> {{line, Line+1}, {column, 1}};
+    _ -> {{line, Line}, {column, Col+1}}
+  end.
diff --git a/inttest/neotoma1/neotoma_src_rt.erl b/inttest/neotoma1/neotoma_src_rt.erl
new file mode 100644
index 0000000..568bc31
--- /dev/null
+++ b/inttest/neotoma1/neotoma_src_rt.erl
@@ -0,0 +1,81 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+%% -------------------------------------------------------------------
+%%
+%% rebar: Erlang Build Tools
+%%
+%% Copyright (c) 2015 Luis Rascao (luis.rascao@gmail.com)
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+%% -------------------------------------------------------------------
+-module(neotoma_src_rt).
+
+-export([files/0, run/1]).
+
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("deps/retest/include/retest.hrl").
+
+-define(GENERATED_MODULES,
+        [csv_peg]).
+
+files() ->
+    [{copy, "../../rebar", "rebar"},
+     {copy, "rebar.config", "rebar.config"},
+     {copy, "mock", "deps"},
+     {copy, "src", "src"}].
+
+run(Dir) ->
+    retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
+    ?assertMatch({ok, _}, retest:sh("./rebar compile",
+                                    [{async, false}])),
+
+    ok = check_files_generated(),
+
+    retest_log:log(debug, "Verify cleanup~n", []),
+    ?assertMatch({ok, _}, retest_sh:run("./rebar clean",
+                                        [])),
+    ok = check_files_deleted(),
+    ok.
+
+check_files_generated() ->
+    check(fun filelib:is_regular/1,
+          generated_erl_files()).
+
+check_files_deleted() ->
+    check(fun file_does_not_exist/1,
+          generated_erl_files()).
+
+generated_erl_files() ->
+    add_dir("src", add_ext(?GENERATED_MODULES, ".erl")).
+
+add_ext(Modules, Ext) ->
+    [lists:concat([Module, Ext]) || Module <- Modules].
+
+add_dir(Dir, Files) ->
+    [filename:join(Dir, File) || File <- Files].
+
+file_does_not_exist(F) ->
+    not filelib:is_regular(F).
+
+check(Check, Files) ->
+    lists:foreach(
+      fun(F) ->
+              ?assertMatch({true, _}, {Check(F), F})
+      end,
+      Files).
diff --git a/inttest/neotoma1/rebar.config b/inttest/neotoma1/rebar.config
new file mode 100644
index 0000000..8757da8
--- /dev/null
+++ b/inttest/neotoma1/rebar.config
@@ -0,0 +1,15 @@
+%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 ft=erlang et
+
+{deps,
+ [
+  %% The dependency below to neotoma is needed for "rebar compile" to
+  %% work, thus for the inttest to work, but the neotoma that is actually
+  %% used in inttest is brought in from the inttest/neotoma1/mock
+  %% subdirectory.
+  {neotoma, ".*"}
+ ]}.
+
+{neotoma_opts, [
+    {module_ext, "_peg"}
+]}.
diff --git a/inttest/neotoma1/src/csv.peg b/inttest/neotoma1/src/csv.peg
new file mode 100644
index 0000000..000c00f
--- /dev/null
+++ b/inttest/neotoma1/src/csv.peg
@@ -0,0 +1,31 @@
+rows <- head:row tail:(crlf row)* / ''
+`
+case Node of
+  [] -> [];
+  [""] -> [];
+  _ ->
+    Head = proplists:get_value(head, Node),
+    Tail = [R || [_,R] <- proplists:get_value(tail, Node)],
+    [Head|Tail]
+end
+`;
+
+row <- head:field tail:(field_sep field)* / ''
+`
+case Node of
+  [] -> [];
+  [""] -> [];
+  _ ->
+    Head = proplists:get_value(head, Node),
+    Tail = [F || [_,F] <- proplists:get_value(tail, Node)],
+    [Head|Tail]
+end
+`;
+field <- quoted_field / (!field_sep !crlf .)* `iolist_to_binary(Node)`;
+quoted_field <- '"' string:('""' / (!'"' .))* '"'
+`
+  String = proplists:get_value(string, Node),
+  re:replace(String, "[\"]{2}", "\"",[global, {return, binary}])
+`;
+field_sep <- ',' ~;
+crlf <- [\r]? [\n] ~;
diff --git a/inttest/neotoma1/src/neotoma1.app.src b/inttest/neotoma1/src/neotoma1.app.src
new file mode 100644
index 0000000..96a50e5
--- /dev/null
+++ b/inttest/neotoma1/src/neotoma1.app.src
@@ -0,0 +1,6 @@
+{application, neotoma1,
+    [{vsn, "1"},
+     {modules, []},
+     {registered, []},
+     {applications, [kernel, stdlib]}]}.
+
diff --git a/inttest/port/port_rt.erl b/inttest/port/port_rt.erl
index 90ecbdc..afe991e 100644
--- a/inttest/port/port_rt.erl
+++ b/inttest/port/port_rt.erl
@@ -31,13 +31,16 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "c_src", "c_src"},
      {create, "ebin/foo.app", app(foo, [])}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     %% wait a bit for new files to have different timestamps
@@ -45,48 +48,77 @@
     %% test.so is created during first compile
     ?assertEqual(0, filelib:last_modified("priv/test.so")),
     ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
-    TestSo1 = filelib:last_modified("priv/test.so"),
+    ?assertMatch(true, filelib:is_regular("compile_commands.json")),
+    TestSo1 = filelib:last_modified("priv/test" ++
+                                    shared_library_file_extension(os:type())),
     ?assert(TestSo1 > 0),
     wait(),
     %% nothing happens during second compile
     ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
-    TestSo2 = filelib:last_modified("priv/test.so"),
-    Test1o2 = filelib:last_modified("c_src/test1.o"),
-    Test2o2 = filelib:last_modified("c_src/test2.o"),
+    TestSo2 = filelib:last_modified("priv/test" ++
+                                    shared_library_file_extension(os:type())),
+    Test1o2 = filelib:last_modified("c_src/test1" ++
+                                    object_file_extension(os:type())),
+    Test2o2 = filelib:last_modified("c_src/test2" ++
+                                    object_file_extension(os:type())),
     ?assertEqual(TestSo1, TestSo2),
     ?assert(TestSo1 >= Test1o2),
     ?assert(TestSo1 >= Test2o2),
     wait(),
     %% when test2.c changes, at least test2.o and test.so are rebuilt
-    ?assertMatch({ok, _}, retest_sh:run("touch c_src/test2.c", [])),
+    ?assertMatch({ok, _}, retest:run({touch, "c_src/test2.c"}, [{dir, "."}])),
     ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
-    TestSo3 = filelib:last_modified("priv/test.so"),
-    Test2o3 = filelib:last_modified("c_src/test2.o"),
+    TestSo3 = filelib:last_modified("priv/test" ++
+                                    shared_library_file_extension(os:type())),
+    Test2o3 = filelib:last_modified("c_src/test2" ++
+                                    object_file_extension(os:type())),
     ?assert(TestSo3 > TestSo2),
     ?assert(Test2o3 > TestSo2),
-    wait(),
-    %% when test2.h changes, at least test2.o and test.so are rebuilt
-    ?assertMatch({ok, _}, retest_sh:run("touch c_src/test2.h", [])),
-    ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
-    TestSo4 = filelib:last_modified("priv/test.so"),
-    Test2o4 = filelib:last_modified("c_src/test2.o"),
-    ?assert(TestSo4 > TestSo3),
-    ?assert(Test2o4 > TestSo3),
-    wait(),
-    %% when test1.h changes, everything is rebuilt
-    ?assertMatch({ok, _}, retest_sh:run("touch c_src/test1.h", [])),
-    ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])),
-    TestSo5 = filelib:last_modified("priv/test.so"),
-    Test1o5 = filelib:last_modified("c_src/test1.o"),
-    Test2o5 = filelib:last_modified("c_src/test2.o"),
-    ?assert(TestSo5 > TestSo4),
-    ?assert(Test1o5 > TestSo4),
-    ?assert(Test2o5 > TestSo4),
-    ok.
+    %% detecting the a full recompile is needed when changing a .h file is a feature attained
+    %% by using the -MMD gcc flag which sadly is not available in Windows, so this part of the
+    %% test is only executed in Unix
+    case os:type() of
+        {win32, _} -> ok;
+        _ ->
+            wait(),
+            %% when test2.h changes, at least test2.o and test.so are rebuilt
+            ?assertMatch({ok, _},
+                retest:run({touch, "c_src/test2.h"}, [{dir, "."}])),
+            ?assertMatch({ok, _},
+                retest_sh:run("./rebar compile", [])),
+            TestSo4 = filelib:last_modified("priv/test" ++
+                                            shared_library_file_extension(os:type())),
+            Test2o4 = filelib:last_modified("c_src/test2" ++
+                                            object_file_extension(os:type())),
+            ?assert(TestSo4 > TestSo3),
+            ?assert(Test2o4 > TestSo3),
+            wait(),
+            %% when test1.h changes, everything is rebuilt
+            ?assertMatch({ok, _},
+                retest:run({touch, "c_src/test1.h"}, [{dir, "."}])),
+            ?assertMatch({ok, _},
+                retest_sh:run("./rebar compile", [])),
+            TestSo5 = filelib:last_modified("priv/test" ++
+                                            shared_library_file_extension(os:type())),
+            Test1o5 = filelib:last_modified("c_src/test1" ++
+                                            object_file_extension(os:type())),
+            Test2o5 = filelib:last_modified("c_src/test2" ++
+                                            object_file_extension(os:type())),
+            ?assert(TestSo5 > TestSo4),
+            ?assert(Test1o5 > TestSo4),
+            ?assert(Test2o5 > TestSo4),
+            ok
+    end.
 
 wait() ->
     timer:sleep(1000).
 
+object_file_extension({win32, nt}) -> ".o";
+object_file_extension(_) -> ".o".
+
+shared_library_file_extension({win32, nt}) -> ".dll";
+shared_library_file_extension(_) -> ".so".
+
 %%
 %% Generate the contents of a simple .app file
 %%
diff --git a/inttest/port/rebar.config b/inttest/port/rebar.config
index a941218..efab1af 100644
--- a/inttest/port/rebar.config
+++ b/inttest/port/rebar.config
@@ -1 +1,2 @@
-{port_specs, [{"priv/test.so", ["c_src/*.c"]}]}.
+{port_specs, [{"win32", "priv/test.dll", ["c_src/*.c"]},
+              {"priv/test.so", ["c_src/*.c"]}]}.
diff --git a/inttest/port2/c_src/test1.c b/inttest/port2/c_src/test1.c
new file mode 100644
index 0000000..f1c8ef8
--- /dev/null
+++ b/inttest/port2/c_src/test1.c
@@ -0,0 +1,13 @@
+#include "test1.h"
+
+#ifndef TEST1
+#error TEST1 is not defined!
+#endif
+
+#ifndef TEST2
+#error TEST2 is not defined!
+#endif
+
+#ifndef TEST3
+#error TEST3 is not defined!
+#endif
diff --git a/inttest/port2/c_src/test1.h b/inttest/port2/c_src/test1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/inttest/port2/c_src/test1.h
diff --git a/inttest/port2/port2_rt.erl b/inttest/port2/port2_rt.erl
new file mode 100644
index 0000000..ffe8f23
--- /dev/null
+++ b/inttest/port2/port2_rt.erl
@@ -0,0 +1,75 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+%% -------------------------------------------------------------------
+%%
+%% rebar: Erlang Build Tools
+%%
+%% Copyright (c) 2016 Luis Rascao
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+%% -------------------------------------------------------------------
+
+-module(port2_rt).
+-export([files/0,
+         run/1]).
+
+-include_lib("eunit/include/eunit.hrl").
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
+files() ->
+    [
+     {copy, "rebar.config", "rebar.config"},
+     {copy, "c_src", "c_src"},
+     {create, "ebin/foo.app", app(foo, [])}
+    ] ++ inttest_utils:rebar_setup().
+
+run(_Dir) ->
+    %% wait a bit for new files to have different timestamps
+    wait(),
+    %% test.so is created during first compile
+    ?assertEqual(0, filelib:last_modified("priv/test.so")),
+    ?assertMatch({ok, _}, retest_sh:run("./rebar compile",
+                                        [{env, [{"ERL_CFLAGS", "-DTEST3=test3"}]}])),
+    TestSo1 = filelib:last_modified("priv/test" ++
+                                    shared_library_file_extension(os:type())),
+    ?assert(TestSo1 > 0).
+
+wait() ->
+    timer:sleep(1000).
+
+object_file_extension({win32, nt}) -> ".o";
+object_file_extension(_) -> ".o".
+
+shared_library_file_extension({win32, nt}) -> ".dll";
+shared_library_file_extension(_) -> ".so".
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name, Modules) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, Modules},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/port2/rebar.config b/inttest/port2/rebar.config
new file mode 100644
index 0000000..3527ee5
--- /dev/null
+++ b/inttest/port2/rebar.config
@@ -0,0 +1,9 @@
+{port_specs, [
+    {"(darwin|linux|freebsd)", "priv/test.so",
+         ["c_src/*.c"], [
+            {env, [
+                {"CFLAGS", "$CFLAGS -DTEST1=test1"},
+                {"ERL_CFLAGS", "$ERL_CFLAGS -DTEST2=test2"}
+            ]}
+         ]}
+]}.
diff --git a/inttest/profile/profile_rt.erl b/inttest/profile/profile_rt.erl
index b128517..b8a9e09 100644
--- a/inttest/profile/profile_rt.erl
+++ b/inttest/profile/profile_rt.erl
@@ -30,10 +30,12 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [
-     {copy, "../../rebar", "rebar"}
-    ].
+    inttest_utils:rebar_setup().
 
 run(_Dir) ->
     Cmd = "./rebar list-deps",
diff --git a/inttest/proto_gpb/proto_gpb_rt.erl b/inttest/proto_gpb/proto_gpb_rt.erl
index 8a7cacf..307aca0 100644
--- a/inttest/proto_gpb/proto_gpb_rt.erl
+++ b/inttest/proto_gpb/proto_gpb_rt.erl
@@ -30,7 +30,6 @@
 
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("kernel/include/file.hrl").
--include_lib("deps/retest/include/retest.hrl").
 
 -define(MODULES,
         [foo,
@@ -51,9 +50,12 @@
          "c/test4.proto",
          "c/d/test5.proto"]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "rebar2.config", "rebar2.config"},
      {copy, "rebar.bad.config", "rebar.bad.config"},
@@ -63,7 +65,7 @@
      {copy, "proto.bad", "proto.bad"},
      {copy, "mock", "deps"},
      {create, "ebin/foo.app", app(foo, ?MODULES ++ ?GENERATED_MODULES)}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     % perform test obtaining the .proto files from src dir
@@ -99,7 +101,7 @@
     %% the .hrl file was generated before foo was compiled.
     ok = check_beams_generated(),
 
-    ?DEBUG("Verifying recompilation~n", []),
+    retest_log:log(debug, "Verifying recompilation~n", []),
     TestErl = hd(generated_erl_files()),
     TestProto = hd(source_proto_files(ProtoDir)),
     make_proto_newer_than_erl(TestProto, TestErl),
@@ -111,7 +113,7 @@
     TestMTime2 = read_mtime(TestErl),
     ?assert(TestMTime2 > TestMTime1),
 
-    ?DEBUG("Verifying recompilation with no changes~n", []),
+    retest_log:log(debug, "Verifying recompilation with no changes~n", []),
     TestMTime3 = read_mtime(TestErl),
     ?assertMatch({ok, _}, retest_sh:run("./rebar --config "
                                         ++ ConfigFile
@@ -120,7 +122,7 @@
     TestMTime4 = read_mtime(TestErl),
     ?assert(TestMTime3 =:= TestMTime4),
 
-    ?DEBUG("Verify cleanup~n", []),
+    retest_log:log(debug, "Verify cleanup~n", []),
     ?assertMatch({ok, _}, retest_sh:run("./rebar --config "
                                         ++ ConfigFile
                                         ++ " clean",
diff --git a/inttest/proto_protobuffs/proto_protobuffs_rt.erl b/inttest/proto_protobuffs/proto_protobuffs_rt.erl
index 1bb7b5e..ee4c294 100644
--- a/inttest/proto_protobuffs/proto_protobuffs_rt.erl
+++ b/inttest/proto_protobuffs/proto_protobuffs_rt.erl
@@ -42,15 +42,18 @@
          "foo_sup.beam",
          "test_pb.beam"]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "include", "include"},
      {copy, "src", "src"},
      {copy, "mock", "deps"},
      {create, "ebin/foo.app", app(foo, ?MODULES)}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     ?assertMatch({ok, _}, retest_sh:run("./rebar clean", [])),
diff --git a/inttest/rebar3_deps1/a.erl b/inttest/rebar3_deps1/a.erl
new file mode 100644
index 0000000..897b963
--- /dev/null
+++ b/inttest/rebar3_deps1/a.erl
@@ -0,0 +1,8 @@
+-module(a).
+
+-export([hello/0]).
+
+-include_lib("b/include/b.hrl").
+
+hello() ->
+    io:format("~s\n", [?HELLO]).
diff --git a/inttest/rebar3_deps1/a.rebar.config b/inttest/rebar3_deps1/a.rebar.config
new file mode 100644
index 0000000..de3abe3
--- /dev/null
+++ b/inttest/rebar3_deps1/a.rebar.config
@@ -0,0 +1,4 @@
+{deps, [
+	{b, {git, "../repo/b"}},
+	{c, {git, "../repo/c"}, [raw]}
+]}.
diff --git a/inttest/rebar3_deps1/b.hrl b/inttest/rebar3_deps1/b.hrl
new file mode 100644
index 0000000..25dfeda
--- /dev/null
+++ b/inttest/rebar3_deps1/b.hrl
@@ -0,0 +1 @@
+-define(HELLO, "Hi From B").
diff --git a/inttest/rebar3_deps1/c.txt b/inttest/rebar3_deps1/c.txt
new file mode 100644
index 0000000..5adcd3d
--- /dev/null
+++ b/inttest/rebar3_deps1/c.txt
@@ -0,0 +1 @@
+This is a text file.
diff --git a/inttest/rebar3_deps1/rebar3_deps1_rt.erl b/inttest/rebar3_deps1/rebar3_deps1_rt.erl
new file mode 100644
index 0000000..92a1628
--- /dev/null
+++ b/inttest/rebar3_deps1/rebar3_deps1_rt.erl
@@ -0,0 +1,63 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(rebar3_deps1_rt).
+
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
+%% Test deps with rebar3-type dependencies (that is, dependencies without Regexes)
+%% Example: {git, {appname, "git://something/something", {branch, master}}}
+files() ->
+    [
+     %% A application
+     {create, "ebin/a.app", app(a, [a])},
+     {copy, "a.rebar.config", "rebar.config"},
+     {copy, "a.erl", "src/a.erl"},
+
+     %% B application
+     {create, "repo/b/ebin/b.app", app(b, [])},
+     {copy, "b.hrl", "repo/b/include/b.hrl"},
+
+     {copy, "c.txt", "repo/c/c.txt"}
+
+    ] ++ inttest_utils:rebar_setup().
+
+apply_cmds([], _Params) ->
+    ok;
+apply_cmds([Cmd | Rest], Params) ->
+    io:format("Running: ~s (~p)\n", [Cmd, Params]),
+    {ok, _} = retest_sh:run(Cmd, Params),
+    apply_cmds(Rest, Params).
+
+run(_Dir) ->
+    %% Initialize the dep app as git repos so that dependencies pull
+    %% properly
+    GitCmds = ["git init",
+               "git add -A",
+               "git config user.email 'tdeps@example.com'",
+               "git config user.name 'tdeps'",
+               "git commit -a -m \"Initial Commit\""],
+    apply_cmds(GitCmds, [{dir, "repo/b"}]),
+    apply_cmds(GitCmds, [{dir, "repo/c"}]),
+
+    {ok, _} = retest_sh:run("./rebar get-deps", []),
+    {ok, _} = retest_sh:run("./rebar compile", []),
+
+    true = filelib:is_regular("ebin/a.beam"),
+    true = filelib:is_regular("deps/c/c.txt"),
+    ok.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name, Modules) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, Modules},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/require_vsn/require_vsn_rt.erl b/inttest/require_vsn/require_vsn_rt.erl
index 0b947c5..8ff87f7 100644
--- a/inttest/require_vsn/require_vsn_rt.erl
+++ b/inttest/require_vsn/require_vsn_rt.erl
@@ -28,12 +28,15 @@
 -export([files/0,
          run/1]).
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {create, "ebin/require_vsn.app", app(require_vsn, [])}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     SharedExpected = "==> require_vsn_rt \\(compile\\)",
diff --git a/inttest/rgen1/retest.config b/inttest/rgen1/retest.config
index b569f14..244096d 100644
--- a/inttest/rgen1/retest.config
+++ b/inttest/rgen1/retest.config
@@ -1 +1 @@
-{timeout, 120000}.
+{timeout, 240000}.
diff --git a/inttest/rgen1/rgen1_rt.erl b/inttest/rgen1/rgen1_rt.erl
index 1bf36c2..7641ca4 100644
--- a/inttest/rgen1/rgen1_rt.erl
+++ b/inttest/rgen1/rgen1_rt.erl
@@ -2,17 +2,20 @@
 %% ex: ts=4 sw=4 et
 -module(rgen1_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 %% Exercise release generation w/ templating
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
      {copy, "reltool.config"},
      {copy, "test.config"},
-     {copy, "vars.config"},
-     {copy, "../../rebar"}
-    ].
+     {copy, "vars.config"}
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     {ok, _} = retest_sh:run("./rebar -v generate", []),
diff --git a/inttest/t_custom_config/custom_config.erl b/inttest/t_custom_config/custom_config.erl
index 8656201..de964b4 100644
--- a/inttest/t_custom_config/custom_config.erl
+++ b/inttest/t_custom_config/custom_config.erl
@@ -1,6 +1,6 @@
 -module(custom_config).
 
--compile(export_all).
+-export([test/0]).
 
 test() ->
     ok.
diff --git a/inttest/t_custom_config/t_custom_config_rt.erl b/inttest/t_custom_config/t_custom_config_rt.erl
index a6aac9b..bda229e 100644
--- a/inttest/t_custom_config/t_custom_config_rt.erl
+++ b/inttest/t_custom_config/t_custom_config_rt.erl
@@ -2,26 +2,32 @@
 %% ex: ts=4 sw=4 et
 -module(t_custom_config_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
-    [{copy, "../../rebar", "rebar"},
+    [
      {copy, "custom.config", "custom.config"},
-     {create, "ebin/custom_config.app", app(custom_config, [custom_config])}].
+     {create, "ebin/custom_config.app", app(custom_config, [custom_config])}
+    ] ++ inttest_utils:rebar_setup().
 
 run(Dir) ->
     retest_log:log(debug, "Running in Dir: ~s~n", [Dir]),
     Ref = retest:sh("./rebar -C custom.config check-deps -vv",
                     [{async, true}]),
+
     {ok, Captured} =
         retest:sh_expect(Ref,
-                         "DEBUG: Consult config file .*/custom.config.*",
+                         ".*DEBUG: .*Consult config file .*/custom.config.*",
                          [{capture, all, list}]),
     {ok, Missing} =
         retest:sh_expect(Ref,
-                         "DEBUG: Missing deps  : \\[\\{dep,bad_name,"
+                         ".*DEBUG: .*Missing deps  : \\[\\{dep,bad_name,"
                          "boo,\"\\.\",undefined,false\\}\\]",
                          [{capture, all, list}]),
     retest_log:log(debug, "[CAPTURED]: ~s~n", [Captured]),
diff --git a/inttest/tdeps1/a.erl b/inttest/tdeps1/a.erl
index 835522a..897b963 100644
--- a/inttest/tdeps1/a.erl
+++ b/inttest/tdeps1/a.erl
@@ -1,6 +1,6 @@
 -module(a).
 
--compile(export_all).
+-export([hello/0]).
 
 -include_lib("b/include/b.hrl").
 
diff --git a/inttest/tdeps1/tdeps1_rt.erl b/inttest/tdeps1/tdeps1_rt.erl
index 3591ec0..b291b54 100644
--- a/inttest/tdeps1/tdeps1_rt.erl
+++ b/inttest/tdeps1/tdeps1_rt.erl
@@ -2,18 +2,20 @@
 %% ex: ts=4 sw=4 et
 -module(tdeps1_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 %% Exercise transitive dependencies
 %% A -> B -> C, where A includes a .hrl from B which includes .hrl from C
-
 files() ->
     [
      %% A application
      {create, "ebin/a.app", app(a, [a])},
      {copy, "a.rebar.config", "rebar.config"},
      {copy, "a.erl", "src/a.erl"},
-     {copy, "../../rebar", "rebar"},
 
      %% B application
      {create, "repo/b/ebin/b.app", app(b, [])},
@@ -23,7 +25,7 @@
      %% C application
      {create, "repo/c/ebin/c.app", app(c, [])},
      {copy, "c.hrl", "repo/c/include/c.hrl"}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 apply_cmds([], _Params) ->
     ok;
@@ -39,7 +41,7 @@
                "git add -A",
                "git config user.email 'tdeps@example.com'",
                "git config user.name 'tdeps'",
-               "git commit -a -m 'Initial Commit'"],
+               "git commit -a -m \"Initial Commit\""],
     apply_cmds(GitCmds, [{dir, "repo/b"}]),
     apply_cmds(GitCmds, [{dir, "repo/c"}]),
 
diff --git a/inttest/tdeps2/tdeps2_rt.erl b/inttest/tdeps2/tdeps2_rt.erl
index 97a24ce..33a8c15 100644
--- a/inttest/tdeps2/tdeps2_rt.erl
+++ b/inttest/tdeps2/tdeps2_rt.erl
@@ -2,12 +2,15 @@
 %% ex: ts=4 sw=4 et
 -module(tdeps2_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 %% Exercise transitive dependencies where there are multiple files
 %% depending on the same set of deps
 %% [A1, A2] -> B -> C ; A1 and A2 includes B.hrl which includes C.hrl
-
 files() ->
     [
      %% A1 application
@@ -21,7 +24,6 @@
      {template, "a.erl", "apps/a2/src/a2.erl", dict:from_list([{module, a2}])},
 
      {copy, "root.rebar.config", "rebar.config"},
-     {copy, "../../rebar", "rebar"},
 
      %% B application
      {create, "repo/b/ebin/b.app", app(b, [])},
@@ -31,7 +33,7 @@
      %% C application
      {create, "repo/c/ebin/c.app", app(c, [])},
      {copy, "c.hrl", "repo/c/include/c.hrl"}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 apply_cmds([], _Params) ->
     ok;
@@ -47,7 +49,7 @@
                "git add -A",
                "git config user.email 'tdeps@example.com'",
                "git config user.name 'tdeps'",
-               "git commit -a -m 'Initial Commit'"],
+               "git commit -a -m \"Initial Commit\""],
     ok = apply_cmds(GitCmds, [{dir, "repo/b"}]),
     ok = apply_cmds(GitCmds, [{dir, "repo/c"}]),
 
diff --git a/inttest/tdeps3/tdeps3_rt.erl b/inttest/tdeps3/tdeps3_rt.erl
index f56b3ca..e30b64e 100644
--- a/inttest/tdeps3/tdeps3_rt.erl
+++ b/inttest/tdeps3/tdeps3_rt.erl
@@ -2,14 +2,17 @@
 %% ex: ts=4 sw=4 et
 -module(tdeps3_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 %% Exercise transitive dependencies where there are multiple files
 %% depending on the same set of deps as well as lib_dir directives
 %% A -> B -> C -> D -> E
 %%      |--> G(via lib_dir)
 %% |--> F -> D -> E
-
 files() ->
     [
      %% A1 application
@@ -17,7 +20,6 @@
      {template, "a.erl", "src/a.erl", dict:from_list([{module, a}, {dep, b}])},
 
      {copy, "a.rebar.config", "rebar.config"},
-     {copy, "../../rebar", "rebar"},
 
      %% B application
      {create, "repo/b/ebin/b.app", app(b, [b])},
@@ -52,7 +54,7 @@
      {create, "repo/b/apps/g/ebin/g.app", app(g, [])},
      {copy, "e.hrl", "repo/b/apps/g/include/g.hrl"}
 
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 apply_cmds([], _Params) ->
     ok;
@@ -68,7 +70,7 @@
                "git add -A",
                "git config user.email 'tdeps@example.com'",
                "git config user.name 'tdeps'",
-               "git commit -a -m 'Initial Commit'"],
+               "git commit -a -m \"Initial Commit\""],
     ok = apply_cmds(GitCmds, [{dir, "repo/b"}]),
     ok = apply_cmds(GitCmds, [{dir, "repo/c"}]),
     ok = apply_cmds(GitCmds, [{dir, "repo/d"}]),
diff --git a/inttest/tdeps_prefer/a.erl b/inttest/tdeps_prefer/a.erl
new file mode 100644
index 0000000..bf413a6
--- /dev/null
+++ b/inttest/tdeps_prefer/a.erl
@@ -0,0 +1,4 @@
+-module({{module}}).
+
+-include_lib("b/include/b.hrl").
+-include_lib("c/include/c.hrl").
diff --git a/inttest/tdeps_prefer/a.rebar.config b/inttest/tdeps_prefer/a.rebar.config
new file mode 100644
index 0000000..41fe9bc
--- /dev/null
+++ b/inttest/tdeps_prefer/a.rebar.config
@@ -0,0 +1,4 @@
+{deps, [
+	{c, "1", {git, "../repo/c"}},
+	{b, "1", {git, "../repo/b"}}
+]}.
diff --git a/inttest/tdeps_prefer/b.hrl b/inttest/tdeps_prefer/b.hrl
new file mode 100644
index 0000000..9f02fab
--- /dev/null
+++ b/inttest/tdeps_prefer/b.hrl
@@ -0,0 +1 @@
+-define(HELLO, hello).
diff --git a/inttest/tdeps_prefer/c.hrl b/inttest/tdeps_prefer/c.hrl
new file mode 100644
index 0000000..152a99f
--- /dev/null
+++ b/inttest/tdeps_prefer/c.hrl
@@ -0,0 +1 @@
+-define(WORLD, world).
diff --git a/inttest/tdeps_prefer/root.rebar.config b/inttest/tdeps_prefer/root.rebar.config
new file mode 100644
index 0000000..d1c3793
--- /dev/null
+++ b/inttest/tdeps_prefer/root.rebar.config
@@ -0,0 +1 @@
+{sub_dirs, ["apps/a"]}.
diff --git a/inttest/tdeps_prefer/tdeps_prefer_rt.erl b/inttest/tdeps_prefer/tdeps_prefer_rt.erl
new file mode 100644
index 0000000..aca0b96
--- /dev/null
+++ b/inttest/tdeps_prefer/tdeps_prefer_rt.erl
@@ -0,0 +1,68 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(tdeps_prefer_rt).
+
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+    retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+    ok.
+
+%% Test REBAR_DEPS_FORCE_LIB
+%% A -> [B, C]
+%% where B should be found globally and C should be found locally
+files() ->
+    [
+    %% A application
+    {create, "apps/a/ebin/a.app", app(a, [a])},
+    {copy, "a.rebar.config", "apps/a/rebar.config"},
+    {template, "a.erl", "apps/a/src/a.erl", dict:from_list([{module, a}])},
+
+    %% B application
+    {create, "libs/b-1/ebin/b.app", app(b, [])},
+    {copy, "b.hrl", "libs/b-1/include/b.hrl"},
+
+    %% C application
+    {create, "repo/c/ebin/c.app", app(c, [])},
+    {copy, "c.hrl", "repo/c/include/c.hrl"},
+
+    {copy, "root.rebar.config", "rebar.config"}
+    ] ++ inttest_utils:rebar_setup().
+
+apply_cmds([], _Params) ->
+    ok;
+apply_cmds([Cmd | Rest], Params) ->
+    io:format("Running: ~s (~p)\n", [Cmd, Params]),
+    {ok, _} = retest_sh:run(Cmd, Params),
+    apply_cmds(Rest, Params).
+
+run(Dir) ->
+    %% Initialize the c apps as git repos so that dependencies pull
+    %% properly
+    GitCmds = ["git init",
+               "git add -A",
+               "git config user.email 'tdeps@example.com'",
+               "git config user.name 'tdeps'",
+               "git commit -a -m \"Initial Commit\""],
+    ErlLibs = filename:join(Dir, "libs"),
+    ok = apply_cmds(GitCmds, [{dir, "repo/c"}]),
+    Env = [
+        {"REBAR_DEPS_PREFER_LIBS", "1"},
+        {"ERL_LIBS", ErlLibs}
+    ],
+
+    {ok, _} = retest_sh:run("./rebar -v get-deps", [{env, Env}]),
+    {ok, _} = retest_sh:run("./rebar -v compile", [{env, Env}]),
+    ok.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name, Modules) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, Modules},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
diff --git a/inttest/tdeps_update/tdeps_update_rt.erl b/inttest/tdeps_update/tdeps_update_rt.erl
index c53e253..2710534 100644
--- a/inttest/tdeps_update/tdeps_update_rt.erl
+++ b/inttest/tdeps_update/tdeps_update_rt.erl
@@ -2,7 +2,11 @@
 %% ex: ts=4 sw=4 et
 -module(tdeps_update_rt).
 
--compile(export_all).
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 %% Exercises update deps, with recursive dependency updates.
 %% Initially:
@@ -25,7 +29,6 @@
      {template, "a.erl", "apps/a1/src/a1.erl", dict:from_list([{module, a1}])},
 
      {copy, "root.rebar.config", "rebar.config"},
-     {copy, "../../rebar", "rebar"},
 
      %% B application
      {create, "repo/b/ebin/b.app", app(b, [], "0.2.3")},
@@ -64,57 +67,62 @@
      {copy, "c.rebar.config", "c.rebar.config"},
      {copy, "c2.rebar.config", "c2.rebar.config"},
      {copy, "c3.rebar.config", "c3.rebar.config"}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 apply_cmds([], _Params) ->
     ok;
 apply_cmds([Cmd | Rest], Params) ->
-    io:format("Running: ~s (~p)\n", [Cmd, Params]),
-    {ok, _} = retest_sh:run(Cmd, Params),
+    io:format("Running: ~p (~p)\n", [Cmd, Params]),
+    {ok, _} = retest:run(Cmd, Params),
     apply_cmds(Rest, Params).
 
-run(_Dir) ->
+run(Dir) ->
     %% Initialize the b/c/d apps as git repos so that dependencies pull
     %% properly
     GitCmds = ["git init",
                "git add -A",
-               "git config user.email 'tdeps@example.com'",
-               "git config user.name 'tdeps'",
-               "git commit -a -m 'Initial Commit'"],
+               "git config user.email \"tdeps@example.com\"",
+               "git config user.name \"tdeps\"",
+               "git commit -a -m \"Initial Commit\""],
     BCmds = ["git tag 0.2.3",
-             "cp ../../b2.rebar.config rebar.config",
-             "cp ../../b2.app ebin/b.app",
-             "git commit -a -m 'update to 0.2.4'",
+             {copy, "../../b2.rebar.config", "rebar.config"},
+             {copy, "../../b2.app", "ebin/b.app"},
+             {touch, "ebin/b.app"},
+             "git commit -a -m \"update to 0.2.4\"",
              "git tag 0.2.4",
-             "cp ../../b3.rebar.config rebar.config",
-             "cp ../../b3.app ebin/b.app",
-             "git commit -a -m 'update to 0.2.5'",
+             {copy, "../../b3.rebar.config", "rebar.config"},
+             {copy, "../../b3.app", "ebin/b.app"},
+             {touch, "ebin/b.app"},
+             "git commit -a -m \"update to 0.2.5\"",
              "git tag 0.2.5",
-             "cp ../../b4.rebar.config rebar.config",
-             "cp ../../b4.app ebin/b.app",
-             "git commit -a -m 'update to 0.2.6'",
+             {copy, "../../b4.rebar.config", "rebar.config"},
+             {copy, "../../b4.app", "ebin/b.app"},
+             {touch, "ebin/b.app"},
+             "git commit -a -m \"update to 0.2.6\"",
              "git tag 0.2.6"],
              %"git checkout 0.2.3"],
     CCmds = ["git tag 1.0",
-             "cp ../../c2.hrl include/c.hrl",
-             "cp ../../c2.app ebin/c.app",
-             "cp ../../c.rebar.config rebar.config",
+             {copy, "../../c2.hrl", "include/c.hrl"},
+             {copy, "../../c2.app", "ebin/c.app"},
+             {copy, "../../c.rebar.config", "rebar.config"},
              "git add rebar.config",
-             "git commit -a -m 'update to 1.1'",
+             "git commit -a -m \"update to 1.1\"",
              "git tag 1.1",
-             "cp ../../c3.app ebin/c.app",
-             "cp ../../c2.rebar.config rebar.config",
-             "git commit -a -m 'update to 1.2'",
+             {copy, "../../c3.app", "ebin/c.app"},
+             {copy, "../../c2.rebar.config", "rebar.config"},
+             "git commit -a -m \"update to 1.2\"",
              "git tag 1.2",
-             "cp ../../c4.app ebin/c.app",
-             "cp ../../c3.rebar.config rebar.config",
-             "git commit -a -m 'update to 1.3'",
+             {copy, "../../c4.app", "ebin/c.app"},
+             {copy, "../../c3.rebar.config", "rebar.config"},
+             {touch, "rebar.config"},
+             "git commit -a -m \"update to 1.3\"",
              "git tag 1.3"],
              %"git checkout 1.0"],
     DCmds = ["git tag 0.7"],
     ECmds = ["git tag 2.0",
-             "cp ../../e2.app ebin/e.app",
-             "git commit -a -m 'update to 2.1'",
+             {copy, "../../e2.app", "ebin/e.app"},
+             {touch, "ebin/e.app"},
+             "git commit -a -m \"update to 2.1\"",
              "git tag 2.1"],
     FCmds = ["git tag 0.1"],
 
@@ -126,13 +134,16 @@
 
     {ok, _} = retest_sh:run("./rebar -v get-deps", []),
     {ok, _} = retest_sh:run("./rebar -v compile", []),
-    os:cmd("cp a2.rebar.config apps/a1/rebar.config"),
+    retest:run({copy, "a2.rebar.config", "apps/a1/rebar.config"},
+               [{dir, Dir}]),
     {ok, _} = retest_sh:run("./rebar -v update-deps", []),
     {ok, _} = retest_sh:run("./rebar -v compile", []),
-    os:cmd("cp a3.rebar.config apps/a1/rebar.config"),
+    retest:run({copy, "a3.rebar.config", "apps/a1/rebar.config"},
+               [{dir, Dir}]),
     {ok, _} = retest_sh:run("./rebar -v update-deps", []),
     {ok, _} = retest_sh:run("./rebar -v compile", []),
-    os:cmd("cp a4.rebar.config apps/a1/rebar.config"),
+    retest:run({copy, "a4.rebar.config", "apps/a1/rebar.config"},
+               [{dir, Dir}]),
     {ok, _} = retest_sh:run("./rebar -v update-deps", []),
     {ok, _} = retest_sh:run("./rebar -v compile", []),
     ok.
diff --git a/inttest/thooks/fish.erl b/inttest/thooks/fish.erl
index 739cb94..f22194a 100644
--- a/inttest/thooks/fish.erl
+++ b/inttest/thooks/fish.erl
@@ -1,5 +1,5 @@
 -module(fish).
 
--compile(export_all).
+-export([fish/0]).
 
 fish() -> fish.
diff --git a/inttest/thooks/thooks_rt.erl b/inttest/thooks/thooks_rt.erl
index 3cca6bb..5501323 100644
--- a/inttest/thooks/thooks_rt.erl
+++ b/inttest/thooks/thooks_rt.erl
@@ -3,16 +3,19 @@
 -module(thooks_rt).
 
 -include_lib("eunit/include/eunit.hrl").
--compile(export_all).
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
 
 files() ->
     [
      %% dummy lfe files
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "fish.erl", "src/fish.erl"},
      {create, "ebin/fish.app", app(fish, [fish])}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     ?assertMatch({ok, _}, retest_sh:run("./rebar -v clean compile", [])),
@@ -27,7 +30,13 @@
     ?assert(filelib:is_regular(File)),
     %% ensure that this command only ran once (not for each module)
     {ok, Content} = file:read_file(File),
-    ?assertEqual(Command ++ "\n", binary_to_list(Content)).
+    %% echo behaves differently in windows and unix
+    case os:type() of
+        {win32, nt} ->
+            ?assertEqual(Command ++ " \r\n", binary_to_list(Content));
+        _ ->
+            ?assertEqual(Command ++ "\n", binary_to_list(Content))
+    end.
 
 %%
 %% Generate the contents of a simple .app file
diff --git a/inttest/tplugins/bad_plugin.erl b/inttest/tplugins/bad_plugin.erl
index 77ec01b..5730a6d 100644
--- a/inttest/tplugins/bad_plugin.erl
+++ b/inttest/tplugins/bad_plugin.erl
@@ -1,5 +1,6 @@
 -module(bad_plugin).
--compile(export_all).
+
+-export([fwibble/2]).
 
 %% this plugin contains numerous DELIBERATE syntax errors
 
diff --git a/inttest/tplugins/fish.erl b/inttest/tplugins/fish.erl
index 739cb94..aa0639d 100644
--- a/inttest/tplugins/fish.erl
+++ b/inttest/tplugins/fish.erl
@@ -1,5 +1,5 @@
 -module(fish).
 
--compile(export_all).
+-expoort([fish/0]).
 
 fish() -> fish.
diff --git a/inttest/tplugins/test_plugin.erl b/inttest/tplugins/test_plugin.erl
index 461247c..5b8494f 100644
--- a/inttest/tplugins/test_plugin.erl
+++ b/inttest/tplugins/test_plugin.erl
@@ -1,5 +1,6 @@
 -module(test_plugin).
--compile(export_all).
+
+-export([fwibble/2]).
 
 fwibble(Config, _) ->
     Pwd = rebar_utils:get_cwd(),
diff --git a/inttest/tplugins/tplugins_rt.erl b/inttest/tplugins/tplugins_rt.erl
index 997661b..c833f62 100644
--- a/inttest/tplugins/tplugins_rt.erl
+++ b/inttest/tplugins/tplugins_rt.erl
@@ -1,16 +1,19 @@
 %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
 %% ex: ts=4 sw=4 et
 -module(tplugins_rt).
--compile(export_all).
+-export([setup/1, files/0, run/1]).
 
 -include_lib("eunit/include/eunit.hrl").
 
 -define(COMPILE_ERROR,
         "ERROR: Plugin bad_plugin contains compilation errors:").
 
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
 files() ->
     [
-     {copy, "../../rebar", "rebar"},
      {copy, "rebar.config", "rebar.config"},
      {copy, "bad.config", "bad.config"},
      {copy, "fish.erl", "src/fish.erl"},
@@ -18,13 +21,13 @@
      {copy, "bad_plugin.erl", "bad_plugins/bad_plugin.erl"},
      {create, "fwibble.test", <<"fwibble">>},
      {create, "ebin/fish.app", app(fish, [fish])}
-    ].
+    ] ++ inttest_utils:rebar_setup().
 
 run(_Dir) ->
     ?assertMatch({ok, _}, retest_sh:run("./rebar fwibble -v", [])),
     ?assertEqual(false, filelib:is_regular("fwibble.test")),
     Ref = retest:sh("./rebar -C bad.config -v clean", [{async, true}]),
-    {ok, _} = retest:sh_expect(Ref, "ERROR: Plugin .*bad_plugin.erl "
+    {ok, _} = retest:sh_expect(Ref, ".*ERROR: .*Plugin .*bad_plugin.erl "
                                "contains compilation errors:.*",
                                [{newline, any}]),
     ok.
diff --git a/inttest/vsn_cache/main.erl b/inttest/vsn_cache/main.erl
new file mode 100644
index 0000000..67b6465
--- /dev/null
+++ b/inttest/vsn_cache/main.erl
@@ -0,0 +1,13 @@
+-module(main).
+-behaviour(application).
+     
+-export([start/0,start/1,start/2,stop/1]).
+
+start() ->
+	start(permanent).
+start(_Restart) ->
+	ok.
+start(_Type,_Args) ->
+	ok.
+stop(_State) ->
+	ok.
diff --git a/inttest/vsn_cache/vsn_cache_rt.erl b/inttest/vsn_cache/vsn_cache_rt.erl
new file mode 100644
index 0000000..18c98ab
--- /dev/null
+++ b/inttest/vsn_cache/vsn_cache_rt.erl
@@ -0,0 +1,90 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(vsn_cache_rt).
+
+-export([setup/1, files/0, run/1]).
+
+setup([Target]) ->
+    retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+    ok.
+
+files() ->
+    [
+    %% Cache save check
+    {create, "save/src/save.app.src", app(save, [main])},
+    {create, "save/vsn_cache_file", ""},
+    {copy, "main.erl", "save/src/main.erl"},
+
+    %% Cache load check
+    {create, "load/src/load.app.src", app(load, [main])},
+    {copy, "main.erl", "load/src/main.erl"}
+    ] ++ inttest_utils:rebar_setup().
+
+apply_cmds([], _Params) ->
+    ok;
+apply_cmds([Cmd | Rest], Params) ->
+    io:format("Running: ~s (~p)\n", [Cmd, Params]),
+    {ok, _} = retest_sh:run(Cmd, Params),
+    apply_cmds(Rest, Params).
+
+run_save(Dir) ->
+    GitCmds = ["git init",
+               "git add -A",
+               "git config user.email 'vsn_cache@example.com'",
+               "git config user.name 'vsn_cache'",
+               "git commit -a -m \"Initial Commit\""],
+    AppDir = filename:join(Dir, "save"),
+    EbinDir = filename:join(AppDir, "ebin"),
+    AppFile = filename:join(EbinDir, "save.app"),
+    VsnCacheFile = filename:join(AppDir, "vsn_cache_file"),
+    Env = [{"REBAR_VSN_CACHE_FILE", VsnCacheFile}],
+
+    %% Initialize test git repository 
+    ok = apply_cmds(GitCmds, [{dir, AppDir}]),
+    %% Compile test project with vsn cache enabled
+    {ok, _} = retest_sh:run("../rebar -v compile", [{env, Env}, {dir, AppDir}]),
+    %% Vsn cache file has an entry
+    {ok, [{{git, AppDir}, Hash}]} = file:consult(VsnCacheFile),
+    %% This vsn entry must coincide with entry from ebin/save.app
+    {ok, [{application, save, PropList}]} = file:consult(AppFile),
+    Hash = proplists:get_value(vsn, PropList),
+    ok.
+
+run_load(Dir) ->
+    AppDir = filename:join(Dir, "load"),
+    EbinDir = filename:join(AppDir, "ebin"),
+    AppFile = filename:join(EbinDir, "load.app"),
+    VsnCacheFile = filename:join(AppDir, "vsn_cache_file"),
+    Hash = "deadbeef",
+    CacheEntries = [{{git, AppDir}, Hash}],
+    Env = [{"REBAR_VSN_CACHE_FILE", VsnCacheFile}],
+
+    %% Initialize dummy vsn cache file
+    vsn_cache_file(VsnCacheFile, CacheEntries),
+    %% Compile test project with vsn cache enabled
+    {ok, _} = retest_sh:run("../rebar -v compile", [{env, Env}, {dir, AppDir}]),
+    %% This vsn entry in cache file must coincide with entry in ebin/load.app
+    {ok, [{application, load, PropList}]} = file:consult(AppFile),
+    Hash = proplists:get_value(vsn, PropList),
+    ok.
+
+run(Dir) ->
+    run_save(Dir),
+    run_load(Dir),
+    ok.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name, Modules) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, git},
+            {modules, Modules},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
+
+vsn_cache_file(Name, Entries) ->
+    file:write_file(Name,
+        [io_lib:format("~p.~n", [X]) || X <- Entries]).
diff --git a/inttest/xref_behavior/gen_xref_behavior.erl b/inttest/xref_behavior/gen_xref_behavior.erl
new file mode 100644
index 0000000..9ac66d2
--- /dev/null
+++ b/inttest/xref_behavior/gen_xref_behavior.erl
@@ -0,0 +1,9 @@
+-module(gen_xref_behavior).
+
+-export([behaviour_info/1]). -ignore_xref([{behaviour_info, 1}]).
+
+behaviour_info(callbacks) ->
+    [{init,1}, {handle, 1}];
+behaviour_info(_Other) ->
+    undefined.
+
diff --git a/inttest/xref_behavior/rebar.config b/inttest/xref_behavior/rebar.config
new file mode 100644
index 0000000..c2e5af6
--- /dev/null
+++ b/inttest/xref_behavior/rebar.config
@@ -0,0 +1,6 @@
+{xref_warnings, true}.
+
+{xref_checks, [undefined_function_calls, undefined_functions,
+               locals_not_used, exports_not_used,
+               deprecated_function_calls, deprecated_functions]}.
+
diff --git a/inttest/xref_behavior/xref_behavior.erl b/inttest/xref_behavior/xref_behavior.erl
new file mode 100644
index 0000000..30b6959
--- /dev/null
+++ b/inttest/xref_behavior/xref_behavior.erl
@@ -0,0 +1,10 @@
+-module(xref_behavior).
+-behavior(gen_xref_behavior).
+
+% behavior-defined callbacks don't require xref_ignore
+-export([init/1, handle/1]).
+
+init(_Args) -> ok.
+
+handle(_Atom) -> next_event.
+
diff --git a/inttest/xref_behavior/xref_behavior_rt.erl b/inttest/xref_behavior/xref_behavior_rt.erl
new file mode 100644
index 0000000..f6d5ff8
--- /dev/null
+++ b/inttest/xref_behavior/xref_behavior_rt.erl
@@ -0,0 +1,35 @@
+-module(xref_behavior_rt).
+
+-export([files/0, run/1]).
+
+setup([Target]) ->
+  retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+  ok.
+
+files() ->
+    [
+     {copy, "rebar.config", "rebar.config"},
+     {copy, "xref_behavior.erl", "src/xref_behavior.erl"},
+     {copy, "gen_xref_behavior.erl", "src/gen_xref_behavior.erl"},
+     {create, "ebin/xref_behavior.app", app(xref_behavior,
+                                            [xref_behavior,
+                                             gen_xref_behavior])}
+    ] ++ inttest_utils:rebar_setup().
+
+run(_Dir) ->
+    {ok, _} = retest_sh:run("./rebar compile", []),
+    {ok, _} = retest_sh:run("./rebar xref", []),
+    ok.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name, Modules) ->
+    App = {application, Name,
+           [{description, atom_to_list(Name)},
+            {vsn, "1"},
+            {modules, Modules},
+            {registered, []},
+            {applications, [kernel, stdlib]}]},
+    io_lib:format("~p.\n", [App]).
+
diff --git a/pr2relnotes.py b/pr2relnotes.py
index 6e9a4f4..c58920c 100755
--- a/pr2relnotes.py
+++ b/pr2relnotes.py
@@ -1,5 +1,27 @@
 #!/usr/bin/env python
 
+# The MIT License (MIT)
+#
+# Copyright (c) 2015 Jared Morrow (github.com/jaredmorrow)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
 ## Install info
 ##   $ virtualenv env
 ##   $ source env/bin/activate
diff --git a/priv/shell-completion/bash/rebar b/priv/shell-completion/bash/rebar
index c017d20..5889e17 100644
--- a/priv/shell-completion/bash/rebar
+++ b/priv/shell-completion/bash/rebar
@@ -55,11 +55,12 @@
         jobs= \
         suites= \
         verbose=1 \
+        libid= \
         appid= \
+        nodeid= \
         overlay_vars= \
         previous_release= \
         profiler= \
-        nodeid= \
         root_dir= \
         skip_deps=true \
         skip_apps= \
diff --git a/priv/shell-completion/zsh/_rebar b/priv/shell-completion/zsh/_rebar
index 2ba7cdc..66a9264 100644
--- a/priv/shell-completion/zsh/_rebar
+++ b/priv/shell-completion/zsh/_rebar
@@ -63,11 +63,12 @@
         'jobs[Number of workers]::workers:(0 1 2 3 4 5 6 7 8 9)' \
         'suites[Common Test suites]::suite name:_path_files -W "(src test)" -g "*.erl(:r)"' \
         'verbose[Verbosity level]::verbosity level:(0 1 2 3)' \
+        'libid[Library id]:' \
         'appid[Application id]:' \
+        'nodeid[Node id]:' \
         'overlay_vars[Overlay variables file]:' \
         'previous_release[Previous release path]:' \
         'profiler[Select profiler]::flag:(fprof eflame)' \
-        'nodeid[Node id]:' \
         'root_dir[Reltool config root directory]::directory:_files -/' \
         'shell[Start a shell similar to erl -pa ebin -pa deps/*/ebin]' \
         'skip_deps[Skip deps]::flag:(true false)' \
diff --git a/priv/templates/ctsuite.erl b/priv/templates/ctsuite.erl
index 33a8fac..bed2ae6 100644
--- a/priv/templates/ctsuite.erl
+++ b/priv/templates/ctsuite.erl
@@ -3,7 +3,20 @@
 -module({{testmod}}_SUITE).
 -include_lib("common_test/include/ct.hrl").
 
--compile(export_all).
+-export([ suite/0
+        , groups/0
+        , all/0
+        , init_per_suite/1
+        , end_per_suite/1
+        , init_per_group/2
+        , end_per_group/2
+        , init_per_testcase/2
+        , end_per_testcase/2
+        ]).
+
+-export([ test_{{testmod}}/0
+        , test_{{testmod}}/1
+        ]).
 
 %%--------------------------------------------------------------------
 %% Function: suite() -> Info
@@ -57,12 +70,16 @@
 %%      NB: By default, we export all 1-arity user defined functions
 %%--------------------------------------------------------------------
 all() ->
-    [ {exports, Functions} | _ ] = ?MODULE:module_info(),
+    { exports, Functions } = lists:keyfind(exports, 1, ?MODULE:module_info()),
     [ FName || {FName, _} <- lists:filter(
                                fun ({module_info,_}) -> false;
                                    ({all,_}) -> false;
                                    ({init_per_suite,1}) -> false;
                                    ({end_per_suite,1}) -> false;
+                                   ({init_per_group,2}) -> false;
+                                   ({end_per_group,2}) -> false;
+                                   ({init_per_testcase,2}) -> false;
+                                   ({end_per_testcase,2}) -> false;
                                    ({_,1}) -> true;
                                    ({_,_}) -> false
                                end, Functions)].
@@ -108,7 +125,7 @@
 %%
 %% Description: Initialization before each test case group.
 %%--------------------------------------------------------------------
-init_per_group(_group, Config) ->
+init_per_group(_GroupName, Config) ->
     Config.
 
 %%--------------------------------------------------------------------
@@ -122,7 +139,7 @@
 %%
 %% Description: Cleanup after each test case group.
 %%--------------------------------------------------------------------
-end_per_group(_group, Config) ->
+end_per_group(_GroupName, Config) ->
     Config.
 
 %%--------------------------------------------------------------------
@@ -141,7 +158,7 @@
 %% Note: This function is free to add any key/value pairs to the Config
 %% variable, but should NOT alter/remove any existing entries.
 %%--------------------------------------------------------------------
-init_per_testcase(TestCase, Config) ->
+init_per_testcase(_TestCase, Config) ->
     Config.
 
 %%--------------------------------------------------------------------
@@ -157,7 +174,7 @@
 %%
 %% Description: Cleanup after each test case.
 %%--------------------------------------------------------------------
-end_per_testcase(TestCase, Config) ->
+end_per_testcase(_TestCase, Config) ->
     Config.
 
 test_{{testmod}}() ->
diff --git a/priv/templates/simplenode.runner b/priv/templates/simplenode.runner
index a605513..814b112 100755
--- a/priv/templates/simplenode.runner
+++ b/priv/templates/simplenode.runner
@@ -6,7 +6,8 @@
 if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
     POSIX_SHELL="true"
     export POSIX_SHELL
-    # To support 'whoami' add /usr/ucb to path
+    # To support 'whoami' on old Solaris systems, add /usr/ucb to path
+    # (New Solaris systems do not have 'whoami')
     PATH=/usr/ucb:$PATH
     export PATH
     exec /usr/bin/ksh $0 "$@"
@@ -25,17 +26,31 @@
 # Note the trailing slash on $PIPE_DIR/
 PIPE_DIR=/tmp/$RUNNER_BASE_DIR/
 RUNNER_USER=
-WHOAMI=$(whoami)
 
 # Make sure this script is running as the appropriate user
-if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
-    type sudo > /dev/null 2>&1
+if [ "$RUNNER_USER" ]; then
+    WHOAMI=$(id -un 2>/dev/null || whoami 2>/dev/null)
     if [ $? -ne 0 ]; then
-        echo "sudo doesn't appear to be installed and your EUID isn't $RUNNER_USER" 1>&2
+        echo "Could not determine user name."
         exit 1
     fi
-    echo "Attempting to restart script through sudo -H -u $RUNNER_USER" >&2
-    exec sudo -H -u $RUNNER_USER -i $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@
+    if [ "x$WHOAMI" != "x$RUNNER_USER" ]; then
+        # The 'su' command is more portable, but can't be configured as 'sudo'
+        # can to allow non-interactive calls from non-root users.
+        type sudo > /dev/null 2>&1
+        if [ $? -eq 0 ]; then
+            echo "Attempting to restart script through sudo -H -u $RUNNER_USER" >&2
+            exec sudo -H -u $RUNNER_USER -i $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@
+        else
+            if [ "x$WHOAMI" != "xroot" ]; then
+                echo "Only root can run $RUNNER_SCRIPT as $RUNNER_USER without requiring a password."
+                exit 1
+            else
+                echo "Attempting to restart script through su $RUNNER_USER" >&2
+                exec su $RUNNER_USER -c $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@
+            fi
+        fi
+    fi
 fi
 
 # Identify the script name
diff --git a/priv/templates/simplenode.windows.runner.cmd b/priv/templates/simplenode.windows.runner.cmd
index d71a8c7..1e3a3f3 100644
--- a/priv/templates/simplenode.windows.runner.cmd
+++ b/priv/templates/simplenode.windows.runner.cmd
@@ -17,8 +17,18 @@
     @call :set_trim release_version %%J
 )
 
-@set vm_args=%releases_dir%\%release_version%\vm.args
-@set sys_config=%releases_dir%\%release_version%\sys.config
+@if exist "%releases_dir%\%release_version%\vm.args" (
+    @set vm_args="%releases_dir%\%release_version%\vm.args"
+) else (
+    @set vm_args="%node_root%\etc\vm.args"
+)
+
+@if exist "%releases_dir%\%release_version%\sys.config" (
+    @set sys_config="%releases_dir%\%release_version%\sys.config"
+) else (
+    @set sys_config="%node_root%\etc\app.config"
+)
+
 @set node_boot_script=%releases_dir%\%release_version%\%node_name%
 @set clean_boot_script=%releases_dir%\%release_version%\start_clean
 
diff --git a/rebar.config b/rebar.config
index a3849ec..eda5a2c 100644
--- a/rebar.config
+++ b/rebar.config
@@ -29,7 +29,10 @@
       - (\"gpb_compile\":\"format_error\"/\"1\")
       - (\"diameter_codegen\":\"from_dict\"/\"4\")
       - (\"diameter_dict_util\":\"format_error\"/\"1\")
-      - (\"diameter_dict_util\":\"parse\"/\"2\"))",
+      - (\"diameter_dict_util\":\"parse\"/\"2\")
+      - (\"erlang\":\"timestamp\"/\"0\")
+      - (\"rebar_rnd\":\"seed\"/\"1\")
+      - (\"rebar_rnd\":\"uniform\"/\"0\"))",
          []}]}.
 
 {dialyzer,
diff --git a/rebar.config.sample b/rebar.config.sample
index 916e47c..224c85c 100644
--- a/rebar.config.sample
+++ b/rebar.config.sample
@@ -148,6 +148,10 @@
 %% Option to use short names (i.e., -sname test) when starting ct
 {ct_use_short_names, true}.
 
+%% Recursively search for .spec files from the test dir, default
+%% is false (ie. the search will be from the current working directory)
+{ct_search_specs_from_test_dir, true}.
+
 %% == QuickCheck ==
 
 %% If qc_mod is unspecified, rebar tries to detect Triq or EQC
diff --git a/rebar.config.script b/rebar.config.script
index 6735645..67389b0 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -1,7 +1,8 @@
 %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
 %% ex: ts=4 sw=4 ft=erlang et
 
-ExtraDeps = [{retest, ".*", {git, "git://github.com/dizzyd/retest.git"}}],
+ExtraDeps = [{retest, ".*", {git, "https://github.com/rebar/retest",
+                             {tag, "1.1.0"}}}],
 
 case os:getenv("REBAR_EXTRA_DEPS") of
     false ->
diff --git a/src/rebar.erl b/src/rebar.erl
index dcfb353..d35e492 100644
--- a/src/rebar.erl
+++ b/src/rebar.erl
@@ -143,7 +143,7 @@
     %% Keep track of how many operations we do, so we can detect bad commands
     BaseConfig1 = rebar_config:set_xconf(BaseConfig, operations, 0),
     %% Initialize vsn cache
-    rebar_config:set_xconf(BaseConfig1, vsn_cache, dict:new()).
+    rebar_utils:init_vsn_cache(BaseConfig1).
 
 init_config1(BaseConfig) ->
     %% Determine the location of the rebar executable; important for pulling
@@ -156,9 +156,6 @@
     rebar_config:set_xconf(BaseConfig1, base_dir, AbsCwd).
 
 profile(BaseConfig1, Commands) ->
-    ?CONSOLE("Please take note that profiler=[fprof|eflame] is preliminary"
-             " and will be~nreplaced with a different command line flag"
-             " in the next release.~n", []),
     Profiler = rebar_config:get_global(BaseConfig1, profiler, "fprof"),
     profile(BaseConfig1, Commands, list_to_atom(Profiler)).
 
@@ -220,6 +217,9 @@
         {error, {already_started, _}} -> ok
     end,
 
+    %% Make sure rebar_rnd module is generated, compiled, and loaded
+    {ok, rebar_rnd} = rebar_rand_compat:init("rebar_rnd"),
+
     %% Convert command strings to atoms
     CommandAtoms = [list_to_atom(C) || C <- Commands],
 
@@ -284,7 +284,12 @@
                       {"freebsd", compile, "c_src/freebsd_tweaks.sh"},
                       {eunit, "touch file2.out"},
                       {compile, "touch postcompile.out"}]}
-       ]).
+       ]),
+    ?CONSOLE(
+       "Environment variables:~n"
+       "  REBAR_DEPS_PREFER_LIBS to look for dependecies in system libs prior fetching.~n"
+       "  REBAR_VSN_CACHE_FILE to load vsn cache from and save to specified file.~n"
+       "~n", []).
 
 %%
 %% Parse command line arguments using getopt and also filtering out any
@@ -501,7 +506,9 @@
      {profile,  $p, "profile",  undefined,
       "Profile this run of rebar. Via profiler= you can optionally select "
       "either fprof (default) or eflame. The result can be found in "
-      "fprof.analysis or eflame.svg."},
+      "fprof.analysis or eflame.svg. Additionally, in fprof mode, if "
+      "erlgrind can be found in $PATH, a Cachegrind file (fprof.cgrind) "
+      "will be generated as well."},
      {keep_going, $k, "keep-going", undefined,
       "Keep running after a command fails"},
      {recursive, $r, "recursive", boolean,
@@ -583,7 +590,7 @@
         [FullCommand] ->
             [FullCommand | unabbreviate_command_names(Commands)];
         Candidates ->
-            ?ABORT("Found more than one match for abbreviated command name "
+            ?ABORT("Found more than one match for abbreviated command name"
                    " '~s',~nplease be more specific. Possible candidates:~n"
                    "  ~s~n",
                    [Command, string:join(Candidates, ", ")])
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index 0650430..747fe97 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -106,7 +106,7 @@
                                                       ParentConfig2),
             %% Wipe out vsn cache to avoid invalid hits when
             %% dependencies are updated
-            rebar_config:set_xconf(ParentConfig3, vsn_cache, dict:new())
+            rebar_utils:init_vsn_cache(ParentConfig3)
         catch
             throw:rebar_abort ->
                 case rebar_config:get_xconf(ParentConfig1, keep_going, false) of
@@ -190,8 +190,8 @@
                  WouldCd);
 skip_or_process_dir(Dir, Command, Config, DirSet, CurrentCodePath,
                     {_, File}=ModuleSet, WouldCd) ->
-    case lists:suffix(".app.src", File)
-        orelse lists:suffix(".app", File) of
+    case lists:suffix(".app", File)
+        orelse rebar_app_utils:is_app_src(File) of
         true ->
             %% .app or .app.src file, check if is_skipped_app
             skip_or_process_dir1(Dir, Command, Config, DirSet, CurrentCodePath,
diff --git a/src/rebar_cover_utils.erl b/src/rebar_cover_utils.erl
index 3fcba63..7b85f1c 100644
--- a/src/rebar_cover_utils.erl
+++ b/src/rebar_cover_utils.erl
@@ -35,6 +35,8 @@
 
 -include("rebar.hrl").
 
+-dialyzer({no_opaque, has_header/2}).
+
 %% ====================================================================
 %% Internal functions
 %% ====================================================================
diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl
index 022dfc4..c033c58 100644
--- a/src/rebar_ct.erl
+++ b/src/rebar_ct.erl
@@ -66,6 +66,7 @@
        "  ~p~n"
        "  ~p~n"
        "  ~p~n"
+       "  ~p~n"
        "Valid command line options:~n"
        "  suites=Suite1,Suite2,...,SuiteN~n"
        "      - run Suite1_SUITE, Suite2_SUITE, ..., SuiteN_SUITE~n"
@@ -81,7 +82,8 @@
         {ct_dir, "itest"},
         {ct_log_dir, "test/logs"},
         {ct_extra_params, "-boot start_sasl -s myapp"},
-        {ct_use_short_names, true}
+        {ct_use_short_names, true},
+        {ct_search_specs_from_test_dir, false}
        ]).
 
 run_test_if_present(TestDir, LogDir, Config, File) ->
@@ -113,7 +115,12 @@
                  false ->
                      " >> " ++ RawLog ++ " 2>&1";
                  true ->
+                 case os:type() of
+                   {win32, nt} ->
+                     " >> " ++ RawLog ++ " 2>&1";
+                   _ ->
                      " 2>&1 | tee -a " ++ RawLog
+                 end
              end,
 
     ShOpts = [{env,[{"TESTDIR", TestDir}]}, return_on_error],
@@ -155,14 +162,27 @@
 check_fail_log(Config, RawLog, Command, Result) ->
     check_log(Config, RawLog, failure_logger(Command, Result)).
 
-check_log(Config,RawLog,Fun) ->
-    {ok, Msg} =
-        rebar_utils:sh("grep -e \"TEST COMPLETE\" -e \"{error,make_failed}\" "
-                       ++ RawLog, [{use_stdout, false}]),
-    MakeFailed = string:str(Msg, "{error,make_failed}") =/= 0,
-    RunFailed = string:str(Msg, ", 0 failed") =:= 0,
+check_log(Config,RawLogFilename,Fun) ->
+    %% read the file and split into a list separated by newlines
+    {ok, RawLog} = file:read_file(RawLogFilename),
+    Msg = string:tokens(binary_to_list(RawLog), "\n"),
+    %% now filter out all the list entries that do not have test
+    %% completion strings
+    CompleteRuns = lists:filter(fun(M) ->
+                                  string:str(M, "TEST COMPLETE") =/= 0
+                                end, Msg),
+    MakeFailed = lists:filter(fun(M) ->
+                                  string:str(M, "{error,make_failed}") =/= 0
+                              end, Msg),
+    %% the run has failed if at least one of the tests failed
+    RunFailed = lists:foldl(fun(M, Acc) ->
+                              %% the "0 failed" string must be present for
+                              %% the test to be considered successful
+                              TestFailed = string:str(M, "0 failed") =:= 0,
+                              TestFailed orelse Acc
+                            end, false, CompleteRuns),
     if
-        MakeFailed ->
+        MakeFailed =/= [] ->
             show_log(Config, RawLog),
             ?ERROR("Building tests failed\n",[]),
             ?FAIL;
@@ -173,7 +193,7 @@
             ?FAIL;
 
         true ->
-            Fun(Msg)
+            Fun(string:join(Msg, "\n"))
     end.
 
 
@@ -182,8 +202,7 @@
     ?CONSOLE("Showing log\n", []),
     case rebar_log:is_verbose(Config) of
         false ->
-            {ok, Contents} = file:read_file(RawLog),
-            ?CONSOLE("~s", [Contents]);
+            ?CONSOLE("~s", [RawLog]);
         true ->
             ok
     end.
@@ -218,7 +237,7 @@
     CodeDirs = [io_lib:format("\"~s\"", [Dir]) ||
                    Dir <- [EbinDir|NonLibCodeDirs]],
     CodePathString = string:join(CodeDirs, " "),
-    Cmd = case get_ct_specs(Config, Cwd) of
+    Cmd = case get_ct_specs(Config, search_ct_specs_from(Cwd, TestDir, Config)) of
               undefined ->
                   ?FMT("~s"
                        " -pa ~s"
@@ -259,10 +278,20 @@
     RawLog = filename:join(LogDir, "raw.log"),
     {Cmd, RawLog}.
 
+search_ct_specs_from(Cwd, TestDir, Config) ->
+    case rebar_config:get_local(Config, ct_search_specs_from_test_dir, false) of
+        true -> filename:join(Cwd, TestDir);
+        false ->
+          Cwd
+    end.
+
 build_name(Config) ->
+    %% generate a unique name for our test node, we want
+    %% to make sure the odds of name clashing are low
+    Random = integer_to_list(crypto:rand_uniform(0, 10000)),
     case rebar_config:get_local(Config, ct_use_short_names, false) of
-        true -> "-sname test";
-        false -> " -name test@" ++ net_adm:localhost()
+        true -> "-sname test" ++ Random;
+        false -> " -name test" ++ Random ++ "@" ++ net_adm:localhost()
     end.
 
 get_extra_params(Config) ->
diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl
index a6e5b27..251bdee 100644
--- a/src/rebar_deps.erl
+++ b/src/rebar_deps.erl
@@ -58,16 +58,19 @@
     %% used globally since it will be set on the first time through here
     Config1 = set_shared_deps_dir(Config, get_shared_deps_dir(Config, [])),
 
+    %% Check whether user forced deps resolution via system wide libs
+    Config2 = set_deps_prefer_libs(Config1, get_deps_prefer_libs(Config1, undefined)),
+
     %% Get the list of deps for the current working directory and identify those
     %% deps that are available/present.
-    Deps = rebar_config:get_local(Config1, deps, []),
-    {Config2, {AvailableDeps, MissingDeps}} = find_deps(Config1, find, Deps),
+    Deps = rebar_config:get_local(Config2, deps, []),
+    {Config3, {AvailableDeps, MissingDeps}} = find_deps(Config2, find, Deps),
 
     ?DEBUG("Available deps: ~p\n", [AvailableDeps]),
     ?DEBUG("Missing deps  : ~p\n", [MissingDeps]),
 
     %% Add available deps to code path
-    Config3 = update_deps_code_path(Config2, AvailableDeps),
+    Config4 = update_deps_code_path(Config3, AvailableDeps),
 
     %% Filtering out 'raw' dependencies so that no commands other than
     %% deps-related can be executed on their directories.
@@ -83,8 +86,8 @@
                           fun(D, Acc) ->
                                   rebar_config:set_skip_dir(Acc, D#dep.dir)
                           end,
-                          Config3,
-                          collect_deps(rebar_utils:get_cwd(), Config3)),
+                          Config4,
+                          collect_deps(rebar_utils:get_cwd(), Config4)),
             %% Return the empty list, as we don't want anything processed before
             %% us.
             {ok, NewConfig, []};
@@ -97,12 +100,12 @@
             %% Also, if skip_deps=comma,separated,app,list, then only the given
             %% dependencies are skipped.
             NewConfig =
-                case rebar_config:get_global(Config3, skip_deps, false) of
+                case rebar_config:get_global(Config4, skip_deps, false) of
                     "true" ->
                         lists:foldl(
                           fun(#dep{dir = Dir}, C) ->
                                   rebar_config:set_skip_dir(C, Dir)
-                          end, Config3, AvailableDeps);
+                          end, Config4, AvailableDeps);
                     Apps when is_list(Apps) ->
                         SkipApps = [list_to_atom(App) ||
                                        App <- string:tokens(Apps, ",")],
@@ -112,9 +115,9 @@
                                       true -> rebar_config:set_skip_dir(C, Dir);
                                       false -> C
                                   end
-                          end, Config3, AvailableDeps);
+                          end, Config4, AvailableDeps);
                     _ ->
-                        Config3
+                        Config4
                 end,
 
             %% Return all the available dep directories for process
@@ -254,7 +257,9 @@
        "  ~p~n"
        "  ~p~n"
        "Valid command line options:~n"
-       "  deps_dir=\"deps\" (override default or rebar.config deps_dir)~n",
+       "  deps_dir=\"deps\" (override default or rebar.config deps_dir)~n"
+       "Environment variables:~n"
+       "  REBAR_DEPS_PREFER_LIBS to look for dependecies in system libs prior fetching.~n",
        [
         Description,
         {deps_dir, "deps"},
@@ -263,15 +268,24 @@
           {rebar, "1.0.*"},
           {rebar, ".*",
            {git, "git://github.com/rebar/rebar.git"}},
+          {rebar,
+           {git, "git://github.com/rebar/rebar.git"}},
           {rebar, ".*",
            {git, "git://github.com/rebar/rebar.git", "Rev"}},
+          {rebar,
+           {git, "git://github.com/rebar/rebar.git", "Rev"}},
           {rebar, "1.0.*",
            {git, "git://github.com/rebar/rebar.git", {branch, "master"}}},
+          {rebar,
+           {git, "git://github.com/rebar/rebar.git", {branch, "master"}}},
           {rebar, "1.0.0",
            {git, "git://github.com/rebar/rebar.git", {tag, "1.0.0"}}},
           {rebar, "",
            {git, "git://github.com/rebar/rebar.git", {branch, "master"}},
            [raw]},
+          {rebar,
+           {git, "git://github.com/rebar/rebar.git", {branch, "master"}},
+           [raw]},
           {app_name, ".*", {hg, "https://www.example.org/url"}},
           {app_name, ".*", {rsync, "Url"}},
           {app_name, ".*", {svn, "https://www.example.org/url"}},
@@ -302,6 +316,18 @@
 get_shared_deps_dir(Config, Default) ->
     rebar_config:get_xconf(Config, deps_dir, Default).
 
+set_deps_prefer_libs(Config, undefined) ->
+    DepsPreferLibs = case os:getenv("REBAR_DEPS_PREFER_LIBS") of
+        false -> false;
+        _ -> true
+    end,
+    rebar_config:set_xconf(Config, deps_prefer_libs, DepsPreferLibs);
+set_deps_prefer_libs(Config, _DepsPreferLibs) ->
+    Config.
+
+get_deps_prefer_libs(Config, Default) ->
+    rebar_config:get_xconf(Config, deps_prefer_libs, Default).
+
 get_deps_dir(Config) ->
     get_deps_dir(Config, "").
 
@@ -354,8 +380,12 @@
     {Config, lists:reverse(Deps)};
 find_deps(Config, Mode, [App | Rest], Acc) when is_atom(App) ->
     find_deps(Config, Mode, [{App, ".*", undefined} | Rest], Acc);
+find_deps(Config, Mode, [{App, Source} | Rest], Acc) when is_tuple(Source) ->
+    find_deps(Config, Mode, [{App, ".*", Source} | Rest], Acc);
 find_deps(Config, Mode, [{App, VsnRegex} | Rest], Acc) when is_atom(App) ->
     find_deps(Config, Mode, [{App, VsnRegex, undefined} | Rest], Acc);
+find_deps(Config, Mode, [{App, Source, Opts} | Rest], Acc) when is_tuple(Source) ->
+    find_deps(Config, Mode, [{App, ".*", Source, Opts} | Rest], Acc);
 find_deps(Config, Mode, [{App, VsnRegex, Source} | Rest], Acc) ->
     find_deps(Config, Mode, [{App, VsnRegex, Source, []} | Rest], Acc);
 find_deps(Config, Mode, [{App, VsnRegex, Source, Opts} | Rest], Acc)
@@ -378,9 +408,15 @@
     %% e.g. {git, "https://github.com/mochi/mochiweb.git", "HEAD"}
     %% Deps with a source must be found (or fetched) locally.
     %% Those without a source may be satisfied from lib dir (get_lib_dir).
-    find_dep(Config, Dep, Dep#dep.source).
+    DepsPreferLibs = get_deps_prefer_libs(Config, false),
+    Mode = case {Dep#dep.source, DepsPreferLibs} of
+        {undefined, _DepsPreferLibs} -> maybe_in_lib;
+        {_DepSource, true} -> maybe_in_lib;
+        {_DepSource, false} -> local_only
+    end,
+    find_dep(Config, Dep, Mode).
 
-find_dep(Config, Dep, undefined) ->
+find_dep(Config, Dep, maybe_in_lib) ->
     %% 'source' is undefined.  If Dep is not satisfied locally,
     %% go ahead and find it amongst the lib_dir's.
     case find_dep_in_dir(Config, Dep, get_deps_dir(Config, Dep#dep.app)) of
@@ -389,7 +425,7 @@
         {Config1, {missing, _}} ->
             find_dep_in_dir(Config1, Dep, get_lib_dir(Dep#dep.app))
     end;
-find_dep(Config, Dep, _Source) ->
+find_dep(Config, Dep, local_only) ->
     %% _Source is defined.  Regardless of what it is, we must find it
     %% locally satisfied or fetch it from the original source
     %% into the project's deps
diff --git a/src/rebar_dia_compiler.erl b/src/rebar_dia_compiler.erl
index 56d5189..a45cd55 100644
--- a/src/rebar_dia_compiler.erl
+++ b/src/rebar_dia_compiler.erl
@@ -88,6 +88,8 @@
 compile_dia(Source, Target, Config) ->
     ok = filelib:ensure_dir(Target),
     ok = filelib:ensure_dir(filename:join("include", "dummy.hrl")),
+    ok = filelib:ensure_dir(filename:join("ebin", "dummy.beam")),
+    true = code:add_path(filename:absname("ebin")),
     Opts = [{outdir, "src"}] ++ rebar_config:get(Config, dia_opts, []),
     case diameter_dict_util:parse({path, Source}, []) of
         {ok, Spec} ->
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 5c33239..412b29d 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -236,8 +236,10 @@
     Opts = [O || O <- Opts0, O =/= no_debug_info],
     Config4 = rebar_config:set(Config3, erl_opts, Opts),
 
+    FirstErlFiles = rebar_config:get_list(Config4, erl_first_files, []),
     FirstFilesAtom = list_to_atom(Cmd ++ "_first_files"),
-    FirstErls = rebar_config:get_list(Config4, FirstFilesAtom, []),
+    FirstErlsOther = rebar_config:get_list(Config4, FirstFilesAtom, []),
+    FirstErls = FirstErlFiles ++ FirstErlsOther,
     Config5 = rebar_config:set(Config4, erl_first_files, FirstErls),
     {Config5, Opts}.
 
diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl
index 913f2f9..ebf76bc 100644
--- a/src/rebar_eunit.erl
+++ b/src/rebar_eunit.erl
@@ -54,8 +54,8 @@
 %%   </li>
 %%   <li>
 %%      tests="baz"- For every existing suite, run the first test whose
-%%      name starts with bar and, if no such test exists, run the test
-%%      whose name starts with bar in the suite's _tests module
+%%      name starts with baz and, if no such test exists, run the test
+%%      whose name starts with baz in the suite's _tests module
 %%   </li>
 %% </ul>
 %% Additionally, for projects that have separate folders for the core
@@ -128,6 +128,7 @@
        "               name starts with bar and, if no such test exists,~n"
        "               run the test whose name starts with bar in the~n"
        "               suite's _tests module)~n"
+       "  test[s]=\"foo:bar_test\" (Run bar_test located in module foo)~n"
        "  random_suite_order=true (Run tests in random order)~n"
        "  random_suite_order=Seed (Run tests in random order,~n"
        "                           with the PRNG seeded with Seed)~n"
@@ -292,9 +293,9 @@
     end.
 
 randomize_suites1(Modules, Seed) ->
-    _ = random:seed(35, Seed, 1337),
+    _ = rebar_rnd:seed({35, Seed, 1337}),
     ?CONSOLE("Randomizing suite order with seed ~b~n", [Seed]),
-    [X||{_,X} <- lists:sort([{random:uniform(), M} || M <- Modules])].
+    [X||{_,X} <- lists:sort([{rebar_rnd:uniform(), M} || M <- Modules])].
 
 %%
 %% == get matching tests ==
@@ -460,7 +461,7 @@
                             %% Generator
                             MakePrimitive(generator, M, F2)
                     end,
-                [NewFunction|Acc]
+                [eunit_module_suite(M, NewFunction)|Acc]
         end,
     lists:foldl(F, [], RawTests).
 
@@ -472,6 +473,11 @@
 pre15b02_eunit_primitive(generator, M, F) ->
     {generator, eunit_test:function_wrapper(M, F)}.
 
+% Add a test group for eunit_surefire to be able to deduce the testsuite.
+% Calling eunit:test({module, M}) does exactly this as well.
+eunit_module_suite(M, X) ->
+    {"module '" ++ atom_to_list(M) ++ "'", X}.
+
 %%
 %% == run tests ==
 %%
diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl
index 0fc1403..a4d3be7 100644
--- a/src/rebar_file_utils.erl
+++ b/src/rebar_file_utils.erl
@@ -88,7 +88,7 @@
                         ?FMT("move /y \"~s\" \"~s\" 1> nul",
                              [filename:nativename(Source),
                               filename:nativename(Dest)]),
-                        [{use_stdout, false}, return_on_error]),
+                        [{use_stdout, false}, abort_on_error]),
             case R of
                 [] ->
                     ok;
@@ -131,14 +131,14 @@
 delete_each_dir_win32([Dir | Rest]) ->
     {ok, []} = rebar_utils:sh(?FMT("rd /q /s \"~s\"",
                                    [filename:nativename(Dir)]),
-                              [{use_stdout, false}, return_on_error]),
+                              [{use_stdout, false}, abort_on_error]),
     delete_each_dir_win32(Rest).
 
 xcopy_win32(Source,Dest)->
     {ok, R} = rebar_utils:sh(
                 ?FMT("xcopy \"~s\" \"~s\" /q /y /e 2> nul",
                      [filename:nativename(Source), filename:nativename(Dest)]),
-                [{use_stdout, false}, return_on_error]),
+                [{use_stdout, false}, abort_on_error]),
     case length(R) > 0 of
         %% when xcopy fails, stdout is empty and and error message is printed
         %% to stderr (which is redirected to nul)
@@ -162,8 +162,10 @@
     cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))});
 cp_r_win32({false, Source},{false, Dest}) ->
     %% from file to file
-    {ok,_} = file:copy(Source, Dest),
-    ok;
+    case file:copy(Source, Dest) of
+        {ok,_} -> ok;
+        _ -> throw(rebar_abort)
+    end;
 cp_r_win32({true, SourceDir}, {false, DestDir}) ->
     case filelib:is_regular(DestDir) of
         true ->
diff --git a/src/rebar_lfe_compiler.erl b/src/rebar_lfe_compiler.erl
index 8488b0f..7d37914 100644
--- a/src/rebar_lfe_compiler.erl
+++ b/src/rebar_lfe_compiler.erl
@@ -71,7 +71,9 @@
             ?FAIL;
         _ ->
             ErlOpts = rebar_utils:erl_opts(Config),
-            Opts = [{i, "include"}, {outdir, "ebin"}, return] ++ ErlOpts,
+            LfeOpts = [report, verbose, {i, "include"}, {outdir, "ebin"},
+                       return],
+            Opts = LfeOpts ++ ErlOpts,
             case lfe_comp:file(Source, Opts) of
                 {ok, _Mod, Ws} ->
                     rebar_base_compiler:ok_tuple(Config, Source, Ws);
diff --git a/src/rebar_log.erl b/src/rebar_log.erl
index ba25332..abc2ac5 100644
--- a/src/rebar_log.erl
+++ b/src/rebar_log.erl
@@ -43,6 +43,9 @@
 %% Public API
 %% ===================================================================
 
+%% TODO: Once we have the new getopt version, use a flag that
+%% takes an optional arg but has a default value and fetch the
+%% setting via rebar_config, after it has been set in rebar:main.
 init(Config) ->
     Verbosity = rebar_config:get_global(Config, verbose, default_level()),
     case valid_level(Verbosity) of
@@ -60,9 +63,10 @@
 
 log(Device, Level, Str, Args) ->
     {ok, LogLevel} = application:get_env(rebar, log_level),
+    {ok, LogColored} = application:get_env(rebar, log_colored),
     case should_log(LogLevel, Level) of
         true ->
-            io:format(Device, log_prefix(Level) ++ Str, Args);
+            io:format(Device, log_prefix(Level, LogColored) ++ Str, Args);
         false ->
             ok
     end.
@@ -90,7 +94,40 @@
 should_log(error, _)     -> false;
 should_log(_, _)         -> false.
 
+log_prefix(Level, uncolored) ->
+    log_prefix(Level);
+log_prefix(Level, colored) ->
+    color_for_level(Level) ++ log_prefix(Level) ++ reset_color().
+
 log_prefix(debug) -> "DEBUG: ";
 log_prefix(info)  -> "INFO:  ";
 log_prefix(warn)  -> "WARN:  ";
 log_prefix(error) -> "ERROR: ".
+
+color_for_level(debug) ->
+    color_foreground(blue);
+color_for_level(info) ->
+    color_foreground(green);
+color_for_level(warn) ->
+    color_foreground(yellow);
+color_for_level(error) ->
+    color_bold() ++ color_foreground(red).
+
+%% -type color() :: 'black' | 'red' | 'green' | 'yellow'
+%%                | 'blue' | 'magenta' | 'cyan' | 'white'.
+%% -spec color_foreground(color()) -> string().
+%%
+%% To silence Dialyzer, disable following colors, because they're
+%% unused as of right now: black, magenta, cyan, white
+%%
+%% color_foreground(black)   -> "\e[30m";
+%% color_foreground(magenta) -> "\e[35m";
+%% color_foreground(cyan)    -> "\e[36m";
+%% color_foreground(white)   -> "\e[37m";
+color_foreground(red)     -> "\e[31m";
+color_foreground(green)   -> "\e[32m";
+color_foreground(yellow)  -> "\e[33m";
+color_foreground(blue)    -> "\e[34m".
+
+color_bold()  -> "\e[1m".
+reset_color() -> "\e[0m".
diff --git a/src/rebar_neotoma_compiler.erl b/src/rebar_neotoma_compiler.erl
index 5549dc4..e35dfc4 100644
--- a/src/rebar_neotoma_compiler.erl
+++ b/src/rebar_neotoma_compiler.erl
@@ -40,7 +40,7 @@
 %% source_ext: extension of peg source files
 -module(rebar_neotoma_compiler).
 
--export([compile/2]).
+-export([compile/2, clean/2]).
 
 %% for internal use only
 -export([info/2]).
@@ -59,17 +59,37 @@
                             option(module_ext, NeoOpts) ++ ".erl",
                             fun compile_neo/3, [{check_last_mod, true}]).
 
+-spec clean(rebar_config:config(), file:filename()) -> 'ok'.
+clean(Config, _AppFile) ->
+    NeoOpts = neotoma_opts(Config),
+    GeneratedFiles = neotoma_generated_files(
+                       option(out_dir, NeoOpts),
+                       option(module_ext, NeoOpts),
+                       neotoma_source_files(
+                         option(doc_root, NeoOpts),
+                         option(source_ext, NeoOpts)
+                        )
+                      ),
+    ok = rebar_file_utils:delete_each(GeneratedFiles),
+    ok.
+
 %% ============================================================================
 %% Internal functions
 %% ============================================================================
 
 info(help, compile) ->
+    info_help("Build Neotoma (*.peg) sources.~n");
+info(help, clean) ->
+    info_help("Delete *.peg build results").
+
+info_help(Description) ->
     ?CONSOLE(
-       "Build Neotoma (*.peg) sources.~n"
+       "~s.~n"
        "~n"
        "Valid rebar.config options:~n"
        "  ~p~n",
        [
+        Description,
         {neotoma_opts, [{doc_root, "src"},
                         {out_dir, "src"},
                         {source_ext, ".peg"},
@@ -161,3 +181,20 @@
         _ -> referenced_pegs1(sets:to_list(New), Config,
                               sets:union(New, Seen))
     end.
+
+neotoma_source_files(SrcDir, Ext) ->
+    lists:map(
+      fun filename:basename/1,
+      filelib:wildcard(filename:join([SrcDir, "*" ++ Ext]))
+     ).
+
+
+neotoma_generated_files(OutDir, ModExt, SourceFiles) ->
+    lists:map(
+      fun(PegFile) ->
+              Base = filename:rootname(PegFile),
+              NewName = Base ++ ModExt ++ ".erl",
+              filename:join(OutDir, NewName)
+      end,
+      SourceFiles
+     ).
diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl
index 5855589..9679c80 100644
--- a/src/rebar_port_compiler.erl
+++ b/src/rebar_port_compiler.erl
@@ -35,65 +35,16 @@
 
 -include("rebar.hrl").
 
-%% ===================================================================
-%% Public API
-%% ===================================================================
-
-%% Supported configuration variables:
-%%
-%% * port_specs - Erlang list of tuples of the forms
-%%                {ArchRegex, TargetFile, Sources, Options}
-%%                {ArchRegex, TargetFile, Sources}
-%%                {TargetFile, Sources}
-%%
-%% * port_env - Erlang list of key/value pairs which will control
-%%              the environment when running the compiler and linker.
-%%
-%%              By default, the following variables are defined:
-%%              CC       - C compiler
-%%              CXX      - C++ compiler
-%%              CFLAGS   - C compiler
-%%              CXXFLAGS - C++ compiler
-%%              LDFLAGS  - Link flags
-%%              ERL_CFLAGS  - default -I paths for erts and ei
-%%              ERL_LDFLAGS - default -L and -lerl_interface -lei
-%%              DRV_CFLAGS  - flags that will be used for compiling
-%%              DRV_LDFLAGS - flags that will be used for linking
-%%              EXE_CFLAGS  - flags that will be used for compiling
-%%              EXE_LDFLAGS - flags that will be used for linking
-%%              ERL_EI_LIBDIR - ei library directory
-%%              DRV_CXX_TEMPLATE  - C++ command template
-%%              DRV_CC_TEMPLATE   - C command template
-%%              DRV_LINK_TEMPLATE - Linker command template
-%%              EXE_CXX_TEMPLATE  - C++ command template
-%%              EXE_CC_TEMPLATE   - C command template
-%%              EXE_LINK_TEMPLATE - Linker command template
-%%              PORT_IN_FILES - contains a space separated list of input
-%%                   file(s), (used in command template)
-%%              PORT_OUT_FILE - contains the output filename (used in
-%%                   command template)
-%%
-%%              Note that if you wish to extend (vs. replace) these variables,
-%%              you MUST include a shell-style reference in your definition.
-%%              e.g. to extend CFLAGS, do something like:
-%%
-%%              {port_env, [{"CFLAGS", "$CFLAGS -MyOtherOptions"}]}
-%%
-%%              It is also possible to specify platform specific options
-%%              by specifying a triplet where the first string is a regex
-%%              that is checked against Erlang's system architecture string.
-%%              e.g. to specify a CFLAG that only applies to x86_64 on linux
-%%              do:
-%%
-%%              {port_env, [{"x86_64.*-linux", "CFLAGS",
-%%                           "$CFLAGS -X86Options"}]}
-%%
-
 -record(spec, {type::'drv' | 'exe',
+               link_lang::'cc' | 'cxx',
                target::file:filename(),
                sources = [] :: [file:filename(), ...],
                objects = [] :: [file:filename(), ...],
-               opts = [] ::list() | []}).
+               opts = [] :: list() | []}).
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
 
 compile(Config, AppFile) ->
     case get_specs(Config, AppFile) of
@@ -115,13 +66,15 @@
             %% Only relink if necessary, given the Target
             %% and list of new binaries
             lists:foreach(
-              fun(#spec{target=Target, objects=Bins, opts=Opts}) ->
+              fun(#spec{target=Target, objects=Bins, opts=Opts,
+                        link_lang=LinkLang}) ->
                       AllBins = [sets:from_list(Bins),
                                  sets:from_list(NewBins)],
                       Intersection = sets:intersection(AllBins),
                       case needs_link(Target, sets:to_list(Intersection)) of
                           true ->
-                              LinkTemplate = select_link_template(Target),
+                              LinkTemplate = select_link_template(LinkLang,
+                                                                  Target),
                               Env = proplists:get_value(env, Opts, SharedEnv),
                               Cmd = expand_command(LinkTemplate, Env,
                                                    string:join(Bins, " "),
@@ -164,12 +117,64 @@
        "~s.~n"
        "~n"
        "Valid rebar.config options:~n"
-       "  ~p~n"
-       "  ~p~n",
+       "port_specs - Erlang list of tuples of the forms~n"
+       "             {ArchRegex, TargetFile, Sources, Options}~n"
+       "             {ArchRegex, TargetFile, Sources}~n"
+       "             {TargetFile, Sources}~n"
+       "~n"
+       "             Examples:~n"
+       "             ~p~n"
+       "~n"
+       "port_env - Erlang list of key/value pairs which will control~n"
+       "           the environment when running the compiler and linker.~n"
+       "           Variables set in the surrounding system shell are taken~n"
+       "           into consideration when expanding port_env.~n"
+       "~n"
+       "           By default, the following variables are defined:~n"
+       "           CC       - C compiler~n"
+       "           CXX      - C++ compiler~n"
+       "           CFLAGS   - C compiler~n"
+       "           CXXFLAGS - C++ compiler~n"
+       "           LDFLAGS  - Link flags~n"
+       "           ERL_CFLAGS  - default -I paths for erts and ei~n"
+       "           ERL_LDFLAGS - default -L and -lerl_interface -lei~n"
+       "           DRV_CFLAGS  - flags that will be used for compiling~n"
+       "           DRV_LDFLAGS - flags that will be used for linking~n"
+       "           EXE_CFLAGS  - flags that will be used for compiling~n"
+       "           EXE_LDFLAGS - flags that will be used for linking~n"
+       "           ERL_EI_LIBDIR - ei library directory~n"
+       "           DRV_CXX_TEMPLATE      - C++ command template~n"
+       "           DRV_CC_TEMPLATE       - C command template~n"
+       "           DRV_LINK_TEMPLATE     - C Linker command template~n"
+       "           DRV_LINK_CXX_TEMPLATE - C++ Linker command template~n"
+       "           EXE_CXX_TEMPLATE      - C++ command template~n"
+       "           EXE_CC_TEMPLATE       - C command template~n"
+       "           EXE_LINK_TEMPLATE     - C Linker command template~n"
+       "           EXE_LINK_CXX_TEMPLATE - C++ Linker command template~n"
+       "~n"
+       "           Note that if you wish to extend (vs. replace) these variables,~n"
+       "           you MUST include a shell-style reference in your definition.~n"
+       "           e.g. to extend CFLAGS, do something like:~n"
+       "~n"
+       "           {port_env, [{\"CFLAGS\", \"$CFLAGS -MyOtherOptions\"}]}~n"
+       "~n"
+       "           It is also possible to specify platform specific options~n"
+       "           by specifying a triplet where the first string is a regex~n"
+       "           that is checked against Erlang's system architecture string.~n"
+       "           e.g. to specify a CFLAG that only applies to x86_64 on linux~n"
+       "           do:~n"
+       "           {port_env, [{\"x86_64.*-linux\", \"CFLAGS\",~n"
+       "                        \"$CFLAGS -X86Options\"}]}~n"
+       "~n"
+       "Cross-arch environment variables to configure toolchain:~n"
+       "  REBAR_TARGET_ARCH to set the tool chain name to use~n"
+       "  REBAR_TARGET_ARCH_WORDSIZE (optional - "
+       "if CC fails to determine word size)~n"
+       "  fallback word size is 32~n"
+       "  REBAR_TARGET_ARCH_VSN (optional - "
+       "if a special version of CC/CXX is requested)~n",
        [
         Description,
-        {port_env, [{"CFLAGS", "$CFLAGS -Ifoo"},
-                    {"freebsd", "LDFLAGS", "$LDFLAGS -lfoo"}]},
         {port_specs, [{"priv/so_name.so", ["c_src/*.c"]},
                       {"linux", "priv/hello_linux", ["c_src/hello_linux.c"]},
                       {"linux", "priv/hello_linux", ["c_src/*.c"], [{env, []}]}]}
@@ -183,8 +188,10 @@
 
     %% Get any port-specific envs; use port_env first and then fallback
     %% to port_envs for compatibility
-    RawPortEnv = rebar_config:get_list(Config, port_env,
-                          rebar_config:get_list(Config, port_envs, [])),
+    RawPortEnv = rebar_config:get_list(
+                   Config,
+                   port_env,
+                   rebar_config:get_list(Config, port_envs, [])),
 
     PortEnv = filter_env(RawPortEnv, []),
     Defines = get_defines(Config),
@@ -209,29 +216,72 @@
 %%
 
 compile_sources(Config, Specs, SharedEnv) ->
-    lists:foldl(
-      fun(#spec{sources=Sources, type=Type, opts=Opts}, NewBins) ->
-              Env = proplists:get_value(env, Opts, SharedEnv),
-              compile_each(Config, Sources, Type, Env, NewBins)
-      end, [], Specs).
+    {NewBins, Db} =
+        lists:foldl(
+          fun(#spec{sources=Sources, type=Type, opts=Opts}, Acc) ->
+                  Env = proplists:get_value(env, Opts, SharedEnv),
+                  compile_each(Config, Sources, Type, Env, Acc)
+          end, {[], []}, Specs),
+    %% Rewrite clang compile commands database file only if something
+    %% was compiled.
+    case NewBins of
+        [] ->
+            ok;
+        _ ->
+            {ok, ClangDbFile} = file:open("compile_commands.json", [write]),
+            ok = io:fwrite(ClangDbFile, "[~n", []),
+            lists:foreach(fun(E) -> ok = io:fwrite(ClangDbFile, E, []) end, Db),
+            ok = io:fwrite(ClangDbFile, "]~n", []),
+            ok = file:close(ClangDbFile)
+    end,
+    NewBins.
 
-compile_each(_Config, [], _Type, _Env, NewBins) ->
-    lists:reverse(NewBins);
-compile_each(Config, [Source | Rest], Type, Env, NewBins) ->
+compile_each(_Config, [], _Type, _Env, {NewBins, CDB}) ->
+    {lists:reverse(NewBins), lists:reverse(CDB)};
+compile_each(Config, [Source | Rest], Type, Env, {NewBins, CDB}) ->
     Ext = filename:extension(Source),
     Bin = replace_extension(Source, Ext, ".o"),
+    Template = select_compile_template(Type, compiler(Ext)),
+    Cmd = expand_command(Template, Env, Source, Bin),
+    CDBEnt = cdb_entry(Source, Cmd, Rest),
+    NewCDB = [CDBEnt | CDB],
     case needs_compile(Source, Bin) of
         true ->
-            Template = select_compile_template(Type, compiler(Ext)),
-            Cmd = expand_command(Template, Env, Source, Bin),
             ShOpts = [{env, Env}, return_on_error, {use_stdout, false}],
             exec_compiler(Config, Source, Cmd, ShOpts),
-            compile_each(Config, Rest, Type, Env, [Bin | NewBins]);
+            compile_each(Config, Rest, Type, Env,
+                         {[Bin | NewBins], NewCDB});
         false ->
             ?INFO("Skipping ~s\n", [Source]),
-            compile_each(Config, Rest, Type, Env, NewBins)
+            compile_each(Config, Rest, Type, Env, {NewBins, NewCDB})
     end.
 
+%% Generate a clang compilation db entry for Src and Cmd
+cdb_entry(Src, Cmd, SrcRest) ->
+    %% Omit all variables from cmd, and use that as cmd in
+    %% CDB, because otherwise clang-* will complain about it.
+    CDBCmd = string:join(
+               lists:filter(
+                 fun("$"++_) -> false;
+                    (_)      -> true
+                 end,
+                 string:tokens(Cmd, " ")),
+               " "),
+
+    Cwd = rebar_utils:get_cwd(),
+    %% If there are more source files, make sure we end the CDB entry
+    %% with a comma.
+    Sep = case SrcRest of
+              [] -> "~n";
+              _  -> ",~n"
+          end,
+    %% CDB entry
+    ?FMT("{ \"file\"      : ~p~n"
+         ", \"directory\" : ~p~n"
+         ", \"command\"   : ~p~n"
+         "}~s",
+         [Src, Cwd, CDBCmd, Sep]).
+
 exec_compiler(Config, Source, Cmd, ShOpts) ->
     case rebar_utils:sh(Cmd, ShOpts) of
         {error, {_RC, RawError}} ->
@@ -321,6 +371,7 @@
     Sources = port_sources(rebar_config:get_list(Config, port_sources,
                                                  ["c_src/*.c"])),
     #spec { type = target_type(Target),
+            link_lang = cc,
             target = maybe_switch_extension(os:type(), Target),
             sources = Sources,
             objects = port_objects(Sources) }.
@@ -341,9 +392,18 @@
     get_port_spec(Config, OsType, {Arch, Target, Sources, []});
 get_port_spec(Config, OsType, {_Arch, Target, Sources, Opts}) ->
     SourceFiles = port_sources(Sources),
+    LinkLang =
+        case lists:any(
+               fun(Src) -> compiler(filename:extension(Src)) == "$CXX" end,
+               SourceFiles)
+        of
+            true  -> cxx;
+            false -> cc
+        end,
     ObjectFiles = port_objects(SourceFiles),
     #spec{type=target_type(Target),
           target=maybe_switch_extension(OsType, Target),
+          link_lang=LinkLang,
           sources=SourceFiles,
           objects=ObjectFiles,
           opts=port_opts(Config, Opts)}.
@@ -546,10 +606,12 @@
 select_compile_exe_template("$CC")  -> "EXE_CC_TEMPLATE";
 select_compile_exe_template("$CXX") -> "EXE_CXX_TEMPLATE".
 
-select_link_template(Target) ->
-    case target_type(Target) of
-        drv -> "DRV_LINK_TEMPLATE";
-        exe -> "EXE_LINK_TEMPLATE"
+select_link_template(LinkLang, Target) ->
+    case {LinkLang, target_type(Target)} of
+        {cc,  drv} -> "DRV_LINK_TEMPLATE";
+        {cxx, drv} -> "DRV_LINK_CXX_TEMPLATE";
+        {cc,  exe} -> "EXE_LINK_TEMPLATE";
+        {cxx, exe} -> "EXE_LINK_CXX_TEMPLATE"
     end.
 
 target_type(Target) -> target_type1(filename:extension(Target)).
@@ -568,29 +630,48 @@
     end.
 
 default_env() ->
+    Arch = os:getenv("REBAR_TARGET_ARCH"),
+    Vsn = os:getenv("REBAR_TARGET_ARCH_VSN"),
     [
-     {"CC" , "cc"},
-     {"CXX", "c++"},
+     {"CC", get_tool(Arch, Vsn, "gcc", "cc")},
+     {"CXX", get_tool(Arch, Vsn, "g++", "c++")},
+     {"AR", get_tool(Arch, "ar", "ar")},
+     {"AS", get_tool(Arch, "as", "as")},
+     {"CPP", get_tool(Arch, Vsn, "cpp", "cpp")},
+     {"LD", get_tool(Arch, "ld", "ld")},
+     {"RANLIB", get_tool(Arch, Vsn, "ranlib", "ranlib")},
+     {"STRIP", get_tool(Arch, "strip", "strip")},
+     {"NM", get_tool(Arch, "nm", "nm")},
+     {"OBJCOPY", get_tool(Arch, "objcopy", "objcopy")},
+     {"OBJDUMP", get_tool(Arch, "objdump", "objdump")},
+
      {"DRV_CXX_TEMPLATE",
       "$CXX -c $CXXFLAGS $DRV_CFLAGS $PORT_IN_FILES -o $PORT_OUT_FILE"},
      {"DRV_CC_TEMPLATE",
       "$CC -c $CFLAGS $DRV_CFLAGS $PORT_IN_FILES -o $PORT_OUT_FILE"},
      {"DRV_LINK_TEMPLATE",
       "$CC $PORT_IN_FILES $LDFLAGS $DRV_LDFLAGS -o $PORT_OUT_FILE"},
+     {"DRV_LINK_CXX_TEMPLATE",
+      "$CXX $PORT_IN_FILES $LDFLAGS $DRV_LDFLAGS -o $PORT_OUT_FILE"},
      {"EXE_CXX_TEMPLATE",
       "$CXX -c $CXXFLAGS $EXE_CFLAGS $PORT_IN_FILES -o $PORT_OUT_FILE"},
      {"EXE_CC_TEMPLATE",
       "$CC -c $CFLAGS $EXE_CFLAGS $PORT_IN_FILES -o $PORT_OUT_FILE"},
      {"EXE_LINK_TEMPLATE",
       "$CC $PORT_IN_FILES $LDFLAGS $EXE_LDFLAGS -o $PORT_OUT_FILE"},
+     {"EXE_LINK_CXX_TEMPLATE",
+      "$CXX $PORT_IN_FILES $LDFLAGS $EXE_LDFLAGS -o $PORT_OUT_FILE"},
      {"DRV_CFLAGS" , "-g -Wall -fPIC -MMD $ERL_CFLAGS"},
      {"DRV_LDFLAGS", "-shared $ERL_LDFLAGS"},
      {"EXE_CFLAGS" , "-g -Wall -fPIC -MMD $ERL_CFLAGS"},
      {"EXE_LDFLAGS", "$ERL_LDFLAGS"},
 
-     {"ERL_CFLAGS", lists:concat([" -I\"", erl_interface_dir(include),
-                                  "\" -I\"", filename:join(erts_dir(), "include"),
-                                  "\" "])},
+     {"ERL_CFLAGS", lists:concat(
+                      [
+                       " -I\"", erl_interface_dir(include),
+                       "\" -I\"", filename:join(erts_dir(), "include"),
+                       "\" "
+                      ])},
      {"ERL_EI_LIBDIR", lists:concat(["\"", erl_interface_dir(lib), "\""])},
      {"ERL_LDFLAGS"  , " -L$ERL_EI_LIBDIR -lerl_interface -lei"},
      {"ERLANG_ARCH"  , rebar_utils:wordsize()},
@@ -604,20 +685,20 @@
      {"solaris.*-64$", "CXXFLAGS", "-D_REENTRANT -m64 $CXXFLAGS"},
      {"solaris.*-64$", "LDFLAGS", "-m64 $LDFLAGS"},
 
-     %% Linux specific flags for multiarch
-     {"linux.*-64$", "CFLAGS", "-m64 $CFLAGS"},
-     {"linux.*-64$", "CXXFLAGS", "-m64 $CXXFLAGS"},
-     {"linux.*-64$", "LDFLAGS", "$LDFLAGS"},
-
      %% OS X Leopard flags for 64-bit
      {"darwin9.*-64$", "CFLAGS", "-m64 $CFLAGS"},
      {"darwin9.*-64$", "CXXFLAGS", "-m64 $CXXFLAGS"},
-     {"darwin9.*-64$", "LDFLAGS", "-arch x86_64 $LDFLAGS"},
+     {"darwin9.*-64$", "LDFLAGS", "-arch x86_64 -flat_namespace -undefined suppress $LDFLAGS"},
+
+     %% OS X Lion onwards flags for 64-bit
+     {"darwin1[0-4].*-64$", "CFLAGS", "-m64 $CFLAGS"},
+     {"darwin1[0-4].*-64$", "CXXFLAGS", "-m64 $CXXFLAGS"},
+     {"darwin1[0-4].*-64$", "LDFLAGS", "-arch x86_64 -flat_namespace -undefined suppress $LDFLAGS"},
 
      %% OS X Snow Leopard, Lion, and Mountain Lion flags for 32-bit
      {"darwin1[0-2].*-32", "CFLAGS", "-m32 $CFLAGS"},
      {"darwin1[0-2].*-32", "CXXFLAGS", "-m32 $CXXFLAGS"},
-     {"darwin1[0-2].*-32", "LDFLAGS", "-arch i386 $LDFLAGS"},
+     {"darwin1[0-2].*-32", "LDFLAGS", "-arch i386 -flat_namespace -undefined suppress $LDFLAGS"},
 
      %% Windows specific flags
      %% add MS Visual C++ support to rebar on Windows
@@ -639,7 +720,17 @@
      {"win32", "EXE_LINK_TEMPLATE",
       "$LINKER $PORT_IN_FILES $LDFLAGS $EXE_LDFLAGS /OUT:$PORT_OUT_FILE"},
      %% ERL_CFLAGS are ok as -I even though strictly it should be /I
-     {"win32", "ERL_LDFLAGS", " /LIBPATH:$ERL_EI_LIBDIR erl_interface.lib ei.lib"},
+     {"win32", "ERL_LDFLAGS",
+      " /LIBPATH:$ERL_EI_LIBDIR erl_interface.lib ei.lib"},
      {"win32", "DRV_CFLAGS", "/Zi /Wall $ERL_CFLAGS"},
      {"win32", "DRV_LDFLAGS", "/DLL $ERL_LDFLAGS"}
     ].
+
+get_tool(Arch, Tool, Default) ->
+    get_tool(Arch, false, Tool, Default).
+
+get_tool(false, _, _, Default) -> Default;
+get_tool("", _, _, Default) -> Default;
+get_tool(Arch, false, Tool, _Default) -> Arch++"-"++Tool;
+get_tool(Arch, "", Tool, _Default) -> Arch++"-"++Tool;
+get_tool(Arch, Vsn, Tool, _Default) -> Arch++"-"++Tool++"-"++Vsn.
diff --git a/src/rebar_qc.erl b/src/rebar_qc.erl
index 80b2102..9fa2465 100644
--- a/src/rebar_qc.erl
+++ b/src/rebar_qc.erl
@@ -4,7 +4,7 @@
 %%
 %% rebar: Erlang Build Tools
 %%
-%% Copyright (c) 2011-2014 Tuncer Ayaz
+%% Copyright (c) 2011-2016 Tuncer Ayaz
 %%
 %% Permission is hereby granted, free of charge, to any person obtaining a copy
 %% of this software and associated documentation files (the "Software"), to deal
@@ -43,16 +43,13 @@
 %% ===================================================================
 
 qc(Config, _AppFile) ->
-    ?CONSOLE("NOTICE: Using experimental 'qc' command~n", []),
     run_qc(Config, qc_opts(Config)).
 
 triq(Config, _AppFile) ->
-    ?CONSOLE("NOTICE: Using experimental 'triq' command~n", []),
     ok = load_qc_mod(triq),
     run_qc(Config, qc_opts(Config), triq).
 
 eqc(Config, _AppFile) ->
-    ?CONSOLE("NOTICE: Using experimental 'eqc' command~n", []),
     ok = load_qc_mod(eqc),
     run_qc(Config, qc_opts(Config), eqc).
 
diff --git a/src/rebar_rand_compat.erl b/src/rebar_rand_compat.erl
new file mode 100644
index 0000000..849ee35
--- /dev/null
+++ b/src/rebar_rand_compat.erl
@@ -0,0 +1,178 @@
+%%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%%% ex: ts=4 sw=4 et
+%%%
+%%% Copyright (c) 2016 Tuncer Ayaz
+%%%
+%%% Permission to use, copy, modify, and/or distribute this software
+%%% for any purpose with or without fee is hereby granted, provided
+%%% that the above copyright notice and this permission notice appear
+%%% in all copies.
+%%%
+%%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+%%% WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+%%% WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+%%% AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+%%% CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+%%% LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+%%% NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+%%% CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(rebar_rand_compat).
+
+%% API
+-export([ init/0
+        , init/1
+        ]).
+
+-define(DEFAULT_MODNAME, "rnd").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Generate, compile and load rnd module.
+%% @end
+%%--------------------------------------------------------------------
+-spec init() -> {'ok', module()}.
+init() ->
+    init(?DEFAULT_MODNAME).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Generate, compile and load ModName module.
+%% @end
+%%--------------------------------------------------------------------
+-spec init(string()) -> {'ok', module()}.
+init(ModName) ->
+    %% First, select the right module, then generate the appropriate code as a
+    %% string, and finally compile and load it as ModName.
+    Src = select(ModName),
+    {ok, Mod, Bin, []} = compile(Src),
+    {module, Mod} = code:load_binary(Mod, ModName++".erl", Bin),
+    {ok, Mod}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+%% Select right rand module and return wrapper module's source as string
+-spec select(string()) -> string().
+select(ModName) ->
+    case code:which(rand) of
+        non_existing ->
+            src(ModName, fun funs_random/0);
+        _ ->
+            src(ModName, fun funs_rand/0)
+    end.
+
+%% Return module's implementation as a string.
+-spec src(string(), fun(() -> binary())) -> string().
+src(ModName, GenFuns) ->
+    lists:flatten(
+      io_lib:format(
+        <<"
+-module(~s).
+-export([ seed/0
+        , seed/1
+        , uniform/0
+        , uniform/1
+        , uniform_s/1
+        , uniform_s/2
+        ]).
+
+%% Functions
+~s
+">>
+, [ModName, GenFuns()])).
+
+%% random.beam wrapper
+funs_random() ->
+    <<"
+seed()           -> random:seed().
+seed(Exp)        -> random:seed(Exp).
+uniform()        -> random:uniform().
+uniform(N)       -> random:uniform(N).
+uniform_s(St)    -> random:uniform_s(St).
+uniform_s(N, St) -> random:uniform_s(N, St).
+">>.
+
+%% rand.beam wrapper
+funs_rand() ->
+    <<"
+seed()           -> rand:seed(exsplus).
+seed(Exp)        -> rand:seed(exsplus, Exp).
+uniform()        -> rand:uniform().
+uniform(N)       -> rand:uniform(N).
+uniform_s(St)    -> rand:uniform_s(St).
+uniform_s(N, St) -> rand:uniform_s(N, St).
+">>.
+
+compile(String) ->
+    Forms = convert(String ++ eof, []),
+    compile:forms(Forms, [return]).
+
+%% Parse string into forms for compiler.
+convert({done, {eof, _EndLocation}, _LeftOverChars}, Acc)->
+    %% Finished
+    lists:reverse(Acc);
+convert({done, {error, ErrorInfo, _EndLocation}, _LeftOverChars}, _Acc)->
+    ErrorInfo;
+convert({done, {ok, Tokens, _EndLocation}, LeftOverChars}, Acc)->
+    case erl_parse:parse_form(Tokens) of
+        {ok, AbsForm} ->
+            convert(LeftOverChars, [AbsForm|Acc]);
+        {error, AbsForm} ->
+            convert(LeftOverChars, AbsForm)
+    end;
+convert({more, Continuation}, Acc)->
+    convert(erl_scan:tokens(Continuation, [], 1), Acc);
+convert(String, Acc) ->
+    convert(erl_scan:tokens([], String, 1), Acc).
+
+%%%===================================================================
+%%% Tests
+%%%===================================================================
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+init_test() ->
+    DefMod = list_to_atom(?DEFAULT_MODNAME),
+    ok = unload(DefMod),
+    ?assertMatch(false, code:is_loaded(DefMod)),
+    ?assertMatch({ok, DefMod}, init()),
+    ?assertMatch({file, _}, code:is_loaded(DefMod)),
+    check_api(DefMod),
+    CustomMod = foornd,
+    CustomName = "foornd",
+    ok = unload(CustomMod),
+    ?assertMatch(false, code:is_loaded(CustomMod)),
+    ?assertMatch({ok, CustomMod}, init(CustomName)),
+    ?assertMatch({file, _}, code:is_loaded(CustomMod)),
+    check_api(CustomMod).
+
+unload(Mod) ->
+    case code:is_loaded(Mod) of
+        false ->
+            ok;
+        {file, _} ->
+            code:delete(Mod),
+            code:purge(Mod),
+            ok
+    end.
+
+check_api(Mod) ->
+    Exports = [ {seed, 0}
+              , {seed, 1}
+              , {uniform, 0}
+              , {uniform, 1}
+              , {uniform_s, 1}
+              , {uniform_s, 2}
+              , {module_info, 0}
+              , {module_info, 1}
+              ],
+    ?assertMatch(Exports, Mod:module_info(exports)).
+
+-endif.
diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl
index 5eecf74..684578a 100644
--- a/src/rebar_require_vsn.erl
+++ b/src/rebar_require_vsn.erl
@@ -31,7 +31,8 @@
 -include("rebar.hrl").
 
 -export([compile/2,
-         eunit/2]).
+         eunit/2,
+         version_tuple/1]).
 
 %% for internal use only
 -export([info/2,
@@ -103,12 +104,12 @@
     case rebar_config:get(Config, require_min_otp_vsn, undefined) of
         undefined -> ?DEBUG("Min OTP version unconfigured~n", []);
         MinOtpVsn ->
-            {MinMaj, MinMin} = version_tuple(ShouldAbort, MinOtpVsn,
+            {MinMaj, MinMin, MinPatch} = version_tuple(ShouldAbort, MinOtpVsn,
                                              "configured"),
-            {OtpMaj, OtpMin} = version_tuple(ShouldAbort,
+            {OtpMaj, OtpMin, OtpPatch} = version_tuple(ShouldAbort,
                                              erlang:system_info(otp_release),
                                              "OTP Release"),
-            case {OtpMaj, OtpMin} >= {MinMaj, MinMin} of
+            case {OtpMaj, OtpMin, OtpPatch} >= {MinMaj, MinMin, MinPatch} of
                 true ->
                     ?DEBUG("~s satisfies the requirement for vsn ~s~n",
                            [erlang:system_info(otp_release),
@@ -122,12 +123,17 @@
             end
     end.
 
+version_tuple(OtpRelease) ->
+    version_tuple(keep_going, OtpRelease, "").
+
 version_tuple(ShouldAbort, OtpRelease, Type) ->
-    case re:run(OtpRelease, "R?(\\d+)B?-?(\\d+)?", [{capture, all, list}]) of
+    case re:run(OtpRelease, "R?(\\d+)B?\.?(\\d+)?\.?-?(\\d+)?", [{capture, all, list}]) of
+        {match, [_Full, Maj, Min, Patch]} ->
+            {list_to_integer(Maj), list_to_integer(Min), list_to_integer(Patch)};
         {match, [_Full, Maj, Min]} ->
-            {list_to_integer(Maj), list_to_integer(Min)};
+            {list_to_integer(Maj), list_to_integer(Min), 0};
         {match, [_Full, Maj]} ->
-            {list_to_integer(Maj), 0};
+            {list_to_integer(Maj), 0, 0};
         nomatch ->
             maybe_abort(ShouldAbort,
                         "Cannot parse ~s version string: ~s~n",
diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl
index 23da5a3..01edbd2 100644
--- a/src/rebar_upgrade.erl
+++ b/src/rebar_upgrade.erl
@@ -44,18 +44,24 @@
 'generate-upgrade'(Config0, ReltoolFile) ->
     %% Get the old release path
     {Config, ReltoolConfig} = rebar_rel_utils:load_config(Config0, ReltoolFile),
+    ?DEBUG("reltool.config: ~p~n", [ReltoolConfig]),
     TargetParentDir = rebar_rel_utils:get_target_parent_dir(Config,
                                                             ReltoolConfig),
     TargetDir = rebar_rel_utils:get_target_dir(Config, ReltoolConfig),
+    ?DEBUG("target dir: ~p~n", [TargetDir]),
 
     PrevRelPath = rebar_rel_utils:get_previous_release_path(Config),
     OldVerPath = filename:join([TargetParentDir, PrevRelPath]),
+    ?DEBUG("old version path: ~p~n", [OldVerPath]),
 
     %% Run checks to make sure that building a package is possible
     {NewVerPath, NewName, NewVer, OldVer} = run_checks(Config, OldVerPath,
                                                        ReltoolConfig),
+    ?DEBUG("old version: ~p~n", [OldVer]),
     NameVer = NewName ++ "_" ++ NewVer,
     OldRelName = get_old_rel_name(OldVerPath, OldVer, NewName),
+    ?DEBUG("new version path: ~p~n", [NewVerPath]),
+    ?DEBUG("old version: ~p~n", [NewVer]),
 
     %% Save the code path prior to doing anything
     OrigPath = code:get_path(),
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 9681756..6a62d34 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -67,7 +67,10 @@
          processing_base_dir/1,
          processing_base_dir/2,
          patch_env/2,
-         cleanup_code_path/1]).
+         cleanup_code_path/1,
+         init_vsn_cache/1,
+         save_vsn_cache/1
+        ]).
 
 %% for internal use only
 -export([otp_release/0]).
@@ -92,19 +95,24 @@
             false
     end.
 
+%%
+%% REBAR_TARGET_ARCH, if used, should be set to the "standard"
+%% target string. That is a prefix for binutils tools.
+%% "x86_64-linux-gnu" or "arm-linux-gnueabi" are good candidates
+%% ${REBAR_TARGET_ARCH}-gcc, ${REBAR_TARGET_ARCH}-ld ...
+%%
 get_arch() ->
-    Words = wordsize(),
-    otp_release() ++ "-"
-        ++ erlang:system_info(system_architecture) ++ "-" ++ Words.
+    Arch = os:getenv("REBAR_TARGET_ARCH"),
+    Words = wordsize(Arch),
+    otp_release() ++ "-" ++ get_system_arch(Arch) ++ "-" ++ Words.
+
+get_system_arch(Arch) when Arch =:= false; Arch =:= "" ->
+    erlang:system_info(system_architecture);
+get_system_arch(Arch) ->
+    Arch.
 
 wordsize() ->
-    try erlang:system_info({wordsize, external}) of
-        Val ->
-            integer_to_list(8 * Val)
-    catch
-        error:badarg ->
-            integer_to_list(8 * erlang:system_info(wordsize))
-    end.
+    wordsize(os:getenv("REBAR_TARGET_ARCH")).
 
 sh_send(Command0, String, Options0) ->
     ?INFO("sh_send info:\n\tcwd: ~p\n\tcmd: ~s < ~s\n",
@@ -263,6 +271,23 @@
             re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts)
     end.
 
+init_vsn_cache(Config) ->
+    init_vsn_cache(Config, os:getenv("REBAR_VSN_CACHE_FILE")).
+init_vsn_cache(Config, false) ->
+    rebar_config:set_xconf(Config, vsn_cache, dict:new());
+init_vsn_cache(Config, CacheFile) ->
+    {ok, CacheList} = file:consult(CacheFile),
+    CacheDict = dict:from_list(CacheList),
+    rebar_config:set_xconf(Config, vsn_cache, CacheDict).
+
+save_vsn_cache(Config) ->
+    save_vsn_cache(Config, os:getenv("REBAR_VSN_CACHE_FILE")).
+save_vsn_cache(_Config, false) ->
+    ok;
+save_vsn_cache(Config, CacheFile) ->
+    file:write_file(CacheFile,
+        [io_lib:format("~p.~n", [X]) || X <- dict:to_list(rebar_config:get_xconf(Config, vsn_cache))]).
+
 vcs_vsn(Config, Vsn, Dir) ->
     Key = {Vsn, Dir},
     Cache = rebar_config:get_xconf(Config, vsn_cache),
@@ -271,6 +296,7 @@
             VsnString = vcs_vsn_1(Vsn, Dir),
             Cache1 = dict:store(Key, VsnString, Cache),
             Config1 = rebar_config:set_xconf(Config, vsn_cache, Cache1),
+            _ = save_vsn_cache(Config1),
             {Config1, VsnString};
         {ok, VsnString} ->
             {Config, VsnString}
@@ -673,3 +699,145 @@
         _ ->
             code:set_path(OrigPath)
     end.
+
+wordsize(Arch) when Arch =:= false; Arch =:= "" ->
+    native_wordsize();
+wordsize(Arch) ->
+    AllArchs = [
+                {"i686","32"},
+                {"i386","32"},
+                {"arm","32"},
+                {"aarch64", "64"},
+                {"x86_64","64"}
+               ],
+    case match_wordsize(Arch, AllArchs) of
+        false ->
+            case cross_wordsize(Arch) of
+                "" ->
+                    env_wordsize(os:getenv("REBAR_TARGET_ARCH_WORDSIZE"));
+                WordSize ->
+                    WordSize
+            end;
+        {_, Wordsize} ->
+            Wordsize
+    end.
+
+match_wordsize(Arch, [V={Match,_Bits}|Vs]) ->
+    case re:run(Arch, Match, [{capture, none}]) of
+        match ->
+            V;
+        nomatch ->
+            match_wordsize(Arch, Vs)
+    end;
+match_wordsize(_Arch, []) ->
+    false.
+
+env_wordsize(Wordsize) when Wordsize =:= false;
+                            Wordsize =:= "" ->
+    ?WARN("REBAR_TARGET_ARCH_WORDSIZE not set, assuming 32\n", []),
+    "32";
+env_wordsize(Wordsize) ->
+    case Wordsize of
+        "16" -> Wordsize;
+        "32" -> Wordsize;
+        "64" -> Wordsize;
+        _ ->
+            ?WARN("REBAR_TARGET_ARCH_WORDSIZE bad value: ~p\n", [Wordsize]),
+            "32"
+    end.
+
+%%
+%% Find out the word size of the target by using Arch-gcc
+%%
+cross_wordsize(Arch) ->
+    cross_sizeof(Arch, "void*").
+
+%%
+%% Find the size of target Type using a specially crafted C file
+%% that will report an error on the line of the byte size of the type.
+%%
+cross_sizeof(Arch, Type) ->
+    Compiler = if Arch =:= "" -> "cc";
+                  true -> Arch ++ "-gcc"
+               end,
+    TempFile = mktempfile(".c"),
+    ok = file:write_file(TempFile,
+                         <<"int t01 [1 - 2*(((long) (sizeof (TYPE))) == 1)];\n"
+                           "int t02 [1 - 2*(((long) (sizeof (TYPE))) == 2)];\n"
+                           "int t03 [1 - 2*(((long) (sizeof (TYPE))) == 3)];\n"
+                           "int t04 [1 - 2*(((long) (sizeof (TYPE))) == 4)];\n"
+                           "int t05 [1 - 2*(((long) (sizeof (TYPE))) == 5)];\n"
+                           "int t06 [1 - 2*(((long) (sizeof (TYPE))) == 6)];\n"
+                           "int t07 [1 - 2*(((long) (sizeof (TYPE))) == 7)];\n"
+                           "int t08 [1 - 2*(((long) (sizeof (TYPE))) == 8)];\n"
+                           "int t09 [1 - 2*(((long) (sizeof (TYPE))) == 9)];\n"
+                           "int t10 [1 - 2*(((long) (sizeof (TYPE))) == 10)];\n"
+                           "int t11 [1 - 2*(((long) (sizeof (TYPE))) == 11)];\n"
+                           "int t12 [1 - 2*(((long) (sizeof (TYPE))) == 12)];\n"
+                           "int t13 [1 - 2*(((long) (sizeof (TYPE))) == 13)];\n"
+                           "int t14 [1 - 2*(((long) (sizeof (TYPE))) == 14)];\n"
+                           "int t15 [1 - 2*(((long) (sizeof (TYPE))) == 15)];\n"
+                           "int t16 [1 - 2*(((long) (sizeof (TYPE))) == 16)];\n"
+                         >>),
+    Cmd = Compiler ++ " -DTYPE=\""++Type++"\" " ++ TempFile,
+    ShOpts = [{use_stdout, false}, return_on_error],
+    {error, {_,Res}} = sh(Cmd, ShOpts),
+    ok = file:delete(TempFile),
+    case string:tokens(Res, ":") of
+        [_, Ln | _] ->
+            try list_to_integer(Ln) of
+                NumBytes -> integer_to_list(NumBytes*8)
+            catch
+                error:_ ->
+                    ""
+            end;
+        _ ->
+            ""
+    end.
+
+mktempfile(Suffix) ->
+    {A,B,C} = rebar_now(),
+    Dir = temp_dir(),
+    File = "rebar_"++os:getpid()++
+        integer_to_list(A)++"_"++
+        integer_to_list(B)++"_"++
+        integer_to_list(C)++Suffix,
+    filename:join(Dir, File).
+
+temp_dir() ->
+    case os:type() of
+        {win32, _} -> windows_temp_dir();
+        _ -> "/tmp"
+    end.
+
+windows_temp_dir() ->
+    case os:getenv("TEMP") of
+        false ->
+            case os:getenv("TMP") of
+                false -> "C:/WINDOWS/TEMP";
+                TMP -> TMP
+            end;
+        TEMP -> TEMP
+    end.
+
+rebar_now() ->
+    case erlang:function_exported(erlang, timestamp, 0) of
+        true ->
+            erlang:timestamp();
+        false ->
+            %% erlang:now/0 was deprecated in 18.0. One solution to avoid the
+            %% deprecation warning is to use
+            %% -compile({nowarn_deprecated_function, [{erlang, now, 0}]}), but
+            %% that would raise a warning in versions older than 18.0.  Calling
+            %% erlang:now/0 via apply/3 avoids that.
+            apply(erlang, now, [])
+    end.
+
+native_wordsize() ->
+    try erlang:system_info({wordsize, external}) of
+        Val ->
+            integer_to_list(8 * Val)
+    catch
+        error:badarg ->
+            integer_to_list(8 * erlang:system_info(wordsize))
+    end.
diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl
index 5eb4499..ddfb029 100644
--- a/src/rebar_xref.erl
+++ b/src/rebar_xref.erl
@@ -40,6 +40,8 @@
 %% for internal use only
 -export([info/2]).
 
+-dialyzer({no_opaque, find_function_source/4}).
+
 %% ===================================================================
 %% Public API
 %% ===================================================================
@@ -59,6 +61,11 @@
     OrigPath = code:get_path(),
     true = code:add_path(rebar_utils:ebin_dir()),
 
+    %% Add extra paths to code path to, for example, be used
+    %% when behaviour modules are defined.
+    lists:foreach(fun(P) -> true = code:add_path(P) end,
+                  rebar_config:get(Config, xref_extra_paths, [])),
+
     %% Get list of xref checks we want to run
     ConfXrefChecks = rebar_config:get(Config, xref_checks,
                                       [exports_not_used,
diff --git a/src/rmemo.erl b/src/rmemo.erl
index dd3642f..7de29fc 100644
--- a/src/rmemo.erl
+++ b/src/rmemo.erl
@@ -184,18 +184,14 @@
 
 -spec ets_tab() -> ets:tab().
 ets_tab() ->
-    ErtsApp = filename:join(code:lib_dir(erts, ebin), "erts.app"),
     Concurrency =
-        %% If erts.app exists, we run on at least R14. That means we
-        %% can use ets read_concurrency.
-        %% TODO: Remove and revert to vanilla memo.erl from
-        %% https://github.com/tuncer/memo once we require at least
-        %% R14B and drop support for R13.
-        case filelib:is_regular(ErtsApp) of
+        %% read_concurrency was added in R14. If we're running R13,
+        %% do not try to use it.
+        case erlang:system_info(version) =< "5.8.3" of
             true ->
-                [{read_concurrency, true}];
+                [];
             false ->
-                []
+                [{read_concurrency, true}]
         end,
     ets:new(
       ?TABLE,
diff --git a/test/rebar_compiler_tests.erl b/test/rebar_compiler_tests.erl
index 3ed600b..2afbc92 100644
--- a/test/rebar_compiler_tests.erl
+++ b/test/rebar_compiler_tests.erl
@@ -30,8 +30,6 @@
 %% -------------------------------------------------------------------
 -module(rebar_compiler_tests).
 
--compile(export_all).
-
 -include_lib("eunit/include/eunit.hrl").
 
 %% Assuming this test is run inside the rebar 'eunit'
@@ -84,11 +82,11 @@
      setup,
      fun() ->
              setup_basic_project(),
-             setup_rebar_config(),
-             rebar("compile")
+             setup_rebar_config()
      end,
      fun teardown/1,
-     fun(RebarOut)->
+     fun()->
+             RebarOut = rebar("compile"),
              [
               {"Exit after error",
                ?_assert(string:str(RebarOut, "ERROR: compile failed") =/= 0)}
@@ -167,19 +165,11 @@
                                 ?TMP_DIR ++ "rebar.cmd")
     end.
 
-rebar() ->
-    rebar([]).
-
 rebar(Args) when is_list(Args) ->
     Out = os:cmd(filename:nativename("./rebar") ++ " " ++ Args),
     %% ?debugMsg("**** Begin"), ?debugMsg(Out), ?debugMsg("**** End"),
     Out.
 
-assert_dirs_in(Name, [Dir|T]) ->
-    [{Name ++ " has directory: " ++ Dir, ?_assert(filelib:is_dir(Dir))} |
-         assert_dirs_in(Name, T)];
-assert_dirs_in(_, []) -> [].
-
 assert_files_in(Name, [File|T]) ->
     [{Name ++ " has file: " ++ File, ?_assert(filelib:is_regular(File))} |
          assert_files_in(Name, T)];
diff --git a/test/rebar_dia_tests.erl b/test/rebar_dia_tests.erl
new file mode 100644
index 0000000..0561bbb
--- /dev/null
+++ b/test/rebar_dia_tests.erl
@@ -0,0 +1,110 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(rebar_dia_tests).
+
+-include_lib("eunit/include/eunit.hrl").
+
+-define(REBAR_SCRIPT, "../rebar").
+
+-define(TMP_DIR, "dia_project/").
+
+dia_test_() ->
+    case supported_otp_version() of
+        true ->
+            {"Test the dia compiler",
+             setup, fun() -> setup_project(), rebar("compile") end,
+             fun teardown/1,
+             fun(RebarOut) ->
+                 [{"Check ebin is created",
+                   ?_assert(filelib:is_dir("ebin") =:= true)},
+
+                  {"Check include is created",
+                   ?_assert(filelib:is_dir("include") =:= true)},
+
+                  {"Check dia/a.dia is compiled",
+                   ?_assert(string:str(RebarOut, "Compiled dia/a.dia") /= 0)},
+
+                  {"Check dia/b.dia is compiled",
+                   ?_assert(string:str(RebarOut, "Compiled dia/b.dia") /= 0)}
+                 ]
+             end};
+        false -> {setup, fun() -> ok end, []}
+    end.
+
+
+%% ====================================================================
+%% Setup and Teardown
+%% ====================================================================
+
+-define(myapp_dia_a,
+        ["@id     0\n",
+         "@name   a\n",
+         "@vendor 1 ABC\n",
+         "@avp_types\n",
+         "   IMSI 1 UTF8String V"
+        ]).
+
+-define(myapp_dia_b,
+        ["@id     2\n",
+         "@name   b\n",
+         "@vendor 2 ABC\n",
+         "@inherits a\n",
+         "@avp_types\n",
+         "   IMEIV 900 OctetString MV"
+        ]).
+
+-define(myapp_rebarconfig,
+        ["{dia_first_files, [\"dia/a.dia\"]}.\n",
+         "{dia_opts, []}.\n"
+        ]).
+
+supported_otp_version() ->
+    Min = rebar_require_vsn:version_tuple(keep_going, "15", "configured"),
+    Otp = rebar_require_vsn:version_tuple(keep_going,
+                                          erlang:system_info(otp_release),
+                                          "OTP Release"),
+    Otp >= Min.
+
+
+setup_environment() ->
+    ok = file:make_dir(?TMP_DIR),
+    prepare_rebar_script(),
+    ok = file:set_cwd(?TMP_DIR).
+
+prepare_project() ->
+    setup_environment(),
+    rebar("create-app appid=myapp").
+
+
+setup_project() ->
+    prepare_project(),
+    ok = file:make_dir("dia"),
+    ok = file:write_file("dia/a.dia", ?myapp_dia_a),
+    ok = file:write_file("dia/b.dia", ?myapp_dia_b),
+    ok = file:write_file("rebar.config", ?myapp_rebarconfig).
+
+
+teardown(_) ->
+    ok = file:set_cwd(".."),
+    ok = remove_tmp_dir().
+
+remove_tmp_dir() ->
+    ok = rebar_file_utils:rm_rf(?TMP_DIR).
+
+%% ====================================================================
+%% Helper Functions
+%% ====================================================================
+
+prepare_rebar_script() ->
+    Rebar = ?TMP_DIR ++ "rebar",
+    {ok, _} = file:copy(?REBAR_SCRIPT, Rebar),
+    case os:type() of
+        {unix, _} ->
+            [] = os:cmd("chmod u+x " ++ Rebar);
+        {win32, _} ->
+            {ok, _} = file:copy(?REBAR_SCRIPT ++ ".cmd",
+                                ?TMP_DIR ++ "rebar.cmd")
+    end.
+
+rebar(Args) when is_list(Args) ->
+    os:cmd(filename:nativename("./rebar") ++ " " ++ Args).
diff --git a/test/rebar_eunit_tests.erl b/test/rebar_eunit_tests.erl
index 33f168c..cf1e696 100644
--- a/test/rebar_eunit_tests.erl
+++ b/test/rebar_eunit_tests.erl
@@ -30,8 +30,6 @@
 %% -------------------------------------------------------------------
 -module(rebar_eunit_tests).
 
--compile(export_all).
-
 -include_lib("eunit/include/eunit.hrl").
 
 %% Assuming this test is run inside the rebar 'eunit'
@@ -56,7 +54,7 @@
                ?_assert(string:str(RebarOut, "myapp_mymod:") =/= 0)},
 
               {"Tests are only run once",
-               ?_assert(string:str(RebarOut, "All 2 tests passed") =/= 0)}]
+               ?_assert(string:str(RebarOut, "2 tests passed") =/= 0)}]
      end}.
 
 eunit_with_suites_and_tests_test_() ->
@@ -80,7 +78,7 @@
                 ?_assert(string:str(RebarOut, "myapp_mymod:") =:= 0)},
 
                {"Selected suite tests are only run once",
-                ?_assert(string:str(RebarOut, "All 4 tests passed") =/= 0)}]
+                ?_assert(string:str(RebarOut, "4 tests passed") =/= 0)}]
       end},
      {"Ensure EUnit runs selected _tests suites",
       setup, fun() ->
@@ -102,7 +100,7 @@
                 ?_assert(string:str(RebarOut, "myapp_mymod:") =:= 0)},
 
                {"Selected suite tests are only run once",
-                ?_assert(string:str(RebarOut, "All 2 tests passed") =/= 0)}]
+                ?_assert(string:str(RebarOut, "2 tests passed") =/= 0)}]
       end},
      {"Ensure EUnit runs a specific test defined in a selected suite",
       setup, fun() ->
@@ -131,7 +129,7 @@
 
                {"Selected suite's generator test raises an error",
                 ?_assert(string:str(RebarOut,
-                                    "assertEqual_failed") =/= 0)},
+                                    "assertEqual") =/= 0)},
 
                {"Selected suite tests is run once",
                 ?_assert(string:str(RebarOut, "Failed: 1.") =/= 0)}]
@@ -154,7 +152,7 @@
                                "myapp_mymod2_tests:myfunc2_test/0") =/= 0)]},
 
                {"Selected suite tests are run once",
-                ?_assert(string:str(RebarOut, "All 3 tests passed") =/= 0)}]
+                ?_assert(string:str(RebarOut, "3 tests passed") =/= 0)}]
       end},
      {"Ensure EUnit runs specific test in a _tests suite",
       setup,
@@ -190,7 +188,7 @@
                           =/= 0)]},
 
                {"Selected suite tests is run once",
-                ?_assert(string:str(RebarOut, "All 2 tests passed") =/= 0)}]
+                ?_assert(string:str(RebarOut, "2 tests passed") =/= 0)}]
       end},
      {"Ensure EUnit runs a specific test by qualified function name",
       setup,
@@ -231,7 +229,21 @@
                 [?_assert(string:str(RebarOut,
                                      "Failed: 1.  Skipped: 0.  Passed: 1")
                           =/= 0)]}]
-      end}].
+      end},
+     {"Ensure EUnit runs a test with eunit_first_files",
+      setup,
+      fun() ->
+              setup_eunit_first_files(),
+              rebar("eunit")
+      end,
+      fun teardown/1,
+      fun(RebarOut) ->
+              [
+               {"Don't pass tests without erl_first_file",
+                [?_assert(string:str(RebarOut,
+                                     "Test passed.") =/= 0)]}]
+      end}
+    ].
 
 cover_test_() ->
     {"Ensure Cover runs with tests in a test dir and no defined suite",
@@ -311,7 +323,11 @@
 
 assert_rebar_runs() ->
     prepare_rebar_script(),
-    ?assert(string:str(os:cmd(filename:nativename("./" ++ ?TMP_DIR ++ "rebar")),
+    {ok, Cwd} = file:get_cwd(),
+    ok = file:set_cwd(?TMP_DIR),
+    RebarOut = os:cmd(filename:nativename("./rebar")),
+    ok = file:set_cwd(Cwd),
+    ?assert(string:str(RebarOut,
                        "No command to run specified!") =/= 0).
 
 basic_setup_test_() ->
@@ -394,7 +410,6 @@
 
 -define(myapp_mymod_tests,
         ["-module(myapp_mymod_tests).\n",
-         "-compile([export_all]).\n",
          "-include_lib(\"eunit/include/eunit.hrl\").\n",
          "myfunc_test() -> ?assertMatch(ok, myapp_mymod:myfunc()).\n"]).
 
@@ -408,7 +423,6 @@
 
 -define(myapp_mymod2_tests,
         ["-module(myapp_mymod2_tests).\n",
-         "-compile([export_all]).\n",
          "-include_lib(\"eunit/include/eunit.hrl\").\n",
          "myfunc2_test() -> ?assertMatch(ok, myapp_mymod2:myfunc2()).\n",
          "common_name_test() -> ?assert(true).\n"]).
@@ -420,6 +434,19 @@
          "myfunc3() -> ok.\n",
          "mygenerator_test_() -> [?_assertEqual(true, false)].\n"]).
 
+-define(myapp_mymod4,
+        ["-module(myapp_mymod4).\n",
+         "-compile({parse_transform, myapp_mymod4_parse_transform}).\n",
+         "-include_lib(\"eunit/include/eunit.hrl\").\n",
+         "-export([ok/0]).\n",
+         "pt_test() -> ?assert(myapp_mymod4:ok()).\n"]).
+
+-define(myapp_mymod4_parse_transform,
+        ["-module(myapp_mymod4_parse_transform).\n",
+         "-export([parse_transform/2]).\n",
+         "parse_transform(Forms, _Options) ->\n",
+         "Forms ++ [{function,29,ok,0,[{clause,9,[],[],[{atom,9,true}]}]}].\n"]).
+
 -define(mysuite,
         ["-module(mysuite).\n",
          "-export([all_test_/0]).\n",
@@ -428,7 +455,6 @@
 
 -define(myapp_mymod_defined_in_mysuite_tests,
         ["-module(myapp_mymod_defined_in_mysuite_tests).\n",
-         "-compile([export_all]).\n",
          "-include_lib(\"eunit/include/eunit.hrl\").\n",
          "myfunc_test() -> ?assertMatch(ok, myapp_mymod:myfunc()).\n"]).
 
@@ -462,6 +488,15 @@
     ok = file:write_file("src/myapp_mymod2.erl", ?myapp_mymod2),
     ok = file:write_file("src/myapp_mymod3.erl", ?myapp_mymod3).
 
+setup_eunit_first_files() ->
+    setup_environment(),
+    rebar("create-app appid=myapp"),
+    ok = file:write_file("src/myapp_mymod4.erl", ?myapp_mymod4),
+    ok = file:write_file("src/myapp_mymod4_parse_transform.erl",
+                ?myapp_mymod4_parse_transform),
+    ok = file:write_file("rebar.config",
+        "{erl_first_files, [\"src/myapp_mymod4_parse_transform.erl\"]}.\n").
+
 setup_cover_project() ->
     setup_basic_project(),
     ok = file:write_file("rebar.config", "{cover_enabled, true}.\n").
@@ -497,9 +532,6 @@
                                 ?TMP_DIR ++ "rebar.cmd")
     end.
 
-rebar() ->
-    rebar([]).
-
 rebar(Args) when is_list(Args) ->
     Out = os:cmd(filename:nativename("./rebar") ++ " " ++ Args),
     %% ?debugMsg("**** Begin"), ?debugMsg(Out), ?debugMsg("**** End"),
diff --git a/test/rebar_file_utils_tests.erl b/test/rebar_file_utils_tests.erl
index fc76d58..ca5edf0 100644
--- a/test/rebar_file_utils_tests.erl
+++ b/test/rebar_file_utils_tests.erl
@@ -30,13 +30,11 @@
 %% -------------------------------------------------------------------
 -module(rebar_file_utils_tests).
 
--compile(export_all).
-
 -include_lib("eunit/include/eunit.hrl").
 
 -define(TMP_DIR, "tmp_file_utils").
 
--define(SRC, "source dir?").
+-define(SRC, "source dir").
 -define(DST, "dest (dir)").
 -define(FILE1, "file 1").
 -define(FILE2, "file(2)").
diff --git a/test/rebar_require_vsn_tests.erl b/test/rebar_require_vsn_tests.erl
index a487586..43333d3 100644
--- a/test/rebar_require_vsn_tests.erl
+++ b/test/rebar_require_vsn_tests.erl
@@ -2,23 +2,36 @@
 %% ex: ts=4 sw=4 et
 -module(rebar_require_vsn_tests).
 
--compile(export_all).
-
 -include_lib("eunit/include/eunit.hrl").
 
 version_tuple_test_() ->
     [%% typical cases
-     ?_assert(check("R15B", "eunit") =:= {15, 0}),
-     ?_assert(check("R15B01", "eunit") =:= {15, 1}),
-     ?_assert(check("R15B02", "eunit") =:= {15, 2}),
-     ?_assert(check("R15B03-1", "eunit") =:= {15, 3}),
-     ?_assert(check("R15B03", "eunit") =:= {15, 3}),
-     ?_assert(check("R16B", "eunit") =:= {16, 0}),
-     ?_assert(check("R16B01", "eunit") =:= {16, 1}),
-     ?_assert(check("R16B02", "eunit") =:= {16, 2}),
-     ?_assert(check("R16B03", "eunit") =:= {16, 3}),
-     ?_assert(check("R16B03-1", "eunit") =:= {16, 3}),
-     ?_assert(check("17", "eunit") =:= {17, 0}),
+     ?_assert(check("R14A", "eunit") =:= {14, 0, 0}),
+     ?_assert(check("R14B", "eunit") =:= {14, 0, 0}),
+     ?_assert(check("R14B01", "eunit") =:= {14, 1, 0}),
+     ?_assert(check("R14B02", "eunit") =:= {14, 2, 0}),
+     ?_assert(check("R14B03", "eunit") =:= {14, 3, 0}),
+     ?_assert(check("R14B04", "eunit") =:= {14, 4, 0}),
+     ?_assert(check("R15B", "eunit") =:= {15, 0, 0}),
+     ?_assert(check("R15B01", "eunit") =:= {15, 1, 0}),
+     ?_assert(check("R15B02", "eunit") =:= {15, 2, 0}),
+     ?_assert(check("R15B03-1", "eunit") =:= {15, 3, 1}),
+     ?_assert(check("R15B03", "eunit") =:= {15, 3, 0}),
+     ?_assert(check("R16B", "eunit") =:= {16, 0, 0}),
+     ?_assert(check("R16B01", "eunit") =:= {16, 1, 0}),
+     ?_assert(check("R16B02", "eunit") =:= {16, 2, 0}),
+     ?_assert(check("R16B03", "eunit") =:= {16, 3, 0}),
+     ?_assert(check("R16B03-1", "eunit") =:= {16, 3, 1}),
+     ?_assert(check("17", "eunit") =:= {17, 0, 0}),
+     ?_assert(check("17.0", "eunit") =:= {17, 0, 0}),
+     ?_assert(check("17.1", "eunit") =:= {17, 1, 0}),
+     ?_assert(check("17.3", "eunit") =:= {17, 3, 0}),
+     ?_assert(check("17.4", "eunit") =:= {17, 4, 0}),
+     ?_assert(check("17.5", "eunit") =:= {17, 5, 0}),
+     ?_assert(check("18.0", "eunit") =:= {18, 0, 0}),
+     ?_assert(check("18.1", "eunit") =:= {18, 1, 0}),
+     ?_assert(check("18.2", "eunit") =:= {18, 2, 0}),
+     ?_assert(check("18.2.1", "eunit") =:= {18, 2, 1}),
      %% error cases
      ?_assertException(throw, rebar_abort, check("", "eunit")),
      ?_assertException(throw, rebar_abort, check("abc", "eunit"))
diff --git a/test/rebar_utils_tests.erl b/test/rebar_utils_tests.erl
index 9bc393a..81f5c92 100644
--- a/test/rebar_utils_tests.erl
+++ b/test/rebar_utils_tests.erl
@@ -30,8 +30,6 @@
 %% -------------------------------------------------------------------
 -module(rebar_utils_tests).
 
--compile(export_all).
-
 -include_lib("eunit/include/eunit.hrl").
 
 expand_env_variable_test_() ->
diff --git a/test/rebar_xref_eunit.erl b/test/rebar_xref_eunit.erl
index 341fe2e..13d8a5e 100644
--- a/test/rebar_xref_eunit.erl
+++ b/test/rebar_xref_eunit.erl
@@ -2,8 +2,6 @@
 %% ex: ts=4 sw=4 et
 -module(rebar_xref_eunit).
 
--compile(export_all).
-
 -include_lib("eunit/include/eunit.hrl").
 
 -define(REBAR_SCRIPT, "../rebar").
@@ -16,31 +14,31 @@
      fun teardown/1,
      fun(RebarOut) ->
              [
-              {"Undefined function", ?_assert(string:str(RebarOut, 
+              {"Undefined function", ?_assert(string:str(RebarOut,
                 "myapp_somemod:notavailable/1 is undefined function") =/= 0)},
-              {"Undefined function call", ?_assert(string:str(RebarOut, 
+              {"Undefined function call", ?_assert(string:str(RebarOut,
                 "myapp_othermod:somefunc/0 calls undefined function myapp_somemod:notavailable/1") =/= 0)},
-              {"Deprecated function", ?_assert(string:str(RebarOut, 
+              {"Deprecated function", ?_assert(string:str(RebarOut,
                 "myapp_mymod:fdeprecated/0 is deprecated function") =/= 0)},
-              {"Deprecated function call", ?_assert(string:str(RebarOut, 
+              {"Deprecated function call", ?_assert(string:str(RebarOut,
                 "myapp_othermod:somefunc/0 calls deprecated function myapp_mymod:fdeprecated/0") =/= 0)},
-              {"Unused local", ?_assert(string:str(RebarOut, 
+              {"Unused local", ?_assert(string:str(RebarOut,
                 "myapp_mymod:localfunc2/0 is unused local function") =/= 0)},
-              {"Unused export 1", ?_assert(string:str(RebarOut, 
+              {"Unused export 1", ?_assert(string:str(RebarOut,
                 "myapp_behaviour1:behaviour_info/1 is unused export") =/= 0)},
-              {"Unused export 2", ?_assert(string:str(RebarOut, 
+              {"Unused export 2", ?_assert(string:str(RebarOut,
                 "myapp_behaviour2:behaviour_info/1 is unused export") =/= 0)},
-              {"Unused export 3", ?_assert(string:str(RebarOut, 
+              {"Unused export 3", ?_assert(string:str(RebarOut,
                 "myapp_mymod:other2/1 is unused export") =/= 0)},
-              {"Unused export 4", ?_assert(string:str(RebarOut, 
+              {"Unused export 4", ?_assert(string:str(RebarOut,
                 "myapp_othermod:somefunc/0 is unused export") =/= 0)},
-              {"Suppressed behaviour export 1", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 1", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh1_a/1 is unused export") =:= 0)},
-              {"Suppressed behaviour export 2", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 2", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh1_b/1 is unused export") =:= 0)},
-              {"Suppressed behaviour export 3", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 3", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh2_a/1 is unused export") =:= 0)},
-              {"Suppressed behaviour export 4", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 4", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh2_b/1 is unused export") =:= 0)}
             ]
      end}.
@@ -51,31 +49,31 @@
      fun teardown/1,
      fun(RebarOut) ->
              [
-              {"Undefined function can not be suppressed.", ?_assert(string:str(RebarOut, 
+              {"Undefined function can not be suppressed.", ?_assert(string:str(RebarOut,
                 "myapp_somemod:notavailable/1 is undefined function") =/= 0)},
-              {"Supppressed undefined function call", ?_assert(string:str(RebarOut, 
+              {"Supppressed undefined function call", ?_assert(string:str(RebarOut,
                 "myapp_othermod:somefunc/0 calls undefined function myapp_somemod:notavailable/1") =:= 0)},
-              {"Supppressed deprecated function", ?_assert(string:str(RebarOut, 
+              {"Supppressed deprecated function", ?_assert(string:str(RebarOut,
                 "myapp_mymod:fdeprecated/0 is deprecated function") =:= 0)},
-              {"Supppressed deprecated function call", ?_assert(string:str(RebarOut, 
+              {"Supppressed deprecated function call", ?_assert(string:str(RebarOut,
                 "myapp_othermod:somefunc/0 calls deprecated function myapp_mymod:fdeprecated/0") =:= 0)},
-              {"Supppressed unused local", ?_assert(string:str(RebarOut, 
+              {"Supppressed unused local", ?_assert(string:str(RebarOut,
                 "myapp_mymod:localfunc2/0 is unused local function") =:= 0)},
-              {"Supppressed unused export 1", ?_assert(string:str(RebarOut, 
+              {"Supppressed unused export 1", ?_assert(string:str(RebarOut,
                 "myapp_behaviour1:behaviour_info/1 is unused export") =:= 0)},
-              {"Supppressed unused export 2", ?_assert(string:str(RebarOut, 
+              {"Supppressed unused export 2", ?_assert(string:str(RebarOut,
                 "myapp_behaviour2:behaviour_info/1 is unused export") =:= 0)},
-              {"Supppressed unused export 3", ?_assert(string:str(RebarOut, 
+              {"Supppressed unused export 3", ?_assert(string:str(RebarOut,
                 "myapp_mymod:other2/1 is unused export") =:= 0)},
-              {"Supppressed unused export 4", ?_assert(string:str(RebarOut, 
+              {"Supppressed unused export 4", ?_assert(string:str(RebarOut,
                 "myapp_othermod:somefunc/0 is unused export") =:= 0)},
-              {"Suppressed behaviour export 1", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 1", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh1_a/1 is unused export") =:= 0)},
-              {"Suppressed behaviour export 2", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 2", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh1_b/1 is unused export") =:= 0)},
-              {"Suppressed behaviour export 3", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 3", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh2_a/1 is unused export") =:= 0)},
-              {"Suppressed behaviour export 4", ?_assert(string:str(RebarOut, 
+              {"Suppressed behaviour export 4", ?_assert(string:str(RebarOut,
                 "myapp_mymod:bh2_b/1 is unused export") =:= 0)}
             ]
 
@@ -116,7 +114,7 @@
          "bh2_a(A) -> localfunc1(bh2_a, A).\n",
          "bh2_b(A) -> localfunc1(bh2_b, A).\n",
          "other1(A) -> localfunc1(other1, A).\n", % regular exported functions
-         "other2(A) -> localfunc1(other2, A).\n", 
+         "other2(A) -> localfunc1(other2, A).\n",
          "localfunc1(A, B) -> {A, B}.\n",       % used local
          "localfunc2() -> ok.\n",               % unused local
          "fdeprecated() -> ok.\n"              % deprecated function
@@ -155,7 +153,7 @@
 prepare_project() ->
     setup_environment(),
     rebar("create-app appid=myapp"),
-    ok = file:make_dir("ebin").  
+    ok = file:make_dir("ebin").
 
 setup_project(ignore_xref) ->
     prepare_project(),
@@ -192,13 +190,10 @@
         {unix, _} ->
             [] = os:cmd("chmod u+x " ++ Rebar);
         {win32, _} ->
-            {ok, _} = file:copy(?REBAR_SCRIPT ++ ".bat",
-                                ?TMP_DIR ++ "rebar.bat")
+            {ok, _} = file:copy(?REBAR_SCRIPT ++ ".cmd",
+                                ?TMP_DIR ++ "rebar.cmd")
     end.
 
-rebar() ->
-    rebar([]).
-
 rebar(Args) when is_list(Args) ->
     Out = os:cmd(filename:nativename("./rebar") ++ " " ++ Args),
     %% ?debugMsg("**** Begin"), ?debugMsg(Out), ?debugMsg("**** End"),
diff --git a/test/upgrade_project/rel/files/dummy b/test/upgrade_project/rel/files/dummy
index 67fb2da..7b2caa1 100755
--- a/test/upgrade_project/rel/files/dummy
+++ b/test/upgrade_project/rel/files/dummy
@@ -6,9 +6,6 @@
 if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
     POSIX_SHELL="true"
     export POSIX_SHELL
-    # To support 'whoami' add /usr/ucb to path
-    PATH=/usr/ucb:$PATH
-    export PATH
     exec /usr/bin/ksh $0 "$@"
 fi
 
@@ -24,7 +21,7 @@
 # Note the trailing slash on $PIPE_DIR/
 PIPE_DIR=/tmp/$RUNNER_BASE_DIR/
 RUNNER_USER=
-WHOAMI=$(whoami)
+WHOAMI=$(id -un)
 
 # Make sure this script is running as the appropriate user
 if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then