mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-29 03:37:42 +00:00
Fixes #6320. Part 1 of moving from lerna to a simpler, maintained monorepo solution, using TypeScript Projects and NPM Workspaces. There is more work to be done here. At this point, KeymanWeb builds and runs without errors, but the built file is substantially different, mostly in include order. Using TypeScript Projects, we move away from the need to run build scripts in various locations for almost all the Typescript modules. TODO: Embedded versions and tests have not been verified. TODO: developer/server is not yet verified. TODO: developer/js (needs a rename!) is not yet verified. TODO: Currently, the predictive-text folder needs refactoring to move the construction of the worker wrapper out of the Predictive Text build and into the final assembly of keymanweb.js (as it should be valid to run it as a separate .js anyway). TODO: Most of the `<reference>` paths need to be re-verified. Ideally there should be no references outside the current module for any given .ts. TODO: The embedded vs browser vs node (headless) builds should be tidied up for consistency so that it's obvious what depends on what. This is currently messiest in the predictive-text folder, where the output names diverge from the filenames and the various files are mixed in the same folder (as evidenced by the exclusions listed in each tsconfig.json). TODO: `npm install` should be removed from most build scripts and instead `npm ci` (#6196) should be run only once from the top-level folder for any given build. I've had eliminated side-effects from the `install` action for npm, which makes it easier to reason about state. TODO: verify_npm_setup and related functions can probably be eliminated. TODO: most of the build scripts should be largely eliminated for web. TODO: several ts projects use inconsistent output folders. TODO: it may be possible to generate a .d.ts for models/types so that we can use a consistent reference for those as well. TODO: build.sh, tsconfig.json should always be in the module's top-level folder, not in a subfolder such as src (e.g. see input-processor/src, keyboard-processor/src, web/source). TODO: resources/web-environment should be in common/web. TODO: other js node_modules imports should be wrapped like es6-shim. TODO: fix up the publish code for npm modules TODO: eliminate version numbers from package.json if possible? Whew, that's most of the stuff I noticed!
300 lines
No EOL
8.7 KiB
Bash
Executable file
300 lines
No EOL
8.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
#
|
|
# WARNING: this file is copied into other locations during package builds; do not
|
|
# include other files or make path assumptions when changing this file.
|
|
# See `common/core/desktop/build.sh` for more details.
|
|
#
|
|
|
|
_shf_base_dir=$(dirname "$BASH_SOURCE")/..
|
|
|
|
# Designed to determine which set of browsers should be available for local testing,
|
|
# based upon the current system OS.
|
|
get_builder_OS ( ) {
|
|
# Default value, since it's the most general case/configuration to detect.
|
|
os_id="linux"
|
|
|
|
# Subject to change with future improvements.
|
|
if [[ "${OSTYPE}" = "darwin"* ]]; then
|
|
os_id="mac"
|
|
elif [[ "${OSTYPE}" = "msys" ]]; then
|
|
os_id="win"
|
|
elif [[ "${OSTYPE}" = "cygwin" ]]; then
|
|
os_id="win"
|
|
fi
|
|
}
|
|
|
|
# Allows for a quick macOS check for those scripts requiring a macOS environment.
|
|
verify_on_mac() {
|
|
if [[ "${OSTYPE}" != "darwin"* ]]; then
|
|
fail "This build script will only run in a Mac environment."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# The list of valid projects that our build scripts ought expect.
|
|
projects=("android" "ios" "linux" "lmlayer" "mac" "web" "windows")
|
|
|
|
# Used to validate a specified 'project' parameter.
|
|
verify_project() {
|
|
match=false
|
|
for proj in ${projects[@]}
|
|
do
|
|
if [ $proj = $1 ]; then
|
|
match=true
|
|
fi
|
|
done
|
|
|
|
if [ $match = false ]; then
|
|
fail "Invalid project specified!"
|
|
fi
|
|
}
|
|
|
|
# The list of valid platforms that our build scripts ought expect.
|
|
platforms=("android" "ios" "linux" "lmlayer" "mac" "web" "desktop" "developer")
|
|
|
|
# Used to validate a specified 'platform' parameter.
|
|
verify_platform() {
|
|
match=false
|
|
for proj in ${platforms[@]}
|
|
do
|
|
if [ $proj = $1 ]; then
|
|
match=true
|
|
fi
|
|
done
|
|
|
|
if [ $match = false ]; then
|
|
fail "Invalid platform specified!"
|
|
fi
|
|
}
|
|
|
|
# Gets the folder containing each platform's history.md file, which is also the base folder for most of the platforms.
|
|
# Sets $platform_folder accordingly.
|
|
get_platform_folder() {
|
|
verify_platform $1
|
|
|
|
if [[ $1 = "desktop" || $1 = "developer" ]]; then
|
|
platform_folder="$_shf_base_dir/windows/src/$1"
|
|
elif [[ $1 = "lmlayer" ]]; then
|
|
platform_folder="common/predictive-text"
|
|
else
|
|
platform_folder="$_shf_base_dir/$1"
|
|
fi
|
|
}
|
|
|
|
# The following allows coloring of warning and error lines, but only works if there's a
|
|
# terminal attached, so not on the build machine.
|
|
if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]]; then
|
|
COLOR_RED=$(tput setaf 1)
|
|
COLOR_GREEN=$(tput setaf 2)
|
|
COLOR_BLUE=$(tput setaf 4)
|
|
COLOR_YELLOW=$(tput setaf 3)
|
|
COLOR_RESET=$(tput sgr0)
|
|
else
|
|
COLOR_RED=
|
|
COLOR_GREEN=
|
|
COLOR_BLUE=
|
|
COLOR_YELLOW=
|
|
COLOR_RESET=
|
|
fi
|
|
|
|
echo_heading() {
|
|
echo "${COLOR_BLUE}$*${COLOR_RESET}"
|
|
}
|
|
|
|
fail() {
|
|
FAILURE_MSG="$1"
|
|
if [[ "$FAILURE_MSG" == "" ]]; then
|
|
FAILURE_MSG="Unknown failure"
|
|
fi
|
|
echo "${COLOR_RED}$FAILURE_MSG${COLOR_RESET}"
|
|
exit 1
|
|
}
|
|
|
|
warn() { echo "${COLOR_YELLOW}$*${COLOR_RESET}"; }
|
|
|
|
displayInfo() {
|
|
if [ "$QUIET" != true ]; then
|
|
while [[ $# -gt 0 ]] ; do
|
|
echo $1
|
|
shift # past argument
|
|
done
|
|
fi
|
|
}
|
|
|
|
assertFileExists() {
|
|
if ! [ -f $1 ]; then
|
|
fail "Build failed: missing $1"
|
|
fi
|
|
}
|
|
|
|
assertDirExists() {
|
|
if ! [ -d $1 ]; then
|
|
fail "Build failed: missing $1"
|
|
fi
|
|
}
|
|
|
|
assertValidVersionNbr()
|
|
{
|
|
if [[ "$1" == "" || ! "$1" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
fail "Specified version not valid: '$1'. Version should be in the form Major.Minor.BuildCounter"
|
|
fi
|
|
}
|
|
|
|
assertValidPRVersionNbr()
|
|
{
|
|
if [[ "$1" == "" || ! "$1" =~ ^[0-9]+\.[0-9]+\.pull\.[0-9]+$ ]]; then
|
|
fail "Specified version not valid: '$1'. Version should be in the form Major.Minor.pull.BuildCounter"
|
|
fi
|
|
}
|
|
|
|
dl_info_display_usage() {
|
|
echo "Used to create a metadata file needed on the download site"
|
|
echo "for it to connect to the download.keyman.com API functions."
|
|
echo
|
|
echo "usage: write-download_info <name> <filepath> <version> <tier> <platform>"
|
|
echo
|
|
echo " name Specifies the user-friendly name of the product represented by the file."
|
|
echo " filepath Specifies the path and file in need of a .download_info metadata file."
|
|
echo " version Specifies the build version number, which should be in the"
|
|
echo " form Major.Minor.BuildCounter"
|
|
echo " tier Specifies tier (typically one of: alpha, beta, stable)."
|
|
echo " platform Specifies the target platforms for the file."
|
|
echo " (Should be one of: android, ios, mac, web, windows)"
|
|
echo
|
|
echo "The resulting .downloadinfo file will be automatically placed in the same directory"
|
|
echo "as the originally-specified file."
|
|
exit 1
|
|
}
|
|
|
|
write_download_info() {
|
|
#Process file & path information.
|
|
PRODUCT_NAME="$1"
|
|
BASE_PATH="$2"
|
|
KM_VERSION="$3"
|
|
KM_TIER="$4"
|
|
KM_PLATFORM="$5"
|
|
|
|
verify_project "$KM_PLATFORM"
|
|
|
|
BASE_DIR=$(dirname "${BASE_PATH}")
|
|
BASE_FILE=$(basename "${BASE_PATH}");
|
|
|
|
if ([ -h "${BASE_DIR}" ]) then
|
|
while([ -h "${BASE_DIR}" ]) do BASE_PATH=`readlink "${BASE_DIR}"`;
|
|
done
|
|
fi
|
|
|
|
assertFileExists "$2"
|
|
|
|
pushd . > /dev/null
|
|
cd `dirname ${BASE_DIR}` > /dev/null
|
|
BASE_PATH=`pwd`;
|
|
popd > /dev/null
|
|
|
|
DEST_DIR="$BASE_DIR"
|
|
|
|
#Process version parameter.
|
|
assertValidVersionNbr "$3"
|
|
KM_BLD_COUNTER="$((${KM_VERSION##*.}))"
|
|
|
|
if [ "$KM_VERSION" = "" ]; then
|
|
fail "Required -version parameter not specified!"
|
|
fi
|
|
|
|
if [ "$KM_TIER" = "" ]; then
|
|
fail "Required -tier parameter not specified!"
|
|
fi
|
|
|
|
DOWNLOAD_INFO_FILEPATH="${BASE_PATH}/${BASE_FILE}.download_info"
|
|
if [[ ! -f "${BASE_PATH}/${BASE_FILE}" ]]; then
|
|
fail "Cannot compute file size or MD5 for non-existent DMG file: ${BASE_PATH}/${BASE_FILE}"
|
|
fi
|
|
|
|
FILE_EXTENSION="${BASE_FILE##*.}"
|
|
|
|
FILE_SIZE=$(stat -f"%z" "${BASE_PATH}/${BASE_FILE}")
|
|
MD5_HASH=$(md5 -q "${BASE_PATH}/${BASE_FILE}")
|
|
|
|
if [[ -f "$DOWNLOAD_INFO_FILEPATH" ]]; then
|
|
warn "Overwriting $DOWNLOAD_INFO_FILEPATH"
|
|
fi
|
|
|
|
echo { > "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"name\": \"${PRODUCT_NAME}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"version\": \"${KM_VERSION}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"date\": \"$(date "+%Y-%m-%d")\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"platform\": \"${KM_PLATFORM}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"stability\": \"${KM_TIER}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"file\": \"${BASE_FILE}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"md5\": \"${MD5_HASH}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"type\": \"${FILE_EXTENSION}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"build\": \"${KM_BLD_COUNTER}\"," >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo " \"size\": \"${FILE_SIZE}\"" >> "$DOWNLOAD_INFO_FILEPATH"
|
|
echo } >> "$DOWNLOAD_INFO_FILEPATH"
|
|
}
|
|
|
|
# set_version sets the file version on mac/ios projects
|
|
set_version ( ) {
|
|
PRODUCT_PATH=$1
|
|
|
|
if [ $VERSION ]; then
|
|
if [ $2 ]; then # $2 = product name.
|
|
echo "Setting version numbers in $2 to $VERSION."
|
|
fi
|
|
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $VERSION" "$PRODUCT_PATH/Info.plist"
|
|
/usr/libexec/Plistbuddy -c "Set CFBundleShortVersionString $VERSION" "$PRODUCT_PATH/Info.plist"
|
|
fi
|
|
}
|
|
|
|
|
|
# Uses npm to set the current package version (package.json).
|
|
#
|
|
# This sets the version according to the current VERSION_WITH_TAG.
|
|
#
|
|
# Usage:
|
|
#
|
|
# set_npm_version
|
|
#
|
|
set_npm_version () {
|
|
local version="$VERSION_WITH_TAG"
|
|
# We use --no-git-tag-version because our CI system controls version numbering and
|
|
# already tags releases. We also want to have the version of this match the
|
|
# release of Keyman Developer -- these two versions should be in sync. Because this
|
|
# is a large repo with multiple projects and build systems, it's better for us that
|
|
# individual build systems don't take too much ownership of git tagging. :)
|
|
pushd . > /dev/null
|
|
cd "${KEYMAN_ROOT}"
|
|
npm run version "$version" || fail "Could not set package versions to $version."
|
|
popd > /dev/null
|
|
}
|
|
|
|
# Initializes use of the npm packages within the repo.
|
|
init_npm() {
|
|
if [ "${KEYMAN_ROOT}" = "" ]; then
|
|
fail "KEYMAN_ROOT not defined; cannot install repo's dependencies"
|
|
fi
|
|
pushd "$KEYMAN_ROOT" > /dev/null
|
|
npm install --no-optional
|
|
popd > /dev/null
|
|
}
|
|
|
|
# Accepts an optional parameter.
|
|
# $1 - when set to 'false', only ensures that `npm` and `node` are accessible; does not install dependencies.
|
|
#
|
|
# Designed for use with the projects/packages we have listed in the base folder package.json workspaces.
|
|
verify_npm_setup () {
|
|
if [ $# != 0 ]; then
|
|
fetch_deps=$1
|
|
else
|
|
fetch_deps=true
|
|
fi
|
|
|
|
# Check if Node.JS/npm is installed.
|
|
type npm >/dev/null ||\
|
|
fail "Build environment setup error detected! Please ensure Node.js is installed!"
|
|
|
|
if [ $fetch_deps = true ]; then
|
|
init_npm
|
|
fi
|
|
} |