mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-12 03:45:34 +00:00
Merge branch 'feat/common/kmx-plus-osk-embed-support' into feat/developer/reserve-space-for-kmxplus
This commit is contained in:
commit
3e1c8ed04e
79 changed files with 1057 additions and 7069 deletions
22
.github/workflows/deb-packaging.yml
vendored
22
.github/workflows/deb-packaging.yml
vendored
|
|
@ -31,6 +31,7 @@ env:
|
|||
STATUS_CONTEXT: 'Ubuntu Packaging'
|
||||
DEBFULLNAME: 'Keyman GHA packager'
|
||||
DEBEMAIL: 'support@keyman.com'
|
||||
_builder_timings: false
|
||||
|
||||
jobs:
|
||||
sourcepackage:
|
||||
|
|
@ -135,7 +136,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
dist: [jammy, noble, plucky]
|
||||
dist: [jammy, noble, plucky, questing]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
|
@ -161,7 +162,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
dist: [questing]
|
||||
dist: [devel]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
|
@ -185,6 +186,23 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Free disk space
|
||||
run: |
|
||||
# Free disk space by removing some large directories that we don't use (#15171)
|
||||
# see https://dev.to/mathio/squeezing-disk-space-from-github-actions-runners-an-engineers-guide-3pjg
|
||||
|
||||
# Remove Android SDKs (frees 12 GB on Ubuntu 24.04)
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
|
||||
# Remove Haskell (GHC) (frees 6.4 GB)
|
||||
sudo rm -rf /usr/local/.ghcup
|
||||
|
||||
# Remove CodeQL and other toolcaches (frees 5.8 GB)
|
||||
sudo rm -rf /opt/hostedtoolcache
|
||||
|
||||
# Remove .NET SDKs (frees 4.0 GB)
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
|
||||
- name: Download Source Artifacts
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
with:
|
||||
|
|
|
|||
35
HISTORY.md
35
HISTORY.md
|
|
@ -1,5 +1,40 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 19.0.163 alpha 2025-11-17
|
||||
|
||||
* chore(linux): Update debian changelog (#15133)
|
||||
* fix(windows): handle exceptions when walking stack in exception handler (#15150)
|
||||
* fix(windows): disable OutputDebugString from DllMain (#15151)
|
||||
* change(windows): include map2pdb generation for relevant Delphi projects (#14799)
|
||||
* change(windows): use circular buffer for logging (#15163)
|
||||
* fix(windows): handle forward slash for KEYMAN_ROOT env var (#15156)
|
||||
* maint(mac): handle hdiutil detach failure correctly in make-km-dmg.sh (#15176)
|
||||
|
||||
## 19.0.162 alpha 2025-11-14
|
||||
|
||||
* chore(linux): use `devel` for next Ubuntu release (#15157)
|
||||
* maint(resources): add build timing report to builder (#15114)
|
||||
* maint(resources): add `builder_launch` function (#15129)
|
||||
* fix(web): improve determination of default path (#15159)
|
||||
* maint(linux): free disk space before running autopkgtests (#15172)
|
||||
|
||||
## 19.0.161 alpha 2025-11-13
|
||||
|
||||
* docs(android): Document disclaimer of Keyman NOT containing adware/spyware (#15136)
|
||||
|
||||
## 19.0.160 alpha 2025-11-12
|
||||
|
||||
* fix(android): Change Alert Dialog instead of Toast if package missing keyboard and lexical-model files (#15098)
|
||||
* chore(linux): add support for Ubuntu 26.04 LTS Resolute (#15137)
|
||||
|
||||
## 19.0.159 alpha 2025-11-11
|
||||
|
||||
* maint(core): fix option defaults for Meson >= 1.1 (#15131)
|
||||
|
||||
## 19.0.158 alpha 2025-11-10
|
||||
|
||||
* fix(web): add unit tests for DeadkeyTracker and fix a few bugs (#15113)
|
||||
|
||||
## 19.0.157 alpha 2025-11-06
|
||||
|
||||
* chore(common): Consolidate platformtest.js keyboard to `/common/test/keyboards/` (#15034)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
19.0.158
|
||||
19.0.164
|
||||
|
|
@ -85,7 +85,8 @@ public class PackageActivity extends BaseActivity implements
|
|||
if (pkgTarget.equals(PackageProcessor.PP_TARGET_LEXICAL_MODELS)) {
|
||||
kmpProcessor = new LexicalModelPackageProcessor(resourceRoot);
|
||||
} else if (!pkgTarget.equals(PackageProcessor.PP_TARGET_KEYBOARDS)) {
|
||||
showErrorToast(getString(R.string.no_targets_to_install));
|
||||
// Not using showErrorToast to avoid cluttering Sentry with noise
|
||||
showErrorDialog(context, pkgId, getString(R.string.no_targets_to_install));
|
||||
return;
|
||||
}
|
||||
tempPackagePath = kmpProcessor.unzipKMP(kmpFile);
|
||||
|
|
|
|||
28
android/docs/help/about/adware.md
Normal file
28
android/docs/help/about/adware.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
title: Does Keyman include adware or spyware?
|
||||
---
|
||||
|
||||
No!
|
||||
|
||||
We never have and never will include adware or spyware components.
|
||||
|
||||
When [enabling Keyman as a system keyboard](../start/enabling-system-keyboard), Android displays the following warning, which is the same message that is displayed for any keyboard app that is installed onto an Android device.
|
||||
|
||||

|
||||
|
||||
> Attention: This input method may be able to collect all the text you
|
||||
> type, including personal data like passwords and credit card numbers.
|
||||
> It comes from the app Keyman. Use this input method? Cancel / OK
|
||||
|
||||
The Keyman app does not record the keystrokes you type and does not send keystrokes off-device, unlike many other keyboard apps. All predictive text suggestions are entirely on your device.
|
||||
|
||||
Keyman is an open source application, and you are most welcome to inspect the source code at https://github.com/keymanapp/keyman.
|
||||
|
||||
## Checking for Updates
|
||||
|
||||
Keyman does contact the keyman.com website periodically to check for updates for the keyboards and predictive text dictionaries you have installed.
|
||||
In this process, the only information communicated is the current version of Keyman and the version of the keyboards and dictionaries.
|
||||
|
||||
## Crash Report Information
|
||||
|
||||
When enabled, the Keyman app will send crash reporting information to [Sentry](https://keyman.sentry.io). No personally identifiable information or keyboard strokes are recorded. This can be disabled in the Keyman [settings menu](../basic/config/).
|
||||
|
|
@ -5,5 +5,6 @@ title: About Keyman for Android
|
|||
* [Welcome to Keyman](welcome)
|
||||
* [What's New](whatsnew)
|
||||
* [System Requirements](system-requirements)
|
||||
* [Does Keyman include adware or spyware?](adware)
|
||||
* [Data Privacy Policy](privacy)
|
||||
* [Version History](history)
|
||||
BIN
android/docs/help/android_images/attention.png
Normal file
BIN
android/docs/help/android_images/attention.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
|
|
@ -6,6 +6,7 @@ title: Keyman for Android 19.0 Help
|
|||
* [Welcome to Keyman](about/welcome)
|
||||
* [What's New](about/whatsnew)
|
||||
* [System Requirements](about/system-requirements)
|
||||
* [Does Keyman include adware or spyware?](about/adware)
|
||||
* [Data Privacy Policy](about/privacy)
|
||||
* [Version History](about/history)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
|||
builder_describe \
|
||||
"Keyman common third party Delphi components" \
|
||||
clean configure build test reset \
|
||||
:cef4delphi :dcpcrypt :jwa :sentry :tds2dbg
|
||||
:cef4delphi :dcpcrypt :jwa :sentry
|
||||
|
||||
builder_parse "$@"
|
||||
builder_run_child_actions clean configure build test
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ uses
|
|||
Winapi.Windows,
|
||||
|
||||
jwaimagehlp,
|
||||
jwantstatus,
|
||||
jwawinbase,
|
||||
|
||||
sentry;
|
||||
|
||||
|
|
@ -229,20 +231,41 @@ var
|
|||
Skip: Integer;
|
||||
LastMask: WORD;
|
||||
begin
|
||||
// Floating point state may be broken here, so let's mask it out and continue
|
||||
// We'll restore state afterwards
|
||||
LastMask := Get8087CW;
|
||||
Set8087CW_Threadsafe($1332);
|
||||
try
|
||||
if (ExceptionInfo.ExceptionRecord.ExceptionCode <> EXCEPTION_ACCESS_VIOLATION) and
|
||||
(ExceptionInfo.ExceptionRecord.ExceptionCode <> EXCEPTION_ILLEGAL_INSTRUCTION) and
|
||||
(ExceptionInfo.ExceptionRecord.ExceptionCode <> EXCEPTION_PRIV_INSTRUCTION) and
|
||||
(ExceptionInfo.ExceptionRecord.ExceptionCode <> EXCEPTION_POSSIBLE_DEADLOCK) and
|
||||
(ExceptionInfo.ExceptionRecord.ExceptionCode <> EXCEPTION_IN_PAGE_ERROR) and
|
||||
(ExceptionInfo.ExceptionRecord.ExceptionCode <> EXCEPTION_STACK_OVERFLOW) and
|
||||
(ExceptionInfo.ExceptionRecord.ExceptionCode <> STATUS_INVALID_PARAMETER) and
|
||||
(ExceptionInfo.ExceptionRecord.ExceptionCode <> cDelphiException) then
|
||||
begin
|
||||
// These are the most common exceptions we wish to catch; we won't get
|
||||
// call stacks for any other exception types, but we will still log
|
||||
// important exceptions
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
if ExceptionInfo.ExceptionRecord.ExceptionCode = cDelphiException
|
||||
then Skip := DELPHI_FRAMES_TO_SKIP
|
||||
else Skip := 0;
|
||||
CaptureStackTraceForException(ExceptionInfo.ExceptionRecord.ExceptionAddress, ExceptionInfo, Skip);
|
||||
// Floating point state may be broken here, so let's mask it out and continue
|
||||
// We'll restore state afterwards
|
||||
LastMask := Get8087CW;
|
||||
Set8087CW_Threadsafe($1332);
|
||||
|
||||
// Restore FP state
|
||||
Set8087CW_Threadsafe(LastMask);
|
||||
if ExceptionInfo.ExceptionRecord.ExceptionCode = cDelphiException
|
||||
then Skip := DELPHI_FRAMES_TO_SKIP
|
||||
else Skip := 0;
|
||||
CaptureStackTraceForException(ExceptionInfo.ExceptionRecord.ExceptionAddress, ExceptionInfo, Skip);
|
||||
|
||||
Result := 0; //EXCEPTION_CONTINUE_SEARCH;
|
||||
// Restore FP state
|
||||
Set8087CW_Threadsafe(LastMask);
|
||||
|
||||
Result := 0; //EXCEPTION_CONTINUE_SEARCH;
|
||||
except
|
||||
// Silently handle errors here because we can't do anything with them;
|
||||
// we'll just get no stack
|
||||
Result := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TSentryClient.Create(AOptions: TSentryClientOptions; const ALogger: string; AFlags: TSentryClientFlags);
|
||||
|
|
|
|||
|
|
@ -24,10 +24,8 @@ function do_test() {
|
|||
delphi_msbuild SentryClientTest.dproj "//p:Platform=Win32"
|
||||
delphi_msbuild SentryClientVclTest.dproj "//p:Platform=Win32"
|
||||
|
||||
sentrytool_delphiprep "$WIN32_TARGET_PATH/SentryClientTest.exe" -dpr SentryClientTest.dpr
|
||||
sentrytool_delphiprep "$WIN32_TARGET_PATH/SentryClientVclTest.exe" -dpr SentryClientVclTest.dpr
|
||||
tds2dbg "$WIN32_TARGET_PATH/SentryClientTest.exe"
|
||||
tds2dbg "$WIN32_TARGET_PATH/SentryClientVclTest.exe"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/SentryClientTest.map" "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/SentryClientVclTest.map" "$WIN32_TARGET"
|
||||
|
||||
sentry-cli upload-dif -p keyman-windows --wait --include-sources .
|
||||
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
Keyman Third Party Package Readme: Tds2Dbg
|
||||
===========================================
|
||||
|
||||
Name: Tds2Dbg
|
||||
Purpose: Tds2Dbg converts .tds to .dbg files
|
||||
Source: https://sourceforge.net/projects/tds2dbg/
|
||||
Version: 2014-12-22
|
||||
License: ISC (MIT compatible)
|
||||
Updated for: N/A
|
||||
Documentation: https://sourceforge.net/projects/tds2dbg/
|
||||
Download location: https://sourceforge.net/projects/tds2dbg/
|
||||
Licensed For: Unlimited developers
|
||||
Include Paths: N/A
|
||||
|
||||
|
||||
Installation notes
|
||||
------------------
|
||||
|
||||
Download from site above.
|
||||
|
||||
Build notes
|
||||
-----------
|
||||
|
||||
tds2dbg is used for building .dbg files from .tds files so that Delphi
|
||||
projects can be debugged in WinDbg/Visual Studio and with dump files.
|
||||
|
||||
This project builds with Borland C++ 5.5 and not other compilers;
|
||||
while it may build successfully with other compilers, there appear to
|
||||
be alignment issues. Hence, the executable is included in the repository
|
||||
to avoid requiring another build tool.
|
||||
|
||||
License - ISC
|
||||
-------------
|
||||
|
||||
Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice, this permission notice and the following disclaimer
|
||||
appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
1
common/windows/delphi/ext/tds2dbg/.gitignore
vendored
1
common/windows/delphi/ext/tds2dbg/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
/bin/
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
Get the free Borland C++ Builder 5.5 from
|
||||
https://downloads.embarcadero.com/free/c_builder
|
||||
|
||||
Ensure that the location of bcc32.exe is in your path
|
||||
and type "make.exe" in a command prompt with the
|
||||
current working directory set to the directory
|
||||
holder the sources for tds2dbg.
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
tds2dbg 0.2.0
|
||||
|
||||
* Added support for conversion of public and static symbols.
|
||||
* Corrected padding and alignment.
|
||||
* Preliminary support for conversion of types. Still incomplete.
|
||||
* Can now convert a non-PE CodeView NB09 file to a PE CodeView file.
|
||||
* Can now generate bare CodeView files (i.e. no PE header).
|
||||
|
||||
tds2dbg 0.1.0
|
||||
|
||||
* Initial version
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice, this permission notice and the following disclaimer
|
||||
appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
info:
|
||||
echo The following builds require Borland C++ compiler to be installed and in the path; see Readme.txt for details.
|
||||
echo So, the tds2dbg.bin is kept in the repo in order to make builds simpler
|
||||
|
||||
BCC55DIR=c:\borland\bcc55
|
||||
|
||||
tds2dbg.exe: main.cpp tds2dbg.cpp fileutils.cpp log.cpp
|
||||
# $(CL) /Fe$< /EHsc $**
|
||||
path $(BCC55DIR)\bin;$(PATH)
|
||||
$(BCC55DIR)\bin\bcc32 -y -v -L$(BCC55DIR)\Lib -I$(BCC55DIR)\Include -e$< $**
|
||||
|
||||
test.exe: testa.cpp
|
||||
# $(CL) /Fe$< /EHsc $**
|
||||
$(BCC55DIR)\bin\bcc32 -y -v -M -L$(BCC55DIR)\Lib -I$(BCC55DIR)\Include -e$< $**
|
||||
|
||||
clean:
|
||||
-del /Q tds2dbg.obj fileutils.obj log.obj main.obj tds2dbg.tds
|
||||
-del /Q testa.obj test.exe test.tds test.dbg
|
||||
-rmdir /S /Q html
|
||||
|
||||
doc:
|
||||
doxygen tds2dbg.dcf
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
NAME
|
||||
|
||||
tds2dbg - Borland TDS debug symbol file to Microsft DBG debug symbol file
|
||||
converter.
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
tds2dbg [ [-h|--help] | [-t|--types] [-s|--statics] [--] program.exe ]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
tds2dbg will read the Borland debug symbol file associated with the
|
||||
Microsoft Windows executable program.exe (program.tds) and create a
|
||||
corresponding Microsoft DBG debug symbol file (program.dbg). Additionally,
|
||||
it will modify a flag in program.exe to signal that debug symbols are
|
||||
available externally to the executable.
|
||||
|
||||
The dbg files can be used with, say, windbg available from the
|
||||
Microsoft Debugging Tools at the Microsoft Windows Hardware Developer
|
||||
Central (http://www.microsoft.com/whdc).
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h, --help Prints a help text. Running tds2dbg without arguments
|
||||
will do the same.
|
||||
-v, --verbose Each occurence of this option increases verbosity.
|
||||
-q, --quiet Operate silently.
|
||||
-t, --types Convert types (incomplete feature).
|
||||
-s, --statics Treat statics as publics.
|
||||
-b, --barecv Write bare code view data. No PE header is added.
|
||||
|
||||
KNOWN ISSUES
|
||||
|
||||
tds2dbg is currently only able to insert source code references, public
|
||||
symbols, and static symbols into the generated DBG file. Debug information
|
||||
on local variables is partially generated, but no debugger seems to be
|
||||
able to use this information. Additionally, conversion of types is not
|
||||
fully supported and is only done on request (the -t option).
|
||||
|
||||
VERSION
|
||||
|
||||
This is the documentation for tds2dbg version 0.2.0
|
||||
|
||||
AUTHOR
|
||||
|
||||
Copyright (C) 2009-2010, Bjarne Juul Pasgaard
|
||||
|
||||
LICENSE
|
||||
|
||||
Copyright (C) 2009-2010, Bjarne Juul Pasgaard
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice, this permission notice and the following disclaimer
|
||||
appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
. "${THIS_SCRIPT%/*}/../../../../../resources/build/builder-full.inc.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
|
||||
# TODO: move this out of ext and into tools
|
||||
|
||||
builder_describe "tds2dbg component" clean configure build test
|
||||
builder_parse "$@"
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh"
|
||||
|
||||
builder_describe_outputs \
|
||||
configure:project /resources/build/win/delphi_environment_generated.inc.sh \
|
||||
build:project "$WIN32_TARGET_PATH/tds2dbg.exe"
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
function do_build() {
|
||||
mkdir -p "$WIN32_TARGET_PATH"
|
||||
cp tds2dbg.bin "$WIN32_TARGET_PATH/tds2dbg.exe"
|
||||
|
||||
mkdir -p "$KEYMAN_ROOT/common/windows/bin/tools"
|
||||
cp "$WIN32_TARGET_PATH/tds2dbg.exe" "$KEYMAN_ROOT/common/windows/bin/tools/"
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
builder_run_action configure:project configure_windows_build_environment
|
||||
builder_run_action build:project do_build
|
||||
# builder_run_action test:project do_test
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
// Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice, this permission notice and the following disclaimer
|
||||
// appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/// @file fileutils.cpp File utilities
|
||||
|
||||
#include "fileutils.h"
|
||||
|
||||
FileWrapper::FileWrapper(FILE* f) : m_f(f)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int
|
||||
FileWrapper::tell() const {
|
||||
return ftell(m_f);
|
||||
}
|
||||
|
||||
void
|
||||
FileWrapper::seek(unsigned int pos) throw(std::runtime_error) {
|
||||
if(fseek(m_f,pos,SEEK_SET)) {
|
||||
throw std::runtime_error("Failed to set read/write position");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileWrapper::skip(unsigned int amount) throw(std::runtime_error) {
|
||||
if(fseek(m_f,amount,SEEK_CUR)) {
|
||||
throw std::runtime_error("Failed to advance read/write position");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileWrapper::write1bLpfName(const std::string& name) throw(std::runtime_error)
|
||||
{
|
||||
unsigned char len = (unsigned char) (name.length());
|
||||
|
||||
if((sizeof len) != fwrite(&len,1,(sizeof len),m_f)) {
|
||||
throw std::runtime_error("Failed to write length field of string");
|
||||
}
|
||||
if((unsigned int)(len+1) != fwrite(name.c_str(),1,len+1,m_f)) {
|
||||
throw std::runtime_error("Failed to write string contents");
|
||||
}
|
||||
}
|
||||
|
||||
RecordReader::RecordReader(FileWrapper& tdsFile, unsigned int recSz) :
|
||||
m_tdsFile(tdsFile)
|
||||
{
|
||||
m_recPos = tdsFile.tell();
|
||||
m_endPos = m_recPos + recSz;
|
||||
}
|
||||
|
||||
RecordWriter::~RecordWriter()
|
||||
{
|
||||
WriteQCont::iterator it = m_writeQ.begin();
|
||||
while(m_writeQ.end() != it) {
|
||||
delete *it++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecordWriter::commit(FileWrapper& f) const throw(std::runtime_error)
|
||||
{
|
||||
WriteQCont::const_iterator it = m_writeQ.begin();
|
||||
while(m_writeQ.end() != it) {
|
||||
(*it++)->commit(f);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
RecordWriter::length() const
|
||||
{
|
||||
unsigned int len = 0;
|
||||
WriteQCont::const_iterator it = m_writeQ.begin();
|
||||
while(m_writeQ.end() != it) {
|
||||
len += (*it++)->length();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
RecordWriter::write1bLpfName(const std::string& name)
|
||||
{
|
||||
unsigned char len = (unsigned char) (name.length());
|
||||
|
||||
this->write(len);
|
||||
this->write(*(name.c_str()),len+1);
|
||||
}
|
||||
|
||||
RecordWriter::WriteQueueElement::~WriteQueueElement()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int
|
||||
RecordWriter::CopiedData::length() const
|
||||
{
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
void
|
||||
RecordWriter::CopiedData::commit(FileWrapper& f) const throw(std::runtime_error)
|
||||
{
|
||||
f.write(m_data.front(),m_data.size());
|
||||
}
|
||||
|
||||
RecordWriter::WriteQueueElement*
|
||||
RecordWriter::CopiedData::append(const unsigned char* src, unsigned int len)
|
||||
{
|
||||
m_data.reserve(m_data.size()+len);
|
||||
while(len--) {
|
||||
m_data.push_back(*src++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
RecordWriter::ReferencedData::
|
||||
ReferencedData(const unsigned char* src, unsigned int len)
|
||||
: m_src(src), m_len(len)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int
|
||||
RecordWriter::ReferencedData::length() const
|
||||
{
|
||||
return m_len;
|
||||
}
|
||||
|
||||
void
|
||||
RecordWriter::ReferencedData::commit(FileWrapper& f) const
|
||||
throw(std::runtime_error)
|
||||
{
|
||||
f.write(*m_src,m_len);
|
||||
}
|
||||
|
||||
RecordWriter::WriteQueueElement*
|
||||
RecordWriter::ReferencedData::append(const unsigned char* src, unsigned int len)
|
||||
{
|
||||
CopiedData* c = new CopiedData();
|
||||
c->append(src,len);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
// Local Variables:
|
||||
// mode:c++
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
|
|
@ -1,564 +0,0 @@
|
|||
// Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice, this permission notice and the following disclaimer
|
||||
// appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/// @file fileutils.h File utilities
|
||||
|
||||
#ifndef FILEUTILS_H
|
||||
#define FILEUTILS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
/// @brief Base class for file access wrappers.
|
||||
class FileWrapper {
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param f The file stream being wrapped. Ownership not transferred.
|
||||
FileWrapper(FILE* f);
|
||||
|
||||
/// @brief Returns the current read/write position.
|
||||
/// @return The current write position.
|
||||
unsigned int tell() const;
|
||||
|
||||
/// @brief Sets the current read/write position.
|
||||
///
|
||||
/// @param pos The new (absolute) write position.
|
||||
///
|
||||
/// @throw runtime_error If an error occured.
|
||||
void seek(unsigned int pos) throw(std::runtime_error);
|
||||
|
||||
/// @brief Skips a number of bytes from the input stream.
|
||||
///
|
||||
/// @param amount The number of bytes to skip.
|
||||
///
|
||||
/// @throw runtime_error If an error occured.
|
||||
void skip(unsigned int amount) throw(std::runtime_error);
|
||||
|
||||
/// @brief Reads a sequence of structures from the current read
|
||||
/// position and throws an exception if end of file is
|
||||
/// reached prematurely.
|
||||
///
|
||||
/// @param dst The 1st structure to hold the data read in.
|
||||
/// @param num The number of structures to read.
|
||||
///
|
||||
/// @tparam The class of the structures to read.
|
||||
///
|
||||
/// @throw runtime_error If not all bytes could be read.
|
||||
template <class T>
|
||||
void read(T& dst, unsigned int num = 1) throw(std::runtime_error) {
|
||||
unsigned int n = fread(&dst,1,num*sizeof(T),m_f);
|
||||
if(num*sizeof(T) != n) {
|
||||
throw std::runtime_error("Unexpected end of file");
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Attempts to reads a sequence of structures from the
|
||||
/// current read position.
|
||||
///
|
||||
/// @param dst The 1st structure to hold the data read in.
|
||||
/// @param num The number of structures to read.
|
||||
///
|
||||
/// @return The number of bytes actually read.
|
||||
///
|
||||
/// @tparam The class of the structures to read.
|
||||
template <class T>
|
||||
unsigned int tryRead(T& dst, unsigned int num = 1) {
|
||||
return fread(&dst,1,num*sizeof(T),m_f);
|
||||
}
|
||||
|
||||
/// @brief Writes a sequence of bytes to the current write position.
|
||||
///
|
||||
/// @param src Reference to the 1st structure to be written.
|
||||
/// @param num The number of instances to write.
|
||||
///
|
||||
/// @return The number of bytes actually written.
|
||||
///
|
||||
/// @tparam T Class of the structure to write.
|
||||
///
|
||||
/// @throw runtime_error If an error occured.
|
||||
template <class T>
|
||||
unsigned int
|
||||
write(const T& src, unsigned int num = 1) throw(std::runtime_error) {
|
||||
unsigned int n = fwrite(&src,1,num*sizeof(T),m_f);
|
||||
if(n != num*sizeof(T)) {
|
||||
throw std::runtime_error("Write error in write()");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/// @brief Writes multiple copies of the same structure starting from the
|
||||
/// current write position.
|
||||
///
|
||||
/// @param src Reference to the structure to be written.
|
||||
/// @param num The number of copies to write.
|
||||
///
|
||||
/// @return The number of bytes actually written.
|
||||
///
|
||||
/// @tparam T Class of the structure to write.
|
||||
///
|
||||
/// @throw runtime_error If an error occured.
|
||||
template <class T>
|
||||
unsigned int
|
||||
writeRep(const T& src, unsigned int num = 1) throw(std::runtime_error);
|
||||
|
||||
/// @brief Writes a (1-byte) length-prefixed name to the current
|
||||
/// write position.
|
||||
///
|
||||
/// @param name The name to write.
|
||||
///
|
||||
/// @throw runtime_error If an error occured.
|
||||
void write1bLpfName(const std::string& name) throw(std::runtime_error);
|
||||
|
||||
protected:
|
||||
|
||||
FILE* m_f; ///< The file stream.
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
unsigned int
|
||||
FileWrapper::writeRep(const T& src, unsigned int num)
|
||||
throw(std::runtime_error)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
while(num--) {
|
||||
unsigned int m = fwrite(&src,1,sizeof(T),m_f);
|
||||
if(sizeof(T) != m) {
|
||||
throw std::runtime_error("Write error in writeRep()");
|
||||
}
|
||||
n += m;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/// @brief Reads a record sequentially from a file while keeping track
|
||||
/// of the number of bytes available.
|
||||
class RecordReader {
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param tdsFile The file to read from.
|
||||
/// @param recSz The number of bytes in the record.
|
||||
RecordReader(FileWrapper& tdsFile, unsigned int recSz);
|
||||
|
||||
/// @brief Returns the current read position.
|
||||
///
|
||||
/// @return The current (absolute) read position.
|
||||
unsigned int tell() {
|
||||
return m_tdsFile.tell();
|
||||
}
|
||||
|
||||
/// @brief Determines whether an end-of-record condition is met.
|
||||
///
|
||||
/// @retval true if all bytes have been read.
|
||||
/// @retval false otherwise.
|
||||
bool eor() const {
|
||||
return (m_tdsFile.tell() >= m_endPos);
|
||||
}
|
||||
|
||||
/// @brief Sets the current absolute read position.
|
||||
///
|
||||
/// @param pos The new (absolute) read position.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
void seek(unsigned int pos) throw(std::runtime_error) {
|
||||
m_tdsFile.seek(pos);
|
||||
}
|
||||
|
||||
/// @brief Skips a number of bytes from the input stream.
|
||||
///
|
||||
/// @param amount The number of bytes to skip.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
void skip(unsigned int amount) throw(std::runtime_error) {
|
||||
m_tdsFile.skip(amount);
|
||||
}
|
||||
|
||||
/// @brief Reads a sequence of structures from the current read
|
||||
/// position in the TDS file.
|
||||
///
|
||||
/// @param dst The 1st structure to hold the data read in.
|
||||
/// @param num The number of structures to read.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
template <class T>
|
||||
void read(T& dst, unsigned int num = 1) throw(std::runtime_error) {
|
||||
m_tdsFile.read(dst,num);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
FileWrapper& m_tdsFile; ///< The file to read from.
|
||||
|
||||
unsigned int m_recPos; ///< The position of the current record.
|
||||
|
||||
unsigned int m_endPos; ///< The position after the end of the record list.
|
||||
|
||||
};
|
||||
|
||||
/// @brief Registers data for later writing to a file while counting
|
||||
/// the number of bytes to be written.
|
||||
class RecordWriter {
|
||||
public:
|
||||
|
||||
/// @brief Destructor.
|
||||
~RecordWriter();
|
||||
|
||||
/// @brief Commits the data registered to a file at the current write
|
||||
/// position of the file.
|
||||
///
|
||||
/// @param file The file to write to.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
void commit(FileWrapper& f) const throw(std::runtime_error);
|
||||
|
||||
/// @brief Returns the number of bytes registered for later writing.
|
||||
///
|
||||
/// @return The number of bytes registered.
|
||||
unsigned int length() const;
|
||||
|
||||
/// @brief Appends a sequence of structures to the tail of the
|
||||
/// write queue.
|
||||
///
|
||||
/// The data provided is copied into the internal write queue.
|
||||
///
|
||||
/// @param dst The 1st structure that holds the data to be written.
|
||||
/// @param num The number of structures to write.
|
||||
///
|
||||
/// @return The number of bytes written.
|
||||
template <class T>
|
||||
unsigned int write(const T& src, unsigned int num = 1) {
|
||||
unsigned int n = sizeof(T)*num;
|
||||
WriteQueueElement* e;
|
||||
|
||||
if(0 == m_writeQ.size()) {
|
||||
e = new CopiedData();
|
||||
m_writeQ.push_back(e);
|
||||
}
|
||||
|
||||
e = m_writeQ.back()->append(reinterpret_cast<const unsigned char*>(&src),n);
|
||||
if(e) {
|
||||
// New element created, append it to the queue.
|
||||
m_writeQ.push_back(e);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/// @brief Writes multiple copies of the same structure starting from the
|
||||
/// current write position.
|
||||
///
|
||||
/// @param src Reference to the structure to be written.
|
||||
/// @param num The number of copies to write.
|
||||
///
|
||||
/// @return The number of bytes actually written.
|
||||
///
|
||||
/// @tparam T Class of the structure to write.
|
||||
template <class T>
|
||||
unsigned int writeRep(const T& src, unsigned int num = 1) {
|
||||
unsigned int n = 0;
|
||||
while(num--) {
|
||||
n+= this->write(src);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/// @brief Appends a sequence of structures to the tail of the
|
||||
/// write queue.
|
||||
///
|
||||
/// This menthod appends a reference to the data to the write
|
||||
/// queue. The data provided is not copied.
|
||||
///
|
||||
/// @param dst The 1st structure that holds the data to be written.
|
||||
/// @param num The number of structures to write.
|
||||
///
|
||||
/// @return The number of bytes written.
|
||||
template <class T>
|
||||
unsigned int delayedWrite(const T& src, unsigned int num = 1) {
|
||||
unsigned int n = sizeof(T)*num;
|
||||
m_writeQ.
|
||||
push_back(new
|
||||
ReferencedData(reinterpret_cast<unsigned char*>(&src),n));
|
||||
return n;
|
||||
}
|
||||
|
||||
/// @brief Appends a (1-byte) length-prefixed name to the write queue.
|
||||
///
|
||||
/// @param name The name to write.
|
||||
void write1bLpfName(const std::string& name);
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Base class for write queue data.
|
||||
class WriteQueueElement
|
||||
{
|
||||
public:
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~WriteQueueElement();
|
||||
|
||||
/// @brief Returns the number of bytes registered within this element.
|
||||
///
|
||||
/// @return The number of bytes registered within this element.
|
||||
virtual unsigned int length() const = 0;
|
||||
|
||||
/// @brief Commits the data in this element to the current write
|
||||
/// position of a file.
|
||||
///
|
||||
/// @param f The file to write to.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
virtual void commit(FileWrapper& f) const throw(std::runtime_error) = 0;
|
||||
|
||||
/// @brief Appends a copy of a sequence of bytes to the current
|
||||
/// element.
|
||||
///
|
||||
/// @param src The first byte to copy.
|
||||
/// @param len The number of bytes to copy.
|
||||
///
|
||||
/// @return 0 if the bytes were appended to the current element, or
|
||||
/// a pointer to a new element that received the copied bytes.
|
||||
virtual
|
||||
WriteQueueElement* append(const unsigned char* src, unsigned int len) = 0;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Data copied into the write queue.
|
||||
class CopiedData : public WriteQueueElement
|
||||
{
|
||||
public:
|
||||
|
||||
// Overridden base class method.
|
||||
unsigned int length() const;
|
||||
|
||||
// Overridden base class method.
|
||||
void commit(FileWrapper& f) const throw(std::runtime_error);
|
||||
|
||||
// Overridden base class method.
|
||||
WriteQueueElement* append(const unsigned char* src, unsigned int len);
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<unsigned char> m_data;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Data referenced from the write queue.
|
||||
class ReferencedData : public WriteQueueElement
|
||||
{
|
||||
public:
|
||||
|
||||
// Overridden base class method.
|
||||
unsigned int length() const;
|
||||
|
||||
// Overridden base class method.
|
||||
void commit(FileWrapper& f) const throw(std::runtime_error);
|
||||
|
||||
// Overridden base class method.
|
||||
WriteQueueElement* append(const unsigned char* src, unsigned int len);
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param src The first byte to reference.
|
||||
/// @param len The number of subsequent bytes to reference.
|
||||
ReferencedData(const unsigned char* src, unsigned int len);
|
||||
|
||||
protected:
|
||||
|
||||
const unsigned char* m_src; ///< The first byte referenced.
|
||||
unsigned int m_len; ///< The number of bytes referenced.
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Container underlying the internal write queue.
|
||||
typedef std::vector<WriteQueueElement*> WriteQCont;
|
||||
|
||||
/// @brief The internal write queue.
|
||||
WriteQCont m_writeQ;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Postpones writing of a record until committed.
|
||||
///
|
||||
/// @note It is important to create an instance of this class before writing
|
||||
/// any records that should follow it (in file order).
|
||||
///
|
||||
/// @tparam R The record structure.
|
||||
template <class R>
|
||||
class PpRecordWriter {
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param dbgFile The DBG file to write to.
|
||||
/// @param rec The record to be written when committed to.
|
||||
PpRecordWriter(FileWrapper& dbgFile, R& rec) :
|
||||
m_dbgFile(dbgFile), m_rec(rec), m_len(0)
|
||||
{
|
||||
m_recPos = dbgFile.tell();
|
||||
dbgFile.skip(sizeof(R));
|
||||
}
|
||||
|
||||
/// @brief Commits to the record.
|
||||
///
|
||||
/// This method will write out the record.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
void commit() throw(std::runtime_error) {
|
||||
unsigned int oldPos = m_dbgFile.tell();
|
||||
m_dbgFile.seek(m_recPos);
|
||||
m_len = m_dbgFile.write(m_rec);
|
||||
m_dbgFile.seek(oldPos);
|
||||
}
|
||||
|
||||
/// @brief Returns the number of bytes written.
|
||||
/// @return The number of bytes written.
|
||||
unsigned int length() const {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief The DBG file to write to.
|
||||
FileWrapper& m_dbgFile;
|
||||
|
||||
/// @breif The record to write.
|
||||
R& m_rec;
|
||||
|
||||
/// @brief File position of the record.
|
||||
unsigned int m_recPos;
|
||||
|
||||
/// @brief Number of bytes written.
|
||||
unsigned int m_len;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Postpones writing of a header with a length field to be
|
||||
/// computed until committed.
|
||||
///
|
||||
/// @tparam H The header structure.
|
||||
/// @tparam L The type of the length field.
|
||||
template <class H, class L>
|
||||
class HeaderWithLen {
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param hdr The header to be written when committed to.
|
||||
/// Must remain available during the entire lifetime of the
|
||||
/// object created.
|
||||
/// @param lenFld The length field to update. Must remaining available
|
||||
/// during the entire lifetime of the object created.
|
||||
HeaderWithLen(H& hdr, L& lenFld) : m_hdr(hdr), m_lenFld(lenFld)
|
||||
{
|
||||
}
|
||||
|
||||
/// @brief Writes the header and the data registered by a RecordWriter.
|
||||
///
|
||||
/// This method will write out the header with an updated length field
|
||||
/// as well as the data registered by the RecordWriter.
|
||||
/// The length field will be computed as the size of the header, plus the
|
||||
/// size of the data written by the RecordWriter, minus the size of the
|
||||
/// length field itself.
|
||||
///
|
||||
/// @param f The file to write to.
|
||||
/// @param w The record writer that was used to write the data committed to.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
void
|
||||
commit(FileWrapper& f, const RecordWriter& w) throw(std::runtime_error){
|
||||
m_lenFld = sizeof(H) + w.length()-sizeof(L);
|
||||
f.write(m_hdr);
|
||||
w.commit(f);
|
||||
}
|
||||
|
||||
/// @brief Returns the number of bytes (to be) written by the record writer
|
||||
/// and the header writer itself.
|
||||
///
|
||||
/// @return The number of bytes (to be) written.
|
||||
unsigned int length(const RecordWriter& w) const {
|
||||
return sizeof(H) + w.length();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief The header to write.
|
||||
H& m_hdr;
|
||||
|
||||
/// @brief The length field to update.
|
||||
L& m_lenFld;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Writes a sequence of bytes from one file object to another.
|
||||
///
|
||||
/// @param dst Destination file object.
|
||||
/// @param src Source file object.
|
||||
/// @param amount Number of bytes to copy.
|
||||
///
|
||||
/// @tparam D Class of the destination object.
|
||||
/// @tparam S Class of the source object.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
template <class D, class S>
|
||||
void
|
||||
copyFileContent(D& dst, S& src, unsigned int amount = 1)
|
||||
throw(std::runtime_error)
|
||||
{
|
||||
unsigned char buf[512];
|
||||
unsigned int toRead = (sizeof buf);
|
||||
while(amount) {
|
||||
if(toRead>amount) {
|
||||
toRead = amount;
|
||||
}
|
||||
src.read(buf[0],toRead);
|
||||
amount -= toRead;
|
||||
dst.write(buf[0],toRead);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Appends the contents of one file to another.
|
||||
///
|
||||
/// @param dst Destination file object.
|
||||
/// @param src Source file object.
|
||||
///
|
||||
/// @tparam D Class of the destination object.
|
||||
/// @tparam S Class of the source object.
|
||||
///
|
||||
/// @throw runtime_error In case of errors.
|
||||
template <class D, class S>
|
||||
void
|
||||
copyFile(D& dst, S& src) throw(std::runtime_error)
|
||||
{
|
||||
unsigned char buf[512];
|
||||
unsigned int bytesRead;
|
||||
do {
|
||||
bytesRead = src.tryRead(buf[0],(sizeof buf));
|
||||
dst.write(buf[0],bytesRead);
|
||||
} while((sizeof buf) == bytesRead);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode:c++
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice, this permission notice and the following disclaimer
|
||||
// appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/// @file log.cpp Log utilitites
|
||||
|
||||
#include "log.h"
|
||||
|
||||
std::ostream& Log::operator()(unsigned int verbosity)
|
||||
{
|
||||
if(verbosity<m_verbosity) {
|
||||
return std::cout;
|
||||
} else {
|
||||
return m_nullStream;
|
||||
}
|
||||
}
|
||||
|
||||
Log::NullStreamBuf::NullStreamBuf()
|
||||
{
|
||||
}
|
||||
|
||||
Log& mylog()
|
||||
{
|
||||
static Log _log;
|
||||
return _log;
|
||||
}
|
||||
|
||||
|
||||
// Local Variables:
|
||||
// mode:c++
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
// Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice, this permission notice and the following disclaimer
|
||||
// appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/// @file log.h Log utilities
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/// @brief Logger class.
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
Log() : m_verbosity(0), m_nullStream(&m_nullStreamBuf) {}
|
||||
|
||||
/// @brief Sets the level of verbosity
|
||||
///
|
||||
/// @param verbosity New level of verbosity. 0 means silence.
|
||||
void setVerbosity(unsigned int verbosity) { m_verbosity = verbosity; }
|
||||
|
||||
/// @brief Returns a reference to a stream handling the requested level
|
||||
/// of verbosity.
|
||||
///
|
||||
/// @param verbosity The requested level of verbosity.
|
||||
std::ostream& operator()(unsigned int verbosity = 0);
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Helper class implementing a dummy stream buffer that
|
||||
/// discards everything sent to it.
|
||||
///
|
||||
/// @ingroup HMILoggingFeatures
|
||||
class NullStreamBuf : public std::streambuf
|
||||
{
|
||||
public:
|
||||
|
||||
/// @brief Constructor
|
||||
NullStreamBuf();
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief The current level of verbosity.
|
||||
unsigned int m_verbosity;
|
||||
|
||||
/// @brief Supporting stream buffer for m_nullStream.
|
||||
NullStreamBuf m_nullStreamBuf;
|
||||
|
||||
/// @brief Internal stream used as a null-stream that discards
|
||||
/// everything streamed to it.
|
||||
std::ostream m_nullStream;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Accesser for the global Log instance.
|
||||
///
|
||||
/// @return Reference to the global log.
|
||||
Log& mylog();
|
||||
|
||||
#endif LOG_H
|
||||
|
||||
// Local Variables:
|
||||
// mode:c++
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
// Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice, this permission notice and the following disclaimer
|
||||
// appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "tds2dbg.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <locale>
|
||||
|
||||
void printUsage(const char* argv0)
|
||||
{
|
||||
std::cerr
|
||||
<< "Usage: " << argv0
|
||||
<< " [-h|--help] [-t|--types] [-s|--statics] [--] exefilenamewithextension\n"
|
||||
"Options:\n"
|
||||
" -h, --help Prints this message\n"
|
||||
" -v, --verbose Increase verbosity\n"
|
||||
" -q, --quiet Operate silently\n"
|
||||
" -t, --types Convert types (incomplete feature)\n"
|
||||
" -s, --statics Treat statics as publics\n"
|
||||
" -b, --barecv Write bare code view data\n"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int argNo = 1;
|
||||
unsigned int verbosity = 1;
|
||||
bool convertTypes = false;
|
||||
bool staticsAsPublics = false;
|
||||
bool bareCodeView = false;
|
||||
|
||||
while(argc > 1) {
|
||||
char* a = argv[argNo];
|
||||
if('-' != *a || 0==strcmp("--",a)) {
|
||||
break;
|
||||
} else if(0==strcmp("-h",a) || 0==strcmp("--help",a)) {
|
||||
printUsage(argv[0]);
|
||||
return 0;
|
||||
} else if(0==strcmp("--verbose",a) || 0==strcmp("-v",a)) {
|
||||
if(verbosity) ++verbosity;
|
||||
} else if(0==strcmp("--quiet",a) || 0==strcmp("-q",a)) {
|
||||
verbosity = 0;
|
||||
} else if(0==strcmp("--types",a) || 0==strcmp("-t",a)) {
|
||||
convertTypes = true;
|
||||
} else if(0==strcmp("--statics",a) || 0==strcmp("-s",a)) {
|
||||
staticsAsPublics = true;
|
||||
} else if(0==strcmp("--barecv",a) || 0==strcmp("-b",a)) {
|
||||
bareCodeView = true;
|
||||
} else {
|
||||
std::cerr << "Unknown option " << a << std::endl;
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
--argc;
|
||||
++argNo;
|
||||
}
|
||||
|
||||
if(2 != argc) {
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string exeFile(argv[argNo]);
|
||||
std::string::size_type dotP = exeFile.rfind('.');
|
||||
if(std::string::npos == dotP) {
|
||||
std::cerr
|
||||
<< "Argument exe file name must be specified with extension"
|
||||
<< std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::string tdsFile(exeFile.substr(0,dotP+1));
|
||||
std::string dbgFile(tdsFile);
|
||||
|
||||
const std::ctype<char>& ctf =
|
||||
std::use_facet<std::ctype<char> >(std::locale());
|
||||
std::string::size_type ep = dotP;
|
||||
while(exeFile.length() != ep) {
|
||||
exeFile[ep] = ctf.tolower(exeFile[ep]);
|
||||
++ep;
|
||||
}
|
||||
|
||||
std::string ext(exeFile.substr(dotP+1));
|
||||
|
||||
if(!ext.compare("tds") || !ext.compare("dbg")) {
|
||||
std::cerr
|
||||
<< "Executable file cannot have extension .tds or .dbg"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
tdsFile.append("tds");
|
||||
dbgFile.append("dbg");
|
||||
|
||||
return tds2dbg(exeFile.c_str(),tdsFile.c_str(),dbgFile.c_str(),
|
||||
verbosity,convertTypes,staticsAsPublics,bareCodeView);
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode:c++
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (c) 2009-2010, Bjarne Juul Pasgaard
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice, this permission notice and the following disclaimer
|
||||
// appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef TDS2DBGH
|
||||
#define TDS2DBGH
|
||||
|
||||
/// @brief Converts an exe and a tds file to a dbg file.
|
||||
///
|
||||
/// @param exeFileName Name of EXE file.
|
||||
/// @param tdsFileName Name of TDS file.
|
||||
/// @param dbgFileName Name of DBG file.
|
||||
/// @param verbosity Verbosity level. 0 means silence.
|
||||
/// @param doConvTypes Should types be converted?
|
||||
/// @param staticsAsPublics Treat statics as publics?
|
||||
/// @param bareCodeView Write bare code view (no header).
|
||||
///
|
||||
/// @todo doConvTypes == true is incomplete.
|
||||
int tds2dbg(const char* exeFileName,
|
||||
const char* tdsFileName,
|
||||
const char* dbgFileName,
|
||||
unsigned int verbosity,
|
||||
bool doConvTypes,
|
||||
bool staticsAsPublics,
|
||||
bool bareCodeView);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.1000
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tds2dbg", "tds2dbg.vcxproj", "{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Debug|x64.Build.0 = Debug|x64
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Release|x64.ActiveCfg = Release|x64
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Release|x64.Build.0 = Release|x64
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {50FB6E2C-4FEF-4828-A315-1017276BF47A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{40BFECE3-7FC0-4649-A3DC-E017FF84C75B}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="fileutils.cpp" />
|
||||
<ClCompile Include="log.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="tds2dbg.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="fileutils.h" />
|
||||
<ClInclude Include="log.h" />
|
||||
<ClInclude Include="tds2dbg.h" />
|
||||
<ClInclude Include="tdscvstructs.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="tds2dbg.bin" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="fileutils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tds2dbg.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="fileutils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tds2dbg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tdscvstructs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="tds2dbg.bin">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,27 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
static int a = 1;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
(void) argc; (void) argv;
|
||||
|
||||
int b = a+1;
|
||||
|
||||
printf("%i %i\n",a,b);
|
||||
|
||||
while(a<0xf0000000) {
|
||||
++a;
|
||||
printf("%i\n",a++);
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode:c++
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
|
|
@ -395,7 +395,7 @@ var
|
|||
begin
|
||||
// On developer machines, if we are running within the source repo, then use
|
||||
// those paths
|
||||
keyman_root := GetEnvironmentVariable('KEYMAN_ROOT');
|
||||
keyman_root := GetEnvironmentVariable('KEYMAN_ROOT').Replace('/', '\');
|
||||
if (keyman_root <> '') and SameText(keyman_root, ParamStr(0).Substring(0, keyman_root.Length)) then
|
||||
begin
|
||||
// Source repo, bin folder
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ if "!COMMAND!" == "configure" (
|
|||
if "%1" == "--no-tests" (
|
||||
meson setup build\!ARCH!\!BUILDTYPE! !STATIC_LIBRARY! --buildtype !BUILDTYPE! -Dkeyman_core_tests=false --werror %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel!
|
||||
) else (
|
||||
meson setup build\!ARCH!\!BUILDTYPE! !STATIC_LIBRARY! --buildtype !BUILDTYPE! --werror %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel!
|
||||
meson setup build\!ARCH!\!BUILDTYPE! !STATIC_LIBRARY! --buildtype !BUILDTYPE! -Dkeyman_core_tests=true --werror %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel!
|
||||
)
|
||||
shift
|
||||
)
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ builder_parse "$@"
|
|||
# if we don't plan to run them, for example when doing a dependency build
|
||||
# in CI
|
||||
#
|
||||
MESON_OPTION_keyman_core_tests=
|
||||
MESON_OPTION_keyman_core_tests="-Dkeyman_core_tests=true"
|
||||
BUILD_BAT_keyman_core_tests=
|
||||
|
||||
if builder_is_dep_build || builder_has_option --no-tests; then
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ function do_build() {
|
|||
|
||||
function do_test() {
|
||||
typescript_run_eslint_mocha_tests 50
|
||||
./test/command-line-tests.sh test
|
||||
builder_launch /developer/src/kmc/test/command-line-tests.sh test
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -29,11 +29,10 @@ function do_build() {
|
|||
build_manifest.res
|
||||
run_in_vs_env rc icons.rc
|
||||
delphi_msbuild kmconvert.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" kmconvert.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/kmconvert.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$DEVELOPER_PROGRAM"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/kmconvert.dbg" "$DEVELOPER_DEBUGPATH"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/kmconvert.pdb" "$DEVELOPER_DEBUGPATH"
|
||||
|
||||
rm -rf "$DEVELOPER_PROGRAM/projects/templates"
|
||||
mkdir -p "$DEVELOPER_PROGRAM/projects/templates"
|
||||
|
|
@ -53,7 +52,12 @@ function do_publish() {
|
|||
|
||||
wrap-signcode //d "Keyman Developer" "$DEVELOPER_PROGRAM/kmconvert.exe"
|
||||
wrap-symstore "$DEVELOPER_PROGRAM/kmconvert.exe" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/kmconvert.dbg" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/kmconvert.pdb" //t keyman-developer
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$DEVELOPER_PROGRAM/kmconvert.exe" "$INSTALLPATH_KEYMANDEVELOPER/kmconvert.exe"
|
||||
cp_if_exists "$DEVELOPER_DEBUGPATH/kmconvert.pdb" "$INSTALLPATH_KEYMANDEVELOPER/kmconvert.pdb"
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
|
|
@ -61,5 +65,5 @@ builder_run_action configure:project configure_windows_build_environment
|
|||
builder_run_action build:project do_build
|
||||
builder_run_action test:project do_test
|
||||
builder_run_action publish:project do_publish
|
||||
builder_run_action install:project cp "$DEVELOPER_PROGRAM/kmconvert.exe" "$INSTALLPATH_KEYMANDEVELOPER/kmconvert.exe"
|
||||
builder_run_action install:project do_install
|
||||
builder_run_action edit:project start kmconvert.dproj
|
||||
|
|
|
|||
|
|
@ -28,11 +28,10 @@ function do_build() {
|
|||
build_version.res
|
||||
build_manifest.res
|
||||
delphi_msbuild kmdbrowserhost.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" kmdbrowserhost.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/kmdbrowserhost.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$DEVELOPER_PROGRAM"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/kmdbrowserhost.dbg" "$DEVELOPER_DEBUGPATH"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/kmdbrowserhost.pdb" "$DEVELOPER_DEBUGPATH"
|
||||
}
|
||||
|
||||
function do_publish() {
|
||||
|
|
@ -41,7 +40,12 @@ function do_publish() {
|
|||
|
||||
wrap-signcode //d "Keyman Developer" "$DEVELOPER_PROGRAM/kmdbrowserhost.exe"
|
||||
wrap-symstore "$DEVELOPER_PROGRAM/kmdbrowserhost.exe" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/kmdbrowserhost.dbg" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/kmdbrowserhost.pdb" //t keyman-developer
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$DEVELOPER_PROGRAM/kmdbrowserhost.exe" "$INSTALLPATH_KEYMANDEVELOPER/kmdbrowserhost.exe"
|
||||
cp_if_exists "$DEVELOPER_DEBUGPATH/kmdbrowserhost.pdb" "$INSTALLPATH_KEYMANDEVELOPER/kmdbrowserhost.pdb"
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
|
|
@ -49,6 +53,6 @@ builder_run_action configure:project configure_windows_build_environment
|
|||
builder_run_action build:project do_build
|
||||
# builder_run_action test:project do_test
|
||||
builder_run_action publish:project do_publish
|
||||
builder_run_action install:project cp "$DEVELOPER_PROGRAM/kmdbrowserhost.exe" "$INSTALLPATH_KEYMANDEVELOPER/kmdbrowserhost.exe"
|
||||
builder_run_action install:project do_install
|
||||
builder_run_action edit:project start kmdbrowserhost.dproj
|
||||
|
||||
|
|
|
|||
|
|
@ -30,11 +30,32 @@ function do_build() {
|
|||
build_version.res
|
||||
build_manifest.res
|
||||
delphi_msbuild setup.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" setup.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/setup.map" "$WIN32_TARGET"
|
||||
|
||||
#
|
||||
# The installer needs to be a multiple of 512 bytes in order for the SFX code
|
||||
# to find the ZIP header. After map2pdb appends its header, the file may not
|
||||
# be the right size. So take the file size of setup.exe and generate a nul
|
||||
# file that would expand it to nearest 512 bytes, and append it to the
|
||||
# executable. This will make the file 512 bytes larger if its size is already
|
||||
# on a 512 byte boundary.
|
||||
#
|
||||
|
||||
local file_size expansion_size expansion_file
|
||||
|
||||
file_size=$(stat -c %s "$WIN32_TARGET")
|
||||
expansion_size=$(( 512 - ( $file_size % 512 ) ))
|
||||
expansion_file="$(mktemp)"
|
||||
dd if=/dev/zero of="${expansion_file}" bs=1 count="${expansion_size}"
|
||||
cat "$WIN32_TARGET" "$expansion_file" > "$WIN32_TARGET.out"
|
||||
mv -f "$WIN32_TARGET.out" "$WIN32_TARGET"
|
||||
rm -f "${expansion_file}"
|
||||
|
||||
|
||||
cp "$WIN32_TARGET" "$DEVELOPER_PROGRAM"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/setup.dbg" "$DEVELOPER_DEBUGPATH/devsetup.dbg"
|
||||
builder_if_release_build_level mv "$WIN32_TARGET_PATH/setup.dbg" "$WIN32_TARGET_PATH/devsetup.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/setup.pdb" "$DEVELOPER_DEBUGPATH/devsetup.pdb"
|
||||
# builder_if_release_build_level cp "$WIN32_TARGET_PATH/setup.pdb" "$DEVELOPER_DEBUGPATH/devsetup.pdb"
|
||||
# builder_if_release_build_level mv "$WIN32_TARGET_PATH/setup.pdb" "$WIN32_TARGET_PATH/devsetup.pdb"
|
||||
}
|
||||
|
||||
function do_publish() {
|
||||
|
|
@ -42,7 +63,7 @@ function do_publish() {
|
|||
# Not signing here because we need to sign the bundled installer instead
|
||||
# wrap-signcode /d "Keyman Developer Setup" $(DEVELOPER_PROGRAM)\setup.exe
|
||||
wrap-symstore "$DEVELOPER_PROGRAM/setup.exe" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/setup.dbg" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/setup.pdb" //t keyman-developer
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
|
|
|
|||
|
|
@ -68,16 +68,15 @@ function do_build() {
|
|||
cp -R "$DEVELOPER_ROOT/src/tike/xml/"* "$DEVELOPER_PROGRAM/xml/"
|
||||
|
||||
delphi_msbuild tike.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" tike.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/tike.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$DEVELOPER_PROGRAM"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/tike.pdb" "$DEVELOPER_DEBUGPATH"
|
||||
cp kmc.cmd "$DEVELOPER_PROGRAM"
|
||||
cp "$KEYMAN_ROOT/core/build/x86/$TARGET_PATH/src/$KEYMANCORE_DLL" "$DEVELOPER_PROGRAM"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/tike.dbg" "$DEVELOPER_DEBUGPATH"
|
||||
|
||||
cp "$KEYMAN_ROOT/core/build/x86/$TARGET_PATH/src/$KEYMANCORE_DLL" "$WIN32_TARGET_PATH"
|
||||
builder_if_release_build_level cp "$KEYMAN_ROOT/core/build/x86/$TARGET_PATH/src/$KEYMANCORE_PDB" "$WIN32_TARGET_PATH"
|
||||
builder_if_release_build_level cp "$KEYMAN_ROOT/core/build/x86/$TARGET_PATH/src/$KEYMANCORE_PDB" "$DEVELOPER_DEBUGPATH"
|
||||
|
||||
cp "$KEYMAN_ROOT/common/windows/delphi/ext/sentry/sentry.dll" "$DEVELOPER_PROGRAM/"
|
||||
cp "$KEYMAN_ROOT/common/windows/delphi/ext/sentry/sentry.x64.dll" "$DEVELOPER_PROGRAM/"
|
||||
|
|
@ -96,11 +95,12 @@ function do_publish() {
|
|||
wrap-signcode //d "Keyman Developer" "$DEVELOPER_PROGRAM/sentry.x64.dll"
|
||||
wrap-signcode //d "Keyman Developer" "$DEVELOPER_PROGRAM/crashpad_handler.exe"
|
||||
wrap-symstore "$DEVELOPER_PROGRAM/tike.exe" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/tike.dbg" //t keyman-developer
|
||||
wrap-symstore "$DEVELOPER_DEBUGPATH/tike.pdb" //t keyman-developer
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$DEVELOPER_PROGRAM/tike.exe" "$INSTALLPATH_KEYMANDEVELOPER/tike.exe"
|
||||
cp_if_exists "$DEVELOPER_DEBUGPATH/tike.pdb" "$INSTALLPATH_KEYMANDEVELOPER/tike.pdb"
|
||||
cp "$DEVELOPER_PROGRAM/$KEYMANCORE_DLL" "$INSTALLPATH_KEYMANDEVELOPER/$KEYMANCORE_DLL"
|
||||
}
|
||||
|
||||
|
|
|
|||
2
docs/build/windows.md
vendored
2
docs/build/windows.md
vendored
|
|
@ -345,7 +345,7 @@ SETX KEYMAN_CEF4DELPHI_ROOT "c:\Projects\keyman\CEF4Delphi_Binary"
|
|||
```ps1
|
||||
# Elevated PowerShell
|
||||
choco install 7zip html-help-workshop
|
||||
choco install wixtoolset --version=3.11.1
|
||||
choco install wixtoolset --version=3.14.1
|
||||
git clone https://github.com/keymanapp/CEF4Delphi_Binary C:\Projects\keyman\CEF4Delphi_Binary
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1038,6 +1038,28 @@ fi
|
|||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## `builder_launch` function
|
||||
|
||||
Starts a child script build, passing current build dependency, inheritable
|
||||
options, and timing status through as parameters. This should be used rather
|
||||
than calling the build script directly, to avoid multiple builds of
|
||||
dependencies.
|
||||
|
||||
Do not use builder standard options such as `--deps` or `--debug`.
|
||||
|
||||
### Parameters
|
||||
|
||||
* 1: `script` path to script, relative to root of repo
|
||||
* 2+: `parameters` action(s), target(s), parameters for the child script to run
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
builder_launch core/build.sh configure,build:wasm --no-tests
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## `builder_parse` function
|
||||
|
||||
Initializes a build.sh script, parses command line. Will abort the script if
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
keyman (18.0.244-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Eberhard Beilharz <eb1@sil.org> Mon, 10 Nov 2025 17:06:33 +0100
|
||||
|
||||
keyman (18.0.243-1) unstable; urgency=medium
|
||||
|
||||
* replace dbus-x11 dependency with default-dbus-session-bus | dbus-session-bus
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
set -eu
|
||||
shopt -s inherit_errexit
|
||||
|
||||
# Avoid timing reports as we don't have node in this script
|
||||
export _builder_timings=false
|
||||
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ else
|
|||
fi
|
||||
echo "ppa: ${ppa}"
|
||||
|
||||
distributions="${DIST:-jammy noble plucky questing}"
|
||||
distributions="${DIST:-jammy noble plucky questing resolute}"
|
||||
packageversion="${PACKAGEVERSION:-1~sil1}"
|
||||
|
||||
BASEDIR=$(pwd)
|
||||
|
|
|
|||
|
|
@ -192,12 +192,17 @@ builder_echo info "Detaching \"$WORKING_COPY_OF_IMAGE\""
|
|||
DETACH_SUCCESS=0
|
||||
DETACH_FORCE=
|
||||
while (( DETACH_SUCCESS < 10 )); do
|
||||
DETACH_RESULT=0
|
||||
hdiutil detach $STAGING_DIR $VERBOSITY $DETACH_FORCE || DETACH_RESULT=$?
|
||||
if [[ $DETACH_RESULT != 0 || -d "$STAGING_DIR" ]] ; then
|
||||
if hdiutil detach $STAGING_DIR $VERBOSITY $DETACH_FORCE; then
|
||||
DETACH_RESULT=0
|
||||
echo "hdiutil detach reported success"
|
||||
else
|
||||
DETACH_RESULT=$?
|
||||
echo "hdiutil detach reported failure code ${DETACH_RESULT}"
|
||||
fi
|
||||
if [[ $DETACH_RESULT != 0 ]] || [[ -d "$STAGING_DIR" ]] ; then
|
||||
(( DETACH_SUCCESS++ ))
|
||||
echo "Failed to unmount: \"$STAGING_DIR\" on attempt #$DETACH_SUCCESS. Waiting 5 seconds to try again."
|
||||
if (( DETACH_SUCCESS > 5 )); then
|
||||
if (( DETACH_SUCCESS == 6 )); then
|
||||
echo " Note: Detach failed first five times, so now attempting with '-force'"
|
||||
DETACH_FORCE=-force
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ KEYMAN_MIN_VERSION_NODE_MAJOR=20 # node version source of truth is
|
|||
KEYMAN_MIN_VERSION_NPM=10.5.1 # 10.5.0 has bug, discussed in #10350
|
||||
KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.58 # Use KEYMAN_USE_EMSDK to automatically update to this version
|
||||
KEYMAN_MIN_VERSION_VISUAL_STUDIO=2022 # Visual Studio 2022, see /docs/build/windows.md for workloads and components
|
||||
KEYMAN_MIN_VERSION_MESON=1.0.0
|
||||
KEYMAN_MIN_VERSION_MESON=1.0.0 # TODO: rename meson_options.txt to meson.options when updating to >= 1.1, see #15127.
|
||||
|
||||
KEYMAN_VERSION_GRADLE=8.12 # See /android/KMEA/gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
set -eu
|
||||
|
||||
# Avoid timing reports in unit tests
|
||||
export _builder_timings=false
|
||||
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
|
|
@ -243,7 +246,7 @@ if [[ $KEYMAN_VERSION_ENVIRONMENT == "local" ]]; then
|
|||
expected="$(builder_echo grey "Local build environment detected: setting --debug")"$'\n'"$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test --debug>")"
|
||||
fi
|
||||
if [[ "${parse_output[*]}" != "${expected}" ]]; then
|
||||
builder_die "FAIL: Wrong output for '--feature xyzzy --bar abc --baz def test':\n Actual : ${parse_output[*]}\n Expected: ${expected}"
|
||||
builder_die "FAIL: Wrong output for '--feature xyzzy --bar abc --baz def test':\n Actual : '${parse_output[*]}'\n Expected: '${expected}'"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
|
@ -300,12 +303,12 @@ function builder_echo_start_end_tests() {
|
|||
TEAMCITY_GIT_PATH=""
|
||||
_builder_debug_internal=false
|
||||
_builder_is_child=0
|
||||
expected=""
|
||||
expected="$(builder_echo heading "description")"
|
||||
result=$(builder_echo start "foo" "description")
|
||||
if [[ "${result[*]}" != "${expected}" ]]; then
|
||||
builder_die "FAIL: Wrong output for 'builder_echo start foo description' (no debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}"
|
||||
fi
|
||||
expected=""
|
||||
expected="$(builder_echo success "description")"
|
||||
result=$(builder_echo end "foo" success "description")
|
||||
if [[ "${result[*]}" != "${expected}" ]]; then
|
||||
builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (no debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}"
|
||||
|
|
@ -436,7 +439,7 @@ echo
|
|||
# Finally, run with --help so we can see what it looks like; note:
|
||||
# builder_parse calls `exit 0` on a --help run, so running in a subshell
|
||||
echo -e "${COLOR_BLUE}## Testing --help${COLOR_RESET}"
|
||||
builder_parse --no-color --help
|
||||
builder_parse --no-color --help --no-timings
|
||||
) || builder_die "FAIL: builder-parse unexpectedly returned failure code $?"
|
||||
|
||||
echo -e "${COLOR_GREEN}======================================================${COLOR_RESET}"
|
||||
|
|
|
|||
|
|
@ -30,5 +30,4 @@ DEVELOPER_DEBUGPATH="$DEVELOPER_ROOT/debug"
|
|||
# Delphi build tool macros
|
||||
|
||||
SENTRYTOOL="$COMMON_ROOT/tools/sentrytool/$WIN32_TARGET_PATH/sentrytool.exe"
|
||||
TDS2DBG="$KEYMAN_ROOT/common/windows/bin/tools/tds2dbg"
|
||||
DEVTOOLS="$COMMON_ROOT/tools/devtools/$WIN32_TARGET_PATH/devtools.exe"
|
||||
|
|
|
|||
|
|
@ -72,23 +72,25 @@ run_in_delphi_env() {
|
|||
)
|
||||
}
|
||||
|
||||
sentrytool_delphiprep() {
|
||||
if builder_is_ci_build && builder_is_ci_build_level_build; then
|
||||
builder_echo "Skipping sentrytool_delphiprep - buildLevel=build: $@"
|
||||
return 0
|
||||
#
|
||||
# If map2pdb is on the path, then run it. Note: we do not include it in the repo
|
||||
# because it can have false positives in malware scans. map2pdb is used to
|
||||
# generate .pdb files for Delphi-generated executables, which can then be used
|
||||
# in debuggers such as WinDbg, or profilers such as VTune.
|
||||
#
|
||||
do_map2pdb() {
|
||||
if hash map2pdb 2>/dev/null; then
|
||||
map2pdb "$1" -bind:"$2"
|
||||
fi
|
||||
|
||||
local EXE_PATH="$1"
|
||||
local DPR_PATH="$2"
|
||||
(
|
||||
builder_echo heading "### delphi: sentrytool_delphiprep $1 $2"
|
||||
source "$KEYMAN_ROOT/resources/build/win/delphi_environment.inc.sh"
|
||||
"$SENTRYTOOL" delphiprep -r "$KEYMAN_ROOT" -i "$DELPHIINCLUDES" "$(cygpath -w "$EXE_PATH")" -dpr "$DPR_PATH"
|
||||
)
|
||||
}
|
||||
|
||||
tds2dbg() {
|
||||
builder_if_release_build_level "$TDS2DBG" "$@"
|
||||
#
|
||||
# If the first parameter is a file that exists, do the copy, otherwise, no-op.
|
||||
#
|
||||
cp_if_exists() {
|
||||
if [[ -f "$1" ]]; then
|
||||
cp "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
delphi_msbuild() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
WIXPATH="$ProgramFilesx86/WiX Toolset v3.11/bin"
|
||||
WIXPATH="$ProgramFilesx86/WiX Toolset v3.14/bin"
|
||||
|
||||
# !IFDEF LINT
|
||||
WIXLIGHTLINT=()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ set -eu
|
|||
#
|
||||
SHLVL=0
|
||||
|
||||
# A regex of reserved builder parameters, must be kept in sync with
|
||||
# the matching of builder parameters in _builder_parse_expanded_parameters
|
||||
_builder_reserved_parameters='^(--help|-h|--color|--no-color|--verbose|-v|--timings|--no-timings|--debug|--release|--deps|--no-deps|--force-deps|--builder-dep-parent|--builder-child|--builder-report-dependencies|--builder-completion-describe|--offline|--builder-ignore-unknown-options)$'
|
||||
|
||||
|
||||
# _builder_init is called internally at the bottom of this file after we have
|
||||
# all function declarations in place.
|
||||
function _builder_init() {
|
||||
|
|
@ -180,7 +185,7 @@ function builder_heading() {
|
|||
|
||||
|
||||
builder_echo() {
|
||||
local color=white message= mark= block= action= do_output=true test=
|
||||
local color=white message= mark= block= action= test=
|
||||
local echo_target=echo
|
||||
|
||||
if [[ $# -gt 1 ]]; then
|
||||
|
|
@ -194,9 +199,6 @@ builder_echo() {
|
|||
shift 2
|
||||
action="start"
|
||||
color="heading"
|
||||
if ! builder_is_running_on_teamcity && builder_is_child_build; then
|
||||
do_output=${_builder_debug_internal:-false}
|
||||
fi
|
||||
elif [[ $1 == "end" ]] || [[ $1 == "endTest" ]]; then
|
||||
# builder_echo end block status message
|
||||
test="$1"
|
||||
|
|
@ -204,9 +206,6 @@ builder_echo() {
|
|||
color="$3"
|
||||
shift 3
|
||||
action="end"
|
||||
if [[ "${color}" != "error" ]] && ! builder_is_running_on_teamcity && builder_is_child_build; then
|
||||
do_output=${_builder_debug_internal:-false}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
message="$*"
|
||||
|
|
@ -219,30 +218,28 @@ builder_echo() {
|
|||
fi
|
||||
fi
|
||||
|
||||
if ${do_output}; then
|
||||
if [[ ! -z ${COLOR_RED+x} ]]; then
|
||||
case $color in
|
||||
white) color="$COLOR_WHITE" ;;
|
||||
grey) color="$COLOR_GREY" ;;
|
||||
green|success) color="$COLOR_GREEN" ;;
|
||||
blue|heading) color="$COLOR_BLUE" ;;
|
||||
yellow|warning) color="$COLOR_YELLOW" ;;
|
||||
red|error) color="$COLOR_RED"; echo_target=_builder_error_echo ;;
|
||||
purple) color="$COLOR_PURPLE" ;;
|
||||
brightwhite) color="$COLOR_BRIGHTWHITE" ;;
|
||||
teal|debug) color="$COLOR_TEAL" ;;
|
||||
setmark) mark="$HEADING_SETMARK" color="$COLOR_PURPLE" ;;
|
||||
esac
|
||||
if [[ ! -z ${COLOR_RED+x} ]]; then
|
||||
case $color in
|
||||
white) color="$COLOR_WHITE" ;;
|
||||
grey) color="$COLOR_GREY" ;;
|
||||
green|success) color="$COLOR_GREEN" ;;
|
||||
blue|heading) color="$COLOR_BLUE" ;;
|
||||
yellow|warning) color="$COLOR_YELLOW" ;;
|
||||
red|error) color="$COLOR_RED"; echo_target=_builder_error_echo ;;
|
||||
purple) color="$COLOR_PURPLE" ;;
|
||||
brightwhite) color="$COLOR_BRIGHTWHITE" ;;
|
||||
teal|debug) color="$COLOR_TEAL" ;;
|
||||
setmark) mark="$HEADING_SETMARK" color="$COLOR_PURPLE" ;;
|
||||
esac
|
||||
|
||||
if builder_is_dep_build; then
|
||||
$echo_target -e "$mark$COLOR_GREY[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET"
|
||||
else
|
||||
$echo_target -e "$mark$BUILDER_BOLD$COLOR_BRIGHT_WHITE[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET"
|
||||
fi
|
||||
if builder_is_dep_build; then
|
||||
$echo_target -e "$mark$COLOR_GREY[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET"
|
||||
else
|
||||
# Cope with the case of pre-init message and just emit plain text
|
||||
$echo_target -e "$message"
|
||||
$echo_target -e "$mark$BUILDER_BOLD$COLOR_BRIGHT_WHITE[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET"
|
||||
fi
|
||||
else
|
||||
# Cope with the case of pre-init message and just emit plain text
|
||||
$echo_target -e "$message"
|
||||
fi
|
||||
|
||||
if [[ "${action}" == "end" ]] && builder_is_running_on_teamcity; then
|
||||
|
|
@ -377,7 +374,7 @@ _builder_item_is_target() {
|
|||
|
||||
function _builder_warn_if_incomplete() {
|
||||
if [ -n "${_builder_current_action}" ]; then
|
||||
builder_echo warning "$_builder_current_action never reported success or failure"
|
||||
builder_echo warning "WARNING: $_builder_current_action never reported success or failure"
|
||||
# exit 1 # If we wanted this scenario to result in a forced build-script fail.
|
||||
fi
|
||||
|
||||
|
|
@ -392,6 +389,7 @@ _builder_failure_trap() {
|
|||
local action target
|
||||
|
||||
_builder_cleanup_deps
|
||||
_builder_timing_cleanup_and_report $trappedExitCode
|
||||
|
||||
# Since 'exit' is also trapped, we can also handle end-of-script incomplete actions.
|
||||
if [[ $trappedExitCode == 0 ]]; then
|
||||
|
|
@ -440,20 +438,70 @@ _builder_cleanup_deps() {
|
|||
# Child scripts
|
||||
#------------------------------------------------------------------------------------------
|
||||
|
||||
_builder_execute_child() {
|
||||
local action=$1
|
||||
local target=$2
|
||||
#
|
||||
# Starts a child script build, passing current build dependency, inheritable
|
||||
# options, and timing status through as parameters. This should be used rather
|
||||
# than calling the build script directly, to avoid multiple builds of
|
||||
# dependencies.
|
||||
#
|
||||
# Do not use builder standard options such as `--deps` or `--debug`.
|
||||
#
|
||||
# ### Parameters
|
||||
#
|
||||
# * 1: `script` path to script, relative to root of repo
|
||||
# * 2+: `parameters` action(s), target(s), parameters for the child script to run
|
||||
#
|
||||
# ### Example
|
||||
#
|
||||
# ```bash
|
||||
# builder_launch core/build.sh configure,build:wasm --no-tests
|
||||
# ```
|
||||
#
|
||||
builder_launch() {
|
||||
local script="$1"
|
||||
local param
|
||||
shift
|
||||
|
||||
if [[ ! "$script" =~ ^/(.+) ]]; then
|
||||
builder_die "Error: builder_launch: script path must start with /, and is relative to repo root"
|
||||
fi
|
||||
|
||||
for param in "$@"; do
|
||||
if [[ "${param}" =~ ${_builder_reserved_parameters} ]]; then
|
||||
builder_die "Error: builder_launch: reserved parameter '${param}' used"
|
||||
fi
|
||||
done
|
||||
|
||||
builder_echo grey "## script '$script $*' launched..."
|
||||
_builder_execute_child_script "${KEYMAN_ROOT}${script}" "$@"
|
||||
builder_echo grey "## script '$script $*' completed"
|
||||
}
|
||||
|
||||
_builder_execute_child() {
|
||||
local action="$1"
|
||||
local target="$2"
|
||||
local script="$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh"
|
||||
|
||||
builder_echo start "$action$target" "## $action$target starting..."
|
||||
builder_echo grey "## child $action$target starting..."
|
||||
_builder_execute_child_script "$script" "$action"
|
||||
builder_echo grey "## child $action$target completed successfully"
|
||||
}
|
||||
|
||||
# ### Parameters
|
||||
#
|
||||
# * 1: `script` path to script
|
||||
# * 2+: `parameters` action(s), target(s), parameters for the child script to run
|
||||
_builder_execute_child_script() {
|
||||
local script="$1"
|
||||
# subsequent parameters passed as $@/$* below
|
||||
shift
|
||||
|
||||
# Build array of specified inheritable options
|
||||
local child_options=()
|
||||
local opt
|
||||
for opt in "${_builder_options_inheritable[@]}"; do
|
||||
if builder_has_option $opt; then
|
||||
child_options+=($opt)
|
||||
if builder_has_option "${opt}"; then
|
||||
child_options+=("${opt}")
|
||||
fi
|
||||
done
|
||||
|
||||
|
|
@ -469,16 +517,14 @@ _builder_execute_child() {
|
|||
--builder-child \
|
||||
$_builder_build_deps \
|
||||
$dep_flag "$dep_module" \
|
||||
$action \
|
||||
${child_options[@]} \
|
||||
"$@" \
|
||||
"${child_options[@]}" \
|
||||
$builder_verbose \
|
||||
$builder_debug \
|
||||
$_builder_offline \
|
||||
&& (
|
||||
builder_echo end "$action$target" success "## $action$target completed successfully"
|
||||
) || (
|
||||
|| (
|
||||
result=$?
|
||||
builder_echo end "$action$target" error "## $action$target failed with exit code $result"
|
||||
builder_echo error "## child script '$script $*' failed with exit code $result"
|
||||
exit $result
|
||||
) || exit $? # Required due to above subshell masking exit
|
||||
}
|
||||
|
|
@ -679,6 +725,9 @@ builder_start_action() {
|
|||
fi
|
||||
_builder_current_action="${_builder_matched_action}"
|
||||
|
||||
# Note: we include the action's dependencies in timing
|
||||
_builder_timing_start "${_builder_matched_action}"
|
||||
|
||||
# Build dependencies as required
|
||||
_builder_do_build_deps "${_builder_matched_action}"
|
||||
return 0
|
||||
|
|
@ -687,6 +736,139 @@ builder_start_action() {
|
|||
fi
|
||||
}
|
||||
|
||||
###################################################################################################
|
||||
# Timing
|
||||
###################################################################################################
|
||||
|
||||
_builder_timing_setup() {
|
||||
if $_builder_timings; then
|
||||
export _builder_timing_report_file=`mktemp`
|
||||
_builder_timing_start "build.sh:top"
|
||||
fi
|
||||
}
|
||||
|
||||
_builder_timing_start() {
|
||||
local context="$1"
|
||||
if [[ ! -z "${_builder_timing_report_file:+x}" ]]; then
|
||||
echo "START $THIS_SCRIPT_IDENTIFIER:$context $(date +%s.%N)" >> "$_builder_timing_report_file"
|
||||
fi
|
||||
}
|
||||
|
||||
_builder_timing_stop() {
|
||||
local context="$1"
|
||||
if [[ ! -z "${_builder_timing_report_file:+x}" ]]; then
|
||||
echo "STOP $THIS_SCRIPT_IDENTIFIER:$context $(date +%s.%N)" >> "$_builder_timing_report_file"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Removes temporary `_builder_timing_report_file` file when top-level build
|
||||
# script finishes and reports on timings if they were requested.
|
||||
#
|
||||
_builder_timing_cleanup_and_report() {
|
||||
local build_exit_code="$1"
|
||||
if builder_is_dep_build || builder_is_child_build || [[ -z ${_builder_timing_report_file:+x} ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$build_exit_code" != 0 ]]; then
|
||||
# Hide the timings report if build failed, but still cleanup
|
||||
_builder_timings=false
|
||||
fi
|
||||
|
||||
if $_builder_timings; then
|
||||
_builder_timing_stop "build.sh:top"
|
||||
|
||||
if ! command -v node > /dev/null; then
|
||||
builder_warn "WARNING: node.js not found, skipping timings report"
|
||||
else
|
||||
builder_heading "## Build timings"
|
||||
|
||||
# for simplicity of distribution, we embed the node.js script here
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
node -e '
|
||||
const fs = require("node:fs");
|
||||
const process = require("node:process");
|
||||
|
||||
let
|
||||
COLOR_RED="", COLOR_GREEN="", COLOR_YELLOW="", COLOR_BLUE="", COLOR_PURPLE="", COLOR_TEAL="",
|
||||
COLOR_WHITE="", COLOR_BRIGHT_WHITE="", COLOR_GREY="", COLOR_RESET="", BUILDER_BOLD="";
|
||||
|
||||
if(process.stdout.isTTY) {
|
||||
COLOR_RED="\x1b[31m"; COLOR_GREEN="\x1b[32m"; COLOR_YELLOW="\x1b[33m"; COLOR_BLUE="\x1b[34m";
|
||||
COLOR_PURPLE="\x1b[35m"; COLOR_TEAL="\x1b[36m"; COLOR_WHITE="\x1b[38;5;252m";
|
||||
COLOR_BRIGHT_WHITE="\x1b[38;5;255m"; COLOR_GREY="\x1b[90m"; COLOR_RESET="\x1b(B\x1b[m";
|
||||
BUILDER_BOLD="\x1b[1m";
|
||||
}
|
||||
|
||||
const log = fs.readFileSync(process.argv[process.argv.length-1], "utf8").split("\n");
|
||||
|
||||
let top = null;
|
||||
const modules = {};
|
||||
const tree = [];
|
||||
|
||||
for(const line of log) {
|
||||
if(line.trim() == "") continue;
|
||||
const [event, area, time] = line.split(" ");
|
||||
const [module, action, target, sub] = area.split(":");
|
||||
if(event == "START") {
|
||||
const mod = {area, module, action, target: target ? ":"+target : "", sub: sub ?? "", start:parseFloat(time), stop:null, modules:[]};
|
||||
if(!top) top = mod;
|
||||
modules[area] = mod;
|
||||
if(tree.length) {
|
||||
tree[tree.length-1].modules.push(mod);
|
||||
}
|
||||
tree.push(mod);
|
||||
} else if(event == "STOP") {
|
||||
if(tree.length) {
|
||||
const mod = tree.pop();
|
||||
if(mod.area != area) {
|
||||
console.error(`Expected ${area} to equal ${mod.area}`);
|
||||
}
|
||||
}
|
||||
const mod = modules[area];
|
||||
if(!mod) {
|
||||
console.error(`START not found for ${area}`);
|
||||
} else {
|
||||
mod.stop = parseFloat(time);
|
||||
}
|
||||
} else {
|
||||
console.error(`Unrecognized line: "${line}"`);
|
||||
}
|
||||
}
|
||||
|
||||
if(tree.length) {
|
||||
console.error(`Expected tree to be empty`);
|
||||
console.dir(tree);
|
||||
}
|
||||
|
||||
if(!Object.keys(modules).length || !top) {
|
||||
console.error(`Expected report to be non-empty`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Write out the tree with Pretty Printing
|
||||
|
||||
printModule("", top);
|
||||
|
||||
function printModule(indent, mod) {
|
||||
const duration = Math.round((mod.stop - mod.start) * 10) / 10;
|
||||
console.log(`${indent}${BUILDER_BOLD}[${mod.module}]${COLOR_RESET} ${COLOR_GREEN}${mod.action}${mod.target}${COLOR_RESET} ${mod.sub} ${duration}`);
|
||||
for(const submod of mod.modules) {
|
||||
printModule(indent+" ", submod);
|
||||
}
|
||||
}
|
||||
' "${_builder_timing_report_file}"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f "$_builder_timing_report_file"
|
||||
_builder_timing_report_file=
|
||||
}
|
||||
|
||||
###################################################################################################
|
||||
|
||||
#
|
||||
# Returns 0 if the user has --option on the command line
|
||||
#
|
||||
|
|
@ -1096,6 +1278,7 @@ _builder_get_default_description() {
|
|||
:engine) description="engine module" ;;
|
||||
:module) description="this module" ;;
|
||||
:tools) description="build tools for this project" ;;
|
||||
--timings) description="report on timings" ;;
|
||||
--debug) description="debug build" ;;
|
||||
--release) description="release build (prevents --debug in local-env builds)" ;;
|
||||
esac
|
||||
|
|
@ -1318,6 +1501,16 @@ builder_parse() {
|
|||
_builder_parse_expanded_parameters() {
|
||||
_builder_build_deps=--deps
|
||||
builder_verbose=
|
||||
|
||||
if [[ -z "${_builder_timings+x}" ]]; then
|
||||
# Only set _builder_timings if not already set
|
||||
if builder_is_ci_build; then
|
||||
_builder_timings=true
|
||||
else
|
||||
_builder_timings=false
|
||||
fi
|
||||
export _builder_timings
|
||||
fi
|
||||
builder_debug=
|
||||
local is_release=false
|
||||
local _params=($@)
|
||||
|
|
@ -1354,7 +1547,7 @@ _builder_parse_expanded_parameters() {
|
|||
action=$new_action
|
||||
;;
|
||||
*)
|
||||
builder_warn "Parameter $action has $? matches, could mean any of {$new_action}"
|
||||
builder_warn "ERROR: Parameter $action has $? matches, could mean any of {$new_action}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
@ -1365,7 +1558,7 @@ _builder_parse_expanded_parameters() {
|
|||
target=$new_target
|
||||
;;
|
||||
*)
|
||||
builder_warn "Parameter $target has $? matches, could mean any of {$new_target}"
|
||||
builder_warn "ERROR: Parameter $target has $? matches, could mean any of {$new_target}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
@ -1423,6 +1616,7 @@ _builder_parse_expanded_parameters() {
|
|||
fi
|
||||
|
||||
else
|
||||
# See also _builder_reserved_parameters
|
||||
case "$key" in
|
||||
--help|-h)
|
||||
builder_display_usage
|
||||
|
|
@ -1438,6 +1632,12 @@ _builder_parse_expanded_parameters() {
|
|||
_builder_chosen_options+=(--verbose)
|
||||
builder_verbose=--verbose
|
||||
;;
|
||||
--timings)
|
||||
_builder_timings=true
|
||||
;;
|
||||
--no-timings)
|
||||
_builder_timings=false
|
||||
;;
|
||||
--debug)
|
||||
_builder_chosen_options+=(--debug)
|
||||
builder_debug=--debug
|
||||
|
|
@ -1529,18 +1729,23 @@ _builder_parse_expanded_parameters() {
|
|||
fi
|
||||
|
||||
if builder_is_dep_build; then
|
||||
if [[ -z ${_builder_deps_built+x} ]]; then
|
||||
builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set"
|
||||
fi
|
||||
_builder_verify_expected_sub_process_variables
|
||||
elif builder_is_child_build; then
|
||||
if [[ -z ${_builder_deps_built+x} ]]; then
|
||||
builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set"
|
||||
fi
|
||||
_builder_verify_expected_sub_process_variables
|
||||
else
|
||||
|
||||
# For now, we'll leave this warning disabled, but may re-enable in #15130
|
||||
# if [[ ! -z "${_builder_deps_built+x}" ]]; then
|
||||
# builder_warn "WARNING: Child build '${THIS_SCRIPT_IDENTIFIER}' instantiated without using builder_launch"
|
||||
# fi
|
||||
|
||||
# This is a top-level invocation, so we want to track which dependencies
|
||||
# have been built, so they don't get built multiple times.
|
||||
export _builder_deps_built=`mktemp`
|
||||
|
||||
# We will also track timings
|
||||
_builder_timing_setup
|
||||
|
||||
# Per #11106, local builds use --debug by default.
|
||||
# Second condition prevents the block (and message) from executing when --debug is already specified explicitly.
|
||||
if [[ ${KEYMAN_VERSION_ENVIRONMENT:-} == "local" ]] && [[ $builder_debug != --debug ]] && ! $is_release; then
|
||||
|
|
@ -1575,6 +1780,17 @@ _builder_parse_expanded_parameters() {
|
|||
fi
|
||||
}
|
||||
|
||||
_builder_verify_expected_sub_process_variables() {
|
||||
if [[ -z ${_builder_deps_built+x} ]]; then
|
||||
builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set"
|
||||
fi
|
||||
if $_builder_timings; then
|
||||
if [[ -z ${_builder_timing_report_file+x} ]]; then
|
||||
builder_die "FATAL ERROR: Expected '_builder_timing_report_file' variable to be set"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Returns 0 (true) if --builder-ignore-unknown-options flag has been specified
|
||||
# in the command line
|
||||
|
|
@ -1596,21 +1812,14 @@ _builder_completion_describe() {
|
|||
echo -n "; "
|
||||
printf '%s ' "${_builder_targets[@]}"
|
||||
echo -n "; "
|
||||
# Remove all '+' suffixes from options; they're a config on the option, not part
|
||||
# of the actual option text itself.
|
||||
local _builder_opts=()
|
||||
for e in "${!_builder_params[@]}"; do
|
||||
if [[ $e =~ ^-- ]]; then
|
||||
_builder_opts+=(${e%+*})
|
||||
fi
|
||||
done
|
||||
|
||||
# Add default options
|
||||
_builder_opts+=( --verbose --debug --color --no-color --offline --help )
|
||||
local opts=("${_builder_options[@]}")
|
||||
# Add default options; see also _builder_reserved_parameters
|
||||
opts+=( --verbose --debug --release --color --no-color --offline --help --timings --no-timings )
|
||||
if builder_has_dependencies; then
|
||||
_builder_opts+=( --deps --no-deps --force-deps )
|
||||
opts+=( --deps --no-deps --force-deps )
|
||||
fi
|
||||
printf '%s ' "${_builder_opts[@]}"
|
||||
printf '%s ' "${opts[@]}"
|
||||
}
|
||||
|
||||
builder_display_usage() {
|
||||
|
|
@ -1686,6 +1895,7 @@ builder_display_usage() {
|
|||
fi
|
||||
done
|
||||
|
||||
# See also _builder_reserved_parameters
|
||||
_builder_pad $width " --verbose, -v" "Verbose logging"
|
||||
_builder_pad $width " --debug, -d" "Debug build"
|
||||
_builder_pad $width " --color" "Force colorized output"
|
||||
|
|
@ -1755,6 +1965,8 @@ builder_finish_action() {
|
|||
builder_echo end "$action_name" error "## $action_name failed with message: $result"
|
||||
fi
|
||||
|
||||
_builder_timing_stop "${_builder_matched_action}"
|
||||
|
||||
# Remove $action$target from the array; it is no longer a current action
|
||||
_builder_current_action=
|
||||
else
|
||||
|
|
@ -1833,6 +2045,8 @@ _builder_do_build_deps() {
|
|||
return 0
|
||||
fi
|
||||
|
||||
_builder_timing_start "$1:dependencies"
|
||||
|
||||
for dep in "${_builder_deps[@]}"; do
|
||||
# Don't attempt to build dependencies that don't match the current
|
||||
# action:target (wildcards supported for matches here)
|
||||
|
|
@ -1861,7 +2075,7 @@ _builder_do_build_deps() {
|
|||
$_builder_build_deps \
|
||||
--builder-dep-parent "$THIS_SCRIPT_IDENTIFIER" && (
|
||||
if $_builder_debug_internal; then
|
||||
builder_echo success "## Dependency $dep$dep_target for $_builder_matched_action_name successfully"
|
||||
builder_echo success "## Dependency $dep$dep_target for $_builder_matched_action_name completed successfully"
|
||||
fi
|
||||
) || (
|
||||
result=$?
|
||||
|
|
@ -1869,6 +2083,8 @@ _builder_do_build_deps() {
|
|||
exit $result
|
||||
) || exit $? # Required due to above subshell masking exit
|
||||
done
|
||||
|
||||
_builder_timing_stop "$1:dependencies"
|
||||
}
|
||||
|
||||
#
|
||||
|
|
@ -2115,13 +2331,13 @@ builder_describe_platform() {
|
|||
|
||||
# For testing, we can override the current platform
|
||||
if [[ ! -z "${BUILDER_PLATFORM_OVERRIDE+x}" ]]; then
|
||||
builder_warn "BUILDER_PLATFORM_OVERRIDE variable found. Overriding detected platform '$builder_platform' with '$BUILDER_PLATFORM_OVERRIDE'"
|
||||
builder_warn "WARNING: BUILDER_PLATFORM_OVERRIDE variable found. Overriding detected platform '$builder_platform' with '$BUILDER_PLATFORM_OVERRIDE'"
|
||||
builder_platform="$BUILDER_PLATFORM_OVERRIDE"
|
||||
fi
|
||||
|
||||
# For testing, we can override the current tools
|
||||
if [[ ! -z "${BUILDER_TOOLS_OVERRIDE+x}" ]]; then
|
||||
builder_warn "BUILDER_TOOLS_OVERRIDE variable found. Overriding detected tools (${builder_installed_tools[@]}) with (${BUILDER_TOOLS_OVERRIDE[@]})"
|
||||
builder_warn "WARNING: BUILDER_TOOLS_OVERRIDE variable found. Overriding detected tools (${builder_installed_tools[@]}) with (${BUILDER_TOOLS_OVERRIDE[@]})"
|
||||
builder_installed_tools=("${BUILDER_TOOLS_OVERRIDE[@]}")
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
import { KeymanEngine } from './keymanEngine.js'
|
||||
import { SourcemappedWorker } from '@keymanapp/lexical-model-layer/web'
|
||||
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*
|
||||
* This can only be done during load when the active script will be the
|
||||
* last script loaded. Otherwise the script must be identified by name.
|
||||
*/
|
||||
const scripts = document.getElementsByTagName('script');
|
||||
const ss = scripts[scripts.length-1].src;
|
||||
const sPath = ss.substr(0,ss.lastIndexOf('/')+1);
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*/
|
||||
const ss = (document.currentScript as HTMLScriptElement)?.src;
|
||||
const sPath = ss ? ss.substring(0, ss.lastIndexOf('/') + 1) : './';
|
||||
|
||||
// @ts-ignore
|
||||
window['keyman'] = new KeymanEngine(SourcemappedWorker, sPath);
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
import { KeymanEngine } from './keymanEngine.js'
|
||||
import { Worker } from '@keymanapp/lexical-model-layer/web'
|
||||
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*
|
||||
* This can only be done during load when the active script will be the
|
||||
* last script loaded. Otherwise the script must be identified by name.
|
||||
*/
|
||||
const scripts = document.getElementsByTagName('script');
|
||||
const ss = scripts[scripts.length-1].src;
|
||||
const sPath = ss.substr(0,ss.lastIndexOf('/')+1);
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*/
|
||||
const ss = (document.currentScript as HTMLScriptElement)?.src;
|
||||
const sPath = ss ? ss.substring(0, ss.lastIndexOf('/') + 1) : './';
|
||||
|
||||
// @ts-ignore
|
||||
window['keyman'] = new KeymanEngine(Worker, sPath);
|
||||
|
|
@ -78,7 +78,7 @@ compile_and_copy() {
|
|||
node map-polyfill-bundler.js
|
||||
|
||||
# For dependent test pages.
|
||||
"$KEYMAN_ROOT/web/src/test/manual/embed/android-harness/build.sh"
|
||||
builder_launch /web/src/test/manual/embed/android-harness/build.sh configure,build
|
||||
}
|
||||
|
||||
builder_run_action configure node_select_version_and_npm_ci
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
import { KeymanEngine } from './keymanEngine.js'
|
||||
import { SourcemappedWorker } from '@keymanapp/lexical-model-layer/web'
|
||||
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*
|
||||
* This can only be done during load when the active script will be the
|
||||
* last script loaded. Otherwise the script must be identified by name.
|
||||
*/
|
||||
const scripts = document.getElementsByTagName('script');
|
||||
const ss = scripts[scripts.length-1].src;
|
||||
const sPath = ss.substring(0,ss.lastIndexOf('/')+1);
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*/
|
||||
const ss = (document.currentScript as HTMLScriptElement)?.src;
|
||||
const sPath = ss ? ss.substring(0, ss.lastIndexOf('/') + 1) : './';
|
||||
|
||||
// @ts-ignore
|
||||
window['keyman'] = new KeymanEngine(SourcemappedWorker, sPath);
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
import { KeymanEngine } from './keymanEngine.js'
|
||||
import { Worker } from '@keymanapp/lexical-model-layer/web'
|
||||
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*
|
||||
* This can only be done during load when the active script will be the
|
||||
* last script loaded. Otherwise the script must be identified by name.
|
||||
*/
|
||||
const scripts = document.getElementsByTagName('script');
|
||||
const ss = scripts[scripts.length-1].src;
|
||||
const sPath = ss.substring(0,ss.lastIndexOf('/')+1);
|
||||
/**
|
||||
* Determine path and protocol of executing script, setting them as
|
||||
* construction defaults.
|
||||
*/
|
||||
const ss = (document.currentScript as HTMLScriptElement)?.src;
|
||||
const sPath = ss ? ss.substring(0, ss.lastIndexOf('/') + 1) : './';
|
||||
|
||||
// @ts-ignore
|
||||
window['keyman'] = new KeymanEngine(Worker, sPath);
|
||||
|
|
@ -36,7 +36,12 @@ do_build () {
|
|||
--format esm
|
||||
}
|
||||
|
||||
do_test() {
|
||||
test-headless "${SUBPROJECT_NAME}" ""
|
||||
test-headless-typescript "${SUBPROJECT_NAME}"
|
||||
}
|
||||
|
||||
builder_run_action configure node_select_version_and_npm_ci
|
||||
builder_run_action clean rm -rf "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}"
|
||||
builder_run_action build do_build
|
||||
builder_run_action test test-headless "${SUBPROJECT_NAME}" ""
|
||||
builder_run_action test do_test
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// Defines the base Deadkey-tracking object.
|
||||
export class Deadkey {
|
||||
p: number; // Position of deadkey
|
||||
p: number; // Position of deadkey in the textstore (deadkey comes before the character at this position)
|
||||
d: number; // Numerical id of the deadkey
|
||||
o: number; // Ordinal value of the deadkey (resolves same-place conflicts)
|
||||
matched: number;
|
||||
|
|
@ -11,10 +11,11 @@ export class Deadkey {
|
|||
this.p = pos;
|
||||
this.d = id;
|
||||
this.o = Deadkey.ordinalSeed++;
|
||||
this.matched = 0;
|
||||
}
|
||||
|
||||
match(p: number, d: number): boolean {
|
||||
const result:boolean = (this.p == p && this.d == d);
|
||||
match(pos: number, deadkey: number): boolean {
|
||||
const result:boolean = (this.p == pos && this.d == deadkey);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -39,7 +40,7 @@ export class Deadkey {
|
|||
}
|
||||
|
||||
equal(other: Deadkey) {
|
||||
return this.d == other.d && this.p == other.d && this.o == other.o;
|
||||
return this.d == other.d && this.p == other.p && this.o == other.o;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,22 +82,25 @@ export class DeadkeyTracker {
|
|||
* Function isMatch
|
||||
* Scope Public
|
||||
* @param {number} caretPos current cursor position
|
||||
* @param {number} n expected offset of deadkey from cursor
|
||||
* @param {number} d deadkey
|
||||
* @return {boolean} True if deadkey found selected context matches val
|
||||
* @param {number} offset expected offset to add to deadkey position to get to caretPos
|
||||
* @param {number} deadkey deadkey to match
|
||||
* @return {boolean} True if deadkey found at offset position
|
||||
* Description Match deadkey at current cursor position
|
||||
*/
|
||||
isMatch(caretPos: number, n: number, d: number): boolean {
|
||||
isMatch(caretPos: number, offset: number, deadkey: number): boolean {
|
||||
if(this.dks.length == 0) {
|
||||
return false; // I3318
|
||||
}
|
||||
|
||||
const sp=caretPos;
|
||||
n = sp - n;
|
||||
// Calculate position of deadkey from beginning of context.
|
||||
// Caret position is always after the deadkey position (although this
|
||||
// doesn't really matter for the calculation).
|
||||
const dkPosition = caretPos - offset;
|
||||
|
||||
for(let i = 0; i < this.dks.length; i++) {
|
||||
// Don't re-match an already-matched deadkey. It's possible to have two identical
|
||||
// entries, and they should be kept separately.
|
||||
if(this.dks[i].match(n, d) && !this.dks[i].matched) {
|
||||
if (this.dks[i].match(dkPosition, deadkey) && !this.dks[i].matched) {
|
||||
this.dks[i].set();
|
||||
// Assumption: since we match the first possible entry in the array, we
|
||||
// match the entry with the lower ordinal - the 'first' deadkey in the position.
|
||||
|
|
@ -115,7 +119,11 @@ export class DeadkeyTracker {
|
|||
|
||||
remove(dk: Deadkey) {
|
||||
const index = this.dks.indexOf(dk);
|
||||
this.dks.splice(index, 1);
|
||||
if (index > -1) {
|
||||
this.dks.splice(index, 1);
|
||||
} else {
|
||||
console.warn(`Deadkey ${JSON.stringify(dk)} to remove not found in DeadkeyTracker.`);
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
|
|
@ -160,17 +168,15 @@ export class DeadkeyTracker {
|
|||
return false;
|
||||
}
|
||||
|
||||
const otherDks = other.dks;
|
||||
const matchedDks: Deadkey[] = [];
|
||||
|
||||
for(const dk of this.dks) {
|
||||
const match = otherDks.find((otherDk) => dk.equal(otherDk));
|
||||
if(!match) {
|
||||
const sortedDeadkeys = this.toSortedArray();
|
||||
const otherDks = other.toSortedArray();
|
||||
for(let i = 0; i < sortedDeadkeys.length; i++) {
|
||||
if(!sortedDeadkeys[i].equal(otherDks[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return matchedDks.length == otherDks.length;
|
||||
return true;
|
||||
}
|
||||
|
||||
count(): number {
|
||||
|
|
|
|||
|
|
@ -9,3 +9,12 @@ export { default as OutputTarget } from "./outputTarget.js";
|
|||
export * from "./outputTarget.js";
|
||||
export { Mock } from "./mock.js";
|
||||
export * from "./stringDivergence.js";
|
||||
|
||||
import { DeadkeyTracker } from './deadkeys.js';
|
||||
|
||||
/**
|
||||
* these are exported only for unit tests, do not use
|
||||
*/
|
||||
export const unitTestEndpoints = {
|
||||
DeadkeyTracker,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -613,6 +613,8 @@ export default class KeyboardInterface extends KeyboardHarness {
|
|||
* @param {number} d deadkey
|
||||
* @return {boolean} True if deadkey found selected context matches val
|
||||
* Description Match deadkey at current cursor position
|
||||
*
|
||||
* Deprecated: use `fullContextMatch` instead.
|
||||
*/
|
||||
deadkeyMatch(n: number, outputTarget: OutputTarget, d: number): boolean {
|
||||
return outputTarget.hasDeadkeyMatch(n, d);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,373 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { Deadkey, unitTestEndpoints } from 'keyman/engine/js-processor';
|
||||
|
||||
const DeadkeyTracker = unitTestEndpoints.DeadkeyTracker;
|
||||
|
||||
describe('DeadkeyTracker', function() {
|
||||
it('can add deadkeys and return count', function() {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.equal(tracker.dks.length, 3);
|
||||
assert.equal(tracker.count(), 3);
|
||||
});
|
||||
|
||||
it('sorts deadkeys by position, latest first', function() {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
const sortedDeadkeys = tracker.toSortedArray();
|
||||
|
||||
assert.equal(sortedDeadkeys[0].p, 10);
|
||||
assert.equal(sortedDeadkeys[1].p, 5);
|
||||
assert.equal(sortedDeadkeys[2].p, 3);
|
||||
});
|
||||
|
||||
it('can adjust positions', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
tracker.adjustPositions(4, 2); // adjust deadkeys after position 4 by +2
|
||||
|
||||
const sortedDeadkeys = tracker.toSortedArray();
|
||||
assert.equal(sortedDeadkeys[0].p, 12); // 10 + 2
|
||||
assert.equal(sortedDeadkeys[1].p, 7); // 5 + 2
|
||||
assert.equal(sortedDeadkeys[2].p, 3); // unchanged
|
||||
});
|
||||
|
||||
describe('equal', function () {
|
||||
it('treats cloned tracker as equal', function () {
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(new Deadkey(3, 1));
|
||||
tracker1.add(new Deadkey(5, 2));
|
||||
tracker1.add(new Deadkey(10, 3));
|
||||
|
||||
const tracker2 = tracker1.clone();
|
||||
|
||||
assert.isTrue(tracker1.equal(tracker2));
|
||||
});
|
||||
|
||||
it('treats two trackers with identical deadkeys as equal', function () {
|
||||
const dk1 = new Deadkey(3, 1);
|
||||
const dk2 = new Deadkey(5, 2);
|
||||
const dk3 = new Deadkey(10, 3);
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(dk1);
|
||||
tracker1.add(dk2);
|
||||
tracker1.add(dk3);
|
||||
|
||||
const tracker2 = new DeadkeyTracker();
|
||||
tracker2.add(dk1);
|
||||
tracker2.add(dk2);
|
||||
tracker2.add(dk3);
|
||||
|
||||
assert.isTrue(tracker1.equal(tracker2));
|
||||
});
|
||||
|
||||
it('treats two trackers with same deadkeys create separately not as equal', function () {
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(new Deadkey(3, 1));
|
||||
tracker1.add(new Deadkey(5, 2));
|
||||
tracker1.add(new Deadkey(10, 3));
|
||||
|
||||
const tracker2 = new DeadkeyTracker();
|
||||
tracker2.add(new Deadkey(3, 1));
|
||||
tracker2.add(new Deadkey(5, 2));
|
||||
tracker2.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isFalse(tracker1.equal(tracker2));
|
||||
});
|
||||
|
||||
it('treats two trackers with same deadkeys in different order not as equal', function () {
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(new Deadkey(5, 2));
|
||||
tracker1.add(new Deadkey(3, 1));
|
||||
tracker1.add(new Deadkey(10, 3));
|
||||
|
||||
const tracker2 = new DeadkeyTracker();
|
||||
tracker2.add(new Deadkey(10, 3));
|
||||
tracker2.add(new Deadkey(5, 2));
|
||||
tracker2.add(new Deadkey(3, 1));
|
||||
|
||||
assert.isFalse(tracker1.equal(tracker2));
|
||||
});
|
||||
|
||||
it('treats two trackers with same deadkeys in different places not as equal', function () {
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(new Deadkey(7, 2));
|
||||
tracker1.add(new Deadkey(3, 1));
|
||||
tracker1.add(new Deadkey(12, 3));
|
||||
|
||||
const tracker2 = new DeadkeyTracker();
|
||||
tracker2.add(new Deadkey(10, 3));
|
||||
tracker2.add(new Deadkey(5, 2));
|
||||
tracker2.add(new Deadkey(3, 1));
|
||||
|
||||
assert.isFalse(tracker1.equal(tracker2));
|
||||
});
|
||||
|
||||
it('treats a tracker with additional deadkeys not as equal', function () {
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(new Deadkey(3, 1));
|
||||
tracker1.add(new Deadkey(5, 2));
|
||||
tracker1.add(new Deadkey(10, 3));
|
||||
|
||||
const tracker2 = tracker1.clone();
|
||||
tracker2.add(new Deadkey(15, 4));
|
||||
|
||||
assert.isFalse(tracker1.equal(tracker2));
|
||||
});
|
||||
|
||||
it('treats non-indentical trackers with duplicate deadkeys not as equal', function () {
|
||||
const dk1 = new Deadkey(3, 1);
|
||||
const dk2 = new Deadkey(5, 2);
|
||||
const dk3 = new Deadkey(10, 3);
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(dk1);
|
||||
tracker1.add(dk1); // add same again
|
||||
tracker1.add(dk2);
|
||||
|
||||
const tracker2 = new DeadkeyTracker();
|
||||
tracker2.add(dk1);
|
||||
tracker2.add(dk2);
|
||||
tracker2.add(dk3);
|
||||
|
||||
assert.isFalse(tracker1.equal(tracker2));
|
||||
});
|
||||
|
||||
it('treats indentical trackers with duplicate deadkeys as equal', function () {
|
||||
const dk1 = new Deadkey(3, 1);
|
||||
const dk2 = new Deadkey(5, 2);
|
||||
const dk3 = new Deadkey(10, 3);
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(dk1);
|
||||
tracker1.add(dk1); // add same again
|
||||
tracker1.add(dk2);
|
||||
tracker1.add(dk3);
|
||||
|
||||
const tracker2 = new DeadkeyTracker();
|
||||
tracker2.add(dk1);
|
||||
tracker2.add(dk1); // add same again
|
||||
tracker2.add(dk2);
|
||||
tracker2.add(dk3);
|
||||
|
||||
assert.isTrue(tracker1.equal(tracker2));
|
||||
});
|
||||
});
|
||||
|
||||
it('can clear deadkeys', function() {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
tracker.clear();
|
||||
|
||||
assert.equal(tracker.count(), 0);
|
||||
});
|
||||
|
||||
describe('remove', function () {
|
||||
it('can remove existing deadkey', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
const dk = new Deadkey(5, 2);
|
||||
tracker.add(dk);
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
tracker.remove(dk);
|
||||
|
||||
assert.equal(tracker.count(), 2);
|
||||
assert.equal(tracker.dks[0].p, 3);
|
||||
assert.equal(tracker.dks[1].p, 10);
|
||||
});
|
||||
|
||||
it('does not remove similar deadkey', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
tracker.remove(new Deadkey(5, 2));
|
||||
|
||||
assert.equal(tracker.count(), 3);
|
||||
assert.equal(tracker.dks[0].p, 3);
|
||||
assert.equal(tracker.dks[1].p, 5);
|
||||
assert.equal(tracker.dks[2].p, 10);
|
||||
});
|
||||
});
|
||||
|
||||
it('sorts deadkeys in cloned tracker', function () {
|
||||
const tracker1 = new DeadkeyTracker();
|
||||
tracker1.add(new Deadkey(5, 1));
|
||||
tracker1.add(new Deadkey(3, 2));
|
||||
tracker1.add(new Deadkey(10, 3));
|
||||
|
||||
const tracker2 = tracker1.clone();
|
||||
|
||||
assert.equal(tracker2.count(), 3);
|
||||
assert.equal(tracker2.dks[0].p, 10);
|
||||
assert.equal(tracker2.dks[1].p, 5);
|
||||
assert.equal(tracker2.dks[2].p, 3);
|
||||
});
|
||||
|
||||
it('can delete matched deadkeys', function () {
|
||||
const dk1 = new Deadkey(5, 1);
|
||||
const dk2 = new Deadkey(3, 2);
|
||||
const dk3 = new Deadkey(10, 3);
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(dk1);
|
||||
tracker.add(dk2);
|
||||
tracker.add(dk3);
|
||||
dk2.set();
|
||||
dk3.set();
|
||||
|
||||
tracker.deleteMatched();
|
||||
|
||||
assert.equal(tracker.count(), 1);
|
||||
assert.equal(tracker.dks[0].p, 5);
|
||||
});
|
||||
|
||||
it('can reset matched deadkeys', function () {
|
||||
const dk1 = new Deadkey(5, 1);
|
||||
const dk2 = new Deadkey(3, 2);
|
||||
const dk3 = new Deadkey(10, 3);
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(dk1);
|
||||
tracker.add(dk2);
|
||||
tracker.add(dk3);
|
||||
dk2.set();
|
||||
dk3.set();
|
||||
|
||||
tracker.resetMatched();
|
||||
|
||||
assert.equal(tracker.count(), 3);
|
||||
assert.equal(tracker.dks[0].matched, 0);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
describe('isMatch', function () {
|
||||
it('returns false without having any deadkeys', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
|
||||
assert.isFalse(tracker.isMatch(0, 1, 2));
|
||||
});
|
||||
|
||||
it('returns false for non-matching deadkey', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isFalse(tracker.isMatch(0, 88, 99));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 0);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
it('returns false if offset is wrong', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isFalse(tracker.isMatch(0, 3, 1));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 0);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
it('returns true if offset is correct and we have multiple deadkeys with same id', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 1));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isTrue(tracker.isMatch(7, 2, 1));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 0);
|
||||
assert.equal(tracker.dks[1].matched, 1);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
it('matches entry with lowest ordinal value', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isTrue(tracker.isMatch(0, -3, 1));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 1);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
it('matches entry with lowest ordinal value if caret is after deadkey', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isTrue(tracker.isMatch(5, 2, 1));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 1);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
it('returns true for matching deadkey and sets matched flag on deadkey', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isTrue(tracker.isMatch(0, -3, 1));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 1);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
it('returns true for matching deadkey if caret on dk', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
|
||||
assert.isTrue(tracker.isMatch(3, 0, 1));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 1);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
|
||||
it('returns false for matching deadkey if already matched and resets matched flag', function () {
|
||||
const tracker = new DeadkeyTracker();
|
||||
tracker.add(new Deadkey(3, 1));
|
||||
tracker.add(new Deadkey(5, 2));
|
||||
tracker.add(new Deadkey(10, 3));
|
||||
tracker.dks[0].matched = 1;
|
||||
tracker.dks[1].matched = 1;
|
||||
tracker.dks[2].matched = 1;
|
||||
|
||||
assert.isFalse(tracker.isMatch(0, -3, 1));
|
||||
|
||||
assert.equal(tracker.dks[0].matched, 0);
|
||||
assert.equal(tracker.dks[1].matched, 0);
|
||||
assert.equal(tracker.dks[2].matched, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -90,10 +90,6 @@ function do_publish() {
|
|||
rm -f setup.inf
|
||||
cat "$WINDOWS_PROGRAM_APP/setup-redist.exe" keymandesktop.zip > keymandesktop.exe
|
||||
rm -f keymandesktop.zip
|
||||
|
||||
#
|
||||
# Sign the installer
|
||||
#
|
||||
wrap-signcode //d "Keyman for Windows" keymandesktop.exe
|
||||
|
||||
builder_if_release_build_level copy-installer
|
||||
|
|
|
|||
|
|
@ -29,11 +29,10 @@ function do_build() {
|
|||
# TODO: why no manifest?
|
||||
# build_manifest.res
|
||||
delphi_msbuild insthelp.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" insthelp.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/insthelp.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_APP"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/insthelp.dbg" "$WINDOWS_DEBUGPATH_APP/insthelp.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/insthelp.pdb" "$WINDOWS_DEBUGPATH_APP"
|
||||
}
|
||||
|
||||
function do_publish() {
|
||||
|
|
@ -43,7 +42,7 @@ function do_publish() {
|
|||
|
||||
wrap-signcode //d "Keyman for Windows Install Helper" "$WINDOWS_PROGRAM_APP/insthelp.exe"
|
||||
wrap-symstore "$WINDOWS_PROGRAM_APP/insthelp.exe" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/insthelp.dbg" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/insthelp.pdb" //t keyman-windows
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
|
|
|
|||
|
|
@ -28,11 +28,10 @@ function do_build() {
|
|||
build_version.res
|
||||
build_manifest.res
|
||||
delphi_msbuild kmbrowserhost.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" kmbrowserhost.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/kmbrowserhost.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_APP"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/kmbrowserhost.dbg" "$WINDOWS_DEBUGPATH_APP/kmbrowserhost.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/kmbrowserhost.pdb" "$WINDOWS_DEBUGPATH_APP"
|
||||
}
|
||||
|
||||
function do_publish() {
|
||||
|
|
@ -41,7 +40,12 @@ function do_publish() {
|
|||
|
||||
wrap-signcode //d "Keyman for Windows" "$WINDOWS_PROGRAM_APP/kmbrowserhost.exe"
|
||||
wrap-symstore "$WINDOWS_PROGRAM_APP/kmbrowserhost.exe" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/kmbrowserhost.dbg" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/kmbrowserhost.pdb" //t keyman-windows
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$WINDOWS_PROGRAM_APP/kmbrowserhost.exe" "$INSTALLPATH_KEYMANAPP/kmbrowserhost.exe"
|
||||
cp_if_exists "$WINDOWS_DEBUGPATH_APP/kmbrowserhost.pdb" "$INSTALLPATH_KEYMANAPP/kmbrowserhost.pdb"
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
|
|
@ -49,5 +53,5 @@ builder_run_action configure:project configure_windows_build_environment
|
|||
builder_run_action build:project do_build
|
||||
# builder_run_action test:project do_test
|
||||
builder_run_action publish:project do_publish
|
||||
builder_run_action install:project cp "$WINDOWS_PROGRAM_APP/kmbrowserhost.exe" "$INSTALLPATH_KEYMANAPP/kmbrowserhost.exe"
|
||||
builder_run_action install:project do_install
|
||||
builder_run_action edit:project start kmbrowserhost.dproj
|
||||
|
|
|
|||
|
|
@ -28,11 +28,10 @@ function do_build() {
|
|||
build_version.res
|
||||
build_manifest.res
|
||||
delphi_msbuild kmconfig.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" kmconfig.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/kmconfig.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_APP"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/kmconfig.dbg" "$WINDOWS_DEBUGPATH_APP/kmconfig.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/kmconfig.pdb" "$WINDOWS_DEBUGPATH_APP"
|
||||
}
|
||||
|
||||
function do_publish() {
|
||||
|
|
@ -41,7 +40,12 @@ function do_publish() {
|
|||
|
||||
wrap-signcode //d "Keyman for Windows" "$WINDOWS_PROGRAM_APP/kmconfig.exe"
|
||||
wrap-symstore "$WINDOWS_PROGRAM_APP/kmconfig.exe" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/kmconfig.dbg" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/kmconfig.pdb" //t keyman-windows
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$WINDOWS_PROGRAM_APP/kmconfig.exe" "$INSTALLPATH_KEYMANAPP/kmconfig.exe"
|
||||
cp_if_exists "$WINDOWS_DEBUGPATH_APP/kmconfig.pdb" "$INSTALLPATH_KEYMANAPP/kmconfig.pdb"
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
|
|
@ -49,5 +53,5 @@ builder_run_action configure:project configure_windows_build_environment
|
|||
builder_run_action build:project do_build
|
||||
# builder_run_action test:project do_test
|
||||
builder_run_action publish:project do_publish
|
||||
builder_run_action install:project cp "$WINDOWS_PROGRAM_APP/kmconfig.exe" "$INSTALLPATH_KEYMANAPP/kmconfig.exe"
|
||||
builder_run_action install:project do_install
|
||||
builder_run_action edit:project start kmconfig.dproj
|
||||
|
|
|
|||
|
|
@ -35,11 +35,10 @@ function do_build() {
|
|||
build_manifest.res
|
||||
run_in_vs_env rc icons.rc
|
||||
delphi_msbuild kmshell.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" kmshell.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/kmshell.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_APP"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/kmshell.dbg" "$WINDOWS_DEBUGPATH_APP/kmshell.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/kmshell.pdb" "$WINDOWS_DEBUGPATH_APP"
|
||||
|
||||
do_build_data
|
||||
}
|
||||
|
|
@ -73,11 +72,13 @@ function do_publish() {
|
|||
|
||||
wrap-signcode //d "Keyman for Windows" "$WINDOWS_PROGRAM_APP/kmshell.exe"
|
||||
wrap-symstore "$WINDOWS_PROGRAM_APP/kmshell.exe" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/kmshell.dbg" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/kmshell.pdb" //t keyman-windows
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$WINDOWS_PROGRAM_APP/kmshell.exe" "$INSTALLPATH_KEYMANAPP/kmshell.exe"
|
||||
cp_if_exists "$WINDOWS_DEBUGPATH_APP/kmshell.pdb" "$INSTALLPATH_KEYMANAPP/kmshell.pdb"
|
||||
|
||||
rm -rf "$INSTALLPATH_KEYMANAPP/xml"
|
||||
mkdir -p "$INSTALLPATH_KEYMANAPP/xml"
|
||||
cp -r "$WINDOWS_PROGRAM_APP/xml"/* "$INSTALLPATH_KEYMANAPP/xml/"
|
||||
|
|
|
|||
|
|
@ -37,13 +37,32 @@ function do_build() {
|
|||
"$DEVTOOLS" -buildsetupstrings locale\\ .\\
|
||||
|
||||
delphi_msbuild setup.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" setup.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/setup.map" "$WIN32_TARGET"
|
||||
|
||||
#
|
||||
# The installer needs to be a multiple of 512 bytes in order for the SFX code
|
||||
# to find the ZIP header. After map2pdb appends its header, the file may not
|
||||
# be the right size. So take the file size of setup.exe and generate a nul
|
||||
# file that would expand it to nearest 512 bytes, and append it to the
|
||||
# executable. This will make the file 512 bytes larger if its size is already
|
||||
# on a 512 byte boundary.
|
||||
#
|
||||
|
||||
local file_size expansion_size expansion_file
|
||||
|
||||
file_size=$(stat -c %s "$WIN32_TARGET")
|
||||
expansion_size=$(( 512 - ( $file_size % 512 ) ))
|
||||
expansion_file="$(mktemp)"
|
||||
dd if=/dev/zero of="${expansion_file}" bs=1 count="${expansion_size}"
|
||||
cat "$WIN32_TARGET" "$expansion_file" > "$WIN32_TARGET.out"
|
||||
mv -f "$WIN32_TARGET.out" "$WIN32_TARGET"
|
||||
rm -f "${expansion_file}"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_APP"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/setup.pdb" "$WINDOWS_DEBUGPATH_APP"
|
||||
|
||||
# setup-redist.exe does not get signed as it is intended for a bundled installer
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_APP/setup-redist.exe"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/setup.dbg" "$WINDOWS_DEBUGPATH_APP/setup.dbg"
|
||||
}
|
||||
|
||||
function do_build_debug_manifest() {
|
||||
|
|
@ -61,7 +80,7 @@ function do_publish() {
|
|||
|
||||
wrap-signcode //d "Keyman for Windows Setup" "$WINDOWS_PROGRAM_APP/setup.exe"
|
||||
wrap-symstore "$WINDOWS_PROGRAM_APP/setup.exe" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/setup.dbg" //t keyman-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_APP/setup.pdb" //t keyman-windows
|
||||
}
|
||||
|
||||
builder_run_action clean:project do_clean
|
||||
|
|
|
|||
|
|
@ -27,18 +27,17 @@ function do_build() {
|
|||
create-windows-output-folders
|
||||
build_version.res
|
||||
delphi_msbuild insthelper.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" insthelper.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/insthelper.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_ENGINE"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/insthelper.dbg" "$WINDOWS_DEBUGPATH_ENGINE/insthelper.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/insthelper.pdb" "$WINDOWS_DEBUGPATH_ENGINE"
|
||||
}
|
||||
|
||||
function do_publish() {
|
||||
wrap-signcode //d "Keyman Engine for Windows" "$WINDOWS_PROGRAM_ENGINE/insthelper.dll"
|
||||
|
||||
wrap-symstore "$WINDOWS_PROGRAM_ENGINE/insthelper.dll" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/insthelper.dbg" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/insthelper.pdb" //t keyman-engine-windows
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
|
|
|
|||
|
|
@ -38,11 +38,10 @@ function do_build() {
|
|||
run_in_vs_env rc osktoolbar.rc
|
||||
run_in_vs_env rc langswitch/langswitchmanager.rc
|
||||
delphi_msbuild keyman.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" keyman.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/keyman.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_ENGINE"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/keyman.dbg" "$WINDOWS_DEBUGPATH_ENGINE/keyman.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/keyman.pdb" "$WINDOWS_DEBUGPATH_ENGINE"
|
||||
|
||||
# Also copy sentry files here
|
||||
cp "$KEYMAN_ROOT/common/windows/delphi/ext/sentry/sentry.dll" \
|
||||
|
|
@ -65,7 +64,7 @@ function do_publish() {
|
|||
wrap-signcode //d "Keyman Engine for Windows" "$WINDOWS_PROGRAM_ENGINE/crashpad_handler.exe"
|
||||
|
||||
wrap-symstore "$WINDOWS_PROGRAM_ENGINE/keyman.exe" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/keyman.dbg" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/keyman.pdb" //t keyman-engine-windows
|
||||
}
|
||||
|
||||
function do_build_debug_manifest() {
|
||||
|
|
@ -77,12 +76,17 @@ function do_build_debug_manifest() {
|
|||
mv -f std-manifest.tmp manifest.in
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$WINDOWS_PROGRAM_ENGINE/keyman.exe" "$INSTALLPATH_KEYMANENGINE/keyman.exe"
|
||||
cp_if_exists "$WINDOWS_DEBUGPATH_ENGINE/keyman.pdb" "$INSTALLPATH_KEYMANENGINE/keyman.pdb"
|
||||
}
|
||||
|
||||
builder_run_action clean:project do_clean
|
||||
builder_run_action configure:project configure_windows_build_environment
|
||||
builder_run_action build:project do_build
|
||||
# builder_run_action test:project do_test
|
||||
builder_run_action publish:project do_publish
|
||||
builder_run_action install:project cp "$WINDOWS_PROGRAM_ENGINE/keyman.exe" "$INSTALLPATH_KEYMANENGINE/keyman.exe"
|
||||
builder_run_action install:project do_install
|
||||
|
||||
builder_run_action debug-manifest:project do_build_debug_manifest
|
||||
builder_run_action edit:project start keyman.dproj
|
||||
|
|
|
|||
|
|
@ -133,18 +133,14 @@ PKEYMAN64THREADDATA Globals_InitThread()
|
|||
|
||||
void Globals_UninitThread()
|
||||
{
|
||||
OutputThreadDebugString("Globals_UninitThread");
|
||||
// OutputThreadDebugString("Globals_UninitThread");
|
||||
if (!Globals_ProcessInitialised()) {
|
||||
OutputThreadDebugString("Globals_UninitThread aborted without cleanup");
|
||||
// OutputThreadDebugString("Globals_UninitThread aborted without cleanup");
|
||||
return;
|
||||
}
|
||||
|
||||
ISerialKeyEventClient::Shutdown();
|
||||
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if (_td) {
|
||||
delete _td->pSerialKeyEventClient;
|
||||
}
|
||||
CloseThreadSharedBufferManager();
|
||||
|
||||
EnterCriticalSection(&csGlobals);
|
||||
|
|
|
|||
|
|
@ -119,27 +119,20 @@ BOOL __stdcall DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID reserved)
|
|||
switch(fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
//OutputThreadDebugString("DLL_PROCESS_ATTACH");
|
||||
if(!Globals_InitProcess()) return FALSE;
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
if (reserved == NULL) {
|
||||
// If reserved == NULL, that means the library is being unloaded, but
|
||||
// the process is not terminating.
|
||||
//OutputThreadDebugString("DLL_PROCESS_DETACH not terminating");
|
||||
UninitialiseProcess(FALSE);
|
||||
Globals_UninitProcess();
|
||||
}
|
||||
else {
|
||||
//OutputThreadDebugString("DLL_PROCESS_DETACH terminating");
|
||||
}
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
//OutputThreadDebugString("DLL_THREAD_ATTACH");
|
||||
Globals_InitThread();
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
//OutputThreadDebugString("DLL_THREAD_DETACH");
|
||||
UninitialiseProcess(FALSE);
|
||||
Globals_UninitThread();
|
||||
break;
|
||||
|
|
@ -838,7 +831,7 @@ void RefreshKeyboards(BOOL Initialising)
|
|||
|
||||
void ReleaseKeyboards(BOOL Lock)
|
||||
{
|
||||
OutputThreadDebugString("ReleaseKeyboards");
|
||||
// OutputThreadDebugString("ReleaseKeyboards");
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td || !_td->lpKeyboards) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,25 +22,25 @@ public:
|
|||
|
||||
m_hKeyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, GLOBAL_KEY_EVENT_NAME);
|
||||
if (m_hKeyEvent == 0) {
|
||||
DebugLastError("OpenEvent");
|
||||
// DebugLastError("OpenEvent");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hKeyMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, GLOBAL_KEY_MUTEX_NAME);
|
||||
if (m_hKeyMutex == 0) {
|
||||
DebugLastError("OpenMutex");
|
||||
// DebugLastError("OpenMutex");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hMMF = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, GLOBAL_FILE_MAPPING_NAME);
|
||||
if (m_hMMF == 0) {
|
||||
DebugLastError("OpenFileMapping");
|
||||
// DebugLastError("OpenFileMapping");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pSharedData = (SerialKeyEventSharedData *)MapViewOfFile(m_hMMF, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(SerialKeyEventSharedData));
|
||||
if (!m_pSharedData) {
|
||||
DebugLastError("MapViewOfFile");
|
||||
// DebugLastError("MapViewOfFile");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -48,25 +48,25 @@ public:
|
|||
SerialKeyEventClient::~SerialKeyEventClient() {
|
||||
if (m_pSharedData != NULL) {
|
||||
if (!UnmapViewOfFile(m_pSharedData)) {
|
||||
DebugLastError("UnmapViewOfFile");
|
||||
// DebugLastError("UnmapViewOfFile");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_hMMF != NULL) {
|
||||
if (!CloseHandle(m_hMMF)) {
|
||||
DebugLastError("CloseHandle(m_hMMF)");
|
||||
// DebugLastError("CloseHandle(m_hMMF)");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_hKeyMutex != NULL) {
|
||||
if (!CloseHandle(m_hKeyMutex)) {
|
||||
DebugLastError("CloseHandle(m_hKeyMutex)");
|
||||
// DebugLastError("CloseHandle(m_hKeyMutex)");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_hKeyEvent != NULL) {
|
||||
if (!CloseHandle(m_hKeyEvent)) {
|
||||
DebugLastError("CloseHandle(m_hKeyEvent)");
|
||||
// DebugLastError("CloseHandle(m_hKeyEvent)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ public:
|
|||
};
|
||||
|
||||
void ISerialKeyEventClient::Startup() {
|
||||
OutputThreadDebugString("ISerialKeyEventClient::Startup");
|
||||
// OutputThreadDebugString("ISerialKeyEventClient::Startup");
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if (_td) {
|
||||
_td->pSerialKeyEventClient = new SerialKeyEventClient();
|
||||
|
|
@ -157,7 +157,7 @@ void ISerialKeyEventClient::Startup() {
|
|||
}
|
||||
|
||||
void ISerialKeyEventClient::Shutdown() {
|
||||
OutputThreadDebugString("ISerialKeyEventClient::Shutdown");
|
||||
// OutputThreadDebugString("ISerialKeyEventClient::Shutdown");
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if (_td && _td->pSerialKeyEventClient) {
|
||||
delete _td->pSerialKeyEventClient;
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ function do_build() {
|
|||
|
||||
function do_install() {
|
||||
cp "$WINDOWS_PROGRAM_ENGINE/keymanmc.dll" "$INSTALLPATH_KEYMANENGINE/keymanmc.dll"
|
||||
reg add 'HKLM\\SYSTEM\\CurrentControlSet\\services\\eventlog\\Application\\Keyman' //v CategoryCount //t REG_DWORD //d 1 //f
|
||||
reg add 'HKLM\\SYSTEM\\CurrentControlSet\\services\\eventlog\\Application\\Keyman' //v CategoryMessageFile //t REG_SZ //d "$INSTALLPATH_KEYMANENGINE\\keymanmc.dll" //f
|
||||
reg add 'HKLM\\SYSTEM\\CurrentControlSet\\services\\eventlog\\Application\\Keyman' //v EventMessageFile //t REG_SZ //d "$INSTALLPATH_KEYMANENGINE\\keymanmc.dll" //f
|
||||
reg add 'HKLM\\SYSTEM\\CurrentControlSet\\services\\eventlog\\Application\\Keyman' //v TypesSupported //t REG_DWORD //d 7 //f
|
||||
reg add 'HKLM\SYSTEM\CurrentControlSet\services\eventlog\Application\Keyman' //v CategoryCount //t REG_DWORD //d 1 //f
|
||||
reg add 'HKLM\SYSTEM\CurrentControlSet\services\eventlog\Application\Keyman' //v CategoryMessageFile //t REG_SZ //d "$INSTALLPATH_KEYMANENGINE\\keymanmc.dll" //f
|
||||
reg add 'HKLM\SYSTEM\CurrentControlSet\services\eventlog\Application\Keyman' //v EventMessageFile //t REG_SZ //d "$INSTALLPATH_KEYMANENGINE\\keymanmc.dll" //f
|
||||
reg add 'HKLM\SYSTEM\CurrentControlSet\services\eventlog\Application\Keyman' //v TypesSupported //t REG_DWORD //d 7 //f
|
||||
}
|
||||
|
||||
builder_run_action clean:project rm -f keymanmc.dll keymanmc.h keymanmc.rc keymanmc.res MSG00409.bin
|
||||
|
|
|
|||
|
|
@ -36,15 +36,16 @@ function do_build() {
|
|||
run_in_vs_env gentlb -Tkmcomapi.tlb kmcomapi.ridl
|
||||
|
||||
delphi_msbuild kmcomapi.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" kmcomapi.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/kmcomapi.map" "$WIN32_TARGET"
|
||||
# TODO: map2pdb for .x64
|
||||
|
||||
delphi_msbuild kmcomapi.dproj "//p:Platform=Win64"
|
||||
# Delphi does not allow us to build to a different target filename so we rename after build
|
||||
mv -f "$WIN64_TARGET_PATH/kmcomapi.dll" "$WIN64_TARGET_PATH/kmcomapi.x64.dll"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_ENGINE"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/kmcomapi.dbg" "$WINDOWS_DEBUGPATH_ENGINE/kmcomapi.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/kmcomapi.pdb" "$WINDOWS_DEBUGPATH_ENGINE"
|
||||
|
||||
cp "$WIN64_TARGET_PATH/kmcomapi.x64.dll" "$WINDOWS_PROGRAM_ENGINE/kmcomapi.x64.dll"
|
||||
|
||||
# x64 Delphi symbols not supported: cp "$WIN64_TARGET_PATH/kmcomapi.dbg" "$WINDOWS_PROGRAM_ENGINE/kmcomapi.x64.dbg"
|
||||
|
|
@ -56,7 +57,7 @@ function do_publish() {
|
|||
|
||||
wrap-symstore "$WINDOWS_PROGRAM_ENGINE/kmcomapi.dll" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_PROGRAM_ENGINE/kmcomapi.x64.dll" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/kmcomapi.dbg" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/kmcomapi.pdb" //t keyman-engine-windows
|
||||
# No support for 64-bit delphi symbols
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +66,8 @@ function do_install() {
|
|||
cp "$WINDOWS_PROGRAM_ENGINE/kmcomapi.dll" "$INSTALLPATH_KEYMANENGINE/kmcomapi.dll"
|
||||
regsvr32 //s "$INSTALLPATH_KEYMANENGINE/kmcomapi.dll"
|
||||
|
||||
cp_if_exists "$WINDOWS_DEBUGPATH_ENGINE/kmcomapi.pdb" "$INSTALLPATH_KEYMANENGINE/kmcomapi.pdb"
|
||||
|
||||
regsvr32 //s //u "$INSTALLPATH_KEYMANENGINE/kmcomapi.x64.dll"
|
||||
cp "$WINDOWS_PROGRAM_ENGINE/kmcomapi.x64.dll" "$INSTALLPATH_KEYMANENGINE/kmcomapi.x64.dll"
|
||||
regsvr32 //s "$INSTALLPATH_KEYMANENGINE/kmcomapi.x64.dll"
|
||||
|
|
|
|||
|
|
@ -42,12 +42,11 @@ function do_build() {
|
|||
rm -f tsysinfox64.bin
|
||||
|
||||
delphi_msbuild tsysinfo.dproj "//p:Platform=Win32"
|
||||
sentrytool_delphiprep "$WIN32_TARGET" tsysinfo.dpr
|
||||
tds2dbg "$WIN32_TARGET"
|
||||
do_map2pdb "$WIN32_TARGET_PATH/tsysinfo.map" "$WIN32_TARGET"
|
||||
|
||||
cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_ENGINE"
|
||||
cp *.xslt "$WINDOWS_PROGRAM_ENGINE/"
|
||||
builder_if_release_build_level cp "$WIN32_TARGET_PATH/tsysinfo.dbg" "$WINDOWS_DEBUGPATH_ENGINE/tsysinfo.dbg"
|
||||
cp_if_exists "$WIN32_TARGET_PATH/tsysinfo.pdb" "$WINDOWS_DEBUGPATH_ENGINE"
|
||||
}
|
||||
|
||||
function do_publish() {
|
||||
|
|
@ -57,11 +56,12 @@ function do_publish() {
|
|||
wrap-signcode //d "Keyman Engine for Windows" "$WINDOWS_PROGRAM_ENGINE/tsysinfo.exe"
|
||||
|
||||
wrap-symstore "$WINDOWS_PROGRAM_ENGINE/tsysinfo.exe" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/tsysinfo.dbg" //t keyman-engine-windows
|
||||
wrap-symstore "$WINDOWS_DEBUGPATH_ENGINE/tsysinfo.pdb" //t keyman-engine-windows
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$WINDOWS_PROGRAM_ENGINE/tsysinfo.exe" "$INSTALLPATH_KEYMANENGINE/tsysinfo.exe"
|
||||
cp_if_exists "$WINDOWS_DEBUGPATH_ENGINE/tsysinfo.pdb" "$INSTALLPATH_KEYMANENGINE/tsysinfo.pdb"
|
||||
cp *.xslt "$INSTALLPATH_KEYMANENGINE/"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,15 +39,10 @@ function do_publish() {
|
|||
wrap-signcode //d "Keyman Engine for Windows" "$WINDOWS_PROGRAM_ENGINE/tsysinfox64.exe"
|
||||
}
|
||||
|
||||
function do_install() {
|
||||
cp "$WINDOWS_PROGRAM_ENGINE/tsysinfox64.exe" "$INSTALLPATH_KEYMANENGINE/tsysinfox64.exe"
|
||||
cp *.xslt "$INSTALLPATH_KEYMANENGINE/"
|
||||
}
|
||||
|
||||
builder_run_action clean:project clean_windows_project_files
|
||||
builder_run_action configure:project configure_windows_build_environment
|
||||
builder_run_action build:project do_build
|
||||
# builder_run_action test:project do_test
|
||||
# builder_run_action test:project (no current tests)
|
||||
builder_run_action publish:project do_publish
|
||||
builder_run_action install:project do_install
|
||||
# builder_run_action install:project (installed as part of tsysinfo)
|
||||
builder_run_action edit:project start tsysinfox64.dproj
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ begin
|
|||
pSessionProperties.Wnode.Flags := WNODE_FLAG_TRACED_GUID;
|
||||
pSessionProperties.Wnode.ClientContext := 1; //QPC clock resolution
|
||||
pSessionProperties.Wnode.Guid := SessionGuid;
|
||||
pSessionProperties.LogFileMode := EVENT_TRACE_FILE_MODE_SEQUENTIAL;
|
||||
pSessionProperties.LogFileMode := EVENT_TRACE_FILE_MODE_CIRCULAR;
|
||||
pSessionProperties.MaximumFileSize := 256; // 256 MB
|
||||
pSessionProperties.LoggerNameOffset := sizeof(EVENT_TRACE_PROPERTIES);
|
||||
pSessionProperties.LogFileNameOffset := sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGSESSION_NAME);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue