diff --git a/HISTORY.md b/HISTORY.md
index 7bb236717b..904e03468a 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,5 +1,25 @@
# Keyman Version History
+## 18.0.97 alpha 2024-08-24
+
+* refactor(linux): cleanup API of kvk2ldml.py (#12276)
+* chore(common): adjust build settings for windows clean builds (#12264)
+* chore(windows): remove remaining unused Makefiles (#12274)
+* docs(developer): update build documentation to refer to build.sh (#12272)
+
+## 18.0.96 alpha 2024-08-23
+
+* fix(android): Fix navigation arrows in Info Activity for RTL (#12244)
+* fix(web): fix documentation-keyboard spacebar-text scaling (#12232)
+* fix(android): Use increment and decrement arrows on longpress delay menu (#12242)
+* fix(android): Add RTL assets for adjusting keyboard height menu (#12261)
+* chore(common): use `npm install` in emsdk update (#12269)
+* docs: refresh windows.md (#12248)
+
+## 18.0.95 alpha 2024-08-22
+
+* chore(common): allow build agents to automatically select emsdk version, and enable support for 3.1.60+ (#12243)
+
## 18.0.94 alpha 2024-08-21
* fix(core): look for `emcc` instead of `emcc.py` (#12235)
diff --git a/VERSION.md b/VERSION.md
index a41e5425c0..48b8081cd1 100644
--- a/VERSION.md
+++ b/VERSION.md
@@ -1 +1 @@
-18.0.95
\ No newline at end of file
+18.0.98
\ No newline at end of file
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-hdpi/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-hdpi/blank_osk.png
new file mode 100644
index 0000000000..c5d555caca
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-hdpi/blank_osk.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-land-hdpi/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-land-hdpi/blank_osk.png
new file mode 100644
index 0000000000..3e41a359a0
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-land-hdpi/blank_osk.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp-land/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp-land/blank_osk.png
new file mode 100644
index 0000000000..282606a9d5
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp-land/blank_osk.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp/blank_osk.png
new file mode 100644
index 0000000000..8246a64168
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp/blank_osk.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp-land/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp-land/blank_osk.png
new file mode 100644
index 0000000000..740c8559c9
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp-land/blank_osk.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp/blank_osk.png
new file mode 100644
index 0000000000..0e3343bbd1
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp/blank_osk.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml
index ed0bed54a9..ef1ebd613b 100644
--- a/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml
+++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml
@@ -23,7 +23,7 @@
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:contentDescription="@string/ic_delay_time_down"
- android:src="@drawable/ic_light_dialog_textsize_down" />
+ android:src="@drawable/ic_action_decrement" />
+ android:src="@drawable/ic_action_increment" />
diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml
index 3b71e87178..314a503412 100644
--- a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml
+++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml
@@ -1,12 +1,12 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="@color/ms_white"
+ tools:context=".InfoActivity" >
-
-
+ android:orientation="horizontal">
-
+
+
+
+
+
nul 2>nul
- $(CLEAN) ExcMagic.Debug *.wixpdb *.identcache *.embed.manifest *.embed.manifest.res *.intermediate.manifest error.log >nul 2>nul
- if exist bin rd /s/q bin
- if exist obj rd /s/q obj
-
-!CMDSWITCHES -S
-
-# This virtual rule forces targets which are folders, e.g. `kmshell` to
-# always execute
-.virtual:
- rem always execute
diff --git a/common/windows/delphi/components/common_components.dproj b/common/windows/delphi/components/common_components.dproj
index 2bd91473ab..4ecda90464 100644
--- a/common/windows/delphi/components/common_components.dproj
+++ b/common/windows/delphi/components/common_components.dproj
@@ -13,31 +13,6 @@
true
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
- trueBase
@@ -59,6 +34,12 @@
Basetrue
+
+ true
+ Cfg_2
+ true
+ true
+ .\obj\$(Platform)\$(Config).\$(Platform)\$(Config)
@@ -77,23 +58,6 @@
3081CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
-
- None
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- None
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- None
-
-
- None
-
-
- None
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)Debug
@@ -113,6 +77,7 @@
falsetrue1033
+ ..\..\libfalse
@@ -120,6 +85,11 @@
00
+
+ ..\..\lib
+ true
+ 1033
+ MainSource
@@ -164,8 +134,6 @@
common_components.dpk
- File c:\projects\keyman\app\windows\lib\DCPdelphi2009.bpl not found
- File c:\projects\keyman\app\windows\lib\delphiprojectmanager.bpl not foundMicrosoft Office 2000 Sample Automation Server Wrapper ComponentsMicrosoft Office XP Sample Automation Server Wrapper Components
@@ -944,13 +912,6 @@
- False
- False
- False
- False
- False
- False
- FalseTrueFalse
diff --git a/common/windows/delphi/ext/cef4delphi/packages/CEF4Delphi.res b/common/windows/delphi/ext/cef4delphi/packages/CEF4Delphi.res
deleted file mode 100644
index b9b013c212..0000000000
Binary files a/common/windows/delphi/ext/cef4delphi/packages/CEF4Delphi.res and /dev/null differ
diff --git a/common/windows/delphi/tools/certificates/build.sh b/common/windows/delphi/tools/certificates/build.sh
index 378723a125..10ab4c75ce 100755
--- a/common/windows/delphi/tools/certificates/build.sh
+++ b/common/windows/delphi/tools/certificates/build.sh
@@ -21,6 +21,8 @@ builder_describe_outputs \
function do_certificates() {
rm -f KeymanTestCA-sha1.* KeymanTest-sha1.* KeymanTest-sha256.* KeymanTestCA-sha256.*
+ source "$KEYMAN_ROOT/resources/build/win/visualstudio_environment.inc.sh"
+
makecert -r -pe -n "CN=Keyman Test CA SHA1" -ss CA -sr CurrentUser -a sha1 -cy authority -sky signature -sv KeymanTestCA-sha1.pvk KeymanTestCA-sha1.cer
certutil -user -addstore Root KeymanTestCA-sha1.cer
makecert -pe -n "CN=Keyman Test Certificate SHA1" -a sha1 -cy end -sky signature -ic KeymanTestCA-sha1.cer -iv KeymanTestCA-sha1.pvk -sv KeymanTest-sha1.pvk KeymanTest-sha1.cer
diff --git a/developer/src/README.md b/developer/src/README.md
index 7e7ea9d336..d789b63f08 100644
--- a/developer/src/README.md
+++ b/developer/src/README.md
@@ -2,6 +2,42 @@
This is the current home for Keyman Developer.
+## Build Prerequisites
+
+* See [Windows Build Environment Configuration](../../docs/build/windows.md).
+
+## Building Keyman Developer
+
+1. Start 'Git Bash' (part of Git for Windows).
+2. Run `developer/src/build.sh`.
+3. Artifacts from a successful build will be placed in **developer/bin** folder.
+
+*Note*: running `build.sh` will currently reset the packages and path settings
+in your Delphi environment. If you use Delphi for other projects, you should
+consider building Keyman under a login user dedicated to it, or in a VM.
+
+Type `build.sh` to see build targets and actions. Common build actions are:
+
+* `build.sh build`
+: builds Keyman Developer
+
+* `build.sh clean`
+: remove temporary files and build artifacts
+
+* `build.sh publish`
+: makes a release of all Keyman Developer projects
+
+* `build.sh install`
+: install some or all components to Program Files (requires elevated command prompt).
+
+### Building without Delphi
+
+It is possible to build all components that do _not_ require Delphi. Currently a
+few components are Delphi-based (TIKE, setup, a few others), but you may be able
+to get away without building them. In this situation, we recommend copying the
+relevant Delphi-built components into developer/bin folders from a compatible
+installed version of Keyman Developer for testing and debugging purposes.
+
# Folders
## common
@@ -106,4 +142,6 @@ testing and packing keyboards for distribution.
## tools
-Various build-time tools for Keyman Developer.
\ No newline at end of file
+Various build-time tools for Keyman Developer.
+
+
diff --git a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts
index 6182e6e2c8..6d76bc403e 100644
--- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts
+++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts
@@ -3,6 +3,23 @@ import { LDMLKeyboard, CompilerCallbacks } from "@keymanapp/developer-utils";
import { KeysCompiler } from "./keys.js";
import { LdmlCompilerMessages } from "./ldml-compiler-messages.js";
+// This is a partial polyfill for findLast, so not polluting Array.prototype
+// https://medium.com/@stheodorejohn/findlast-method-polyfill-in-javascript-bridging-browser-gaps-c3baf6aabae1
+// TODO: remove and replace with Array.prototype.findLast when it is
+// well-supported
+function findLast(arr: any, callback: any) {
+ if (!arr) {
+ return undefined;
+ }
+ const len = arr.length >>> 0;
+ for (let i = len - 1; i >= 0; i--) {
+ if (callback(arr[i], i, arr)) {
+ return arr[i];
+ }
+ }
+ return undefined;
+}
+
export class LdmlKeyboardVisualKeyboardCompiler {
public constructor(private callbacks: CompilerCallbacks) {
}
@@ -57,7 +74,8 @@ export class LdmlKeyboardVisualKeyboardCompiler {
const keyId = key;
x++;
- let keydef = source.keyboard3.keys?.key?.find(x => x.id == key);
+ //@ts-ignore
+ let keydef = findLast(source.keyboard3.keys?.key, x => x.id == key);
if (!keydef) {
this.callbacks.reportMessage(
diff --git a/developer/src/kmc-model/test/test-compile-model.ts b/developer/src/kmc-model/test/test-compile-model.ts
index e3074d697a..7de9d6d5da 100644
--- a/developer/src/kmc-model/test/test-compile-model.ts
+++ b/developer/src/kmc-model/test/test-compile-model.ts
@@ -9,6 +9,8 @@ import { KeymanFileTypes } from '@keymanapp/common-types';
describe('LexicalModelCompiler', function () {
let callbacks = new TestCompilerCallbacks();
+ this.timeout(5000);
+
// Try to compile ALL of the correct models.
const MODELS = [
'example.qaa.sencoten',
diff --git a/developer/src/tike/build.sh b/developer/src/tike/build.sh
index 1ab9dbe320..fd81ca692d 100755
--- a/developer/src/tike/build.sh
+++ b/developer/src/tike/build.sh
@@ -19,7 +19,7 @@ source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh"
WIN32_TARGET="$WIN32_TARGET_PATH/tike.exe"
builder_describe_outputs \
- configure:project /resources/build/win/delphi_environment_generated.inc.sh \
+ configure:project /developer/src/tike/xml/layoutbuilder/keymanweb-osk.ttf \
build:project /developer/src/tike/$WIN32_TARGET
#-------------------------------------------------------------------------------------------------------------------
@@ -31,6 +31,7 @@ function do_configure() {
mkdir -p "$DEVELOPER_PROGRAM"
cp "$KEYMAN_ROOT/common/schemas/kps/kps.xsd" "$DEVELOPER_PROGRAM"
cp "$KEYMAN_ROOT/common/resources/fonts/keymanweb-osk.ttf" "$DEVELOPER_ROOT/src/tike/xml/layoutbuilder/keymanweb-osk.ttf"
+ run_in_vs_env rc icons.rc
}
function do_monaco_copy() {
@@ -52,8 +53,6 @@ function do_monaco_copy() {
pushd "$DEVELOPER_ROOT/src/tike/xml/app/lib/sentry"
replaceVersionStrings_Mkver init.js.in init.js
popd
-
- run_in_vs_env rc icons.rc
}
KEYMANCORE_DLL=keymancore-2.dll
diff --git a/docs/build/linux-ubuntu.md b/docs/build/linux-ubuntu.md
index 0107491dda..a45d9390ba 100644
--- a/docs/build/linux-ubuntu.md
+++ b/docs/build/linux-ubuntu.md
@@ -63,17 +63,33 @@ See [node.md](node.md) for more information.
#### Emscripten
-You'll also have to install `emscripten` (version 3.1.44 is known to work):
+You'll also have to install `emscripten`:
```shell
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
-./emsdk install 3.1.44
-./emsdk activate 3.1.44
-export EMSCRIPTEN_BASE=$(pwd)/upstream/emscripten
+./emsdk install 3.1.58
+./emsdk activate 3.1.58
+export EMSCRIPTEN_BASE="$(pwd)/upstream/emscripten"
+echo "export EMSCRIPTEN_BASE=\"$EMSCRIPTEN_BASE\"" >> .bashrc
```
-**NOTE:** Don't put EMSDK on the path, i.e. don't source `emsdk_env.sh`.
+> ![WARNING]
+> Don't put EMSDK on the path, i.e. don't source `emsdk_env.sh`.
+>
+> Emscripten very unhelpfully overwrites `JAVA_HOME`, and adds its own
+> versions of Python, Node and Java to the `PATH`. For best results, restart
+> your shell after installing Emscripten so that you don't end up with the
+> wrong versions.
+
+**Optional environment variables**:
+
+To let the Keyman build scripts control the version of Emscripten installed on
+your computer:
+
+```shell
+export KEYMAN_USE_EMSDK=1
+```
## Keyman Core
diff --git a/docs/build/macos.md b/docs/build/macos.md
index 81b1bcd0e7..25b0c1f82a 100644
--- a/docs/build/macos.md
+++ b/docs/build/macos.md
@@ -91,16 +91,38 @@ See [node.md](node.md) for more information.
### emscripten
-To install emscripten:
+The recommended way to install emscripten is with the official method, as that
+then allows the build scripts to select the appropriate version automatically.
-```shell
-brew install emscripten
+To install emscripten, `cd` to an appropriate path, and then:
+
+```bash
+git clone https://github.com/emscripten-core/emsdk
+cd emsdk
+emsdk install 3.1.58
+emsdk activate 3.1.58
+export EMSCRIPTEN_BASE="$(pwd)/upstream/emscripten"
+echo "export EMSCRIPTEN_BASE=\"$EMSCRIPTEN_BASE\"" >> .bashrc
```
-Note: if you install emscripten with brew on macOS, only emscripten binaries are
-added to the path via symlinks. This makes it reasonably safe to have emscripten
-on the path, unlike on other platforms where emscripten also ends up adding its
-versions of node, python, and other binaries to the path.
+You will want to add `EMSCRIPTEN_BASE` to your .bashrc.
+
+> ![WARNING]
+> Don't put EMSDK on the path, i.e. don't source `emsdk_env.sh`.
+>
+> Emscripten very unhelpfully overwrites `JAVA_HOME`, and adds its own
+> versions of Python, Node and Java to the `PATH`. For best results, restart
+> your shell after installing Emscripten so that you don't end up with the
+> wrong versions.
+
+**Optional environment variables**:
+
+To let the Keyman build scripts control the version of Emscripten installed on
+your computer:
+
+```shell
+export KEYMAN_USE_EMSDK=1
+```
## Keyman for iOS Dependencies
diff --git a/docs/build/windows.md b/docs/build/windows.md
index dcb55ce4a4..3168bcd0ae 100644
--- a/docs/build/windows.md
+++ b/docs/build/windows.md
@@ -6,13 +6,13 @@ On Windows, you can build the following projects:
* [Keyman for Android](#keyman-for-android)
* [Keyman for Windows](#keyman-for-windows)
-* [Keyman Developer](#keyman-developer) (together with Keyman for Windows)
+* [Keyman Developer](#keyman-developer)
* [KeymanWeb](#keymanweb)
The following libraries can also be built:
-* Keyman Core (Windows, wasm targets) (aka core)
-* Common/Web
+* Keyman Core (Windows, wasm targets)
+* Common libraries
The following projects **cannot** be built on Windows:
@@ -63,10 +63,6 @@ Dependencies:
* [Base](#base-dependencies)
* [Windows Platform](#windows-platform-dependencies)
-**Note**: Keyman for Windows is currently built together with Keyman Developer.
-We are working on splitting these projects. For now, you will need the Keyman
-Developer dependencies as well.
-
Building:
* [Building Keyman for Windows](../../windows/src/README.md)
@@ -75,7 +71,7 @@ Building:
Dependencies:
* [Base](#base-dependencies)
* [Web](#web-dependencies)
-* [Windows Platform](#windows-platform-dependencies)
+* [Windows Platform](#windows-platform-dependencies) (optional, for Windows-only components)
Building:
* [Building Keyman Developer](../../windows/src/README.md)
@@ -94,42 +90,19 @@ Building:
**Dependencies**:
* [Base](#base-dependencies)
* [Web](#web-dependencies)
-
-**Additional requirements**:
-* Android SDK
-* Android Studio
-* Ant
-* Gradle
-* Maven
-* Optional: OpenJDK 11 (https://learn.microsoft.com/en-us/java/openjdk/download)
-
-```ps1
-# Elevated PowerShell
-choco install android-sdk android-studio ant gradle maven
-# optionally install sdk images
-sdkmanager "system-images;android-33;google_apis;armeabi-v7a"
-sdkmanager --update
-sdkmanager --licenses
-```
-
-* Run Android Studio once after installation to install additional components
- such as emulator images and SDK updates.
-
-**Required environment variables**:
-* [`JAVA_HOME`](#java_home)
-
-**Optional environment variables**:
-* [`JAVA_HOME_11`](#java_home)
+* [Android](#android-dependencies)
Building:
* [Building Keyman for Android](../../android/README.md)
-## Prerequisites
+---
+
+## Dependencies and Prerequisites
Many dependencies are only required for specific projects.
We prefer [Chocolatey](https://chocolatey.org/install) at present for
-installation of dependencies. Chocolatey should be run in an elevated
+installation of most dependencies. Chocolatey should be run in an elevated
PowerShell.
### Base Dependencies
@@ -150,28 +123,36 @@ PowerShell.
# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138)
$ProgressPreference = 'SilentlyContinue'
choco install git jq python ninja pandoc meson
-refreshenv
```
**Environment variables**:
-* [`KEYMAN_ROOT`](#keyman_root)
-* `PATH`: add your Python scripts folder to your path: it will normally be `%appdata%\Python\Python310\Scripts`.
+
+If you pull the entire `keyman.git` repo to `c:\keyman`, then the paths by
+default will work without changes. Otherwise, you will need to set an
+environment variable `KEYMAN_ROOT` to the root path of the Keyman repo. For
+example:
```bat
-SET KEYMAN_ROOT=c:\Projects\keyman\keyman
-SET PATH=%path%;%appdata%\Python\Python310\Scripts
+SETX KEYMAN_ROOT "c:\Projects\keyman\keyman"
```
-To check whether environment variables are set, run `SET ` in command
-prompt.
+> [!NOTE]
+> The `SETX` command will set persistent environment variables but they do not
+> impact the current shell environment. Start a new shell to see the variables.
-You can use Windows Settings to add these environment variables permanently:
-
-1. In Windows Search, type "environment" and select "Edit System Environment
- Variables"
-2. Click `Environment Variables...`
-3. You can add or edit variables in either User or System settings, as you
- prefer.
+> [!TIP]
+>
+> To check whether environment variables are set, run `SET ` in command
+> prompt.
+>
+> You can alternatively use Windows Settings to add these environment variables
+> permanently:
+>
+> 1. In Windows Search, type "environment" and select "Edit System Environment
+> Variables"
+> 2. Click `Environment Variables...`
+> 3. You can add or edit variables in either User or System settings, as you
+> prefer.
### Web Dependencies
@@ -181,32 +162,46 @@ You can use Windows Settings to add these environment variables permanently:
* KeymanWeb
**Requirements**:
-* emscripten 3.1.46 or later
-* node.js 18+
-* [openjdk 11](https://learn.microsoft.com/en-us/java/openjdk/download#openjdk-11)+
+* Emscripten
+* node.js
-```ps1
-# Elevated PowerShell
+#### Emscripten
-# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138)
-$ProgressPreference = 'SilentlyContinue'
+In bash, run the following commands:
-choco install emscripten --version 3.1.46
+```bash
+cd /c/Projects/keyman
+git clone https://github.com/emscripten-core/emsdk
+cd emsdk
+emsdk install 3.1.58
+emsdk activate 3.1.58
```
-Note: emscripten very unhelpfully overwrites JAVA_HOME, and adds its own
-versions of Python, Node and Java to the PATH. For best results, go ahead
-and remove those paths from your PATH variable before continuing.
+> ![WARNING]
+> Emscripten very unhelpfully overwrites `JAVA_HOME`, and adds its own
+> versions of Python, Node and Java to the `PATH`. For best results, restart
+> your shell after installing Emscripten so that you don't end up with the
+> wrong versions.
There is no need to add emscripten to the path in order to build Keyman.
-However, you should set the EMSCRIPTEN_BASE variable to the path where `emcc`
-can be found, but always in the upstream\emscripten subdirectory where you
-installed emsdk (most likely %LocalAppData%\emsdk\upstream\emscripten)
+However, you should set the `EMSCRIPTEN_BASE` variable to the path where `emcc`
+can be found, in the `upstream\emscripten` subdirectory of where you installed
+emsdk.
**Environment variables**:
-* `EMSCRIPTEN_BASE`: `\upstream\emscripten`
-After installing emscripten, you'll need to install node.js and openjdk.
+```bat
+SETX EMSCRIPTEN_BASE "\upstream\emscripten"
+```
+
+**Optional environment variables**:
+
+To let the Keyman build scripts control the version of Emscripten
+installed on your computer:
+
+```bat
+SETX KEYMAN_USE_EMSDK 1
+```
#### node.js
@@ -214,30 +209,22 @@ Our recommended way to install node.js is to use
[nvm-windows](https://github.com/coreybutler/nvm-windows). This makes it
easy to switch between versions of node.js.
-Alternatively, use Powershell + Chocolatey to install node.js:
-
-```ps1
-# Elevated PowerShell
-
-# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138)
-$ProgressPreference = 'SilentlyContinue'
-choco install nodejs
+```bat
+nvm install 20.16.0
+nvm use 20.16.0
```
-See [node.md](node.md) for more information.
+**Optional environment variables**:
-#### openjdk
+To let the Keyman build scripts control the version of node.js installed
+and active on your computer:
-Use Powershell + Chocolatey to install OpenJDK:
-
-```ps1
-# Elevated PowerShell
-
-# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138)
-$ProgressPreference = 'SilentlyContinue'
-choco install openjdk
-```
+```bat
+SETX KEYMAN_USE_NVM 1
+````
+See [node.md](node.md) for more information, including automatic selection
+of appropriate node versions during builds.
### Windows Platform Dependencies
@@ -260,8 +247,7 @@ choco install openjdk
Start Delphi IDE once after installation as it will create various environment
files and take you through required registration.
- * Note: It is possible to build all components that do _not_ require Delphi by
- adding the environment variable `NODELPHI=1` before starting the build.
+ * Note: It is possible to build all components that do _not_ require Delphi.
Currently many components are Delphi-based, but if you are working just in
Keyman Core, the compiler, or Keyman Engine's C++ components, you may be
able to get away without building them. In this situation, we recommend
@@ -273,10 +259,12 @@ choco install openjdk
```ps1
choco install visualstudio2019community visualstudio2019-workload-nativedesktop visualstudio2019buildtools
```
+
* Verify required build tools are installed
* Run `Visual Studio Installer`
* Check the `Individual components` tab
- * Verify `MSVC v142 - VS 2019 c++ x64/x86 build tools (Latest)` is installed. If not, install it.
+ * Verify `MSVC v142 - VS 2019 c++ x64/x86 build tools (Latest)` is installed.
+ If not, install it.
Recommended: configure Visual Studio to use two-space tab stops:
1. Open the options dialog: Tools > Options.
@@ -284,55 +272,15 @@ choco install openjdk
3. Change 'Tab size' to 2 and 'Indent size' to 2.
4. Select 'Insert spaces'.
+* Windows SDK (C++ Desktop Development)
+
+ https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
+
**Required environment variables**:
* `PATH`
- * Add the C:\Projects\keyman\keyman\windows\lib folder in the Keyman
+ * Add the `C:\Projects\keyman\keyman\windows\lib` folder in the Keyman
repository to your `PATH` environment variable. This is required for
Keyman's design-time packages to load in Delphi.
-* [`KEYMAN_CEF4DELPHI_ROOT`](#keyman_cef4delphi_root)
-
-**Optional environment variables**:
-* [`GIT_BASH_FOR_KEYMAN`](#git_bash_for_keyman)
-* [`USERDEFINES`](#userdefines)
-
-```bat
-SET KEYMAN_CEF4DELPHI_ROOT=c:\Projects\keyman\CEF4Delphi_Binary
-SET GIT_BASH_FOR_KEYMAN="C:\Program Files\Git\bin\bash.exe" --init-file "c:\Program Files\Git\etc\profile" -l
-```
-
-**Additional requirements for release builds**:
-* [Certificates](#certificates)
-* [7-Zip](http://www.7-zip.org/), used for archiving build files
-* [HTML Help Workshop](http://web.archive.org/web/20160201063255/http://download.microsoft.com/download/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe) note: Microsoft no longer offer this download...
-* [WiX 3.11.1](https://github.com/wixtoolset/wix3/releases/tag/wix3111rtm)
-* [CEF4Delphi_Binary](https://github.com/keymanapp/CEF4Delphi_Binary) repository
-
-```ps1
-# Elevated PowerShell
-choco install 7zip html-help-workshop
-choco install wixtoolset --version=3.11.1
-git clone https://github.com/keymanapp/CEF4Delphi_Binary C:\Projects\keyman\CEF4Delphi_Binary
-```
-
-## Certificates
-
-In order to make a release build, you need to sign all the executables. See
-[windows/src/README.md#Certificates](../../windows/src/README.md#Certificates)
-for details on how to create test code signing certificates or specify your own
-certificates for the build.
-
-## Notes on Environment Variables
-
-### KEYMAN_ROOT
-
-If you pull the entire `keyman.git` repo to `c:\keyman`, then the paths by
-default will work without changes. Otherwise, you will need to set an
-environment variable `KEYMAN_ROOT` to the root path of the Keyman repo. For
-example:
-
-```bat
-SET KEYMAN_ROOT=c:\projects\keyman\keyman
-```
### KEYMAN_CEF4DELPHI_ROOT
@@ -349,41 +297,85 @@ release build, the common/windows/cef-checkout.sh script will checkout the corre
branch of the repository automatically and extract any compressed files found in
it.
-### GIT_BASH_FOR_KEYMAN
-
-This environment variable is optional: the build will run bash in a separate
-window in order to build KeymanWeb if it isn't present, but you'll lose logging
-and have the annoyance of a window popping up halfway through the build. To
-resolve both of those issues, set the environment variable to:
+The [`KEYMAN_CEF4DELPHI_ROOT`](#keyman_cef4delphi_root) variable is
+used to specify the path to the CEF4Delphi binaries.
```bat
-SET GIT_BASH_FOR_KEYMAN="C:\Program Files\Git\bin\bash.exe" --init-file "c:\Program Files\Git\etc\profile" -l
+SETX KEYMAN_CEF4DELPHI_ROOT "c:\Projects\keyman\CEF4Delphi_Binary"
```
-You should verify the install location of Git on your computer as it may vary.
+**Additional requirements for release builds**:
+* [Certificates](#certificates)
+* [7-Zip](http://www.7-zip.org/), used for archiving build files
+* [HTML Help Workshop](http://web.archive.org/web/20160201063255/http://download.microsoft.com/download/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe) note: Microsoft no longer offer this download...
+* [WiX 3.11.1](https://github.com/wixtoolset/wix3/releases/tag/wix3111rtm)
+* [CEF4Delphi_Binary](https://github.com/keymanapp/CEF4Delphi_Binary) repository
-### USERDEFINES
-
-You can specify defines that will not be added to the git repository and will be
-used in the build in the UserDefines.mak file in the root folder. This is used
-mostly for code signing certificates. If not specified, a test certificate will
-be used to sign executables when you build a release.
-
-To include UserDefines.mak in the build, use the command line parameter
-`-DUSERDEFINES`. You can also set an environment variable `USERDEFINES=1` to get
-the same result.
-
-### JAVA_HOME
-
-This environment variable tells Gradle what version of Java to use for building Keyman for Android.
-
-**Multiple versions of Java:** If you need to build Keyman for Android 16.0 or older versions, you can set `JAVA_HOME_11` to the OpenJDK 11 path and `JAVA_HOME` to the OpenJDK 8 path. This will build both versions correctly from command line. But note that you do need to update your `JAVA_HOME` env var to the associated version before opening Android Studio and loading any Android projects. `JAVA_HOME_11` is mostly used by CI.
-
-```bat
-SET JAVA_HOME="path to OpenJDK 8"
-SET JAVA_HOME_11="path to OpenJDK 11"
+```ps1
+# Elevated PowerShell
+choco install 7zip html-help-workshop
+choco install wixtoolset --version=3.11.1
+git clone https://github.com/keymanapp/CEF4Delphi_Binary C:\Projects\keyman\CEF4Delphi_Binary
```
+### Android dependencies
+
+**Projects**:
+* Keyman for Android
+
+**Requirements**:
+* Android SDK
+* Android Studio
+* Ant
+* Gradle
+* Maven
+* JDK 11 (Temurin11)
+
+#### JDK 11
+
+Use Powershell + Chocolatey to install JDK 11:
+
+```ps1
+# Elevated PowerShell
+
+# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138)
+$ProgressPreference = 'SilentlyContinue'
+choco install temurin11
+```
+
+**Multiple versions of Java:** If you need to build Keyman for Android 16.0 or
+older versions, you can set `JAVA_HOME_11` to the JDK 11 path and
+`JAVA_HOME` to the JDK 8 path. This will build both versions correctly
+from command line. But note that you do need to update your `JAVA_HOME` env
+var to the associated version before opening Android Studio and loading any
+Android projects. `JAVA_HOME_11` is mostly used by CI.
+
+#### Android Studio and friends
+
+```ps1
+# Elevated PowerShell
+choco install androidstudio ant gradle maven android-sdk
+```
+
+Start a new shell to get the new paths and then update Android SDKs:
+
+```ps1
+# optionally install sdk images
+sdkmanager --update
+# sdkmanager "system-images;android-33;google_apis;armeabi-v7a"
+sdkmanager --licenses
+```
+
+* Run Android Studio once after installation to install additional components
+ such as emulator images and SDK updates.
+
+## Certificates
+
+In order to make a release build, you need to sign all the executables. See
+[windows/src/README.md#Certificates](../../windows/src/README.md#Certificates)
+for details on how to create test code signing certificates or specify your own
+certificates for the build.
+
## Optional Tools
* sentry-cli (optional)
diff --git a/docs/minimum-versions.md b/docs/minimum-versions.md
index a9a2ead26b..f582632007 100644
--- a/docs/minimum-versions.md
+++ b/docs/minimum-versions.md
@@ -49,7 +49,6 @@ https://help.keyman.com/developer/engine/android/latest-version/
| KEYMAN Variable | Value |
|-----------------------------------|--------------|
| KEYMAN_DEFAULT_VERSION_UBUNTU_CONTAINER | noble |
-| KEYMAN_MAX_VERSION_EMSCRIPTEN | 3.1.58 |
| KEYMAN_MIN_TARGET_VERSION_ANDROID | 5 |
| KEYMAN_MIN_TARGET_VERSION_CHROME | 95.0 |
| KEYMAN_MIN_TARGET_VERSION_IOS | 12.2 |
@@ -58,7 +57,7 @@ https://help.keyman.com/developer/engine/android/latest-version/
| KEYMAN_MIN_TARGET_VERSION_WINDOWS | 10 |
| KEYMAN_MIN_VERSION_ANDROID_SDK | 21 |
| KEYMAN_MIN_VERSION_CPP | 17 |
-| KEYMAN_MIN_VERSION_EMSCRIPTEN | 3.1.44 |
+| KEYMAN_MIN_VERSION_EMSCRIPTEN | 3.1.58 |
| KEYMAN_MIN_VERSION_MESON | 1.0.0 |
| KEYMAN_MIN_VERSION_NODE_MAJOR | 20 |
| KEYMAN_MIN_VERSION_NPM | 10.5.1 |
diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift
index 5b77f79307..d1d134b249 100644
--- a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift
+++ b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift
@@ -831,12 +831,22 @@ public class Manager: NSObject, UIGestureRecognizerDelegate {
shared.copyUserDefaults(to: nonShared, withKeys: keysToCopy, shouldOverwrite: true)
do {
try shared.copyFiles(to: nonShared)
- FontManager.shared.registerCustomFonts()
} catch {
let message = ("Failed to copy from shared container: \(error)")
os_log("%{public}s", log:KeymanEngineLogger.settings, type: .error, message)
SentryManager.capture(error, message:message)
}
+
+ // This operation has a surprisingly high cost and isn't critical
+ // for getting the keyboard loaded and available to the OS.
+ //
+ // We certainly want it done _soon_... but we don't want it to cause
+ // the primary, synchronous initialization call from the OS to run so
+ // long that the keyboard fails to start due to its enforced time
+ // constraints.
+ DispatchQueue.main.async {
+ FontManager.shared.registerCustomFonts()
+ }
}
}
diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift
index d64019cc27..6070de2c96 100644
--- a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift
+++ b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift
@@ -26,6 +26,17 @@ public class FontManager {
fonts[url] = RegisteredFont(name: name, isRegistered: false)
return name
}
+
+ private func cachedFont(at url: URL) -> RegisteredFont? {
+ if let font = fonts[url] {
+ return font
+ }
+ guard let name = readFontName(at: url) else {
+ return nil
+ }
+ fonts[url] = RegisteredFont(name: name, isRegistered: false)
+ return fonts[url]
+ }
/// Registers all new fonts found in the font path. Call this after you have preloaded all your font files
/// with `preloadFontFile(atPath:shouldOverwrite:)`
@@ -33,8 +44,50 @@ public class FontManager {
guard let keyboardDirs = Storage.active.keyboardDirs else {
return
}
+
+ var fontSet: Set = []
for dir in keyboardDirs {
- registerFonts(in: dir)
+ fontSet = fontSet.union(listFonts(in: dir))
+ }
+
+ registerListedFonts(fontSet)
+ }
+
+ /**
+ * Iterates across all listed fonts, registering those not yet registered.
+ * Checks for, and filters out, any fonts already registered on the system.
+ * Also initializes the registration cache per URL if needed.
+ */
+ private func registerListedFonts(_ initialFontSet: Set) {
+ // If we are unable to read the font file's properties sufficiently,
+ // skip it. We also don't need to register anything already registered or
+ // that cannot be registered due to loading/parsing errors.
+ //
+ // Calls to `cachedFont` after the `.filter` below may be assumed to have
+ // non-nil return values.
+ var fontSet = initialFontSet.filter { !(cachedFont(at: $0)?.isRegistered ?? true) }
+
+ // The prior line filters out any entries where cachedFont(at: $0) would be nil.
+ // Batch-lookups all fonts lacking cache-confirmation of prior registration.
+ var fontNamesToRegister = missingFonts(from: Set(fontSet.map { cachedFont(at: $0)!.name }))
+
+ for fontUrl in fontSet {
+ let fontName = cachedFont(at: fontUrl)!.name
+
+ guard fontNamesToRegister.contains(fontName) else {
+ let message = "Did not register font at \(fontUrl) because font name \(fontName) is already registered"
+ os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message)
+ continue
+ }
+
+ let didRegister = _registerFont(at: fontUrl)
+ fonts[fontUrl] = RegisteredFont(name: fontName, isRegistered: didRegister)
+
+ // We no longer need to register a font with this name, so drop it from
+ // the set to register.
+ if didRegister {
+ fontNamesToRegister.remove(fontName)
+ }
}
}
@@ -43,6 +96,8 @@ public class FontManager {
guard let keyboardDirs = Storage.active.keyboardDirs else {
return
}
+ // This doesn't use the expensive looped lookup operation seen in missingFonts,
+ // so there's no need to batch similar operations here.
for dir in keyboardDirs {
unregisterFonts(in: dir)
}
@@ -63,44 +118,29 @@ public class FontManager {
}
return name as String
}
+
+ private func _registerFont(at url: URL) -> Bool {
+ var errorRef: Unmanaged?
+ let fontName = fontName(at: url)!
+ let didRegister = CTFontManagerRegisterFontsForURL(url as CFURL, .none, &errorRef)
+ let error = errorRef?.takeRetainedValue() // Releases errorRef
+ if !didRegister {
+ let message = "Failed to register font \(fontName) at \(url) reason: \(String(describing: error))"
+ os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message)
+ } else {
+ let message = "Registered font \(fontName) at \(url)"
+ os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message)
+ }
+
+ return didRegister
+ }
/// - Parameters:
/// - url: URL of the font to register
/// - Returns: Font is registered.
public func registerFont(at url: URL) -> Bool {
- let fontName: String
- if let font = fonts[url] {
- if font.isRegistered {
- return true
- }
- fontName = font.name
- } else {
- guard let name = readFontName(at: url) else {
- return false
- }
- fontName = name
- }
-
- let didRegister: Bool
- if !fontExists(fontName) {
- var errorRef: Unmanaged?
- didRegister = CTFontManagerRegisterFontsForURL(url as CFURL, .none, &errorRef)
- let error = errorRef?.takeRetainedValue() // Releases errorRef
- if !didRegister {
- let message = "Failed to register font \(fontName) at \(url) reason: \(String(describing: error))"
- os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message)
- } else {
- let message = "Registered font \(fontName) at \(url)"
- os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message)
- }
- } else {
- didRegister = false
- let message = "Did not register font at \(url) because font name \(fontName) is already registered"
- os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message)
- }
- let font = RegisteredFont(name: fontName, isRegistered: didRegister)
- fonts[url] = font
- return didRegister
+ registerListedFonts([url])
+ return fonts[url]?.isRegistered ?? false
}
/// - Parameters:
@@ -133,32 +173,53 @@ public class FontManager {
return font.isRegistered
}
-
- public func registerFonts(in directory: URL) {
+
+ private func listFonts(in directory: URL) -> [URL] {
guard let urls = try? FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) else {
let message = "Could not list contents of directory \(directory)"
os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message)
- return
- }
- for url in urls where url.lastPathComponent.hasFontExtension {
- _ = registerFont(at: url)
+ return []
}
+ return urls.filter { $0.lastPathComponent.hasFontExtension }
+ }
+
+ public func registerFonts(in directory: URL) {
+ let fontsToRegister = listFonts(in: directory)
+ registerListedFonts(Set(fontsToRegister))
}
public func unregisterFonts(in directory: URL, fromSystemOnly: Bool = true) {
- guard let urls = try? FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) else {
- let message = "Could not list contents of directory \(directory)"
- os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message)
- return
- }
- for url in urls where url.lastPathComponent.hasFontExtension {
+ let fontsToUnregister = listFonts(in: directory)
+ for url in fontsToUnregister {
_ = unregisterFont(at: url, fromSystemOnly: fromSystemOnly)
}
}
- private func fontExists(_ fontName: String) -> Bool {
- return UIFont.familyNames.contains { familyName in
- UIFont.fontNames(forFamilyName: familyName).contains(fontName)
+ /**
+ * Queries the system for existing registrations for the specified fonts with a single batch run.
+ * Only fonts that could not be found will be returned within the result set.
+ */
+ private func missingFonts(from fontNames: Set) -> Set {
+ var fontsToFind = fontNames
+
+ UIFont.familyNames.forEach { familyName in
+ if fontsToFind.count == 0 {
+ return
+ }
+
+ let familyFonts = UIFont.fontNames(forFamilyName: familyName)
+
+ for font in familyFonts {
+ if fontsToFind.contains(font) {
+ fontsToFind.remove(font)
+ }
+
+ if fontsToFind.count == 0 {
+ break
+ }
+ }
}
+
+ return fontsToFind
}
}
diff --git a/linux/keyman-config/keyman_config/kvk2ldml.py b/linux/keyman-config/keyman_config/kvk2ldml.py
index 5b3ab85ae8..3b3aee281b 100755
--- a/linux/keyman-config/keyman_config/kvk2ldml.py
+++ b/linux/keyman-config/keyman_config/kvk2ldml.py
@@ -164,43 +164,43 @@ VKey_to_Iso = {
}
-def bytecheck(value, check):
+def _bytecheck(value, check):
if bytes([value & check[0]]) == check:
return True
else:
return False
-def get_nkey(file, fileContent, offset):
+def _get_nkey(file, fileContent, offset):
nkey = NKey()
data = struct.unpack_from(" 256:
@@ -224,7 +224,7 @@ def get_nstring(file, fileContent, offset):
return stringdata.decode('utf-16'), offset + 2 + (2 * stringlength[0])
-def get_nbitmap(file, fileContent, offset):
+def _get_nbitmap(file, fileContent, offset):
bitmap = None
bitmaplength = struct.unpack_from("CFBundlePackageType
APPLCFBundleShortVersionString
- Keyman $(PRODUCT_VERSION) for macOS
+ $(PRODUCT_VERSION)CFBundleSignature????CFBundleURLTypes
diff --git a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h
index 6c80417faf..81cc4c3b34 100644
--- a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h
+++ b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h
@@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly) NSString *clientApplicationId;
-(instancetype)initWithClient:(id) client applicationId:(NSString *)appId;
+-(NSString *)description;
-(void)checkCompliance:(id) client;
-(void) checkComplianceAfterInsert:(id) client delete:(NSString *)textToDelete insert:(NSString *)textToInsert;
-(BOOL)isComplianceUncertain;
diff --git a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m
index 0f62fa61a8..e83439794b 100644
--- a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m
+++ b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m
@@ -73,7 +73,7 @@ NSString *const kKMLegacyApps = @"KMLegacyApps";
-(NSString *)description
{
- return [NSString stringWithFormat:@"complianceUncertain: %d, hasCompliantSelectionApi: %d, canReadText: %d, canReplaceText: %d, mustBackspaceUsingEvents: %d, clientAppId: %@, client: %@", self.complianceUncertain, self.hasCompliantSelectionApi, [self canReadText], [self canReplaceText], [self mustBackspaceUsingEvents], _clientApplicationId, _client];
+ return [NSString stringWithFormat:@"complianceUncertain: %d, hasCompliantSelectionApi: %d, canReadText: %d, canReplaceText: %d, mustBackspaceUsingEvents: %d, clientApplicationId: %@, client: %@", self.complianceUncertain, self.hasCompliantSelectionApi, [self canReadText], [self canReplaceText], [self mustBackspaceUsingEvents], _clientApplicationId, _client];
}
/** test to see if the API selectedRange functions properly for the text input client */
diff --git a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m
index 8eb9d974ce..7372a2a548 100644
--- a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m
+++ b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m
@@ -15,23 +15,27 @@
#import "TextApiCompliance.h"
KMInputMethodEventHandler *testEventHandler = nil;
+id testClient = nil;
@interface InputMethodTests : XCTestCase
@end
@interface KMInputMethodEventHandler (Testing)
-
+@property (nonatomic, retain) TextApiCompliance* apiCompliance;
+@property (nonatomic, retain) NSString* clientApplicationId;
+@property BOOL contextChanged;
- (instancetype)initWithClient:(NSString *)clientAppId client:(id) sender;
- (NSRange) calculateInsertRangeForDeletedText:(NSString*)textToDelete selectionRange:(NSRange) selection;
+- (void)checkTextApiCompliance:(id)client;
@end
@implementation InputMethodTests
- (void)setUp {
- id client = [[AppleCompliantTestClient alloc] init];
+ testClient = [[AppleCompliantTestClient alloc] init];
NSString *clientAppId = @"com.compliant.app";
- testEventHandler = [[KMInputMethodEventHandler alloc]initWithClient:clientAppId client:client];
+ testEventHandler = [[KMInputMethodEventHandler alloc]initWithClient:clientAppId client:testClient];
}
- (void)tearDown {
@@ -85,4 +89,43 @@ KMInputMethodEventHandler *testEventHandler = nil;
XCTAssertTrue(correctResult, @"insert or replacement range expected to be {1,2}");
}
+/**
+ * test compliance check of a KMInputMethodEventHandler with a nil client application ID
+ * not sure if this can ever happen, but the lifecycle of the input method is not 100% clear,
+ * and we would like this scenario, if it can occur, to not result in a crash
+ */
+- (void)testCheckCompliance_withUnknownApplicationId_createsComplianceObject {
+ id client = [[AppleCompliantTestClient alloc] init];
+ KMInputMethodEventHandler *eventHandler = [[KMInputMethodEventHandler alloc]initWithClient:nil client:client];
+ [eventHandler checkTextApiCompliance:client];
+ XCTAssertNotNil(eventHandler.apiCompliance, @"apiCompliance object was not created");
+}
+
+- (void)testCheckCompliance_withNilComplianceObject_createsComplianceObject {
+ [testEventHandler checkTextApiCompliance:testClient];
+ XCTAssertNotNil(testEventHandler.apiCompliance, @"apiCompliance object was not created");
+}
+
+- (void)testCheckCompliance_withChangedClientApplicationId_createsNewComplianceObject {
+ // first call causes textApiCompliance object to be created
+ [testEventHandler checkTextApiCompliance:testClient];
+ TextApiCompliance *originalComplianceObject = testEventHandler.apiCompliance;
+
+ testEventHandler.clientApplicationId = @"com.different.app";
+ // second call causes new textApiCompliance object to be created due to stale application ID
+ [testEventHandler checkTextApiCompliance:testClient];
+ XCTAssertNotEqualObjects(originalComplianceObject, testEventHandler.apiCompliance, @"New TextApiCompliance object not created for new client application ID");
+}
+
+- (void)testCheckCompliance_withContextChanged_createsNewComplianceObject {
+ // first call causes textApiCompliance object to be created
+ [testEventHandler checkTextApiCompliance:testClient];
+ TextApiCompliance *originalComplianceObject = testEventHandler.apiCompliance;
+
+ testEventHandler.contextChanged = YES;
+ // second call causes new textApiCompliance object to be created due to setting contextChanged flag
+ [testEventHandler checkTextApiCompliance:testClient];
+ XCTAssertNotEqualObjects(originalComplianceObject, testEventHandler.apiCompliance, @"New TextApiCompliance object not created after contextChanged flag set");
+}
+
@end
diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist b/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist
index 970606a26a..3f42d3e63f 100644
--- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist
+++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageTypeFMWKCFBundleShortVersionString
- Keyman Engine $(PRODUCT_VERSION) for macOS
+ $(PRODUCT_VERSION)CFBundleSignature????CFBundleVersion
diff --git a/resources/build/win/environment.inc.sh b/resources/build/win/environment.inc.sh
index d2b351fcbc..620e96146a 100644
--- a/resources/build/win/environment.inc.sh
+++ b/resources/build/win/environment.inc.sh
@@ -23,8 +23,10 @@ source "$KEYMAN_ROOT/resources/build/win/environment_generated.inc.sh"
WINDOWS_ROOT="$KEYMAN_ROOT/windows"
WINDOWS_PROGRAM_APP="$WINDOWS_ROOT/bin/desktop"
WINDOWS_PROGRAM_ENGINE="$WINDOWS_ROOT/bin/engine"
+WINDOWS_PROGRAM_SUPPORT="$WINDOWS_ROOT/bin/support"
WINDOWS_DEBUGPATH_APP="$WINDOWS_ROOT/debug/desktop"
WINDOWS_DEBUGPATH_ENGINE="$WINDOWS_ROOT/debug/engine"
+WINDOWS_DEBUGPATH_SUPPORT="$WINDOWS_ROOT/debug/suppor"
COMMON_ROOT="$KEYMAN_ROOT/common/windows/delphi"
OUTLIB="$WINDOWS_ROOT/lib"
@@ -141,6 +143,8 @@ create-windows-output-folders() {
mkdir -p "$OUTLIB"
mkdir -p "$WINDOWS_PROGRAM_APP"
mkdir -p "$WINDOWS_PROGRAM_ENGINE"
+ mkdir -p "$WINDOWS_PROGRAM_SUPPORT"
mkdir -p "$WINDOWS_DEBUGPATH_APP"
mkdir -p "$WINDOWS_DEBUGPATH_ENGINE"
+ mkdir -p "$WINDOWS_DEBUGPATH_SUPPORT"
}
\ No newline at end of file
diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh
index f678e8449e..3d470f7577 100644
--- a/resources/locate_emscripten.inc.sh
+++ b/resources/locate_emscripten.inc.sh
@@ -69,5 +69,7 @@ _select_emscripten_version_with_emsdk() {
git pull
./emsdk install "$KEYMAN_MIN_VERSION_EMSCRIPTEN"
./emsdk activate "$KEYMAN_MIN_VERSION_EMSCRIPTEN"
+ cd upstream/emscripten
+ npm install
popd > /dev/null
}
diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts
index 013ad76241..570a82a209 100644
--- a/web/src/engine/osk/src/visualKeyboard.ts
+++ b/web/src/engine/osk/src/visualKeyboard.ts
@@ -1239,6 +1239,7 @@ export default class VisualKeyboard extends EventEmitter implements Ke
const groupStyle = getComputedStyle(this.layerGroup.element);
const isInDOM = computedStyle.height != '' && computedStyle.height != 'auto';
+ const isGroupInDOM = groupStyle.height != '' && groupStyle.height != 'auto';
if (computedStyle.border) {
this._borderWidth = new ParsedLengthStyle(computedStyle.borderWidth).val;
@@ -1251,10 +1252,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke
this._computedHeight = this.height;
} else if (isInDOM) {
this._computedWidth = parseInt(computedStyle.width, 10);
- if (!this._computedWidth) {
- this._computedWidth = parseInt(groupStyle.width, 10);
- }
this._computedHeight = parseInt(computedStyle.height, 10);
+ } else if (isGroupInDOM) {
+ // May occur for documentation-keyboards, which are detached from their VisualKeyboard base.
+ this._computedWidth = parseInt(groupStyle.width, 10);
+ this._computedHeight = parseInt(groupStyle.height, 10);
} else {
// Cannot perform layout operations!
return;
@@ -1597,6 +1599,16 @@ export default class VisualKeyboard extends EventEmitter implements Ke
// the page.
kbdObj.appendStyleSheet();
+ // Unset the width + height we used thus far; this method's consumer may choose to rescale
+ // the returned element. If so, we don't want to use our outdated value by mistake.
+ //
+ // While `kbdObj.setSize()` could be used in theory, it _also_ unsets the element styling.
+ // We actually wish to _leave_ this styling in place - one of our parameters is `height`, and
+ // it should remain in place in the styling on the output element as the default in case
+ // the consumer _doesn't_ add styling afterward.
+ delete kbdObj._width;
+ delete kbdObj._height;
+
return classWrapper;
}
diff --git a/windows/src/.gitignore b/windows/src/.gitignore
index 350b7e4bdb..065f4a07f3 100644
--- a/windows/src/.gitignore
+++ b/windows/src/.gitignore
@@ -34,3 +34,8 @@ keyman-windows-coverity.tgz
# This file is still generated by devtools. TODO: eliminate in future
PathDefines.mak
+
+# .res files, generated during build
+desktop/kmshell/kmshell.res
+engine/keyman/keyman.res
+engine/keyman32/version64.res
diff --git a/windows/src/README.md b/windows/src/README.md
index 1d057482bb..b18b626dc0 100644
--- a/windows/src/README.md
+++ b/windows/src/README.md
@@ -1,40 +1,39 @@
-# Keyman for Windows and Keyman Developer
+# Keyman for Windows
## Build Prerequisites
* See [Windows Build Environment Configuration](../../docs/build/windows.md).
-## Building Keyman for Windows and Keyman Developer
+## Building Keyman for Windows
-1. Start 'Developer Command Prompt for VS 2019'.
-2. Run `nmake build` from the **windows/src** folder.
+1. Start 'Git Bash' (part of Git for Windows).
+2. Run `windows/src/build.sh`.
3. Artifacts from a successful build will be placed in **windows/bin** folder.
-*Note*: running `nmake build` will currently reset the packages and path settings
+*Note*: running `build.sh` will currently reset the packages and path settings
in your Delphi environment. If you use Delphi for other projects, you should
consider building Keyman under a login user dedicated to it, or in a VM.
-Type `nmake` to see build targets. Common build targets are:
+Type `build.sh` to see build targets and actions. Common build actions are:
-* `nmake build`
-: builds Keyman for Windows and Keyman Developer
+* `build.sh build`
+: builds Keyman for Windows
-* `nmake clean`
+* `build.sh clean`
: remove temporary files and build artifacts
-* `nmake release`
+* `build.sh publish`
: makes a release of all Keyman Windows projects
-* `nmake install`
+* `build.sh install`
: install some or all components to Program Files (requires elevated command prompt).
### Building without Delphi
-It is possible to build all components that do _not_ require Delphi by adding
-the environment variable `NODELPHI=1` before starting the build. Currently many
-components are Delphi-based, but if you are working just in Keyman Core, the
-compiler, or Keyman Engine's C++ components, you may be able to get away without
-building them. In this situation, we recommend copying the relevant Delphi-built
+It is possible to build all components that do _not_ require Delphi. Currently
+many components are Delphi-based, but if you are working just in Keyman Core, or
+Keyman Engine's C++ components, you may be able to get away without building
+them. In this situation, we recommend copying the relevant Delphi-built
components into windows/bin folders from a compatible installed version of
Keyman for testing and debugging purposes.
@@ -45,8 +44,8 @@ build, you will need to obtain valid code signing certificates. See
Certificates, below. Official release builds for Keyman are built in the Keyman
project's CI environment.
-1. Start 'Developer Command Prompt for VS 2019'.
-2. Run `nmake release` from the **windows/src** folder.
+1. Start 'Git Bash'.
+2. Run `windows/src/build.sh publish`.
3. Artifacts from a successful build will be placed in **windows/release**
folder.
4. **buildtools/help-keyman-com.sh** will push updated documentation to
@@ -65,7 +64,7 @@ globally trusted. The environment variables `SC_PFX_SHA1` and `SC_PFX_SHA256`
can be set to custom certificate paths.
The Keyman repo can build test certificates for you. To build your own, run
-`./build.sh certificates` from **common/windows/delphi/tools/certificates** to
+`./common/windows/delphi/tools/certificates/build.sh certificates` to
build and install your own local root CA "**KeymanTestCA**" certificates. If you
specify a password for the certificate, you'll need to set that in the
environment variable `SC_PWD`.
@@ -76,7 +75,7 @@ You do not need to install the **KeymanTest** certificates, only the
**KeymanTestCA** certificates.
If you have not already installed the **KeymanTestCA** certificates using the
-`nmake` command above, to manually install the Keyman **KeymanTestCA**
+`build.sh` command above, to manually install the Keyman **KeymanTestCA**
certificates, do the following in **common/windows/delphi/tools/certificates**:
1. Open the certificate and click 'Install certificate...' to open the
diff --git a/windows/src/build.sh b/windows/src/build.sh
index a1fc4d0e1a..4ef6da65b8 100755
--- a/windows/src/build.sh
+++ b/windows/src/build.sh
@@ -18,6 +18,7 @@ builder_describe \
":engine Keyman Engine for Windows" \
":desktop Keyman for Windows" \
":components=global/delphi Delphi components" \
+ ":support Support tools" \
":test=test/unit-tests Shared unit tests" \
":fv=../../oem/firstvoices/windows/src/inst OEM FirstVoices for Windows app"
diff --git a/windows/src/desktop/kmshell/kmshell.res b/windows/src/desktop/kmshell/kmshell.res
deleted file mode 100644
index cfcbd309f1..0000000000
Binary files a/windows/src/desktop/kmshell/kmshell.res and /dev/null differ
diff --git a/windows/src/engine/keyman/build.sh b/windows/src/engine/keyman/build.sh
index 50ef210ce2..ce34599410 100755
--- a/windows/src/engine/keyman/build.sh
+++ b/windows/src/engine/keyman/build.sh
@@ -8,6 +8,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
builder_describe "Keyman main host process (32-bit)" \
@/common/include \
@/common/windows/delphi \
+ @/windows/src/global/delphi \
clean configure build test publish install debug-manifest
builder_parse "$@"
diff --git a/windows/src/support/Makefile b/windows/src/support/Makefile
deleted file mode 100644
index 56609e21e4..0000000000
--- a/windows/src/support/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Support Makefile
-#
-
-!ifdef NODELPHI
-TARGETS=etl2log texteditor
-!else
-TARGETS=oskbulkrenderer etl2log texteditor
-!endif
-CLEANS=clean-support
-
-!include ..\Header.mak
-
-# ----------------------------------------------------------------------
-
-oskbulkrenderer: .virtual
- cd $(ROOT)\src\support\oskbulkrenderer
- $(MAKE) $(TARGET)
-
-etl2log: .virtual
- cd $(ROOT)\src\support\etl2log
- $(MAKE) $(TARGET)
-
-texteditor: .virtual
- cd $(ROOT)\src\support\texteditor
- $(MAKE) $(TARGET)
-
-# ----------------------------------------------------------------------
-
-clean-support:
- cd $(ROOT)\src\support
- -del version.txt
-
-!include ..\Target.mak
-
-# ----------------------------------------------------------------------
-# EOF
-# ----------------------------------------------------------------------
diff --git a/windows/src/support/build.sh b/windows/src/support/build.sh
new file mode 100755
index 0000000000..f9f20f1716
--- /dev/null
+++ b/windows/src/support/build.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+## START STANDARD BUILD SCRIPT INCLUDE
+# adjust relative paths as necessary
+THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
+. "${THIS_SCRIPT%/*}/../../../resources/build/builder.inc.sh"
+## END STANDARD BUILD SCRIPT INCLUDE
+
+builder_describe \
+ "Keyman for Windows support tools" \
+ \
+ clean \
+ configure \
+ build \
+ test \
+ \
+ :oskbulkrenderer \
+ :etl2log \
+ :texteditor
+
+builder_parse "$@"
+
+builder_run_child_actions clean configure build test publish install
diff --git a/windows/src/support/charident/Makefile b/windows/src/support/charident/Makefile
deleted file mode 100644
index cff6741677..0000000000
--- a/windows/src/support/charident/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# charident Makefile
-#
-
-!include ..\..\Defines.mak
-
-build: version.res dirs
- $(DCC32) charident.dpr
- $(COPY) charident.exe $(PROGRAM)\support
-
-clean: def-clean
-
-signcode:
- $(SIGNCODE) /d "Character Identifier" $(PROGRAM)\support\charident.exe
-
-wrap-symbols:
- $(SYMSTORE) $(PROGRAM)\support\charident.exe /t keyman-windows
-#TODO: $(SYMSTORE) $(DEBUGPATH)\support\charident.dbg /t keyman-windows
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/etl2log/Makefile b/windows/src/support/etl2log/Makefile
deleted file mode 100644
index 48bdb1a592..0000000000
--- a/windows/src/support/etl2log/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# etl2log Makefile
-#
-
-!include ..\..\Defines.mak
-
-build: version.res dirs
- $(MSBUILD) etl2log.vcxproj $(MSBUILD_BUILD)
- $(COPY) $(WIN32_TARGET_PATH)\etl2log.exe $(PROGRAM)\support
- $(COPY) $(WIN32_TARGET_PATH)\etl2log.pdb $(DEBUGPATH)\support
-
-clean: def-clean
- $(MSBUILD) etl2log.vcxproj $(MSBUILD_CLEAN)
-
-signcode:
- $(SIGNCODE) /d "Keyman Engine Tools" $(PROGRAM)\support\etl2log.exe
-
-wrap-symbols:
- $(SYMSTORE) $(PROGRAM)\support\etl2log.exe /t keyman-windows
- $(SYMSTORE) $(DEBUGPATH)\support\etl2log.pdb /t keyman-windows
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/etl2log/build.sh b/windows/src/support/etl2log/build.sh
new file mode 100755
index 0000000000..e2fdee1acd
--- /dev/null
+++ b/windows/src/support/etl2log/build.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+## START STANDARD BUILD SCRIPT INCLUDE
+# adjust relative paths as necessary
+THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
+. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh"
+## END STANDARD BUILD SCRIPT INCLUDE
+
+builder_describe "etl2log" \
+ clean configure build test
+
+builder_parse "$@"
+
+#-------------------------------------------------------------------------------------------------------------------
+
+source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh"
+WIN32_TARGET="$WIN32_TARGET_PATH/etl2log.exe"
+
+builder_describe_outputs \
+ configure:project /resources/build/win/delphi_environment_generated.inc.sh \
+ build:project /windows/src/support/etl2log/$WIN32_TARGET
+
+#-------------------------------------------------------------------------------------------------------------------
+
+function do_clean() {
+ vs_msbuild etl2log.vcxproj //t:Clean
+ clean_windows_project_files
+}
+
+function do_build() {
+ create-windows-output-folders
+ build_version.res
+ vs_msbuild etl2log.vcxproj //t:Build "//p:Platform=Win32"
+ cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_SUPPORT"
+ cp "$WIN32_TARGET_PATH/etl2log.pdb" "$WINDOWS_DEBUGPATH_SUPPORT"
+}
+
+builder_run_action clean:project do_clean
+builder_run_action configure:project configure_windows_build_environment
+builder_run_action build:project do_build
+# builder_run_action test:project do_test
diff --git a/windows/src/support/kdebug/Makefile b/windows/src/support/kdebug/Makefile
deleted file mode 100644
index 1a13a18ebe..0000000000
--- a/windows/src/support/kdebug/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# KDebug Makefile
-#
-
-!include ..\..\Defines.mak
-
-!ifdef DEBUG
- NMCFG=kdebug - Win32 Debug
-!else
- NMCFG=kdebug - Win32 Release
-!endif
-
-install: dirs build
-
-build: version.res
- $(NMAKE) /f kdebug.mak "CFG=$(NMCFG)"
-
-clean: def-clean
- $(NMAKE) /f kdebug.mak "CFG=$(NMCFG)" CLEAN
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/keycodetester/Makefile b/windows/src/support/keycodetester/Makefile
deleted file mode 100644
index 38687abaeb..0000000000
--- a/windows/src/support/keycodetester/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Keycodetester Makefile
-#
-
-!include ..\..\Defines.mak
-
-install: dirs build
- $(COPY) keycodetester.exe $(PROGRAM)\bldutil
-
-build:
- $(DCC32) keycodetester.dpr
-
-clean: def-clean
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/km_yim/Makefile b/windows/src/support/km_yim/Makefile
deleted file mode 100644
index 1aef5f80f0..0000000000
--- a/windows/src/support/km_yim/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# TODO: remove this project
-#
-
-!include ..\..\Defines.mak
-
-build:
-# version.res
- $(DCC32) km_yim.dpr
- rem $(TDSPACK) $(PROGRAM)\desktop\km_yim.exe km_yim.tds
- rem $(TDS2DBG) $(PROGRAM)\desktop\km_yim.exe
- $(WZZIP) inst_km_yim.zip km_yim.exe
-# $(WZSE) inst_km_yim -setup -t inst_km_yim.dialog.txt -st "Tavultesoft Keyman Desktop Yahoo Messenger Addin" -c km_yim.exe
-
-clean: def-clean
- if exist inst_km_yim.zip del inst_km_yim.zip
-
-signcode:
- $(SIGNCODE) /d "Tavultesoft Keyman Desktop Yahoo Messenger Addin" inst_km_yim.exe
-
-wrap-symbols:
- rem
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/kmkb0045/Makefile b/windows/src/support/kmkb0045/Makefile
deleted file mode 100644
index 3e914c8acd..0000000000
--- a/windows/src/support/kmkb0045/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# TODO: remove this project
-#
-
-!include ..\..\Defines.mak
-
-build: version.res manifest.res
- $(DCC32) kmkb0045.dpr
- $(SENTRYTOOL_DELPHIPREP) kmkb0045.exe -dpr kmkb0045.dpr
- $(TDS2DBG) kmkb0045.exe
- $(COPY) kmkb0045.exe $(PROGRAM)\support
-
-clean: def-clean
-
-signcode:
- $(SIGNCODE) /d "Tavultesoft KMKB0045" $(PROGRAM)\support\kmkb0045.exe
-
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/oskbulkrenderer/Makefile b/windows/src/support/oskbulkrenderer/Makefile
deleted file mode 100644
index 65b8e02ba6..0000000000
--- a/windows/src/support/oskbulkrenderer/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# oskbulkrenderer Makefile
-#
-
-!include ..\..\Defines.mak
-
-build: version.res dirs
- $(DELPHI_MSBUILD) oskbulkrenderer.dproj "/p:Platform=Win32"
-
- $(SENTRYTOOL_DELPHIPREP) $(WIN32_TARGET_PATH)\oskbulkrenderer.exe -dpr oskbulkrenderer.dpr
- $(TDS2DBG) $(WIN32_TARGET_PATH)\oskbulkrenderer.exe
- $(COPY) $(WIN32_TARGET_PATH)\oskbulkrenderer.exe $(PROGRAM)\support
- if exist $(WIN32_TARGET_PATH)\oskbulkrenderer.dbg $(COPY) $(WIN32_TARGET_PATH)\oskbulkrenderer.dbg $(DEBUGPATH)\support
-
-clean: def-clean
- -rd /s/q Win32
-
-signcode:
- rem Not signing this utility
-
-wrap-symbols:
- @rem
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/oskbulkrenderer/build.sh b/windows/src/support/oskbulkrenderer/build.sh
new file mode 100755
index 0000000000..76fa8a4032
--- /dev/null
+++ b/windows/src/support/oskbulkrenderer/build.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+## START STANDARD BUILD SCRIPT INCLUDE
+# adjust relative paths as necessary
+THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
+. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh"
+## END STANDARD BUILD SCRIPT INCLUDE
+
+builder_describe "oskbuildrenderer" \
+ clean configure build test
+
+builder_parse "$@"
+
+#-------------------------------------------------------------------------------------------------------------------
+
+source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh"
+WIN32_TARGET="$WIN32_TARGET_PATH/oskbulkrenderer.exe"
+
+builder_describe_outputs \
+ configure:project /resources/build/win/delphi_environment_generated.inc.sh \
+ build:project /windows/src/support/oskbulkrenderer/$WIN32_TARGET
+
+#-------------------------------------------------------------------------------------------------------------------
+
+function do_clean() {
+ clean_windows_project_files
+}
+
+function do_build() {
+ create-windows-output-folders
+ build_version.res
+ delphi_msbuild oskbulkrenderer.dproj "//p:Platform=Win32"
+
+ cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_SUPPORT"
+}
+
+builder_run_action clean:project do_clean
+builder_run_action configure:project configure_windows_build_environment
+builder_run_action build:project do_build
+# builder_run_action test:project do_test
diff --git a/windows/src/support/richedit_examine/Makefile b/windows/src/support/richedit_examine/Makefile
deleted file mode 100644
index adacba5901..0000000000
--- a/windows/src/support/richedit_examine/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# richedit_examine Makefile
-#
-
-!include ..\..\Defines.mak
-
-install: dirs build
- $(COPY) richedit_examine.exe $(PROGRAM)\bldutil
-
-build: version.res
- $(DCC32) richedit_examine.dpr
-
-clean: def-clean
-
-!include ..\..\Target.mak
diff --git a/windows/src/support/texteditor/Makefile b/windows/src/support/texteditor/Makefile
deleted file mode 100644
index 473bf57598..0000000000
--- a/windows/src/support/texteditor/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Keyman Text Editor Makefile
-#
-
-!include ..\..\Defines.mak
-
-build:
- $(MSBUILD) editor.vcxproj $(MSBUILD_BUILD) /p:Platform=x86
- $(MSBUILD) editor.vcxproj $(MSBUILD_BUILD) /p:Platform=x64
- $(COPY) $(WIN32_TARGET_PATH)\editor32.exe $(PROGRAM)\support
- $(COPY) $(WIN32_TARGET_PATH)\editor32.pdb $(DEBUGPATH)\support
- $(COPY) $(X64_TARGET_PATH)\editor64.exe $(PROGRAM)\support
- $(COPY) $(X64_TARGET_PATH)\editor64.pdb $(DEBUGPATH)\support
-
-clean: def-clean
- $(MSBUILD) $(MSBUILD_CLEAN) editor.sln
-
-signcode:
- $(SIGNCODE) /d "Text Editor for testing Keyman" $(PROGRAM)\support\editor32.exe
- $(SIGNCODE) /d "Text Editor for testing Keyman" $(PROGRAM)\support\editor64.exe
-
-install:
- $(COPY) $(PROGRAM)\support\editor32.exe "$(INSTALLPATH_KEYMANENGINE)"
- $(COPY) $(PROGRAM)\support\editor64.exe "$(INSTALLPATH_KEYMANENGINE)"
-
-wrap-symbols:
- $(SYMSTORE) $(PROGRAM)\support\editor32.exe /t keyman-windows
- $(SYMSTORE) $(PROGRAM)\support\editor64.exe /t keyman-windows
- $(SYMSTORE) $(DEBUGPATH)\support\editor32.pdb /t keyman-windows
- $(SYMSTORE) $(DEBUGPATH)\support\editor64.pdb /t keyman-windows
-
-
-!include ..\..\Target.mak
-# ----------------------------------------------------------------------
-# EOF
-# ----------------------------------------------------------------------
diff --git a/windows/src/support/texteditor/build.sh b/windows/src/support/texteditor/build.sh
new file mode 100755
index 0000000000..312ee1d0f4
--- /dev/null
+++ b/windows/src/support/texteditor/build.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+## START STANDARD BUILD SCRIPT INCLUDE
+# adjust relative paths as necessary
+THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
+. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh"
+## END STANDARD BUILD SCRIPT INCLUDE
+
+builder_describe "texteditor" \
+ clean configure build test
+
+builder_parse "$@"
+
+#-------------------------------------------------------------------------------------------------------------------
+
+source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh"
+WIN32_TARGET="$WIN32_TARGET_PATH/editor32.exe"
+X64_TARGET="$X64_TARGET_PATH/editor64.exe"
+
+builder_describe_outputs \
+ configure:project /resources/build/win/delphi_environment_generated.inc.sh \
+ build:project /windows/src/support/texteditor/$WIN32_TARGET
+
+#-------------------------------------------------------------------------------------------------------------------
+
+function do_clean() {
+ vs_msbuild Editor.vcxproj //t:Clean
+ clean_windows_project_files
+}
+
+function do_build() {
+ create-windows-output-folders
+ # build_version.res
+ vs_msbuild Editor.vcxproj //t:Build "//p:Platform=Win32"
+ vs_msbuild Editor.vcxproj //t:Build "//p:Platform=x64"
+ cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_SUPPORT"
+ cp "$X64_TARGET" "$WINDOWS_PROGRAM_SUPPORT"
+ cp "$WIN32_TARGET_PATH/editor32.pdb" "$WINDOWS_DEBUGPATH_SUPPORT"
+ cp "$X64_TARGET_PATH/editor64.pdb" "$WINDOWS_DEBUGPATH_SUPPORT"
+}
+
+builder_run_action clean:project do_clean
+builder_run_action configure:project configure_windows_build_environment
+builder_run_action build:project do_build
+# builder_run_action test:project do_test
diff --git a/windows/src/support/windowinfo/Makefile b/windows/src/support/windowinfo/Makefile
deleted file mode 100644
index ac7da2c182..0000000000
--- a/windows/src/support/windowinfo/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# windowinfo Makefile
-#
-
-!include ..\..\Defines.mak
-
-install: dirs build
- $(COPY) windowinfo.exe $(PROGRAM)\bldutil
-
-build: version.res
- $(DCC32) windowinfo.dpr
-
-clean: def-clean
-
-!include ..\..\Target.mak
diff --git a/windows/src/test/manual-tests/integration-tests/Makefile b/windows/src/test/manual-tests/integration-tests/Makefile
deleted file mode 100644
index 093dc44140..0000000000
--- a/windows/src/test/manual-tests/integration-tests/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Integration Tests Makefile.
-#
-
-# ----------------------------------------------------------------------
-
-TARGETS=keymanapi
-
-test:
- $(MAKE) "TARGET=test" $(TARGETS)
-
-!include ..\..\Header.mak
-
-# ----------------------------------------------------------------------
-
-keymanapi:
- cd $(ROOT)\src\test\integration-tests\keymanapi
- $(MAKE) $(TARGET)
-
-# ----------------------------------------------------------------------
-
-!include ..\..\Target.mak
-
-# ----------------------------------------------------------------------
-# EOF
-# ----------------------------------------------------------------------
diff --git a/windows/src/test/manual-tests/integration-tests/keymanapi/Makefile b/windows/src/test/manual-tests/integration-tests/keymanapi/Makefile
deleted file mode 100644
index 7becbb044d..0000000000
--- a/windows/src/test/manual-tests/integration-tests/keymanapi/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Integration tests for keymanapi
-#
-
-!include ..\..\..\Defines.mak
-
-!ifdef EXCLUDE_ELEVATED
-TEST_MODE=--exclude:Elevated
-!endif
-
-test: build
- $(WIN32_TARGET_PATH)\keymanapi_test.exe -b -exit:continue $(TEST_MODE)
- $(WIN64_TARGET_PATH)\keymanapi_test.exe -b -exit:continue $(TEST_MODE)
-
-build:
- $(DELPHI_MSBUILD) "/p:Platform=Win32" keymanapi_test.dproj
- $(DELPHI_MSBUILD) "/p:Platform=Win64" keymanapi_test.dproj
-
-clean: def-clean
- -rd /s/q Win32
- -rd /s/q Win64
-
-!include ..\..\..\Target.mak
diff --git a/windows/src/test/manual-tests/regressiontest/Makefile b/windows/src/test/manual-tests/regressiontest/Makefile
deleted file mode 100644
index dbfa70078c..0000000000
--- a/windows/src/test/manual-tests/regressiontest/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# REGRESSIONTEST Makefile
-#
-
-
-!include ..\..\Defines.mak
-
-build: dirs
- $(DCC32) regressiontest.dpr
- $(COPY) regressiontest.exe $(PROGRAM)\support
-
-clean: def-clean
- cd tests
- $(MAKE) clean
-
-!include ..\..\Target.mak
diff --git a/windows/src/test/manual-tests/regressiontest/tests/Makefile b/windows/src/test/manual-tests/regressiontest/tests/Makefile
deleted file mode 100644
index 01f8705399..0000000000
--- a/windows/src/test/manual-tests/regressiontest/tests/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-
-!include ..\..\..\Defines.mak
-
-all:
- for %d in (*.kmn) do $(PROGRAM)\bin\kmc.cmd build "%d"
-
-.kmn.kmx:
- &$(PROGRAM)\bin\kmc.cmd build $**
-
-clean:
- -del *.kmx
diff --git a/windows/src/test/manual-tests/test_httpuploader/Makefile b/windows/src/test/manual-tests/test_httpuploader/Makefile
deleted file mode 100644
index b6250f4bfd..0000000000
--- a/windows/src/test/manual-tests/test_httpuploader/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# test_httpuploader Makefile
-#
-
-!include ..\..\Defines.mak
-
-build: version.res manifest.res
- $(DCC32) test_httpuploader.dpr
-
-icons:
- rc icons.rc
-
-clean: def-clean
-
-signcode:
- rem no signcode
-
-!include ..\..\Target.mak