Merge pull request #5162 from keymanapp/feat/common/rust-infrastructure

feat(common): Rust infrastructure
This commit is contained in:
Marc Durdin 2021-06-08 08:34:04 +10:00 committed by GitHub
commit bc911053c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 1187 additions and 152 deletions

View file

@ -1,3 +1,8 @@
.vs/
build*/
build/
configure/
# These files may be copied here during Linux package builds
TIER.md
VERSION.md
shellHelperFunctions.sh

View file

@ -1,15 +1,9 @@
@echo off
rem ****************************************************************
rem Run build.sh, not this file directly, to build on Windows.
rem ****************************************************************
setlocal enabledelayedexpansion
if "!SDKVER!"=="" (
if "!WindowsSDKVersion!"=="" (
set SDKVER=8.1
) else (
set SDKVER=!WindowsSDKVersion:~0,-1!
)
)
if "%1"=="" goto help
if "%1"=="all" goto all
if "%1"=="x86" goto build
@ -21,9 +15,14 @@ goto help
rem ----------------------------------
:help
echo Usage: build-core.bat x86^|x64^|all [-c]
echo Usage: %0 x86^|x64^|all debug^|release [build] [tests]
echo or
echo Usage: %0 x86^|x64^|all -c
echo -c will leave your environment configured for Visual Studio for selected platform.
echo -c can be used only with x86 and x64 options
echo.
echo Otherwise, %0 is intended to be used by build.sh, not directly.
echo At least one of 'build' or 'tests' is required.
goto :eof
rem ----------------------------------
@ -32,12 +31,10 @@ rem ----------------------------------
setlocal
cd %KEYMAN_ROOT%\common\core\desktop
cmd /c build.bat x86
if errorlevel 1 exit /b !errorlevel!
cmd /c build.bat x86 %2 %3 %4 %5 || exit !errorlevel!
cd %KEYMAN_ROOT%\common\core\desktop
cmd /c build.bat x64
if errorlevel 1 exit /b !errorlevel!
cmd /c build.bat x64 %2 %3 %4 %5 || exit !errorlevel!
goto :eof
@ -48,7 +45,6 @@ rem ----------------------------------
if "%2"=="-c" goto :setup
set ARCH=%1
echo Building Keyman Core for Windows !ARCH!
echo === Locating Visual Studio ===
@ -68,27 +64,43 @@ if not exist "!VCVARSALL!" (
)
echo === Configuring VC++ ===
call !VCVARSALL! !ARCH! !SDKVER!
if errorlevel 1 exit /b !errorlevel!
call !VCVARSALL! !ARCH! || exit !errorlevel!
echo === Calling meson setup ===
cd %KEYMAN_ROOT%\common\core\desktop
meson build-!ARCH! --werror
if errorlevel 1 exit /b !errorlevel!
echo === Building Keyman Core ===
cd build-!ARCH!
if errorlevel 1 exit /b !errorlevel!
set BUILDTYPE=%2
ninja
if errorlevel 1 exit /b !errorlevel!
if "%3" == "--static" (
set STATIC_LIBRARY=--default-library static
shift
) else (
set STATIC_LIBRARY=
)
echo === Running tests ===
rem Run test cases immediately as they are quick
meson test --print-errorlogs
if errorlevel 1 exit /b !errorlevel!
echo "Is static build = !STATIC_LIBRARY! (%3)"
cd ..
if "%3" == "build" (
echo === Calling meson build for Windows !ARCH! !BUILDTYPE! ===
if exist build\!ARCH!\!BUILDTYPE! rd /s/q build\!ARCH!\!BUILDTYPE!
meson build\!ARCH!\!BUILDTYPE! !STATIC_LIBRARY! --buildtype !BUILDTYPE! --werror || exit !errorlevel!
echo === Building Keyman Core for Windows !ARCH! !BUILDTYPE! ===
cd build\!ARCH!\!BUILDTYPE! || exit !errorlevel!
ninja || exit !errorlevel!
cd ..\..\..
shift
)
if "%3" == "tests" (
cd build\!ARCH!/!BUILDTYPE! || exit !errorlevel!
echo === Running tests for Windows !ARCH! !BUILDTYPE! ===
meson test --print-errorlogs || exit !errorlevel!
cd ..\..\..
)
goto :eof
@ -102,7 +114,7 @@ endlocal
for /f "usebackq tokens=*" %%i in (`..\..\..\resources\build\vswhere -latest -requires Microsoft.Component.MSBuild -find **\vcvarsall.bat`) do (
set VCVARSALL="%%i"
)
%VCVARSALL% %1 8.1
%VCVARSALL% %1
goto :eof
rem ----------------------------------

298
common/core/desktop/build.sh Executable file
View file

@ -0,0 +1,298 @@
#!/usr/bin/env bash
set -e
set -u
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")"
# NOTE: this is slightly non-standard; see longer discussion below
## END STANDARD BUILD SCRIPT INCLUDE
# This script does not use our normal shared build-utils.sh because Linux package builds
# cannot access anything outside of the `common/core/desktop` directory. This means that:
# 1. `shellHelperFunctions.sh`, `VERSION.md` and `TIER.md` are copied here by the script
# `linux/scripts/dist.sh` for inclusion locally in Linux package builds.
# 2. `getversion.sh` and `gettier.sh` will use current folder if we can't access the
# root level `VERSION.md` and `TIER.md`.
# 3. `$SCRIPTS_DIR` is set to this folder by the package build Makefile
# `common/core/desktop/debian/rules`
SCRIPTS_DIR=${SCRIPTS_DIR:-$(dirname "$THIS_SCRIPT")/../../../resources}
. "${SCRIPTS_DIR}/shellHelperFunctions.sh"
THIS_DIR="$(dirname "$THIS_SCRIPT")"
pushd $THIS_DIR > /dev/null
VERSION=$(./getversion.sh)
TIER=$(./gettier.sh)
popd > /dev/null
display_usage() {
echo "usage: build.sh [build options] [targets] [-- options to pass to c++ configure]"
echo
echo "Build options:"
echo " --debug, -d Debug build"
echo " --target, -t Target path (linux,macos only, default build/)"
echo
echo "Targets (all except install if not specified):"
echo " configure Configure libraries (linux,macos only)"
echo " build Build all libraries"
echo " build-rust Build rust libraries"
echo " build-cpp Build c++ libraries"
echo " tests Run all tests"
echo " tests-rust Run rust tests"
echo " tests-cpp Run c++ and c++/rust integration tests"
echo " install Install all libraries"
echo " install-rust Install rust libraries"
echo " install-cpp Install c++ libraries"
echo
echo "Rust libraries will be in: TARGETPATH/rust/<arch>/<buildtype>"
echo "C++ libraries will be in: TARGETPATH/<arch>/<buildtype>/src"
echo "On Windows, <arch> will be 'x86' or 'x64'; elsewhere it is 'arch'"
exit 0
}
get_builder_OS
CARGO_TARGET=--release
MESON_TARGET=release
HAS_TARGET=false
CONFIGURE=false
BUILD_RUST=false
BUILD_CPP=false
TESTS_RUST=false
TESTS_CPP=false
INSTALL_RUST=false
INSTALL_CPP=false
QUIET=false
TARGET_PATH="$THIS_DIR/build"
ADDITIONAL_ARGS=
# Parse args
shopt -s nocasematch
while [[ $# -gt 0 ]] ; do
key="$1"
case $key in
--debug|-d)
CARGO_TARGET=
MESON_TARGET=debug
;;
--help|-\?)
display_usage
;;
--target|-t)
TARGET_PATH=$(readlink -f "$2")
shift
;;
configure)
HAS_TARGET=true
CONFIGURE=true
# meson depends on the rust build in order
# to do its configure step, for now anyway
BUILD_RUST=true
;;
build)
HAS_TARGET=true
BUILD_RUST=true
BUILD_CPP=true
;;
build-rust)
HAS_TARGET=true
BUILD_RUST=true
;;
build-cpp)
HAS_TARGET=true
BUILD_CPP=true
;;
tests)
HAS_TARGET=true
TESTS_RUST=true
TESTS_CPP=true
;;
tests-rust)
HAS_TARGET=true
TESTS_RUST=true
;;
tests-cpp)
HAS_TARGET=true
TESTS_CPP=true
;;
install)
HAS_TARGET=true
INSTALL_RUST=true
INSTALL_CPP=true
;;
install-rust)
HAS_TARGET=true
INSTALL_RUST=true
;;
install-cpp)
HAS_TARGET=true
INSTALL_CPP=true
;;
--)
shift
ADDITIONAL_ARGS=$@
break
;;
*)
fail "Invalid parameters. Use --help for help"
esac
shift
done
if ! $HAS_TARGET; then
CONFIGURE=true
BUILD_RUST=true
BUILD_CPP=true
TESTS_RUST=true
TESTS_CPP=true
fi
MESON_PATH="$TARGET_PATH/arch/$MESON_TARGET"
displayInfo "" \
"VERSION: $VERSION" \
"TIER: $TIER" \
"CONFIGURE: $CONFIGURE" \
"BUILD_RUST: $BUILD_RUST" \
"BUILD_CPP: $BUILD_CPP" \
"TESTS_RUST: $TESTS_RUST" \
"TESTS_CPP: $TESTS_CPP" \
"INSTALL_RUST: $INSTALL_RUST" \
"INSTALL_CPP: $INSTALL_CPP" \
"CARGO_TARGET: $CARGO_TARGET" \
"MESON_TARGET: $MESON_TARGET" \
"TARGET_PATH: $TARGET_PATH" \
""
build_test_rust() {
local TARGETBASE="$1"
if [ -z ${2+x} ]; then local TARGET=""; else local TARGET="$2"; fi
if [ ! -z $TARGET ]; then
local TARGET_FLAG=--target=$TARGET
else
local TARGET_FLAG=
fi
pushd "$THIS_DIR/src/rust" >/dev/null
if $BUILD_RUST; then
echo_heading "======= Building rust library for $TARGETBASE $TARGET ======="
# Built library path for multi-arch (Windows) vs single (*nix)
cargo build --target-dir="$TARGET_PATH/rust/$TARGETBASE" $TARGET_FLAG $CARGO_TARGET
# On Windows, final output path is ./build/rust/<arch>/<arch_rust>/debug|release/<libraryname>
# On other platforms, the final file is already in the right place (TARGET=="")
if [ ! -z $TARGET ]; then
local LIB="rust_mock_processor"
# Library name on Windows vs *nix
[ $os_id == "win" ] && \
local LIBNAME=$LIB.lib || \
local LIBNAME=lib$LIB.a
local BUILT_PATH="$TARGET_PATH/rust/$TARGETBASE/$TARGET/$MESON_TARGET"
local RUST_TARGET_PATH="$TARGET_PATH/rust/$TARGETBASE/$MESON_TARGET"
cp "$BUILT_PATH/$LIBNAME" "$RUST_TARGET_PATH/$LIBNAME"
fi
fi
if $TESTS_RUST; then
echo_heading "======= Testing rust library for $TARGETBASE $TARGET ======="
cargo test --target-dir="$TARGET_PATH/rust/$TARGETBASE" $TARGET $CARGO_TARGET
fi
popd >/dev/null
}
build_windows() {
# Build targets for Windows
# Build the rust targets, both x86 and x64
build_test_rust x86 i686-pc-windows-msvc
build_test_rust x64 x86_64-pc-windows-msvc
# Build the meson targets, both x86 and x64 also
# We need to use a batch file here so we can get
# the Visual Studio build environment with vcvarsall.bat
if $BUILD_CPP; then
if $TESTS_CPP; then
echo_heading "======= Building and Testing C++ library for Windows (x86, x64) ======="
cmd //C build.bat all $MESON_TARGET build tests
else
echo_heading "======= Building C++ library for Windows (x86, x64) ======="
cmd //C build.bat all $MESON_TARGET build
fi
elif $TESTS_CPP; then
echo_heading "======= Testing C++ library for Windows (x86, x64) ======="
cmd //C build.bat all $MESON_TARGET tests
fi
}
build_linux_macos() {
# Build rust targets
build_test_rust arch
# Build meson targets
if $CONFIGURE; then
echo_heading "======= Configuring C++ library for $os_id ======="
pushd $THIS_DIR > /dev/null
meson $MESON_PATH --werror --buildtype $MESON_TARGET $ADDITIONAL_ARGS
popd > /dev/null
fi
if $BUILD_CPP; then
echo_heading "======= Building C++ library for $os_id ======="
pushd $MESON_PATH > /dev/null
ninja
popd > /dev/null
fi
if $TESTS_CPP; then
echo_heading "======= Testing C++ library for $os_id ======="
pushd $MESON_PATH > /dev/null
meson test --print-errorlogs
popd > /dev/null
fi
if $INSTALL_RUST; then
echo_heading "======= Installing Rust libraries for $os_id ======="
# TODO
fi
if $INSTALL_CPP; then
echo_heading "======= Installing C++ libraries for $os_id ======="
pushd $MESON_PATH > /dev/null
ninja install
popd > /dev/null
fi
}
build_macos() {
build_linux_macos
}
build_linux() {
build_linux_macos
}
###
case $os_id in
"linux")
build_linux
;;
"mac")
build_macos
;;
"win")
build_windows
;;
esac

View file

@ -0,0 +1,41 @@
@echo off
setlocal
rem due to some painful cmd-in-bash-in-cmd-in-make-in-cmd interactions
rem causing path confusion for Cargo, it's easier to just call out to a
rem batch file to build our rust targets on Windows
if "%1"=="--debug" (
set CARGO_TARGET=
set MESON_TARGET=debug
) else (
set CARGO_TARGET=--release
set MESON_TARGET=release
)
call :build_test_rust x86 i686-pc-windows-msvc || exit /b !errorlevel!
call :build_test_rust x64 x86_64-pc-windows-msvc || exit /b !errorlevel!
exit /b 0
:build_test_rust
set TARGETBASE=%1
set TARGET=%2
set TARGET_FLAG=--target=%TARGET%
set TARGET_PATH=%~dp0build
cd "%TARGET_PATH%\..\src\rust" || exit !errorlevel!
cargo build --target-dir="%TARGET_PATH%\rust\%TARGETBASE%" %TARGET_FLAG% %CARGO_TARGET% || exit !errorlevel!
:: On Windows, final output path is ./build/rust/<arch>/<arch_rust>/debug|release/<libraryname>
:: On other platforms, the final file is already in the right place (TARGET=="")
set LIB=rust_mock_processor
set LIBNAME=%LIB%.lib
set BUILT_PATH=%TARGET_PATH%\rust\%TARGETBASE%\%TARGET%\%MESON_TARGET%
set RUST_TARGET_PATH=%TARGET_PATH%\rust\%TARGETBASE%\%MESON_TARGET%
copy "%BUILT_PATH%\%LIBNAME%" "%RUST_TARGET_PATH%\%LIBNAME%" || exit !errorlevel!
goto :eof

View file

@ -10,6 +10,7 @@ Build-Depends:
debhelper (>= 11),
meson (>= 0.45),
ninja-build,
cargo,
Standards-Version: 4.5.1
Vcs-Git: https://github.com/keymanapp/keyman.git
Vcs-Browser: https://github.com/keymanapp/keyman/tree/master/common/core/desktop

View file

@ -1,7 +1,9 @@
#!/usr/bin/make -f
export DH_VERBOSE=1
#export DH_OPTIONS=-v
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
export SCRIPTS_DIR = $(shell pwd)/scripts
# xenial needs this to be explicit
export LC_ALL=C.UTF-8
@ -9,5 +11,18 @@ export LC_ALL=C.UTF-8
%:
dh $@
override_dh_auto_configure:
./build.sh configure -- --wrap-mode=nodownload --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=lib/$(DEB_TARGET_GNU_TYPE) --libexecdir=lib/$(DEB_TARGET_GNU_TYPE)
override_dh_auto_build:
./build.sh build
override_dh_auto_test:
./build.sh tests
override_dh_auto_install:
install -d $(shell pwd)/debian/tmp
DESTDIR=$(shell pwd)/debian/tmp ./build.sh install
override_dh_missing:
dh_missing --fail-missing

View file

@ -5,96 +5,148 @@
- Python 3
- Meson build system 0.50 or later.
- C++14 or later compiler (VC++ 2019 or later for Windows).
- Rust from <https://www.rust-lang.org/tools/install> (or `cargo` package on Linux)
- lib std::fs
- kmcomp (for tests) -- must be added to path
## Installing Python3
### Linux
You will be able to install a python3 package in any reputable recent version
of linux using its package manager if it's not already installed.
### Mac OS X
You can get the official installer from the official Python site:
<https://www.python.org/downloads/mac-osx/>
### Windows
You can get the official installer from the official Python site:
You can get the official Python installer from the official Python site:
<https://www.python.org/downloads/windows/>
## Installing Meson
Ensure you have Python3 correctly installed and can run the command `pip`.
Ensure you have Python3 correctly installed and can run the command `pip3`.
Then install meson:
```bash
python3 -m pip install meson
```
Note on paths for kmcomp:
The search path can be edited through System settings / Advanced system settings
/ Environment Variables / User environment variables.
If you have Keyman Developer installed, add `%KeymanDeveloperPath%` to your
path. Otherwise, add the path where you extracted the kmcomp archive.
#### Installing Rust
After downloading and running the executable from:
<https://www.rust-lang.org/tools/install>
Run the command:
```bash
rustup target add i686-pc-windows-msvc
```
### Linux
#### Ubuntu and Debian
You can install `meson` and Rust through the package manager:
```bash
sudo apt update
sudo apt install meson cargo
rustup target add i686-pc-windows-msvc
```
You'll also need the `kmcomp` wrapper - see below.
#### Other Linux distributions
You will be able to install a python3 package in any reputable recent version of
linux using its package manager if it's not already installed.
Then install meson:
```bash
sudo apt install python3 python3-pip
python3 -m pip install meson
```
Install Rust from <https://www.rust-lang.org/tools/install>, then:
```bash
rustup target add i686-pc-windows-msvc
```
You'll also need the `kmcomp` wrapper - see below.
#### All Linux platforms
If you want to rebuild keyboards for tests, you need a wrapper `kmcomp` shell
script:
```bash
#!/usr/bin/env bash
wine `dirname "$0"`/kmcomp.exe "$@"
```
Place this in the same folder as you extracted kmcomp.exe, and
`chmod +x kmcomp`. Add the folder to the path (e.g.
`export PATH=/path/to/kmcomp:$PATH`, which you can add to `.bashrc`).
### macOS
You can get the official Python installer from the official Python site:
<https://www.python.org/downloads/mac-osx/>
Install meson and rust:
```bash
brew install meson # if you haven't already installed via pip
curl https://sh.rustup.rs -sSf | sh
rustup target add i686-pc-windows-msvc
```
If you want to rebuild keyboards for tests, you'll also need WINE:
```bash
brew tap homebrew/cask-versions
brew install --cask --no-quarantine wine-stable
```
And you will also need a wrapper `kmcomp` shell script:
```bash
#!/usr/bin/env bash
wine64 `dirname "$0"`/kmcomp.exe "$@"
```
Place this in the same folder as you extracted kmcomp.exe, and
`chmod +x kmcomp`. Add the folder to the path (e.g.
`export PATH=/path/to/kmcomp:$PATH`, which you can add to `.bashrc`).
## Building
### Building on Windows
### Prerequisite on Windows
For Windows, use `build.bat` -- this handles environment and x86/x64
cross-compiles with Visual Studio 2017+.
You may need to set `SDKVER` environement variable to the current
On Windows you may need to set `SDKVER` environment variable to the current
Windows SDK version, if it cannot be automatically detected, e.g.:
```DOS
set SDKVER=10.0.19041.0
```
To build:
You'll also need to install x86 support for Rust:
```DOS
build.bat all
rustup target add i686-pc-windows-msvc
```
### Building on Linux, macOS
### Building on all platforms
For all other platforms, in your source directory do the following:
On all platforms, use `build.sh`.
```bash
cd desktop
meson build --werror
cd build
ninja
meson test
./build.sh --debug
```
For a debug build, pass `--buildtype debug` to meson.
## Note on kmcomp
kmcomp is the command-line compiler from Keyman Developer, available from <https://keyman.com/> or
in this repo in `/windows/src/developer/kmcomp`. The compiler is currently available as a Windows
PE executable only, but it does run under WINE.
## Additional configuration notes
### Windows
The search path can be edited through System settings / Advanced system settings /
Environment Variables / User environment variables.
If you have Keyman Developer installed, add `%KeymanDeveloperPath%` to your path. Otherwise, add
the path where you extracted the kmcomp archive.
### Linux
You need a wrapper `kmcomp` shell script:
```bash
#!/bin/bash
wine `dirname "$0"`/kmcomp.exe "$@"
```
Place this in the same folder as you extracted kmcomp.exe, and `chmod +x kmcomp`. Add the folder
to the path (e.g. `export PATH=/path/to/kmcomp:$PATH`, which you can add to `.bashrc`)
### macOS
TODO
kmcomp is the command-line compiler from Keyman Developer, available from
<https://keyman.com/developer/download> or in this repo in
`/windows/src/developer/kmcomp`. The compiler is currently available as a
Windows PE executable only, but it does run under WINE.

