mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(platform): win64-сборка падала на GetEnvironmentVariable
Модуль Windows стоит в uses ПОСЛЕ SysUtils, поэтому его трёхпараметрический GetEnvironmentVariable(PChar;PChar;DWORD) перекрывает однопараметрический из SysUtils, и три вызова в PlatformUtils падали с «wrong number of parameters». Лечение — явная квалификация SysUtils.GetEnvironmentVariable. ★Сломалось это не сейчас: unit Windows появился в uses ещё вd209697(вместе с QueryPerformanceCounter для монотонных часов), и с тех пор под win64 не собиралось вовсе — просто сборочная машина туда не заходила. GetAppCfgDir с %APPDATA% живёт сe9f4bf1и доd209697работал. Новый стенд test/platform. Кросс-RTL обычно не установлен, поэтому ветки {$IFDEF WINDOWS} и {$IFDEF DARWIN} на Linux не компилируются ВООБЩЕ, и ошибка в них всплывает только на сборочной машине. Стенд переписывает копию PlatformUtils.pas так, чтобы платформенные условия читались как свои (-dSIMWIN / -dSIMMAC), и компилирует без линковки (-Cn): системных функций тут нет, но синтаксис, типы и — главное — разрешение имён проверяются по-настоящему. Для Windows подкладывается заглушка unit Windows, объявляющая ровно те имена, которыми настоящий перекрывает SysUtils; на ней и держится вся проверка. ★Негативный контроль: на коде до правки стенд выдаёт РОВНО те же три ошибки (строки 210, 271, 273), что и сборочная машина. Чего он не делает: живых вызовов системных счётчиков — их правильность доказывает только прогон на самой платформе. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bkwwyj7xVRrqnSVEseTRfV
This commit is contained in:
+7
-3
@@ -207,7 +207,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
// Бандл под LaunchServices не может передать argv, поэтому тот же
|
// Бандл под LaunchServices не может передать argv, поэтому тот же
|
||||||
// переключатель читается из окружения (Info.plist -> LSEnvironment).
|
// переключатель читается из окружения (Info.plist -> LSEnvironment).
|
||||||
S := LowerCase(Trim(GetEnvironmentVariable('EWSDR_OPENGL')));
|
// ★Явная квалификация: на Windows в uses стоит unit Windows, и его
|
||||||
|
// GetEnvironmentVariable(PChar;PChar;DWORD) перекрывает однопараметрический
|
||||||
|
// из SysUtils — сборка под win64 падала на «wrong number of parameters».
|
||||||
|
S := LowerCase(Trim(SysUtils.GetEnvironmentVariable('EWSDR_OPENGL')));
|
||||||
if (S = '1') or (S = 'true') or (S = 'yes') or (S = 'on') then
|
if (S = '1') or (S = 'true') or (S = 'yes') or (S = 'on') then
|
||||||
Exit(True);
|
Exit(True);
|
||||||
end;
|
end;
|
||||||
@@ -268,9 +271,10 @@ end;
|
|||||||
function GetAppCfgDir: string;
|
function GetAppCfgDir: string;
|
||||||
begin
|
begin
|
||||||
{$IFDEF WINDOWS}
|
{$IFDEF WINDOWS}
|
||||||
Result := GetEnvironmentVariable('APPDATA');
|
// Квалификация обязательна — см. HasOpenGLSpectrumSwitch.
|
||||||
|
Result := SysUtils.GetEnvironmentVariable('APPDATA');
|
||||||
if Result = '' then
|
if Result = '' then
|
||||||
Result := GetEnvironmentVariable('LOCALAPPDATA');
|
Result := SysUtils.GetEnvironmentVariable('LOCALAPPDATA');
|
||||||
if Result = '' then
|
if Result = '' then
|
||||||
Result := ExtractFilePath(ParamStr(0));
|
Result := ExtractFilePath(ParamStr(0));
|
||||||
Result := IncludeTrailingPathDelimiter(Result) + 'ewsdr' + PathDelim;
|
Result := IncludeTrailingPathDelimiter(Result) + 'ewsdr' + PathDelim;
|
||||||
|
|||||||
Executable
+44
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Проверка ветвей PlatformUtils под Windows и macOS БЕЗ этих платформ.
|
||||||
|
#
|
||||||
|
# Зачем. Кросс-RTL обычно не установлен, поэтому ветки {$IFDEF WINDOWS} и
|
||||||
|
# {$IFDEF DARWIN} на Linux не компилируются ВООБЩЕ — ошибка в них всплывает
|
||||||
|
# только на сборочной машине, через полчаса после коммита. Так и вышло: unit
|
||||||
|
# Windows, добавленный ради QueryPerformanceCounter, перекрыл однопараметрический
|
||||||
|
# SysUtils.GetEnvironmentVariable, и win64-сборка легла на трёх вызовах.
|
||||||
|
#
|
||||||
|
# Как. Копию PlatformUtils.pas переписываем так, чтобы платформенные условия
|
||||||
|
# читались как наши собственные (-dSIMWIN / -dSIMMAC), и компилируем БЕЗ
|
||||||
|
# ЛИНКОВКИ (-Cn): системных функций на Linux нет, но синтаксис, типы и — главное —
|
||||||
|
# разрешение имён проверяются по-настоящему. Для Windows подкладывается
|
||||||
|
# заглушка unit Windows с теми же перекрывающими объявлениями (win_stub/).
|
||||||
|
#
|
||||||
|
# Чего проверка НЕ делает: живых вызовов системных счётчиков. Их правильность
|
||||||
|
# доказывает только прогон на самой платформе.
|
||||||
|
set -e
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
SRC=../../PlatformUtils.pas
|
||||||
|
WORK=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$WORK"' EXIT
|
||||||
|
|
||||||
|
# ── Windows ──
|
||||||
|
mkdir -p "$WORK/win"
|
||||||
|
cp win_stub/Windows.pas "$WORK/win/"
|
||||||
|
sed -e 's/{\$IFDEF WINDOWS}/{$IFDEF SIMWIN}/g' \
|
||||||
|
-e 's/{\$IFNDEF WINDOWS}/{$IFNDEF SIMWIN}/g' "$SRC" > "$WORK/win/PlatformUtils.pas"
|
||||||
|
( cd "$WORK/win" && fpc -B -Mobjfpc -dHEADLESS -dSIMWIN -Fu. -FU. -Cn PlatformUtils.pas >"$WORK/win.log" 2>&1 ) \
|
||||||
|
|| { echo "WINDOWS-ветка НЕ компилируется:"; cat "$WORK/win.log"; exit 1; }
|
||||||
|
echo " ok PlatformUtils: ветка WINDOWS компилируется (заглушка unit Windows перекрывает SysUtils, как настоящий)"
|
||||||
|
|
||||||
|
# ── macOS ──
|
||||||
|
mkdir -p "$WORK/mac"
|
||||||
|
sed -e 's/{\$IFDEF LINUX}/{$IFDEF SIMLINUX}/g' \
|
||||||
|
-e 's/{\$IFDEF DARWIN}/{$IFDEF SIMMAC}/g' \
|
||||||
|
-e 's/{\$IF DEFINED(DARWIN) AND NOT DEFINED(HEADLESS)}/{$IF DEFINED(SIMMAC) AND NOT DEFINED(HEADLESS)}/g' \
|
||||||
|
"$SRC" > "$WORK/mac/PlatformUtils.pas"
|
||||||
|
( cd "$WORK/mac" && fpc -B -Mobjfpc -dHEADLESS -dSIMMAC -Fu. -FU. -Cn PlatformUtils.pas >"$WORK/mac.log" 2>&1 ) \
|
||||||
|
|| { echo "DARWIN-ветка НЕ компилируется:"; cat "$WORK/mac.log"; exit 1; }
|
||||||
|
echo " ok PlatformUtils: ветка DARWIN компилируется (mach_absolute_time, без линковки)"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Итого: 2 проверки, провалено 0"
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
unit Windows;
|
||||||
|
|
||||||
|
{
|
||||||
|
Заглушка модуля Windows для проверки WINDOWS-ветки на Linux.
|
||||||
|
|
||||||
|
Объявляет РОВНО те имена, которыми настоящий Windows перекрывает SysUtils —
|
||||||
|
само перекрытие и ловит ошибки, невидимые на Linux: unit Windows стоит в uses
|
||||||
|
ПОСЛЕ SysUtils, поэтому его трёхпараметрический GetEnvironmentVariable
|
||||||
|
выигрывает у однопараметрического из SysUtils, и вызов падает с «wrong number
|
||||||
|
of parameters». Ровно так win64-сборка и легла.
|
||||||
|
}
|
||||||
|
|
||||||
|
{$MODE Delphi}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
type
|
||||||
|
DWORD = LongWord;
|
||||||
|
function GetEnvironmentVariable(lpName, lpBuffer: PChar; nSize: DWORD): DWORD; stdcall;
|
||||||
|
function QueryPerformanceCounter(var lpPerformanceCount: Int64): LongBool; stdcall;
|
||||||
|
function QueryPerformanceFrequency(var lpFrequency: Int64): LongBool; stdcall;
|
||||||
|
function GetTickCount64: QWord; stdcall;
|
||||||
|
implementation
|
||||||
|
function GetEnvironmentVariable(lpName, lpBuffer: PChar; nSize: DWORD): DWORD; stdcall;
|
||||||
|
begin Result := 0; end;
|
||||||
|
function QueryPerformanceCounter(var lpPerformanceCount: Int64): LongBool; stdcall;
|
||||||
|
begin lpPerformanceCount := 123456789; Result := True; end;
|
||||||
|
function QueryPerformanceFrequency(var lpFrequency: Int64): LongBool; stdcall;
|
||||||
|
begin lpFrequency := 10000000; Result := True; end;
|
||||||
|
function GetTickCount64: QWord; stdcall;
|
||||||
|
begin Result := 42; end;
|
||||||
|
end.
|
||||||
Reference in New Issue
Block a user