From c1f0ad9fcd80418b9fa27a821625460e68d806fc Mon Sep 17 00:00:00 2001 From: Bob Tolbert Date: Sat, 22 Aug 2020 12:31:16 -0600 Subject: [PATCH] Fix emsdk_env.sh for multiple shells (#594) This change allows sourcing emsdk_env.sh from bash, zsh and ksh. The script works out the true location of the emsdk directory, even if it is a symlink or the script itself is a symlink. Added a test in scripts/test_source_env.sh to try sourcing via all the shells and with various paths. Co-authored-by: Bob Tolbert --- .circleci/config.yml | 3 +- emsdk_env.sh | 65 +++++++++++++++--- scripts/test_source_env.sh | 132 +++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+), 11 deletions(-) create mode 100755 scripts/test_source_env.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index f4a2db2..36acaf1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,8 +34,9 @@ jobs: - checkout - run: name: Install debian packages - command: apt-get update -q && apt-get install -q -y cmake build-essential openjdk-8-jre-headless + command: apt-get update -q && apt-get install -q -y cmake build-essential openjdk-8-jre-headless ksh zsh - run: scripts/test.sh + - run: scripts/test_source_env.sh - run: name: test.py command: | diff --git a/emsdk_env.sh b/emsdk_env.sh index 2b57fda..7341255 100644 --- a/emsdk_env.sh +++ b/emsdk_env.sh @@ -1,26 +1,71 @@ # This script is sourced by the user and uses -# their shell. Try not to use bashisms. - +# their shell. +# +# This script tries to find its location but +# this does not work in every shell. +# +# It is known to work in bash, zsh and ksh +# # Do not execute this script without sourcing, # because it won't have any effect then. # That is, always run this script with # -# . ./emsdk_env.sh +# . /path/to/emsdk_env.sh +# # or -# source ./emsdk_env.sh +# +# source /path/to/emsdk_env.sh # # instead of just plainly running with # # ./emsdk_env.sh # # which won't have any effect. -if [ -z "$BASH_SOURCE" ]; then - if [ ! -f "./emsdk.py" ]; then - echo "error: You must be in the same directory as emsdk_env.sh when sourcing it (or switch to the bash shell)" 1>&2 + +CURRENT_SCRIPT= +DIR="." + +# use shell specific method to get the path +# to the current file being source'd. +# +# To add a shell, add another conditional below, +# then add tests to scripts/test_source_env.sh + +if [ -n "$BASH_SOURCE" ]; then + CURRENT_SCRIPT="$BASH_SOURCE" +elif [ -n "$ZSH_VERSION" ]; then + CURRENT_SCRIPT="${(%):-%x}" +elif [ -n "$KSH_VERSION" ]; then + CURRENT_SCRIPT=${.sh.file} +fi + +if [ -n "$CURRENT_SCRIPT" ]; then + DIR=$(dirname "$CURRENT_SCRIPT") + if [ -h "$CURRENT_SCRIPT" ]; then + # Now work out actual DIR since this is part of a symlink. + # Since we can't be sure that readlink or realpath + # are available, use tools more likely to be installed. + # (This will still fail if sed is not available.) + SYMDIR=$(dirname "$(ls -l "$CURRENT_SCRIPT" | sed -n "s/.*-> //p")") + if [ -z "$SYMDIR" ]; then + SYMDIR="." + fi + FULLDIR="$DIR/$SYMDIR" + DIR=$(cd "$FULLDIR" > /dev/null 2>&1; /bin/pwd) + unset SYMDIR + unset FULLDIR fi - DIR="." -else - DIR="$(dirname "$BASH_SOURCE")" +fi +unset CURRENT_SCRIPT + +if [ ! -f "$DIR/emsdk.py" ]; then + echo "Error: unable to determine 'emsdk' directory. Perhaps you are using a shell or" 1>&2 + echo " environment that this script does not support." 1>&2 + echo 1>&2 + echo "A possible solution is to source this script while in the 'emsdk' directory." 1>&2 + echo 1>&2 + unset DIR + return fi # Force emsdk to use bash syntax so that this works in windows + bash too diff --git a/scripts/test_source_env.sh b/scripts/test_source_env.sh new file mode 100755 index 0000000..71a3e40 --- /dev/null +++ b/scripts/test_source_env.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash + +echo "Test ability to source emsdk_env.sh in different shells" + +if [ -n "$EMSDK" ]; then + echo "EMSDK is already defined in this shell. Run tests in a shell without sourcing emsdk_env.sh first" + exit 1 +fi + +DIR=$(dirname "$BASH_SOURCE") + +# setup a symlink relative to the current dir +REL_LINK_DIR="$DIR/tmp" +if [ -d "$REL_LINK_DIR" ]; then + rm -rf "$REL_LINK_DIR" +fi +echo "Creating links in $REL_LINK_DIR" +mkdir -p "$REL_LINK_DIR" +(cd $DIR/.. && ln -s `pwd` "$REL_LINK_DIR/emsdk") +(cd $DIR/.. && ln -s `pwd`/emsdk_env.sh "$REL_LINK_DIR") + +# setup a symlink in an absolute directory +ABS_LINK_DIR="/tmp/emsdk_env_test" +if [ -d "$ABS_LINK_DIR" ]; then + rm -rf "$ABS_LINK_DIR" +fi +echo "Creating links in $ABS_LINK_DIR" +mkdir -p "$ABS_LINK_DIR" +(cd $DIR/.. && ln -s `pwd` "$ABS_LINK_DIR/emsdk") +(cd $DIR/.. && ln -s `pwd`/emsdk_env.sh "$ABS_LINK_DIR") + +PATH1="$DIR/../emsdk_env.sh" +PATH2="$REL_LINK_DIR/emsdk/emsdk_env.sh" +PATH3="$REL_LINK_DIR/emsdk_env.sh" +PATH4="$ABS_LINK_DIR/emsdk/emsdk_env.sh" +PATH5="$ABS_LINK_DIR/emsdk_env.sh" + +assert_emcc() { + current=$1 + cmd=$2 + value=$3 + if [ -z "$value" ] || [ "$value" == "false" ]; then + echo "FAILED: $current" + echo " unable to get EMSDK in $current using '$cmd'" + else + echo "SUCCESS: $current testing $cmd" + echo " -> EMSDK = $value" + fi +} + +test_bash() { + value=$(bash --rcfile <(echo $1)) + assert_emcc bash "$1" "$value" +} + +test_zsh() { + value=$(zsh -d -c "$1") + assert_emcc zsh "$1" "$value" +} + +test_ksh() { + value=$(ksh -c "$1") + assert_emcc ksh "$1" "$value" +} + +it_tests_direct_path() { + TEST_SCRIPT=". ${PATH1}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" + TEST_SCRIPT="source ${PATH1}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" +} + +it_tests_via_relative_dir_symlink() { + TEST_SCRIPT=". ${PATH2}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" + TEST_SCRIPT="source ${PATH2}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" +} + +it_tests_via_relative_file_symlink() { + TEST_SCRIPT=". ${PATH3}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" + TEST_SCRIPT="source ${PATH3}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" +} + +it_tests_via_absolute_dir_symlink() { + TEST_SCRIPT=". ${PATH4}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" + TEST_SCRIPT="source ${PATH4}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" +} + +it_tests_via_absolute_file_symlink() { + TEST_SCRIPT=". ${PATH5}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" + TEST_SCRIPT="source ${PATH5}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit' + test_bash "$TEST_SCRIPT" + test_zsh "$TEST_SCRIPT" + test_ksh "$TEST_SCRIPT" +} + +run_bash_tests() { + it_tests_direct_path + it_tests_via_relative_dir_symlink + it_tests_via_relative_file_symlink + it_tests_via_absolute_dir_symlink + it_tests_via_absolute_file_symlink +} + +run_bash_tests + +rm -rf $REL_LINK_DIR +rm -rf $ABS_LINK_DIR