7
common/core/desktop/gettier.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
# Get the tier from TIER.md
# When building from a Linux source package, `TIER.md` is in the
# same directory as this script.
TIERFILE=TIER.md
[ -f ../../../TIER.md ] && TIERFILE=../../../TIER.md
cat $TIERFILE

0
common/core/desktop/getversion.sh Normal file → Executable file
View file

View file

@ -889,7 +889,8 @@ enum km_kbp_tech_value {
KM_KBP_TECH_UNSPECIFIED = 0,
KM_KBP_TECH_MOCK = 1 << 0,
KM_KBP_TECH_KMX = 1 << 1,
KM_KBP_TECH_LDML = 1 << 2
KM_KBP_TECH_LDML = 1 << 2,
KM_KBP_TECH_RUST_MOCK = 1 << 3
};

View file

@ -23,6 +23,29 @@ endif
py = import('python3')
python = py.find_python()
# Rust library path search
if host_machine.system() == 'windows'
if host_machine.cpu_family() == 'x86'
rust_platform = 'x86' #i686-pc-windows-msvc in rust
else
rust_platform = 'x64' #x86_64-pc-windows-msvc in rust
endif
else
if host_machine.system() == 'darwin'
# todo we need to support M1 targets as well, eventually
rust_platform = 'arch'
else #linux
# we only build for our current arch
rust_platform = 'arch'
endif
endif
rust_path = join_paths(meson.current_build_dir(), '..', '..', 'rust', rust_platform, get_option('buildtype'))
# message('rust library path is: '+rust_path)
cc = meson.get_compiler('c')
rust_mock_processor = cc.find_library('rust_mock_processor', dirs: rust_path)
subdir('doc')
subdir('include')
subdir('src')

View file

@ -15,6 +15,7 @@
#include "processor.hpp"
#include "kmx/kmx_processevent.hpp"
#include "mock/mock_processor.hpp"
#include "rust/rust_mock_processor.hpp"
using namespace km::kbp;
@ -29,6 +30,9 @@ namespace
else if (kb_path.suffix() == ".mock") {
return new mock_processor(kb_path);
}
else if (kb_path.suffix() == ".rust_mock") {
return new rust_mock_processor(kb_path);
}
else {
return new null_processor();
}

View file

@ -107,7 +107,7 @@ void KMX_Context::Set(const KMX_WCHAR *buf)
}
*q = 0;
pos = (intptr_t)(q-CurContext);
pos = (int)(intptr_t)(q-CurContext);
CurContext[MAXCONTEXT-1] = 0;
//DebugLog("KMX_Context::Set(%s): EXIT [%d]: %s", Debug_UnicodeString(buf), pos, Debug_UnicodeString(CurContext, 1));

View file

@ -33,7 +33,7 @@ if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang'
endif
if host_machine.system() == 'darwin'
warns += ['-Wno-ctor-dtor-privacy', '-Wno-non-virtual-dtor ']
warns += ['-Wno-ctor-dtor-privacy', '-Wno-non-virtual-dtor']
endif
endif
@ -49,34 +49,36 @@ if compiler.get_id() == 'msvc'
endif
lib = library('kmnkbp0',
'option.cpp',
'keyboard.cpp',
'state.cpp',
'km_kbp_context_api.cpp',
'km_kbp_keyboard_api.cpp',
'km_kbp_options_api.cpp',
'km_kbp_state_api.cpp',
'km_kbp_processevent_api.cpp',
'json.cpp',
'mock/mock_processor.cpp',
'kmx/kmx_consts.cpp',
'kmx/kmx_processevent.cpp',
'kmx/kmx_actions.cpp',
'kmx/kmx_capslock.cpp',
'kmx/kmx_context.cpp',
'kmx/kmx_debug.cpp',
'kmx/kmx_environment.cpp',
'kmx/kmx_file.cpp',
'kmx/kmx_modifiers.cpp',
'kmx/kmx_options.cpp',
'kmx/kmx_processor.cpp',
'kmx/kmx_xstring.cpp',
'utfcodec.cpp',
cpp_args: defns + warns + flags,
link_args: links,
version: lib_version,
include_directories: inc,
install: true)
'option.cpp',
'keyboard.cpp',
'state.cpp',
'km_kbp_context_api.cpp',
'km_kbp_keyboard_api.cpp',
'km_kbp_options_api.cpp',
'km_kbp_state_api.cpp',
'km_kbp_processevent_api.cpp',
'json.cpp',
'mock/mock_processor.cpp',
'rust/rust_mock_processor.cpp',
'kmx/kmx_consts.cpp',
'kmx/kmx_processevent.cpp',
'kmx/kmx_actions.cpp',
'kmx/kmx_capslock.cpp',
'kmx/kmx_context.cpp',
'kmx/kmx_debug.cpp',
'kmx/kmx_environment.cpp',
'kmx/kmx_file.cpp',
'kmx/kmx_modifiers.cpp',
'kmx/kmx_options.cpp',
'kmx/kmx_processor.cpp',
'kmx/kmx_xstring.cpp',
'utfcodec.cpp',
cpp_args: defns + warns + flags,
link_args: links,
dependencies: [rust_mock_processor],
version: lib_version,
include_directories: inc,
install: true)
kmnkbp = declare_dependency(link_with: lib, include_directories: inc)

5
common/core/desktop/src/rust/Cargo.lock generated Normal file
View file

@ -0,0 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "rust_mock_processor"
version = "0.1.0"

View file

@ -0,0 +1,7 @@
[package]
name = "rust_mock_processor"
version = "0.1.0"
[lib]
name = "rust_mock_processor"
crate-type = ["staticlib"]

View file

