build: add ./dev

This commit is contained in:
Zaiming (Stone) Shi 2023-05-01 21:34:33 +02:00
parent 516c52bdc7
commit dbcb75f35b
1 changed files with 250 additions and 0 deletions

250
dev Executable file
View File

@ -0,0 +1,250 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<EOF
Run EMQX without building a release (which takes longer time).
USAGE: $0 [OPTION]
OPTIONS:
-h Print this help usage info.
-p 'emqx' or 'emqx-enterprise', defaults to 'PROFILE' env.
-c Force recompile, otherwise starts with the already built libs
in '_build/\$PROFILE/lib/'.
ENVIRONMENT VARIABLES:
PROFILE: Overriden by -p option, defaults to 'emqx'.
EMQX_NODE_NAME: The node name of the EMQX node. Default to emqx@127.0.0.1'.
EOF
}
if [ -n "${DEBUG:-}" ]; then
set -x
fi
export HOCON_ENV_OVERRIDE_PREFIX='EMQX_'
EMQX_NODE_NAME="${EMQX_NODE_NAME:-emqx@127.0.0.1}"
PROFILE="${PROFILE:-emqx}"
FORCE_COMPILE=0
while getopts ":p:ch" opt; do
case "${opt}" in
h)
usage
exit 0
;;
p)
PROFILE="${OPTARG}"
;;
c)
FORCE_COMPILE=1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
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
PROJ_ROOT="$(git rev-parse --show-toplevel)"
cd "$PROJ_ROOT"
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"
COOKIE='emqxsecretcookie'
mkdir -p "$EMQX_ETC_DIR" "$EMQX_DATA_DIR/patches" "$EMQX_LOG_DIR" "$CONFIGS_DIR"
## 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.<time>.config and vm.<time>.args
## NOTE: the generate command merges environment variables to the base config (emqx.conf),
## but does not include the cluster-override.conf and local-override.conf
## meaning, certain overrides will not be mapped to app.<time>.config file
call_hocon -v -t "$NOW_TIME" -s "$SCHEMA_MOD" -c "$EMQX_ETC_DIR"/emqx.conf -d "$EMQX_DATA_DIR"/configs generate
## filenames are per-hocon convention
CONF_FILE="$CONFIGS_DIR/app.$NOW_TIME.config"
ARGS_FILE="$CONFIGS_DIR/vm.$NOW_TIME.args"
}
# apps/emqx/etc/vm.args.cloud
append_args_file() {
## ensure a new line at the end
echo '' >> "$ARGS_FILE"
cat <<EOF >> "$ARGS_FILE"
-name $EMQX_NODE_NAME
-mnesia dir '"$EMQX_DATA_DIR/mnesia/$EMQX_NODE_NAME"'
-stdlib restricted_shell emqx_restricted_shell
+spp true
+A 4
+IOt 4
+SDio 8
-shutdown_time 30000
-pa '"$EMQX_DATA_DIR/patches"'
-mnesia dump_log_write_threshold 5000
-mnesia dump_log_time_threshold 60000
-os_mon start_disksup false
EOF
}
# copy cert files and acl.conf to etc
copy_other_conf_files() {
cp -r apps/emqx/etc/certs "$EMQX_ETC_DIR"/
cp apps/emqx_authz/etc/acl.conf "$EMQX_ETC_DIR"/
}
is_current_profile_app() {
local app="$1"
case "$app" in
lib-ee*)
if [ "$PROFILE" = 'emqx-enterprise' ]; then
return 0
else
return 1
fi
;;
*)
if [ "$PROFILE" = 'emqx' ]; then
if [ -f "$app"/BSL.txt ]; then
return 1
else
return 0
fi
else
return 0
fi
;;
esac
}
## apps to load
apps_to_load() {
local apps csl
apps="$(./scripts/find-apps.sh | xargs)"
csl=""
for app in $apps; do
if ! is_current_profile_app "$app"; then
continue
fi
name="$(basename "$app")"
if [ -z "$csl" ]; then
csl="$name"
else
csl="$csl,$name"
fi
done
echo "$csl"
}
## Make erl command aware where to load all the beams
## this should be done before every erl command
prepare_erl_libs "$PROFILE"
render_hocon_conf
generate_app_conf
append_args_file
copy_other_conf_files
APPS="$(apps_to_load)"
BOOT_SEQUENCE="
Apps=[${APPS}],
ok=lists:foreach(fun application:load/1, Apps),
io:format(user, \"~nLoaded ~p apps~n\", [length(Apps)]),
application:ensure_all_started(emqx_machine).
"
erl -name "$EMQX_NODE_NAME" \
-start_epmd false \
-epmd_module ekka_epmd \
-proto_dist ekka \
-args_file "$ARGS_FILE" \
-config "$CONF_FILE" \
-s emqx_restricted_shell set_prompt_func \
-eval "$BOOT_SEQUENCE"