├── rebar.lock ├── .gitignore ├── src ├── rebar3_run.app.src └── rebar3_run.erl ├── rebar.config ├── .github └── workflows │ └── ci.yml ├── README.md ├── LICENSE └── c_src ├── rebar3_run.c └── Makefile /rebar.lock: -------------------------------------------------------------------------------- 1 | []. 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.so 6 | *.beam 7 | *.plt 8 | *.swp 9 | *.swo 10 | .erlang.cookie 11 | ebin 12 | log 13 | erl_crash.dump 14 | .rebar 15 | _rel 16 | _deps 17 | _plugins 18 | _tdeps 19 | logs 20 | -------------------------------------------------------------------------------- /src/rebar3_run.app.src: -------------------------------------------------------------------------------- 1 | {application, rebar3_run, 2 | [{description, "A rebar plugin"} 3 | ,{vsn, "git"} 4 | ,{registered, []} 5 | ,{applications, 6 | [kernel,stdlib]} 7 | ,{env,[]} 8 | ,{modules, []} 9 | 10 | ,{licenses,["MIT"]} 11 | ,{links,[{"Github", "https://github.com/tsloughter/rebar3_run"}]} 12 | ]}. 13 | -------------------------------------------------------------------------------- /rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, []}. 3 | 4 | {pre_hooks, [{"(linux|darwin|solaris)", compile, "make -C c_src/"}, 5 | {"(freebsd)", compile, "gmake -C c_src/"}]}. 6 | 7 | {xref_checks, [ 8 | deprecated_function_calls, 9 | locals_not_used 10 | ]}. 11 | 12 | {dialyzer, [ 13 | {warnings, [ 14 | error_handling, 15 | underspecs, 16 | unmatched_returns 17 | ]} 18 | ]}. 19 | 20 | {project_plugins, [rebar3_hank]}. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: build 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | jobs: 11 | ci: 12 | name: Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}} 13 | runs-on: ${{matrix.os}} 14 | strategy: 15 | matrix: 16 | otp_vsn: [21, 22, 23, 24] 17 | os: [ubuntu-latest] 18 | steps: 19 | - uses: actions/checkout@v2 20 | - uses: erlef/setup-beam@v1 21 | with: 22 | otp-version: ${{matrix.otp_vsn}} 23 | rebar3-version: '3.15' 24 | - run: rebar3 xref 25 | - run: rebar3 hank 26 | - run: rebar3 dialyzer 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rebar3_run 2 | ===== 3 | 4 | Run a release with one simple command. 5 | 6 | Build 7 | ----- 8 | 9 | $ rebar3 compile 10 | 11 | Use 12 | --- 13 | 14 | Add the plugin to your rebar config or `~/.config/rebar3/rebar.config`: 15 | 16 | {plugins, [ 17 | rebar3_run 18 | ]}. 19 | 20 | Assuming you have a `relx` config section in your `rebar.config` with `extended_start_script` set to true: 21 | 22 | ``` 23 | {relx, [{release, {, }, []}, 24 | {dev_mode, true}, 25 | {include_erts, false}, 26 | {extended_start_script, true}]}. 27 | ``` 28 | 29 | Then just call your plugin directly in an existing project: 30 | 31 | 32 | $ rebar3 run 33 | ===> Fetching rebar3_run 34 | ===> Compiling rebar3_run 35 | ===> Starting relx build process ... 36 | ===> Resolving OTP Applications from directories: 37 | ..... 38 | Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] 39 | 40 | Eshell V6.4 (abort with ^G) 41 | (@127.0.0.1)1> 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Tristan Sloughter . 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | * The names of its contributors may not be used to endorse or promote 16 | products derived from this software without specific prior written 17 | permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/rebar3_run.erl: -------------------------------------------------------------------------------- 1 | -module(rebar3_run). 2 | 3 | -export([init/1, 4 | do/1, 5 | format_error/1]). 6 | 7 | -export([exec/2]). 8 | 9 | -define(PROVIDER, run). 10 | -define(DEPS, [release]). 11 | 12 | %% =================================================================== 13 | %% Public API 14 | %% =================================================================== 15 | 16 | -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. 17 | init(State) -> 18 | Provider = providers:create([ 19 | {name, ?PROVIDER}, 20 | {module, ?MODULE}, 21 | {bare, false}, 22 | {deps, ?DEPS}, 23 | {example, "rebar3 run"}, 24 | {short_desc, "Run release console."}, 25 | {desc, ""}, 26 | {opts, []} 27 | ]), 28 | State1 = rebar_state:add_provider(State, Provider), 29 | {ok, State1}. 30 | 31 | -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, {rebar3_run, no_release}}. 32 | do(State) -> 33 | %% Can't use on_load since rebar3 loads/unloads plugins, screwing up nifs 34 | init(), 35 | 36 | ReleaseDir = filename:join(rebar_dir:base_dir(State), "rel"), 37 | Config = rebar_state:get(State, relx, []), 38 | case lists:keyfind(release, 1, Config) of 39 | {release, {Name, _Vsn}, _} -> 40 | StartScript = filename:join([ReleaseDir, Name, "bin", Name]), 41 | exec(StartScript, ["console"]), 42 | {ok, State}; 43 | false -> 44 | {error, {?MODULE, no_release}} 45 | end. 46 | 47 | format_error(no_release) -> 48 | "No release to run was found.". 49 | 50 | init() -> 51 | _ = application:load(rebar3_run), 52 | PrivDir = code:priv_dir(rebar3_run), 53 | ok = erlang:load_nif(filename:join(PrivDir, "rebar3_run"), 0). 54 | 55 | exec(_Path, _Args) -> 56 | erlang:nif_error(nif_library_not_loaded). 57 | -------------------------------------------------------------------------------- /c_src/rebar3_run.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) */ 2 | 3 | /* Copyright (c) 2015 Ahmad Sherif */ 4 | 5 | /* Permission is hereby granted, free of charge, to any person obtaining a copy */ 6 | /* of this software and associated documentation files (the "Software"), to deal */ 7 | /* in the Software without restriction, including without limitation the rights */ 8 | /* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ 9 | /* copies of the Software, and to permit persons to whom the Software is */ 10 | /* furnished to do so, subject to the following conditions: */ 11 | 12 | /* The above copyright notice and this permission notice shall be included in all */ 13 | /* copies or substantial portions of the Software. */ 14 | 15 | #include 16 | 17 | #include "erl_nif.h" 18 | 19 | static ERL_NIF_TERM exec_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 20 | { 21 | unsigned path_length, args_count, arg_length; 22 | ERL_NIF_TERM head, tail; 23 | int i = 0; 24 | 25 | enif_get_list_length(env, argv[0], &path_length); 26 | enif_get_list_length(env, argv[1], &args_count); 27 | 28 | char* exec_argv[args_count + 2]; 29 | char path[path_length + 1]; 30 | 31 | if (!enif_get_string(env, argv[0], path, path_length + 1, ERL_NIF_LATIN1) || !enif_is_list(env, argv[1])) { 32 | return enif_make_badarg(env); 33 | } 34 | 35 | tail = argv[1]; 36 | while(enif_get_list_cell(env, tail, &head, &tail) != 0) { 37 | enif_get_list_length(env, head, &arg_length); 38 | 39 | char* arg = (char*) malloc(sizeof(char) * (arg_length + 1)); 40 | 41 | if (!enif_get_string(env, head, arg, arg_length + 1, ERL_NIF_LATIN1)) { 42 | return enif_make_badarg(env); 43 | } 44 | 45 | exec_argv[i + 1] = arg; 46 | 47 | i++; 48 | } 49 | 50 | exec_argv[0] = path; 51 | exec_argv[args_count + 1] = NULL; 52 | 53 | execv(path, exec_argv); 54 | 55 | return enif_make_atom(env, "ok"); 56 | } 57 | 58 | static ErlNifFunc nif_funcs[] = { 59 | {"exec", 2, exec_nif} 60 | }; 61 | 62 | ERL_NIF_INIT(rebar3_run, nif_funcs, NULL, NULL, NULL, NULL); 63 | -------------------------------------------------------------------------------- /c_src/Makefile: -------------------------------------------------------------------------------- 1 | # Based on c_src.mk from erlang.mk by Loic Hoguin 2 | 3 | CURDIR := $(shell pwd) 4 | BASEDIR := $(abspath $(CURDIR)/..) 5 | 6 | PROJECT ?= $(notdir $(BASEDIR)) 7 | PROJECT := $(strip $(PROJECT)) 8 | 9 | ERTS_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~s/erts-~s/include/\", [code:root_dir(), erlang:system_info(version)])." -s erlang halt) 10 | ERL_INTERFACE_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~s\", [code:lib_dir(erl_interface, include)])." -s erlang halt) 11 | ERL_INTERFACE_LIB_DIR ?= $(shell erl -noshell -eval "io:format(\"~s\", [code:lib_dir(erl_interface, lib)])." -s erlang halt) 12 | 13 | C_SRC_DIR = $(CURDIR) 14 | C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so 15 | 16 | # System type and C compiler/flags. 17 | 18 | ARCH ?= $(shell arch) 19 | UNAME_SYS := $(shell uname -s) 20 | ifeq ($(UNAME_SYS),Darwin) 21 | CC ?= cc 22 | CFLAGS ?= -O3 -std=c99 -arch $(ARCH) -finline-functions -Wall -Wmissing-prototypes 23 | CXXFLAGS ?= -O3 -arch $(ARCH) -finline-functions -Wall 24 | LDFLAGS ?= -arch $(ARCH) -flat_namespace -undefined suppress 25 | else ifeq ($(UNAME_SYS),FreeBSD) 26 | CC ?= cc 27 | CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes 28 | CXXFLAGS ?= -O3 -finline-functions -Wall 29 | else ifeq ($(UNAME_SYS),Linux) 30 | CC ?= gcc 31 | CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes 32 | CXXFLAGS ?= -O3 -finline-functions -Wall 33 | endif 34 | 35 | CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) 36 | CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) 37 | 38 | LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lei 39 | LDFLAGS += -shared 40 | 41 | # Verbosity. 42 | 43 | V ?= 44 | 45 | c_verbose_ ?= 46 | c_verbose_0 = @echo " C " $(?F); 47 | c_verbose = $(c_verbose_$(V)) 48 | 49 | cpp_verbose_ ?= 50 | cpp_verbose_0 = @echo " CPP " $(?F); 51 | cpp_verbose = $(cpp_verbose_$(V)) 52 | 53 | link_verbose_ ?= 54 | link_verbose_0 = @echo " LD " $(@F); 55 | link_verbose = $(link_verbose_$(V)) 56 | 57 | SOURCES := $(shell find $(C_SRC_DIR) -type f \( -name "*.c" -o -name "*.C" -o -name "*.cc" -o -name "*.cpp" \)) 58 | OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) 59 | 60 | CPPFLAGS ?= 61 | COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c 62 | COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c 63 | 64 | $(C_SRC_OUTPUT): $(OBJECTS) 65 | @mkdir -p $(BASEDIR)/priv/ 66 | @$(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT) 67 | 68 | %.o: %.c 69 | @$(COMPILE_C) $(OUTPUT_OPTION) $< 70 | 71 | %.o: %.cc 72 | @$(COMPILE_CPP) $(OUTPUT_OPTION) $< 73 | 74 | %.o: %.C 75 | @$(COMPILE_CPP) $(OUTPUT_OPTION) $< 76 | 77 | %.o: %.cpp 78 | @$(COMPILE_CPP) $(OUTPUT_OPTION) $< 79 | 80 | clean: 81 | @rm -f $(C_SRC_OUTPUT) $(OBJECTS) 82 | --------------------------------------------------------------------------------