Jelajahi Sumber

build: add ./dev

Zaiming (Stone) Shi 2 tahun lalu
induk
melakukan
dbcb75f35b
1 mengubah file dengan 250 tambahan dan 0 penghapusan
  1. 250 0
      dev

+ 250 - 0
dev

@@ -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"