diff --git a/Makefile b/Makefile index a39f44c07..d1a478279 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,11 @@ COMMON_DEPS := $(REBAR) $(REL_PROFILES:%=%): $(COMMON_DEPS) @$(BUILD) $(@) rel +.PHONY: compile $(PROFILES:%=compile-%) +compile: $(PROFILES:%=compile-%) +$(PROFILES:%=compile-%): + @$(BUILD) $(@:compile-%=%) apps + ## Not calling rebar3 clean because ## 1. rebar3 clean relies on rebar3, meaning it reads config, fetches dependencies etc. ## 2. it's slow @@ -223,11 +228,11 @@ endef $(foreach pt,$(PKG_PROFILES),$(eval $(call gen-pkg-target,$(pt)))) .PHONY: run -run: $(PROFILE) quickrun +run: compile-$(PROFILE) quickrun .PHONY: quickrun quickrun: - ./_build/$(PROFILE)/rel/emqx/bin/emqx console + ./dev -p $(PROFILE) ## Take the currently set PROFILE docker: diff --git a/bin/emqx b/bin/emqx index fc0124b96..6d4c5cd4e 100755 --- a/bin/emqx +++ b/bin/emqx @@ -396,7 +396,7 @@ relx_get_pid() { remsh() { # Generate a unique id used to allow multiple remsh to the same node # transparently - id="remsh$(relx_gen_id)-${NAME}" + id="remsh$(gen_node_id)-${NAME}" # shellcheck disable=SC2086 # Setup remote shell command to control node @@ -424,7 +424,7 @@ remsh() { } # Generate a random id -relx_gen_id() { +gen_node_id() { od -t u -N 4 /dev/urandom | head -n1 | awk '{print $2 % 1000}' } @@ -1273,7 +1273,7 @@ case "${COMMAND}" in then "$REL_DIR/elixir" \ --hidden \ - --name "rand-$(relx_gen_id)-$NAME" \ + --name "rand-$(gen_node_id)-$NAME" \ --cookie "$COOKIE" \ --boot "$REL_DIR/start_clean" \ --boot-var RELEASE_LIB "$ERTS_LIB_DIR" \ diff --git a/build b/build index eb75317cc..2924f8a6f 100755 --- a/build +++ b/build @@ -124,16 +124,19 @@ assert_no_compile_time_only_deps() { : } -make_rel() { - local release_or_tar="${1}" +just_compile() { ./scripts/pre-compile.sh "$PROFILE" # make_elixir_rel always create rebar.lock # delete it to make git clone + checkout work because we use shallow close for rebar deps rm -f rebar.lock # compile all beams ./rebar3 as "$PROFILE" compile - # generate docs (require beam compiled), generated to etc and priv dirs make_docs +} + +make_rel() { + local release_or_tar="${1}" + just_compile # now assemble the release tar ./rebar3 as "$PROFILE" "$release_or_tar" assert_no_compile_time_only_deps @@ -375,6 +378,9 @@ export_elixir_release_vars() { log "building artifact=$ARTIFACT for profile=$PROFILE" case "$ARTIFACT" in + apps) + just_compile + ;; doc|docs) make_docs ;; diff --git a/dev b/dev new file mode 100755 index 000000000..39bdfbc41 --- /dev/null +++ b/dev @@ -0,0 +1,303 @@ +#!/usr/bin/env bash + +set -euo pipefail + +PROJ_ROOT="$(git rev-parse --show-toplevel)" +cd "$PROJ_ROOT" + +usage() { +cat <&2 + exit 1 + ;; + esac + shift 1; +done + +case "${PROFILE}" in + ce|emqx) + PROFILE='emqx' + ;; + ee|emqx-enterprise) + PROFILE='emqx-enterprise' + ;; + *) + echo "Unknown profile $PROFILE" + exit 1 + ;; +esac +export PROFILE + +case "${PROFILE}" in + emqx) + SCHEMA_MOD='emqx_conf_schema' + ;; + emqx-enterprise) + SCHEMA_MOD='emqx_ee_conf_schema' + ;; +esac + +BASE_DIR="_build/dev-run/$PROFILE" +export EMQX_ETC_DIR="$BASE_DIR/etc" +export EMQX_DATA_DIR="$BASE_DIR/data" +export EMQX_LOG_DIR="$BASE_DIR/log" +CONFIGS_DIR="$EMQX_DATA_DIR/configs" +# Use your cookie so your IDE can connect to it. +COOKIE="${EMQX_NODE__COOKIE:-${EMQX_NODE_COOKIE:-$(cat ~/.erlang.cookie || echo 'emqxsecretcookie')}}" +mkdir -p "$EMQX_ETC_DIR" "$EMQX_DATA_DIR/patches" "$EMQX_LOG_DIR" "$CONFIGS_DIR" +if [ $EKKA_EPMD -eq 1 ]; then + EPMD_ARGS='-start_epmd false -epmd_module ekka_epmd' +else + EPMD_ARGS='' +fi + + +## build compile the profile is it's not compiled yet +prepare_erl_libs() { + local profile="$1" + local libs_dir="_build/${profile}/lib" + local erl_libs='' + if [ $FORCE_COMPILE -eq 1 ] || [ ! -d "$libs_dir" ]; then + make "compile-${PROFILE}" + else + echo "Running from code in $libs_dir" + fi + for app in "${libs_dir}"/*; do + erl_libs="${erl_libs}:${app}" + done + export ERL_LIBS="$erl_libs" +} + +## poorman's mustache templating +mustache() { + local name="$1" + local value="$2" + local file="$3" + sed -i "s|{{\s*${name}\s*}}|${value}|g" "$file" +} + +## render the merged boot conf file. +## the merge action is done before the profile is compiled +render_hocon_conf() { + input="apps/emqx_conf/etc/emqx.conf.all" + output="$EMQX_ETC_DIR/emqx.conf" + cp "$input" "$output" + mustache emqx_default_erlang_cookie "$COOKIE" "$output" + mustache platform_data_dir "${EMQX_DATA_DIR}" "$output" + mustache platform_log_dir "${EMQX_LOG_DIR}" "$output" + mustache platform_etc_dir "${EMQX_ETC_DIR}" "$output" +} + +call_hocon() { + local in=("$@") + local args='' + for arg in "${in[@]}"; do + if [ -z "$args" ]; then + args="\"$arg\"" + else + args="$args, \"$arg\"" + fi + done + erl -noshell -eval "{ok, _} = application:ensure_all_started(hocon), ok = hocon_cli:main([$args]), init:stop()." +} + +# Function to generate app.config and vm.args +# sets two environment variables CONF_FILE and ARGS_FILE +generate_app_conf() { + ## timestamp for each generation + local NOW_TIME + NOW_TIME="$(date +'%Y.%m.%d.%H.%M.%S')" + + ## this command populates two files: app.