@ -0,0 +1,79 @@
/*
Copyright: © 2021 SIL International.
Description: This is an interface to a rust mock implementation.
TODO: Add a mechanism to trigger output of PERSIST_OPT &
RESET_OPT actions items, options support and context matching.
Authors: Marc Durdin
*/
#include "rust/rust_mock_processor.hpp"
#include "state.hpp"
namespace
{
// This is metadata about the Rust implementation
constexpr km_kbp_attr const engine_attrs = {
256,
KM_KBP_LIB_CURRENT,
KM_KBP_LIB_AGE,
KM_KBP_LIB_REVISION,
KM_KBP_TECH_RUST_MOCK,
"SIL International"
};
}
namespace km {
namespace kbp
{
rust_mock_processor::rust_mock_processor(kbp::path const & path)
: abstract_processor(
keyboard_attributes(path.stem(), u"3.145", path.parent(), {
option{KM_KBP_OPT_KEYBOARD, u"__test_point", u"not triggered"},
})),
_options({
{u"\x01__test_point", u"not triggered"},
{u"\x02hello", u"-"}
})
{
}
char16_t const * rust_mock_processor::lookup_option(km_kbp_option_scope scope,
std::u16string const & key) const
{
// TODO: move to rust
auto i = _options.find(char16_t(scope) + key);
return i != _options.end() ? i->second.c_str() : nullptr;
}
option rust_mock_processor::update_option(km_kbp_option_scope scope,
std::u16string const & key,
std::u16string const & value)
{
// TODO: move to rust
auto i = _options.find(char16_t(scope) + key);
if (i == _options.end()) return option();
i->second = value;
persisted_store()[key] = value;
return option(scope, key, i->second);
}
extern "C" uint32_t rust_mock_process_event(uint16_t vk, uint16_t modifier);
km_kbp_status rust_mock_processor::process_event(km_kbp_state *state, km_kbp_virtual_key vk, uint16_t modifier_state)
{
(void)(state);
//km_kbd_rust_state rust_state(state);
return rust_mock_process_event(vk, modifier_state);
}
km_kbp_attr const & rust_mock_processor::attributes() const {
return engine_attrs;
}
km_kbp_status rust_mock_processor::validate() const { return KM_KBP_STATUS_OK; }
km_kbp_status rust_null_processor::validate() const { return KM_KBP_STATUS_INVALID_ARGUMENT; }
} // namespace kbp
} // namespace km

View file

@ -0,0 +1,53 @@
/*
Copyright: © 2021 SIL International.
Description: Internal keyboard class and adaptor class for the Rust API implementations.
Authors: Marc Durdin; starting from mock_processor.hpp
*/
#pragma once
#include <string>
#include <unordered_map>
#include <keyman/keyboardprocessor.h>
#include "processor.hpp"
#include "option.hpp"
namespace km {
namespace kbp
{
class rust_mock_processor : public abstract_processor
{
std::unordered_map<std::u16string, std::u16string> _options;
public:
rust_mock_processor(km::kbp::path const &);
// ~mock_processor() override;
km_kbp_status process_event(km_kbp_state *state,
km_kbp_virtual_key vk,
uint16_t modifier_state) override;
virtual km_kbp_attr const & attributes() const override;
km_kbp_status validate() const override;
char16_t const * lookup_option(km_kbp_option_scope,
std::u16string const & key) const override;
option update_option(km_kbp_option_scope,
std::u16string const & key,
std::u16string const & value) override;
};
class rust_null_processor : public rust_mock_processor {
public:
rust_null_processor(): rust_mock_processor(path())
{
_attributes = keyboard_attributes(u"null", u"0.0", path(), {});
}
km_kbp_status validate() const override;
};
} // namespace kbp
} // namespace km

View file

@ -0,0 +1,123 @@
/*
// An table of VKEY to character sequence mappings, one per shift state.
// An empty string inidicates no mapping.
constexpr char const table[2][256][4] = {
{
/*00-0F*/"","","","","","","","","","\t","","","","\015","","",
/*10-1F*/"","","","","","","","","","","","\033","","","","",
/*20-2F*/" ","","","","","","","","","","","","","","","",
/*30-3F*/"0","1","2","3","4","5","6","7","8","9","","","","","","",
/*40-4F*/"","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
/*50-5F*/"p","q","r","s","t","u","v","w","x","y","z","","","","","",
/*60-6F*/"0","1","2","3","4","5","6","7","8","9","*","+","","-",".","/",
/*70-7F*/"f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","f12","f13","f14","f15","f16",
/*80-8F*/"f17","f18","f19","f20","f24","","","","","","","","","","","",
/*90-9F*/"","","","","","","","","","","","","","","","",
/*A0-AF*/"","","","","","","","","","","","","","","","",
/*B0-BF*/"","","","","","","","","","",";","=",",","-",".","/",
/*C0-CF*/"`","","","","","","","","","","","","","","","",
/*D0-DF*/"","","","","","","","","","","","[","\\","]","'","",
/*E0-EF*/"","","","","","","","","","","","","","","","",
/*F0-FF*/"","","","","","","","","","","","","","","","",
},
{
/*00-0F*/"","","","","","","","","","\t","","","","\015","","",
/*10-1F*/"","","","","","","","","","","","\033","","","","",
/*20-2F*/" ","","","","","","","","","","","","","","","",
/*30-3F*/")","!","@","#","$","%","^","&","*","(","","","","","","",
/*40-4F*/"","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
/*50-5F*/"P","Q","R","S","T","U","V","W","X","Y","Z","","","","","",
/*60-6F*/"","","","","","","","","","","","","","","","",
/*70-7F*/"","","","","","","","","","","","","","","","",
/*80-8F*/"","","","","","","","","","","","","","","","",
/*90-9F*/"","","","","","","","","","","","","","","","",
/*A0-AF*/"","","","","","","","","","","","","","","","",
/*B0-BF*/"","","","","","","","","","",":","+","<","_",">","?",
/*C0-CF*/"~","","","","","","","","","","","","","","","",
/*D0-DF*/"","","","","","","","","","","","{","|","}","\"","",
/*E0-EF*/"","","","","","","","","","","","","","","","",
/*F0-FF*/"","","","","","","","","","","","","","","","",
}
};
assert(state);
if (!state)
return KM_KBP_STATUS_INVALID_ARGUMENT;
try
{
// At the start of every process_event always clear the action_items
state->actions().clear();
switch (vk)
{
case KM_KBP_VKEY_BKSP:
state->context().pop_back();
state->actions().push_backspace();
break;
case KM_KBP_VKEY_F2:
{
state->actions().push_persist(
update_option(KM_KBP_OPT_KEYBOARD,
u"__test_point",
u"F2 pressed test save."));
break;
}
case KM_KBP_VKEY_F4:
state->context().push_marker(KM_KBP_VKEY_QUOTE);
state->actions().push_marker(KM_KBP_VKEY_QUOTE);
break;
default:
{
auto shift_state = bool(modifier_state & KM_KBP_MODIFIER_SHIFT);
// Only process further one of the shift states has something to output.
if (table[0][vk][0] || table[1][vk][0])
{
auto char_seq = table[shift_state][vk];
for (auto c = char_seq; *c; ++c)
{
km_kbp_usv usv = *c;
state->context().push_character(usv);
state->actions().push_character(usv);
}
state->actions().commit();
return KM_KBP_STATUS_OK;
}
// Both shift states output nothing, generate an alert.
state->actions().push_alert();
break;
}
}
state->actions().commit();
}
catch (std::bad_alloc &)
{
state->actions().clear();
return KM_KBP_STATUS_NO_MEM;
}
return KM_KBP_STATUS_OK;
*/
#[no_mangle]
pub extern "C" fn rust_mock_process_event(_vk: u16, _modifier: u16) -> u32 {
return 0; //KM_KBP_STATUS_OK
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rust_mock_process_event() {
assert_eq!(0, rust_mock_process_event(0, 0));
}
}

