From 8052ac9bbca50d2ec4ce5e60e0e23a571aeb29e2 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 27 May 2021 11:17:35 +1000 Subject: [PATCH 01/24] feat(common): Rust infrastructure Relates to #5069. This establishes a baseline Rust build environment and linkage with common/core/desktop. This includes: * build script build.sh which handles builds on Windows, macOS, *nix, with multiple targets on Windows only at present (M1 on mac to come when we do the mac integration work.) * a mock rust processor with a very stubbed-out implementation * bare bones interface between Rust library and C++ code * unit tests on Rust and integration tests on C++ side to test the linkage between the libraries. This should deliver a set of libraries that can be linked into our target applications. For ease of deployment, it may be best to make these static libraries, but I haven't made that decision at this point. --- common/core/desktop/.gitignore | 2 +- common/core/desktop/build.bat | 65 +++--- common/core/desktop/build.sh | 219 ++++++++++++++++++ common/core/desktop/doc/BUILDING.md | 110 +++++---- .../include/keyman/keyboardprocessor.h.in | 3 +- common/core/desktop/meson.build | 23 ++ .../core/desktop/src/km_kbp_keyboard_api.cpp | 4 + common/core/desktop/src/meson.build | 4 +- common/core/desktop/src/rust/Cargo.lock | 5 + common/core/desktop/src/rust/Cargo.toml | 7 + .../desktop/src/rust/rust_mock_processor.cpp | 79 +++++++ .../desktop/src/rust/rust_mock_processor.hpp | 53 +++++ common/core/desktop/src/rust/src/lib.rs | 123 ++++++++++ common/core/desktop/tests/meson.build | 3 +- .../desktop/tests/unit/kmnkbd/meson.build | 1 + .../core/desktop/tests/unit/kmx/meson.build | 1 + .../tests/unit/rust_mock/keyboard_api.cpp | 33 +++ .../desktop/tests/unit/rust_mock/meson.build | 20 ++ .../tests/unit/rust_mock/state_api.cpp | 206 ++++++++++++++++ 19 files changed, 883 insertions(+), 78 deletions(-) create mode 100644 common/core/desktop/build.sh create mode 100644 common/core/desktop/src/rust/Cargo.lock create mode 100644 common/core/desktop/src/rust/Cargo.toml create mode 100644 common/core/desktop/src/rust/rust_mock_processor.cpp create mode 100644 common/core/desktop/src/rust/rust_mock_processor.hpp create mode 100644 common/core/desktop/src/rust/src/lib.rs create mode 100644 common/core/desktop/tests/unit/rust_mock/keyboard_api.cpp create mode 100644 common/core/desktop/tests/unit/rust_mock/meson.build create mode 100644 common/core/desktop/tests/unit/rust_mock/state_api.cpp diff --git a/common/core/desktop/.gitignore b/common/core/desktop/.gitignore index cd78b2f40f..d4d94057ce 100644 --- a/common/core/desktop/.gitignore +++ b/common/core/desktop/.gitignore @@ -1,3 +1,3 @@ .vs/ -build*/ +build/ configure/ diff --git a/common/core/desktop/build.bat b/common/core/desktop/build.bat index a83d33a4c3..663415bf82 100644 --- a/common/core/desktop/build.bat +++ b/common/core/desktop/build.bat @@ -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,34 @@ 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" == "build" ( + echo === Calling meson build for Windows !ARCH! !BUILDTYPE! === + if exist build\!ARCH!\!BUILDTYPE! rd /s/q build\!ARCH!\!BUILDTYPE! + meson build\!ARCH!\!BUILDTYPE! --buildtype !BUILDTYPE! --werror || exit !errorlevel! -echo === Running tests === -rem Run test cases immediately as they are quick -meson test --print-errorlogs -if errorlevel 1 exit /b !errorlevel! + echo === Building Keyman Core for Windows !ARCH! !BUILDTYPE! === + cd build\!ARCH!\!BUILDTYPE! || exit !errorlevel! -cd .. + 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 +105,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 ---------------------------------- diff --git a/common/core/desktop/build.sh b/common/core/desktop/build.sh new file mode 100644 index 0000000000..fe62a84468 --- /dev/null +++ b/common/core/desktop/build.sh @@ -0,0 +1,219 @@ +#!/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]}")" +. "$(dirname "$THIS_SCRIPT")/../../../resources/build/build-utils.sh" +. "$(dirname "$THIS_SCRIPT")/../../../resources/shellHelperFunctions.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +display_usage() { + echo "usage: build.sh [build options] [targets]" + echo + echo "Build options:" + echo " --debug, -d Debug build" + echo + echo "Targets (all if not specified):" + 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 + echo "Rust libraries will be in: build/rust//" + echo "C++ libraries will be in: build///src" + echo "On Windows, will be 'x86' or 'x64'; elsewhere it is 'arch'" + exit 0 +} + +get_builder_OS + +THIS_DIR="$(dirname "$THIS_SCRIPT")" +CARGO_TARGET=--release +MESON_TARGET=release +HAS_TARGET=false +BUILD_RUST=false +BUILD_CPP=false +TESTS_RUST=false +TESTS_CPP=false +QUIET=false + +# Parse args +shopt -s nocasematch + + +while [[ $# -gt 0 ]] ; do + key="$1" + case $key in + --debug|-d) + CARGO_TARGET= + MESON_TARGET=debug + ;; + --help|-?) + display_usage + ;; + 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 + ;; + *) + fail "Invalid parameters. Use --help for help" + esac + shift +done + +if ! $HAS_TARGET; then + BUILD_RUST=true + BUILD_CPP=true + TESTS_RUST=true + TESTS_CPP=true +fi + + # "CLEAN: $CLEAN" \ + +displayInfo "" \ + "VERSION: $VERSION" \ + "TIER: $TIER" \ + "BUILD_RUST: $BUILD_RUST" \ + "BUILD_CPP: $BUILD_CPP" \ + "TESTS_RUST: $TESTS_RUST" \ + "TESTS_CPP: $TESTS_CPP" \ + "CARGO_TARGET: $CARGO_TARGET" \ + "MESON_TARGET: $MESON_TARGET" \ + "" + + +build_test_rust() { + local TARGETBASE="$1" + if [ -z ${2+x} ]; then local TARGET=""; else local TARGET="$2"; fi + local LIB="rust_mock_processor" + + 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 =======" + + # Library name on Windows vs *nix + [ $os_id == "win" ] && \ + local LIBN=$LIB.lib || \ + local LIBN=lib$LIB.a + + # Built library path for multi-arch (Windows) vs single (*nix) + [ -z $TARGET ] && \ + local TARGET_PATH="$THIS_DIR/build/rust/$TARGETBASE/$MESON_TARGET" || \ + local TARGET_PATH="$THIS_DIR/build/rust/$TARGETBASE/$TARGET/$MESON_TARGET" + + cargo build --target-dir="$THIS_DIR/build/rust/$TARGETBASE" $TARGET_FLAG $CARGO_TARGET + + local LIBS="$TARGET_PATH/$LIBN" # $(find "$TARGET_PATH" -name $LIBN) + if [ ! -f "$LIBS" ]; then die "could not find $LIBS after build"; fi + # Final output path is ./build/rust//debug|release/ + cp "$LIBS" "$THIS_DIR/build/rust/$TARGETBASE/$MESON_TARGET/$LIBN" + fi + + if $TESTS_RUST; then + echo_heading "======= Testing rust library for $TARGETBASE $TARGET =======" + cargo test --target-dir="$THIS_DIR/build/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 $BUILD_CPP; then + echo_heading "======= Building C++ library for $os_id =======" + meson build/arch/$MESON_TARGET --werror --buildtype $MESON_TARGET + cd build/arch/$MESON_TARGET + ninja + cd .. + fi + + if $TESTS_CPP; then + echo_heading "======= Testing C++ library for $os_id =======" + cd build/arch/$MESON_TARGET + meson test --print-errorlogs + cd .. + 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 diff --git a/common/core/desktop/doc/BUILDING.md b/common/core/desktop/doc/BUILDING.md index bb7ef01ce7..e562c73767 100644 --- a/common/core/desktop/doc/BUILDING.md +++ b/common/core/desktop/doc/BUILDING.md @@ -5,34 +5,82 @@ - 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 - 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: - - ### Windows -You can get the official installer from the official Python site: +You can get the official Python installer from the official Python site: -## 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. + +### 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. + +Then install meson: + +```bash +sudo apt install python3 python3-pip +python3 -m pip install meson +``` + +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 installer from the official Python site: + + +``` +brew install meson # if you haven't already installed via pip +``` + +If you want to rebuild keyboards for tests, you'll also need WINE: + +``` +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 @@ -69,32 +117,8 @@ For a debug build, pass `--buildtype debug` to meson. ## Note on kmcomp -kmcomp is the command-line compiler from Keyman Developer, available from 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. +kmcomp is the command-line compiler from Keyman Developer, available from + 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 diff --git a/common/core/desktop/include/keyman/keyboardprocessor.h.in b/common/core/desktop/include/keyman/keyboardprocessor.h.in index ce86adb5a0..430dc0b455 100644 --- a/common/core/desktop/include/keyman/keyboardprocessor.h.in +++ b/common/core/desktop/include/keyman/keyboardprocessor.h.in @@ -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 }; diff --git a/common/core/desktop/meson.build b/common/core/desktop/meson.build index 60768ca2eb..9cde85437c 100644 --- a/common/core/desktop/meson.build +++ b/common/core/desktop/meson.build @@ -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_source_dir(), 'build', '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') diff --git a/common/core/desktop/src/km_kbp_keyboard_api.cpp b/common/core/desktop/src/km_kbp_keyboard_api.cpp index 26948e72a2..8a2ef7b3ad 100644 --- a/common/core/desktop/src/km_kbp_keyboard_api.cpp +++ b/common/core/desktop/src/km_kbp_keyboard_api.cpp @@ -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(); } diff --git a/common/core/desktop/src/meson.build b/common/core/desktop/src/meson.build index 9bc326f680..52b10ee9fa 100644 --- a/common/core/desktop/src/meson.build +++ b/common/core/desktop/src/meson.build @@ -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 @@ -59,6 +59,7 @@ lib = library('kmnkbp0', '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', @@ -74,6 +75,7 @@ lib = library('kmnkbp0', 'utfcodec.cpp', cpp_args: defns + warns + flags, link_args: links, + dependencies: [rust_mock_processor], version: lib_version, include_directories: inc, install: true) diff --git a/common/core/desktop/src/rust/Cargo.lock b/common/core/desktop/src/rust/Cargo.lock new file mode 100644 index 0000000000..6e559e962d --- /dev/null +++ b/common/core/desktop/src/rust/Cargo.lock @@ -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" diff --git a/common/core/desktop/src/rust/Cargo.toml b/common/core/desktop/src/rust/Cargo.toml new file mode 100644 index 0000000000..294a63871c --- /dev/null +++ b/common/core/desktop/src/rust/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rust_mock_processor" +version = "0.1.0" + +[lib] +name = "rust_mock_processor" +crate-type = ["staticlib"] diff --git a/common/core/desktop/src/rust/rust_mock_processor.cpp b/common/core/desktop/src/rust/rust_mock_processor.cpp new file mode 100644 index 0000000000..6b37e259d3 --- /dev/null +++ b/common/core/desktop/src/rust/rust_mock_processor.cpp @@ -0,0 +1,79 @@ +/* + Copyright: © 2021 SIL International. + Description: This is an interface to a rust mock implementation. + TODO: Add a mecahnism 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 diff --git a/common/core/desktop/src/rust/rust_mock_processor.hpp b/common/core/desktop/src/rust/rust_mock_processor.hpp new file mode 100644 index 0000000000..03bbce5ab0 --- /dev/null +++ b/common/core/desktop/src/rust/rust_mock_processor.hpp @@ -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 +#include +#include + +#include "processor.hpp" +#include "option.hpp" + +namespace km { +namespace kbp +{ + class rust_mock_processor : public abstract_processor + { + std::unordered_map _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 diff --git a/common/core/desktop/src/rust/src/lib.rs b/common/core/desktop/src/rust/src/lib.rs new file mode 100644 index 0000000000..7dc8dbd548 --- /dev/null +++ b/common/core/desktop/src/rust/src/lib.rs @@ -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 allways 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)); + } +} \ No newline at end of file diff --git a/common/core/desktop/tests/meson.build b/common/core/desktop/tests/meson.build index f1f8f83e76..a8e6b427da 100644 --- a/common/core/desktop/tests/meson.build +++ b/common/core/desktop/tests/meson.build @@ -23,4 +23,5 @@ endif subdir('unit/json') subdir('unit/utftest') subdir('unit/kmnkbd') -subdir('unit/kmx') \ No newline at end of file +subdir('unit/kmx') +subdir('unit/rust_mock') \ No newline at end of file diff --git a/common/core/desktop/tests/unit/kmnkbd/meson.build b/common/core/desktop/tests/unit/kmnkbd/meson.build index 92aed00b17..08de6294f2 100644 --- a/common/core/desktop/tests/unit/kmnkbd/meson.build +++ b/common/core/desktop/tests/unit/kmnkbd/meson.build @@ -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) diff --git a/common/core/desktop/tests/unit/kmx/meson.build b/common/core/desktop/tests/unit/kmx/meson.build index 2c57275b86..36ea1d71c7 100644 --- a/common/core/desktop/tests/unit/kmx/meson.build +++ b/common/core/desktop/tests/unit/kmx/meson.build @@ -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:])'] diff --git a/common/core/desktop/tests/unit/rust_mock/keyboard_api.cpp b/common/core/desktop/tests/unit/rust_mock/keyboard_api.cpp new file mode 100644 index 0000000000..5d5b01e047 --- /dev/null +++ b/common/core/desktop/tests/unit/rust_mock/keyboard_api.cpp @@ -0,0 +1,33 @@ +/* + Copyright: © 2021 SIL International. + Description: Tests for the Keyboard API family of functions rust_mock +*/ +#include + +#include +#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; +} diff --git a/common/core/desktop/tests/unit/rust_mock/meson.build b/common/core/desktop/tests/unit/rust_mock/meson.build new file mode 100644 index 0000000000..c787cbc71b --- /dev/null +++ b/common/core/desktop/tests/unit/rust_mock/meson.build @@ -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 diff --git a/common/core/desktop/tests/unit/rust_mock/state_api.cpp b/common/core/desktop/tests/unit/rust_mock/state_api.cpp new file mode 100644 index 0000000000..97e0aafc2e --- /dev/null +++ b/common/core/desktop/tests/unit/rust_mock/state_api.cpp @@ -0,0 +1,206 @@ +/* + Copyright: © 2021 SIL International. + Description: Tests for the rust_mock interfaces. +*/ +#include +#include +#include +#include + +#include +#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 + }; + +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 +}; + +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 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)); +#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; +} From 3690cdf973c4178f2afed0cdbcfa494d303e70de Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 27 May 2021 11:25:15 +1000 Subject: [PATCH 02/24] chore(common): make build.sh executable --- common/core/desktop/build.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 common/core/desktop/build.sh diff --git a/common/core/desktop/build.sh b/common/core/desktop/build.sh old mode 100644 new mode 100755 From 3e0a8ffafc00d35577f125d0bd7738bef226b549 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 27 May 2021 11:45:38 +1000 Subject: [PATCH 03/24] chore(common): tweak build script for cross platform --- common/core/desktop/build.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/common/core/desktop/build.sh b/common/core/desktop/build.sh index fe62a84468..658f8a8862 100755 --- a/common/core/desktop/build.sh +++ b/common/core/desktop/build.sh @@ -112,7 +112,6 @@ displayInfo "" \ build_test_rust() { local TARGETBASE="$1" if [ -z ${2+x} ]; then local TARGET=""; else local TARGET="$2"; fi - local LIB="rust_mock_processor" if [ ! -z $TARGET ]; then local TARGET_FLAG=--target=$TARGET @@ -124,22 +123,23 @@ build_test_rust() { if $BUILD_RUST; then echo_heading "======= Building rust library for $TARGETBASE $TARGET =======" - # Library name on Windows vs *nix - [ $os_id == "win" ] && \ - local LIBN=$LIB.lib || \ - local LIBN=lib$LIB.a - # Built library path for multi-arch (Windows) vs single (*nix) - [ -z $TARGET ] && \ - local TARGET_PATH="$THIS_DIR/build/rust/$TARGETBASE/$MESON_TARGET" || \ - local TARGET_PATH="$THIS_DIR/build/rust/$TARGETBASE/$TARGET/$MESON_TARGET" cargo build --target-dir="$THIS_DIR/build/rust/$TARGETBASE" $TARGET_FLAG $CARGO_TARGET - local LIBS="$TARGET_PATH/$LIBN" # $(find "$TARGET_PATH" -name $LIBN) - if [ ! -f "$LIBS" ]; then die "could not find $LIBS after build"; fi # Final output path is ./build/rust//debug|release/ - cp "$LIBS" "$THIS_DIR/build/rust/$TARGETBASE/$MESON_TARGET/$LIBN" + 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="$THIS_DIR/build/rust/$TARGETBASE/$TARGET/$MESON_TARGET" + local TARGET_PATH="$THIS_DIR/build/rust/$TARGETBASE/$MESON_TARGET" + cp "$BUILT_PATH/$LIBNAME" "$TARGET_PATH/$LIBNAME" + fi fi if $TESTS_RUST; then @@ -184,14 +184,14 @@ build_linux_macos() { meson build/arch/$MESON_TARGET --werror --buildtype $MESON_TARGET cd build/arch/$MESON_TARGET ninja - cd .. + cd ../../.. fi if $TESTS_CPP; then echo_heading "======= Testing C++ library for $os_id =======" cd build/arch/$MESON_TARGET meson test --print-errorlogs - cd .. + cd ../../.. fi } From 73c71e01a36d81db5d7212b4a42c603bea809f47 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 27 May 2021 11:49:43 +1000 Subject: [PATCH 04/24] chore(common): update trigger definitions --- resources/build/trigger-definitions.inc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/build/trigger-definitions.inc.sh b/resources/build/trigger-definitions.inc.sh index 1610bc6bcc..380728ab37 100644 --- a/resources/build/trigger-definitions.inc.sh +++ b/resources/build/trigger-definitions.inc.sh @@ -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 From fdbc2a309a20032e1d029574bac0e5c1ab6c2d49 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 27 May 2021 15:57:10 +1000 Subject: [PATCH 05/24] chore(common): stub out tests to prevent build errors --- common/core/desktop/tests/unit/rust_mock/state_api.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/core/desktop/tests/unit/rust_mock/state_api.cpp b/common/core/desktop/tests/unit/rust_mock/state_api.cpp index 97e0aafc2e..d81f9d00f6 100644 --- a/common/core/desktop/tests/unit/rust_mock/state_api.cpp +++ b/common/core/desktop/tests/unit/rust_mock/state_api.cpp @@ -164,6 +164,11 @@ int main(int, char * []) 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')}}})); From 8103949bdc5ae06450a20cae37593d29f8d2fefa Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 28 May 2021 08:59:17 +1000 Subject: [PATCH 06/24] chore(linux): adjust linux build scripts for rust --- common/core/desktop/build.sh | 61 +++++++++++++++++++++++---------- common/core/desktop/meson.build | 2 +- linux/Makefile | 2 +- linux/scripts/build.sh | 22 ++++++------ linux/scripts/reconf.sh | 2 +- 5 files changed, 57 insertions(+), 32 deletions(-) diff --git a/common/core/desktop/build.sh b/common/core/desktop/build.sh index 658f8a8862..c8a7f07457 100755 --- a/common/core/desktop/build.sh +++ b/common/core/desktop/build.sh @@ -15,8 +15,10 @@ display_usage() { echo echo "Build options:" echo " --debug, -d Debug build" + echo " --target, -t Target path (linux,macos only, default build/)" echo echo "Targets (all 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" @@ -24,8 +26,8 @@ display_usage() { echo " tests-rust Run rust tests" echo " tests-cpp Run c++ and c++/rust integration tests" echo - echo "Rust libraries will be in: build/rust//" - echo "C++ libraries will be in: build///src" + echo "Rust libraries will be in: TARGETPATH/rust//" + echo "C++ libraries will be in: TARGETPATH///src" echo "On Windows, will be 'x86' or 'x64'; elsewhere it is 'arch'" exit 0 } @@ -36,16 +38,17 @@ THIS_DIR="$(dirname "$THIS_SCRIPT")" CARGO_TARGET=--release MESON_TARGET=release HAS_TARGET=false +CONFIGURE=false BUILD_RUST=false BUILD_CPP=false TESTS_RUST=false TESTS_CPP=false QUIET=false +TARGET_PATH="$THIS_DIR/build" # Parse args shopt -s nocasematch - while [[ $# -gt 0 ]] ; do key="$1" case $key in @@ -53,9 +56,20 @@ while [[ $# -gt 0 ]] ; do CARGO_TARGET= MESON_TARGET=debug ;; - --help|-?) - display_usage - ;; + --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 @@ -89,23 +103,26 @@ while [[ $# -gt 0 ]] ; do done if ! $HAS_TARGET; then + CONFIGURE=true BUILD_RUST=true BUILD_CPP=true TESTS_RUST=true TESTS_CPP=true fi - # "CLEAN: $CLEAN" \ +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" \ "CARGO_TARGET: $CARGO_TARGET" \ "MESON_TARGET: $MESON_TARGET" \ + "TARGET_PATH: $TARGET_PATH" \ "" @@ -125,9 +142,10 @@ build_test_rust() { # Built library path for multi-arch (Windows) vs single (*nix) - cargo build --target-dir="$THIS_DIR/build/rust/$TARGETBASE" $TARGET_FLAG $CARGO_TARGET + cargo build --target-dir="$TARGET_PATH/rust/$TARGETBASE" $TARGET_FLAG $CARGO_TARGET - # Final output path is ./build/rust//debug|release/ + # On Windows, final output path is ./build/rust///debug|release/ + # On other platforms, the final file is already in the right place (TARGET=="") if [ ! -z $TARGET ]; then local LIB="rust_mock_processor" @@ -136,15 +154,15 @@ build_test_rust() { local LIBNAME=$LIB.lib || \ local LIBNAME=lib$LIB.a - local BUILT_PATH="$THIS_DIR/build/rust/$TARGETBASE/$TARGET/$MESON_TARGET" - local TARGET_PATH="$THIS_DIR/build/rust/$TARGETBASE/$MESON_TARGET" - cp "$BUILT_PATH/$LIBNAME" "$TARGET_PATH/$LIBNAME" + 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="$THIS_DIR/build/rust/$TARGETBASE" $TARGET $CARGO_TARGET + cargo test --target-dir="$TARGET_PATH/rust/$TARGETBASE" $TARGET $CARGO_TARGET fi popd >/dev/null } @@ -175,23 +193,30 @@ build_windows() { } 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 + popd > /dev/null + fi + if $BUILD_CPP; then echo_heading "======= Building C++ library for $os_id =======" - meson build/arch/$MESON_TARGET --werror --buildtype $MESON_TARGET - cd build/arch/$MESON_TARGET + pushd $MESON_PATH > /dev/null ninja - cd ../../.. + popd > /dev/null fi if $TESTS_CPP; then echo_heading "======= Testing C++ library for $os_id =======" - cd build/arch/$MESON_TARGET + pushd $MESON_PATH > /dev/null meson test --print-errorlogs - cd ../../.. + popd > /dev/null fi } diff --git a/common/core/desktop/meson.build b/common/core/desktop/meson.build index 9cde85437c..498b467722 100644 --- a/common/core/desktop/meson.build +++ b/common/core/desktop/meson.build @@ -41,7 +41,7 @@ else endif endif -rust_path = join_paths(meson.current_source_dir(), 'build', 'rust', rust_platform, get_option('buildtype')) +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) diff --git a/linux/Makefile b/linux/Makefile index e1379b4bb7..5329d79380 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -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 diff --git a/linux/scripts/build.sh b/linux/scripts/build.sh index 850f07f409..f3608b0496 100755 --- a/linux/scripts/build.sh +++ b/linux/scripts/build.sh @@ -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 diff --git a/linux/scripts/reconf.sh b/linux/scripts/reconf.sh index 8ea015955d..a30199c40b 100755 --- a/linux/scripts/reconf.sh +++ b/linux/scripts/reconf.sh @@ -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 From 9107658b3e3a84400fd91d823960956eae1276ae Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 28 May 2021 09:37:41 +1000 Subject: [PATCH 07/24] fix(linux): adjust path for ninja --- linux/scripts/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/scripts/install.sh b/linux/scripts/install.sh index d9db4f4ec0..63fadbfe74 100755 --- a/linux/scripts/install.sh +++ b/linux/scripts/install.sh @@ -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 From 4d0c7d63950c89d4f44b4820e791cad509c3bb77 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 28 May 2021 09:38:53 +1000 Subject: [PATCH 08/24] fix(common): integer precision loss --- common/core/desktop/src/kmx/kmx_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/core/desktop/src/kmx/kmx_context.cpp b/common/core/desktop/src/kmx/kmx_context.cpp index ee391a6036..ffea32be4c 100644 --- a/common/core/desktop/src/kmx/kmx_context.cpp +++ b/common/core/desktop/src/kmx/kmx_context.cpp @@ -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)); From e8b5a32ace7ed41b9ec9161519071d5266281502 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 28 May 2021 09:54:09 +1000 Subject: [PATCH 09/24] chore(linux): update docs --- linux/README.md | 2 ++ linux/README.repo | 2 +- linux/build/agent/dependencies.config | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/linux/README.md b/linux/README.md index 12593c2878..29bea783ba 100644 --- a/linux/README.md +++ b/linux/README.md @@ -25,6 +25,8 @@ See [license information](./LICENSE.md) about licensing. python3-magic python3-numpy python3-pil python3-pip python3-qrcode \ python3-requests python3-requests-cache python3 python3-gi dconf-cli \ dconf-editor + # install rust + curl https://sh.rustup.rs -sSf | sh ``` ## Compiling from Command Line diff --git a/linux/README.repo b/linux/README.repo index c6f28a47c7..708cda84bd 100644 --- a/linux/README.repo +++ b/linux/README.repo @@ -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 diff --git a/linux/build/agent/dependencies.config b/linux/build/agent/dependencies.config index 6925cc72b8..7f9de598d2 100644 --- a/linux/build/agent/dependencies.config +++ b/linux/build/agent/dependencies.config @@ -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 rustc [xenial] any=libx11-dev From 3d2d31a71784aa3cf86c85331817c3099a0402c3 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 1 Jun 2021 20:42:03 +1000 Subject: [PATCH 10/24] chore(common): remove some warnings --- common/core/desktop/tests/unit/rust_mock/state_api.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/core/desktop/tests/unit/rust_mock/state_api.cpp b/common/core/desktop/tests/unit/rust_mock/state_api.cpp index d81f9d00f6..fddbe5d2da 100644 --- a/common/core/desktop/tests/unit/rust_mock/state_api.cpp +++ b/common/core/desktop/tests/unit/rust_mock/state_api.cpp @@ -33,6 +33,7 @@ namespace KM_KBP_OPTIONS_END }; +#if 0 constexpr char const *doc1_expected = u8"\ {\n\ \"$schema\" : \"keyman/keyboardprocessor/doc/introspection.schema\",\n\ @@ -78,6 +79,7 @@ constexpr km_kbp_option_item const expected_persist_opt = { 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) From 92350c2f493e7249f2244bd375bffadcf5b665dc Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 28 May 2021 15:37:17 +0200 Subject: [PATCH 11/24] feat(common): Update Jenkins dependencies for Rust --- linux/scripts/jenkins.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/scripts/jenkins.sh b/linux/scripts/jenkins.sh index cf08b38eec..fa035227d7 100755 --- a/linux/scripts/jenkins.sh +++ b/linux/scripts/jenkins.sh @@ -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-gi python3-magic python3-qrcode cargo build-essential do if ! dpkg -l | grep -q $p; then TOINSTALL="$TOINSTALL $p" From e89fe746d7f7ccfbb2d94c9177fa6749be249d3c Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 28 May 2021 15:38:15 +0200 Subject: [PATCH 12/24] fix(common): fix two Rust warnings --- common/core/desktop/src/rust/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/core/desktop/src/rust/src/lib.rs b/common/core/desktop/src/rust/src/lib.rs index 7dc8dbd548..4de07f3abd 100644 --- a/common/core/desktop/src/rust/src/lib.rs +++ b/common/core/desktop/src/rust/src/lib.rs @@ -108,7 +108,7 @@ */ #[no_mangle] -pub extern "C" fn rust_mock_process_event(vk: u16, modifier: u16) -> u32 { +pub extern "C" fn rust_mock_process_event(_vk: u16, _modifier: u16) -> u32 { return 0; //KM_KBP_STATUS_OK } @@ -120,4 +120,4 @@ mod tests { fn test_rust_mock_process_event() { assert_eq!(0, rust_mock_process_event(0, 0)); } -} \ No newline at end of file +} From b547f7d256fff203028ba4401c2b1825376bb409 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 28 May 2021 15:38:58 +0200 Subject: [PATCH 13/24] docs(common): Update build documentation --- common/core/desktop/doc/BUILDING.md | 48 ++++++++++++++++------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/common/core/desktop/doc/BUILDING.md b/common/core/desktop/doc/BUILDING.md index e562c73767..cf93a9e899 100644 --- a/common/core/desktop/doc/BUILDING.md +++ b/common/core/desktop/doc/BUILDING.md @@ -5,7 +5,7 @@ - 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 +- Rust from (or `cargo` package on Linux) - lib std::fs - kmcomp (for tests) -- must be added to path @@ -32,6 +32,19 @@ path. Otherwise, add the path where you extracted the kmcomp archive. ### Linux +#### Ubuntu and Debian + +You can install `meson` and Rust through the package manager: + +```bash +sudo apt update +sudo apt install meson cargo +``` + +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. @@ -42,6 +55,12 @@ sudo apt install python3 python3-pip python3 -m pip install meson ``` +Install Rust from . + +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: @@ -59,13 +78,13 @@ Place this in the same folder as you extracted kmcomp.exe, and You can get the official installer from the official Python site: -``` +```bash brew install meson # if you haven't already installed via pip ``` 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 ``` @@ -85,36 +104,21 @@ Place this in the same folder as you extracted kmcomp.exe, and ### Building 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` environement variable to the current Windows SDK version, if it cannot be automatically detected, e.g.: ```DOS set SDKVER=10.0.19041.0 ``` -To build: +### Building on all platforms -```DOS -build.bat all -``` - -### Building on Linux, macOS - -For all other platforms, in your source directory do the following: +On all other 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 From ef5df74f532232f9d56643a992de19f8c73112b8 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 28 May 2021 15:45:13 +0200 Subject: [PATCH 14/24] chore(linux): Update package dependencies for Rust infrastructure --- common/core/desktop/debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/core/desktop/debian/control b/common/core/desktop/debian/control index b629e3be02..5e929cc75f 100644 --- a/common/core/desktop/debian/control +++ b/common/core/desktop/debian/control @@ -8,8 +8,9 @@ Uploaders: Eberhard Beilharz , Build-Depends: debhelper (>= 11), - meson (>= 0.45), + meson (>= 0.50), 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 From 7a5a2b977426e45ed511efc21f7434766d38fe2d Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 28 May 2021 16:27:31 +0200 Subject: [PATCH 15/24] chore(linux): Update more dependencies --- linux/README.md | 4 +--- linux/build/agent/dependencies.config | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/linux/README.md b/linux/README.md index 29bea783ba..c5069ea490 100644 --- a/linux/README.md +++ b/linux/README.md @@ -24,9 +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 - # install rust - curl https://sh.rustup.rs -sSf | sh + dconf-editor cargo ``` ## Compiling from Command Line diff --git a/linux/build/agent/dependencies.config b/linux/build/agent/dependencies.config index 7f9de598d2..1a6909f30b 100644 --- a/linux/build/agent/dependencies.config +++ b/linux/build/agent/dependencies.config @@ -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 rustc +any=git autotools-dev build-essential dh-autoreconf libibus-1.0-dev flex bison meson python3 python3-pip cargo [xenial] any=libx11-dev From dec8fba55e12af03348932e2550a3a728a4565e3 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 28 May 2021 16:47:09 +0200 Subject: [PATCH 16/24] chore(linux): Downgrade meson for package building Ubuntu 18.04 Bionic only contains Meson 0.45. The build seems to work with that version, so we partially revert the previous change that set the minimum version to 0.50. --- common/core/desktop/debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/core/desktop/debian/control b/common/core/desktop/debian/control index 5e929cc75f..37e195ecf5 100644 --- a/common/core/desktop/debian/control +++ b/common/core/desktop/debian/control @@ -8,7 +8,7 @@ Uploaders: Eberhard Beilharz , Build-Depends: debhelper (>= 11), - meson (>= 0.50), + meson (>= 0.45), ninja-build, cargo, Standards-Version: 4.5.1 From 54a62a05d735462fcbe6c1a8a3f4b2d38f5f187c Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 1 Jun 2021 17:50:15 +0200 Subject: [PATCH 17/24] feat(linux): Adjust package build for build.sh script This change makes the necessary adjustments so that the package build works with the new `build.sh` script. We no longer can rely on the automatisms of debhelper. This change also adds a install target to `build.sh`, and copies some files from the Keyman root directory to the desktop directory because when package building we only have access to the files in common/core/desktop. Along the same lines it removes embedding `build-utils.h` from `build.sh`. Instead we set the version and tier locally. --- common/core/desktop/build.sh | 60 +++++++++++++++++++++++++++---- common/core/desktop/debian/rules | 15 ++++++++ common/core/desktop/gettier.sh | 7 ++++ common/core/desktop/getversion.sh | 0 linux/scripts/dist.sh | 3 ++ 5 files changed, 78 insertions(+), 7 deletions(-) create mode 100755 common/core/desktop/gettier.sh mode change 100644 => 100755 common/core/desktop/getversion.sh diff --git a/common/core/desktop/build.sh b/common/core/desktop/build.sh index c8a7f07457..479fa53dd4 100755 --- a/common/core/desktop/build.sh +++ b/common/core/desktop/build.sh @@ -6,18 +6,27 @@ 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]}")" -. "$(dirname "$THIS_SCRIPT")/../../../resources/build/build-utils.sh" -. "$(dirname "$THIS_SCRIPT")/../../../resources/shellHelperFunctions.sh" +# when building packages we pass in SCRIPTS_DIR because we can't access anything outside of +# the `desktop` directory +SCRIPTS_DIR=${SCRIPTS_DIR:-$(dirname "$THIS_SCRIPT")/../../../resources} +. "${SCRIPTS_DIR}/shellHelperFunctions.sh" ## END STANDARD BUILD SCRIPT INCLUDE +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]" + 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 if not specified):" + 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" @@ -25,6 +34,9 @@ display_usage() { 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//" echo "C++ libraries will be in: TARGETPATH///src" @@ -34,7 +46,6 @@ display_usage() { get_builder_OS -THIS_DIR="$(dirname "$THIS_SCRIPT")" CARGO_TARGET=--release MESON_TARGET=release HAS_TARGET=false @@ -43,8 +54,11 @@ 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 @@ -66,7 +80,7 @@ while [[ $# -gt 0 ]] ; do configure) HAS_TARGET=true CONFIGURE=true - # meson depends on the rust build in order + # meson depends on the rust build in order # to do its configure step, for now anyway BUILD_RUST=true ;; @@ -96,6 +110,24 @@ while [[ $# -gt 0 ]] ; do 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 @@ -120,6 +152,8 @@ displayInfo "" \ "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" \ @@ -201,7 +235,7 @@ build_linux_macos() { if $CONFIGURE; then echo_heading "======= Configuring C++ library for $os_id =======" pushd $THIS_DIR > /dev/null - meson $MESON_PATH --werror --buildtype $MESON_TARGET + meson $MESON_PATH --werror --buildtype $MESON_TARGET $ADDITIONAL_ARGS popd > /dev/null fi @@ -218,6 +252,18 @@ build_linux_macos() { 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() { diff --git a/common/core/desktop/debian/rules b/common/core/desktop/debian/rules index 3d056fc65d..81c9a7efac 100755 --- a/common/core/desktop/debian/rules +++ b/common/core/desktop/debian/rules @@ -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 diff --git a/common/core/desktop/gettier.sh b/common/core/desktop/gettier.sh new file mode 100755 index 0000000000..c298092649 --- /dev/null +++ b/common/core/desktop/gettier.sh @@ -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 diff --git a/common/core/desktop/getversion.sh b/common/core/desktop/getversion.sh old mode 100644 new mode 100755 diff --git a/linux/scripts/dist.sh b/linux/scripts/dist.sh index b65f840726..36a237a705 100755 --- a/linux/scripts/dist.sh +++ b/linux/scripts/dist.sh @@ -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 From 4dbd0bec796b5e02c8a7d7146e3eca451576634d Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 2 Jun 2021 08:24:15 +1000 Subject: [PATCH 18/24] chore: Apply suggestions from code review --- common/core/desktop/doc/BUILDING.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/core/desktop/doc/BUILDING.md b/common/core/desktop/doc/BUILDING.md index cf93a9e899..845238c4e3 100644 --- a/common/core/desktop/doc/BUILDING.md +++ b/common/core/desktop/doc/BUILDING.md @@ -102,9 +102,9 @@ Place this in the same folder as you extracted kmcomp.exe, and ## Building -### Building on Windows +### Prerequisite on Windows -On Windows 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 @@ -113,7 +113,7 @@ set SDKVER=10.0.19041.0 ### Building on all platforms -On all other platforms, use `build.sh`. +On all platforms, use `build.sh`. ```bash ./build.sh --debug @@ -125,4 +125,3 @@ kmcomp is the command-line compiler from Keyman Developer, available from 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. - From b63e5439773796afe0931aaa692f1033d2b3cf93 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 2 Jun 2021 08:33:32 +1000 Subject: [PATCH 19/24] chore: document Linux package rules --- common/core/desktop/.gitignore | 5 +++++ common/core/desktop/build.sh | 14 +++++++++++--- resources/shellHelperFunctions.sh | 12 +++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/common/core/desktop/.gitignore b/common/core/desktop/.gitignore index d4d94057ce..b9b2e49a3c 100644 --- a/common/core/desktop/.gitignore +++ b/common/core/desktop/.gitignore @@ -1,3 +1,8 @@ .vs/ build/ configure/ + +# These files may be copied here during Linux package builds +TIER.md +VERSION.md +shellHelperFunctions.sh diff --git a/common/core/desktop/build.sh b/common/core/desktop/build.sh index 479fa53dd4..13f9405e55 100755 --- a/common/core/desktop/build.sh +++ b/common/core/desktop/build.sh @@ -6,11 +6,19 @@ 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]}")" -# when building packages we pass in SCRIPTS_DIR because we can't access anything outside of -# the `desktop` directory +# 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" -## END STANDARD BUILD SCRIPT INCLUDE THIS_DIR="$(dirname "$THIS_SCRIPT")" diff --git a/resources/shellHelperFunctions.sh b/resources/shellHelperFunctions.sh index 5d78bed831..49b296df3e 100755 --- a/resources/shellHelperFunctions.sh +++ b/resources/shellHelperFunctions.sh @@ -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: From 4a09dd3b480f10764a5ca35a7a73ea72c4a0d2b2 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 1 Jun 2021 14:57:18 +1000 Subject: [PATCH 20/24] feat(windows): add common core libraries and includes --- common/core/desktop/build.bat | 11 +++++- common/core/desktop/build_cargo.bat | 41 ++++++++++++++++++++ windows/src/engine/keyman32/Keyman32.vcxproj | 12 +++++- windows/src/engine/keyman32/Makefile | 14 ++++++- windows/src/engine/keyman64/keyman64.vcxproj | 12 +++++- 5 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 common/core/desktop/build_cargo.bat diff --git a/common/core/desktop/build.bat b/common/core/desktop/build.bat index 663415bf82..fdcc18a7e6 100644 --- a/common/core/desktop/build.bat +++ b/common/core/desktop/build.bat @@ -70,10 +70,19 @@ cd %KEYMAN_ROOT%\common\core\desktop set BUILDTYPE=%2 +if "%3" == "--static" ( + set STATIC_LIBRARY=--default-library static + shift +) else ( + set STATIC_LIBRARY= +) + +echo "Is static build = !STATIC_LIBRARY! (%3)" + 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! --buildtype !BUILDTYPE! --werror || exit !errorlevel! + 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! diff --git a/common/core/desktop/build_cargo.bat b/common/core/desktop/build_cargo.bat new file mode 100644 index 0000000000..b0e78b29ba --- /dev/null +++ b/common/core/desktop/build_cargo.bat @@ -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///debug|release/ +:: 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 + diff --git a/windows/src/engine/keyman32/Keyman32.vcxproj b/windows/src/engine/keyman32/Keyman32.vcxproj index ac082fe0f4..7753a3adf5 100644 --- a/windows/src/engine/keyman32/Keyman32.vcxproj +++ b/windows/src/engine/keyman32/Keyman32.vcxproj @@ -53,6 +53,14 @@ + + $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath) + $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(IncludePath) + + + $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath) + $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(IncludePath) + NDEBUG;%(PreprocessorDefinitions) @@ -90,7 +98,7 @@ /verbose:lib /section:.SHARDATA,rws %(AdditionalOptions) - psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(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) ./Keyman32.dll true keyman32.def @@ -152,7 +160,7 @@ /verbose:lib /section:.SHARDATA,rws %(AdditionalOptions) - psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(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) ./Keyman32.dll true keyman32.def diff --git a/windows/src/engine/keyman32/Makefile b/windows/src/engine/keyman32/Makefile index b57852a6cb..69acda9bbb 100644 --- a/windows/src/engine/keyman32/Makefile +++ b/windows/src/engine/keyman32/Makefile @@ -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,16 @@ 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 + !include ..\..\Target.mak diff --git a/windows/src/engine/keyman64/keyman64.vcxproj b/windows/src/engine/keyman64/keyman64.vcxproj index e4466b60b0..a753b2aaf3 100644 --- a/windows/src/engine/keyman64/keyman64.vcxproj +++ b/windows/src/engine/keyman64/keyman64.vcxproj @@ -81,6 +81,14 @@ + + $(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x64\$(Configuration);$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\include;$(IncludePath) + + + $(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x64\$(Configuration);$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(ProjectDir)..\..\..\..\common\core\desktop\build\x64\$(Configuration)\include;$(IncludePath) + NDEBUG;%(PreprocessorDefinitions) @@ -119,7 +127,7 @@ /verbose:lib /section:.SHARDATA,rws %(AdditionalOptions) - psapi.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;libcmt.lib;%(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) ./Keyman64.dll true C:\Program Files\Microsoft SDKs\Windows\v7.0\Lib\x64;$(VCInstallDir)lib\amd64;$(VCInstallDir)lib;%(AdditionalLibraryDirectories) @@ -181,7 +189,7 @@ /verbose:lib /section:.SHARDATA,rws %(AdditionalOptions) - psapi.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;libcmt.lib;%(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) ./Keyman64.dll true C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib\x64;$(VCInstallDir)lib\amd64;$(VCInstallDir)lib;%(AdditionalLibraryDirectories) From 1dbad94d789c868c535de333232809c3f2cd0a1a Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 2 Jun 2021 07:57:22 +1000 Subject: [PATCH 21/24] fix(windows): makefile paths --- windows/src/engine/keyman32/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/windows/src/engine/keyman32/Makefile b/windows/src/engine/keyman32/Makefile index 69acda9bbb..6dfe14b9bf 100644 --- a/windows/src/engine/keyman32/Makefile +++ b/windows/src/engine/keyman32/Makefile @@ -44,5 +44,6 @@ 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 From 8ca0fc792858dde74fb8e29bf8f2529cefc4fbe3 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 2 Jun 2021 08:22:03 +1000 Subject: [PATCH 22/24] fix(windows): fix common include paths --- windows/src/engine/keyman32/Keyman32.vcxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/windows/src/engine/keyman32/Keyman32.vcxproj b/windows/src/engine/keyman32/Keyman32.vcxproj index 7753a3adf5..874c0e8eb8 100644 --- a/windows/src/engine/keyman32/Keyman32.vcxproj +++ b/windows/src/engine/keyman32/Keyman32.vcxproj @@ -55,11 +55,11 @@ $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath) - $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(IncludePath) + $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(IncludePath) $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath) - $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(IncludePath) + $(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(IncludePath) From 32b4f54d58093e08ac1fdb2b26ece591cd441418 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 3 Jun 2021 11:22:11 +1000 Subject: [PATCH 23/24] Update BUILDING.md --- common/core/desktop/doc/BUILDING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/core/desktop/doc/BUILDING.md b/common/core/desktop/doc/BUILDING.md index 845238c4e3..72dc537d30 100644 --- a/common/core/desktop/doc/BUILDING.md +++ b/common/core/desktop/doc/BUILDING.md @@ -111,6 +111,12 @@ Windows SDK version, if it cannot be automatically detected, e.g.: set SDKVER=10.0.19041.0 ``` +You'll also need to install x86 support for Rust: + +```DOS +rustup target add i686-pc-windows-msvc +``` + ### Building on all platforms On all platforms, use `build.sh`. From d0834e1f393288ff3af19d44723ffd64998a8946 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 7 Jun 2021 08:44:15 +1000 Subject: [PATCH 24/24] chore: address review comments --- common/core/desktop/doc/BUILDING.md | 23 +++++++- common/core/desktop/src/meson.build | 58 +++++++++---------- .../desktop/src/rust/rust_mock_processor.cpp | 2 +- common/core/desktop/src/rust/src/lib.rs | 2 +- 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/common/core/desktop/doc/BUILDING.md b/common/core/desktop/doc/BUILDING.md index 72dc537d30..777fa4ce5e 100644 --- a/common/core/desktop/doc/BUILDING.md +++ b/common/core/desktop/doc/BUILDING.md @@ -30,6 +30,16 @@ The search path can be edited through System settings / Advanced system settings 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: + + +Run the command: +```bash +rustup target add i686-pc-windows-msvc +``` + ### Linux #### Ubuntu and Debian @@ -39,6 +49,7 @@ 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. @@ -55,7 +66,11 @@ sudo apt install python3 python3-pip python3 -m pip install meson ``` -Install Rust from . +Install Rust from , then: + +```bash +rustup target add i686-pc-windows-msvc +``` You'll also need the `kmcomp` wrapper - see below. @@ -75,11 +90,15 @@ Place this in the same folder as you extracted kmcomp.exe, and ### macOS -You can get the official installer from the official Python site: +You can get the official Python installer from the official Python site: +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: diff --git a/common/core/desktop/src/meson.build b/common/core/desktop/src/meson.build index 52b10ee9fa..15af5a494f 100644 --- a/common/core/desktop/src/meson.build +++ b/common/core/desktop/src/meson.build @@ -49,36 +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', + '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) + '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) diff --git a/common/core/desktop/src/rust/rust_mock_processor.cpp b/common/core/desktop/src/rust/rust_mock_processor.cpp index 6b37e259d3..bbe269c0a2 100644 --- a/common/core/desktop/src/rust/rust_mock_processor.cpp +++ b/common/core/desktop/src/rust/rust_mock_processor.cpp @@ -1,7 +1,7 @@ /* Copyright: © 2021 SIL International. Description: This is an interface to a rust mock implementation. - TODO: Add a mecahnism to trigger output of PERSIST_OPT & + TODO: Add a mechanism to trigger output of PERSIST_OPT & RESET_OPT actions items, options support and context matching. Authors: Marc Durdin */ diff --git a/common/core/desktop/src/rust/src/lib.rs b/common/core/desktop/src/rust/src/lib.rs index 4de07f3abd..59ff1634e6 100644 --- a/common/core/desktop/src/rust/src/lib.rs +++ b/common/core/desktop/src/rust/src/lib.rs @@ -47,7 +47,7 @@ try { - // At the start of every process_event allways clear the action_items + // At the start of every process_event always clear the action_items state->actions().clear(); switch (vk)