View file

@ -23,4 +23,5 @@ endif
subdir('unit/json')
subdir('unit/utftest')
subdir('unit/kmnkbd')
subdir('unit/kmx')
subdir('unit/kmx')
subdir('unit/rust_mock')

View file

@ -18,6 +18,7 @@ foreach t : tests
cpp_args: defns,
include_directories: [inc, libsrc],
link_args: links,
dependencies: [rust_mock_processor],
objects: lib.extract_all_objects())
test(t[0], bin)

View file

@ -9,6 +9,7 @@ kmx = executable('kmx', 'kmx.cpp',
cpp_args: defns,
include_directories: [inc, libsrc],
link_args: links,
dependencies: [rust_mock_processor],
objects: lib.extract_all_objects())
copyfile = ['-c', 'import sys, shutil', 'shutil.copyfile(*sys.argv[1:])']

View file

@ -0,0 +1,33 @@
/*
Copyright: © 2021 SIL International.
Description: Tests for the Keyboard API family of functions rust_mock
*/
#include <string>
#include <keyman/keyboardprocessor.h>
#include "path.hpp"
//#include "keyboard.hpp"
namespace
{
km::kbp::path const test_kb_path = "/a/dummy/keyboard.rust_mock";
}
#define try_status(expr) \
{auto __s = (expr); if (__s != KM_KBP_STATUS_OK) return 100*__LINE__+__s;}
int main(int, char *[])
{
km_kbp_keyboard * test_kb = nullptr;
km_kbp_keyboard_attrs const * kb_attrs = nullptr;
try_status(km_kbp_keyboard_load(test_kb_path.c_str(), &test_kb));
try_status(km_kbp_keyboard_get_attrs(test_kb, &kb_attrs));
if (kb_attrs->folder_path != test_kb_path.parent())
return __LINE__;
km_kbp_keyboard_dispose(test_kb);
return 0;
}

View file

@ -0,0 +1,20 @@
# Copyright: © 2021 SIL International.
# Description: Cross platform build script to compile rust mock API unit tests.
#
defns=['-DKMN_KBP_STATIC']
tests = [
['rust-keyboard-api', 'keyboard_api.cpp'],
['rust-state-api', 'state_api.cpp']
]
foreach t : tests
bin = executable(t[0], t[1],
cpp_args: defns,
include_directories: [inc, libsrc],
link_args: links,
dependencies: [rust_mock_processor],
objects: lib.extract_all_objects())
test(t[0], bin)
endforeach

View file

@ -0,0 +1,213 @@
/*
Copyright: © 2021 SIL International.
Description: Tests for the rust_mock interfaces.
*/
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <keyman/keyboardprocessor.h>
#include "path.hpp"
#include "state.hpp"
#define try_status(expr) \
{auto __s = (expr); if (__s != KM_KBP_STATUS_OK) std::exit(100*__LINE__+__s);}
namespace
{
std::string get_json_doc(km_kbp_state const& state)
{
size_t sz = 0;
try_status(km_kbp_state_to_json(&state, nullptr, &sz));
std::string buf(sz-1, 0);
try_status(km_kbp_state_to_json(&state, &buf[0], &sz));
return buf;
}
km_kbp_option_item test_env_opts[] =
{
{u"hello", u"world", 0},
KM_KBP_OPTIONS_END
};
#if 0
constexpr char const *doc1_expected = u8"\
{\n\
\"$schema\" : \"keyman/keyboardprocessor/doc/introspection.schema\",\n\
\"keyboard\" : {\n\
\"id\" : \"dummy\",\n\
\"folder\" : \"\",\n\
\"version\" : \"3.145\",\n\
\"rules\" : []\n\
},\n\
\"context\" : [\n\
\"H\",\n\
\"e\",\n\
\"l\",\n\
\"l\",\n\
\"o\",\n\
\" \",\n\
\"😁\",\n\
\"S\",\n\
\"I\",\n\
\"L\"\n\
],\n\
\"actions\" : [\n\
{ \"persist\" : { \"keyboard\" : { \"__test_point\" : \"F2 pressed test save.\" } } }\n\
]\n\
}\n";
constexpr char const *doc2_expected = u8"\
{\n\
\"$schema\" : \"keyman/keyboardprocessor/doc/introspection.schema\",\n\
\"keyboard\" : {\n\
\"id\" : \"dummy\",\n\
\"folder\" : \"\",\n\
\"version\" : \"3.145\",\n\
\"rules\" : []\n\
},\n\
\"context\" : [],\n\
\"actions\" : []\n\
}\n";
constexpr km_kbp_option_item const expected_persist_opt = {
u"__test_point",
u"F2 pressed test save.",
KM_KBP_OPT_KEYBOARD
};
#endif
inline
bool operator==(km_kbp_option_item const & lhs, km_kbp_option_item const & rhs)
{
return lhs.scope == rhs.scope
&& std::u16string(lhs.key) == rhs.key
&& std::u16string(lhs.value) == rhs.value;
}
bool operator==(km_kbp_action_item const & lhs,
km_kbp_action_item const & rhs)
{
if (lhs.type != rhs.type) return false;
switch(lhs.type)
{
case KM_KBP_IT_CHAR: return lhs.character == rhs.character;
case KM_KBP_IT_MARKER: return lhs.marker == rhs.marker;
case KM_KBP_IT_PERSIST_OPT: return *lhs.option == *rhs.option;
default: break;
}
return true;
}
#ifdef assert
#undef assert
#endif
#define assert(expr) {if (!(expr)) return __LINE__; }
bool action_items(km_kbp_state const * state,
std::initializer_list<km_kbp_action_item> const & expected)
{
size_t n = 0;
auto act = km_kbp_state_action_items(state, &n);
for (auto &rhs: expected)
if (!(*act++ == rhs)) return false;
return true;
}
} // namespace
int main(int, char * [])
{
km_kbp_keyboard * test_kb = nullptr;
km_kbp_state * test_state = nullptr,
* test_clone = nullptr;
try_status(km_kbp_keyboard_load(km::kbp::path("dummy.rust_mock").c_str(), &test_kb));
// Simple sanity tests.
try_status(km_kbp_state_create(test_kb, test_env_opts, &test_state));
try_status(km_kbp_state_clone(test_state, &test_clone));
// Check sub objects have been copied and not shared.
if (km_kbp_state_context(test_state) == km_kbp_state_context(test_clone))
return __LINE__;
size_t n_actions = 0;
if (km_kbp_state_action_items(test_state, &n_actions) == nullptr
&& n_actions != 0)
return __LINE__;
// Lets add data and do some basic checks of options and km_kbp_context
km_kbp_context_item *citems = nullptr;
try_status(km_kbp_context_items_from_utf16(u"Hello 😁", &citems));
try_status(km_kbp_context_set(km_kbp_state_context(test_state), citems));
km_kbp_context_items_dispose(citems);
if(km_kbp_context_length(km_kbp_state_context(test_state)) != 7)
return __LINE__;
if(km_kbp_context_length(km_kbp_state_context(test_clone)) != 0)
return __LINE__;
// Overwrite some data.
km_kbp_option_item new_opt[] = {
{u"hello", u"globe", KM_KBP_OPT_ENVIRONMENT},
KM_KBP_OPTIONS_END};
try_status(km_kbp_state_options_update(test_clone, new_opt));
// Test the engine
auto attrs = km_kbp_get_engine_attrs(test_state);
// Check the lib supplies our required interface.
if (attrs->current - attrs->age > KM_KBP_LIB_CURRENT
|| attrs->current < KM_KBP_LIB_CURRENT) return __LINE__;
if (attrs->max_context < 16) return __LINE__;
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S,
KM_KBP_MODIFIER_SHIFT));
//TEMP
action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('S')}}});
auto doc1 = get_json_doc(*test_state);
std::cout << doc1 << std::endl;
#if 0
// TODO: enable these tests once we have the data propagating to Rust
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('S')}}}));
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_I,
KM_KBP_MODIFIER_SHIFT));
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('I')}}}));
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_L, 0));
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('l')}}}));
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_BKSP, 0));
assert(action_items(test_state, {{KM_KBP_IT_BACK, {0,}, {0}}}));
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_L,
KM_KBP_MODIFIER_SHIFT));
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('L')}}}));
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_F2,0));
assert(action_items(test_state, {{KM_KBP_IT_PERSIST_OPT, {0,},
{uintptr_t(&expected_persist_opt)}}}));
// Test debug dump
auto doc1 = get_json_doc(*test_state),
doc2 = get_json_doc(*test_clone);
std::cout << doc1 << std::endl;
std::cout << doc2 << std::endl;
// These should not be equal.
if (doc1 == doc2) return __LINE__;
// These should be.
if (doc1 != doc1_expected) return __LINE__;
if (doc2 != doc2_expected) return __LINE__;
#endif
// Destroy them
km_kbp_state_dispose(test_state);
km_kbp_state_dispose(test_clone);
km_kbp_keyboard_dispose(test_kb);
return 0;
}

View file

@ -32,7 +32,7 @@ sources:
./scripts/dist.sh
tmpsources:
PKG_CONFIG_PATH="../keyboardprocessor/meson-private" ./scripts/dist.sh
PKG_CONFIG_PATH="../keyboardprocessor/arch/release/meson-private" ./scripts/dist.sh
origdist:
./scripts/dist.sh origdist

View file

@ -24,7 +24,7 @@ See [license information](./LICENSE.md) about licensing.
libjson-glib-dev libgtk-3-dev libxml2-utils help2man python3-lxml \
python3-magic python3-numpy python3-pil python3-pip python3-qrcode \
python3-requests python3-requests-cache python3 python3-gi dconf-cli \
dconf-editor python3-dbus
dconf-editor cargo python3-dbus
```
## Compiling from Command Line

View file

@ -2,6 +2,6 @@ You need autoconf, autopoint, gettext, automake and libtool to generate the buil
flex and bison are useful to rebuild lex.l and yacc.y in kmflcomp but not essential
For keyboardprocessor you need meson and ninja (meson package pulls both in)
For keyboardprocessor you need rust, meson and ninja (meson package pulls in ninja)
Run `make reconf` to run them

View file

@ -20,7 +20,7 @@
# any=@precise.any
[common]
any=git autotools-dev build-essential dh-autoreconf libibus-1.0-dev flex bison meson python3 python3-pip
any=git autotools-dev build-essential dh-autoreconf libibus-1.0-dev flex bison meson python3 python3-pip cargo
[xenial]
any=libx11-dev

View file

@ -19,10 +19,9 @@ if [[ "${CONFIGUREONLY}" != "no" && "${BUILDONLY}" != "no" ]]; then
fi
if [[ "${BUILDONLY}" == "no" ]]; then
if [ ! -d keyboardprocessor ]; then
meson ../common/core/desktop keyboardprocessor
fi
cd keyboardprocessor
../common/core/desktop/build.sh -t keyboardprocessor configure
cd keyboardprocessor/arch/release
echo "reconfiguring keyboardprocessor meson with prefix ${INSTALLDIR}"
meson configure -Dprefix=${INSTALLDIR} && ninja reconfigure
cd $BASEDIR
@ -30,9 +29,10 @@ fi
if [[ "${CONFIGUREONLY}" == "no" ]]; then
echo "building keyboardprocessor"
cd keyboardprocessor
ninja
cd $BASEDIR
# May 2021: For now, running tests here as well. We could move this elsewhere
# in the future if we want to split out the tests, but they run in a couple of seconds
# at present.
../common/core/desktop/build.sh -t keyboardprocessor build tests
fi
for proj in kmflcomp libkmfl ibus-kmfl ibus-keyman; do
@ -48,15 +48,15 @@ for proj in kmflcomp libkmfl ibus-kmfl ibus-keyman; do
if [[ "${BUILDONLY}" == "no" ]]; then
echo "Configuring $proj"
if [[ "${INSTALLDIR}" == "/tmp/kmfl" ]]; then # don't install ibus-kmfl or ibus-keyman into ibus
../$proj/configure KEYMAN_PROC_CFLAGS="-I\$(top_builddir)/../keyboardprocessor/include -I\$(top_builddir)/../../common/core/desktop/include" \
../$proj/configure KEYMAN_PROC_CFLAGS="-I\$(top_builddir)/../keyboardprocessor/arch/release/include -I\$(top_builddir)/../../common/core/desktop/include" \
CPPFLAGS="-I\$(top_builddir)/../build-kmflcomp -I\$(top_builddir)/../build-libkmfl" \
KEYMAN_PROC_LIBS="-L`pwd`/../build-libkmfl/src -L`pwd`/../keyboardprocessor/src -lkmnkbp0" \
KEYMAN_PROC_LIBS="-L`pwd`/../build-libkmfl/src -L`pwd`/../keyboardprocessor/arch/release/src -lkmnkbp0" \
LDFLAGS="-L`pwd`/../build-kmflcomp/src -L`pwd`/../build-libkmfl/src" --prefix=${INSTALLDIR} --libexecdir=${INSTALLDIR}/lib/ibus
else # install ibus-kmfl and ibus-keyman into ibus
../$proj/configure KEYMAN_PROC_CFLAGS="-I\$(top_builddir)/../keyboardprocessor/include -I\$(top_builddir)/../../common/core/desktop/include" \
../$proj/configure KEYMAN_PROC_CFLAGS="-I\$(top_builddir)/../keyboardprocessor/arch/release/include -I\$(top_builddir)/../../common/core/desktop/include" \
CPPFLAGS="-I\$(top_builddir)/../build-kmflcomp -I\$(top_builddir)/../build-libkmfl" \
LDFLAGS="-L`pwd`/../build-kmflcomp/src -L`pwd`/../build-libkmfl/src" \
KEYMAN_PROC_LIBS="-L`pwd`/../build-libkmfl/src -L`pwd`/../keyboardprocessor/src -lkmnkbp0" \
KEYMAN_PROC_LIBS="-L`pwd`/../build-libkmfl/src -L`pwd`/../keyboardprocessor/arch/release/src -lkmnkbp0" \
--prefix=${INSTALLDIR} --libexecdir=${INSTALLDIR}/lib/ibus --datadir=/usr/share
fi
if [ -d ../$proj/include ]; then

View file

@ -84,6 +84,9 @@ for proj in ${extra_projects}; do
kbpvers="keyman-keyboardprocessor-$VERSION"
cp -a desktop $kbpvers
cp ../../VERSION.md $kbpvers
cp ../../TIER.md $kbpvers
mkdir -p $kbpvers/scripts
cp ../../resources/shellHelperFunctions.sh $kbpvers/scripts
tar cvzf $kbpvers.tar.gz --exclude=debian --exclude=build --exclude=.gitignore $kbpvers
rm -rf $kbpvers
cp $kbpvers.tar.gz ../../linux/dist

View file

@ -47,7 +47,7 @@ if [ -f "/usr/share/ibus/component/keyman.xml" ] && [ "${SUDOINSTALL}" == "yes"
fi
cd keyboardprocessor
cd keyboardprocessor/arch/release
ninja install
cd $BASEDIR

View file

@ -42,7 +42,7 @@ checkAndInstallRequirements()
for p in dh-python gir1.2-webkit2-4.0 python3-all python3-setuptools \
python3-requests python3-requests-cache python3-numpy python3-pil python3-lxml \
python3-gi python3-magic python3-qrcode python3-dbus
python3-gi python3-magic python3-qrcode cargo build-essential python3-dbus
do
if ! dpkg -l | grep -q $p; then
TOINSTALL="$TOINSTALL $p"

View file

@ -54,7 +54,7 @@ for proj in ${extra_projects}; do
if [ "${proj}" == "keyboardprocessor" ]; then
rm -rf keyboardprocessor
cp ../VERSION.md ../common/core/desktop/
meson ../common/core/desktop keyboardprocessor
../common/core/desktop/build.sh -t keyboardprocessor configure
fi
if [ "${proj}" == "keyman-config" ]; then
cd keyman-config

View file

@ -11,8 +11,8 @@ available_platforms=(android ios linux mac web windows)
watch_android='web|common/models|common/predictive-text|common/lexical-model-types|common/core/web'
watch_ios='web|common/models|common/predictive-text|common/lexical-model-types|common/core/web'
watch_linux='common/engine'
watch_mac='common/engine'
watch_linux='common/core/desktop'
watch_mac='common/core/desktop'
watch_web='common/models|common/predictive-text|common/lexical-model-types|common/core/web'
# Windows currently builds Developer and Desktop, so we need everything from common,developer,web

View file

@ -1,5 +1,11 @@
#!/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,
@ -254,7 +260,7 @@ set_npm_version () {
if [ $# == 0 ]; then
fail "set_npm_version requires a specified version."
fi
local version=$1
# 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
@ -303,7 +309,7 @@ verify_npm_setup () {
# Ensure the repo's base resources are installed. (This ensures the local `lerna` install is available.)
npm install --no-optional
# Use lerna to ensure repo-internal dependencies are all properly linked
# Use lerna to ensure repo-internal dependencies are all properly linked
# while also installing external dependencies. Also propagates lerna into
# each project that can use it (once added as a dev-dependency there)
#
@ -328,7 +334,7 @@ verify_npm_setup () {
# npx lerna bootstrap -- --no-optional # ONLY SAFE AT REPO'S BASE (otherwise, temporarily re-downloads `lerna`!)
# - or -
# npm run lerna -- bootstrap -- -- --no-optional # Possible to use within sub-packages with proper setup. (See below.)
# Note: calling the above WITHOUT changing directories to $KEYMAN_ROOT will re-download lerna.
#
# Instead, configuring each package like this:

View file

@ -53,6 +53,14 @@
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -90,7 +98,7 @@
</ResourceCompile>
<Link>
<AdditionalOptions>/verbose:lib /section:.SHARDATA,rws %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libkmnkbp0.a;rust_mock_processor.lib;psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>./Keyman32.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ModuleDefinitionFile>keyman32.def</ModuleDefinitionFile>
@ -152,7 +160,7 @@
</ResourceCompile>
<Link>
<AdditionalOptions>/verbose:lib /section:.SHARDATA,rws %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libkmnkbp0.a;rust_mock_processor.lib;psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>./Keyman32.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ModuleDefinitionFile>keyman32.def</ModuleDefinitionFile>

View file

@ -4,7 +4,7 @@
!include ..\..\Defines.mak
build: version.res dirs
build: version.res dirs pull-core
$(MSBUILD) keyman32.vcxproj $(MSBUILD_BUILD)
$(COPY) keyman32.dll $(PROGRAM)\engine
$(COPY) keyman32.pdb $(DEBUGPATH)\engine
@ -33,4 +33,17 @@ install:
echo You may want to manually tweak keyman-debug-etw.man and fill in $(INSTALLPATH_KEYMANENGINE)\keyman32.dll
echo and then run wevtutil im keyman-debug-etw.man to get the latest event tracing
!ifdef DEBUG
CORE_DEBUG=--debug
MESON_TARGET=debug
!else
MESON_TARGET=release
!endif
pull-core:
cd $(ROOT)\..\common\core\desktop
build_cargo.bat $(CORE_DEBUG)
build.bat all $(MESON_TARGET) --static build tests
cd $(ROOT)\src\engine\keyman32
!include ..\..\Target.mak

View file

@ -81,6 +81,14 @@
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x64\$(Configuration);$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x64\$(Configuration);$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -119,7 +127,7 @@
</ResourceCompile>
<Link>
<AdditionalOptions>/verbose:lib /section:.SHARDATA,rws %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>psapi.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;libcmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>rust_mock_processor.lib;libkmnkbp0.a;psapi.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;libcmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>./Keyman64.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>C:\Program Files\Microsoft SDKs\Windows\v7.0\Lib\x64;$(VCInstallDir)lib\amd64;$(VCInstallDir)lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
@ -181,7 +189,7 @@
</ResourceCompile>
<Link>
<AdditionalOptions>/verbose:lib /section:.SHARDATA,rws %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>psapi.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;libcmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>rust_mock_processor.lib;libkmnkbp0.a;psapi.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;libcmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>./Keyman64.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib\x64;$(VCInstallDir)lib\amd64;$(VCInstallDir)lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>