@tsplc/build 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +6 -2
- package/dist/cli.js +1696 -0
- package/dist/cli.js.map +34 -0
- package/dist/index.js +1683 -0
- package/dist/index.js.map +31 -0
- package/dist/libraries.js +128 -0
- package/dist/libraries.js.map +10 -0
- package/docker/Dockerfile +173 -0
- package/docker/Dockerfile.dockerignore +18 -0
- package/docker/Dockerfile.source +15 -0
- package/docker/build-image +38 -0
- package/docker/codesys-build +5 -0
- package/docker/config.ts +8 -0
- package/docker/control-linux-sl/Dockerfile +38 -0
- package/docker/edge-gateway/Dockerfile +17 -0
- package/docker/entrypoint.sh +10 -0
- package/docker/install/NOTICE.md +21 -0
- package/docker/install/core.sh +36 -0
- package/docker/install/decode.c +12 -0
- package/docker/install/device/Runtime.ico +0 -0
- package/docker/install/device/Runtime.png +0 -0
- package/docker/install/device/codesyscontrol.devdesc.xml +1502 -0
- package/docker/install/extract.py +43 -0
- package/docker/install/helper-launcher.c +46 -0
- package/docker/install/install.sh +94 -0
- package/docker/install/prerequisites.sh +15 -0
- package/docker/install/verify.py +133 -0
- package/docker/install/verify.sh +34 -0
- package/docker/install/wine-ncrypt/COPYING.LIB +502 -0
- package/docker/install/wine-ncrypt/README.md +28 -0
- package/docker/install/wine-ncrypt/enable-oaep.py +34 -0
- package/docker/install/wine-ncrypt/main.c +619 -0
- package/docker/install/wine-ncrypt/oaep.patch +11 -0
- package/docker/install/wine-signal/README.md +22 -0
- package/docker/install/wine-signal/build.sh +10 -0
- package/docker/install/wine-signal/check.sh +34 -0
- package/docker/install/wine-signal/noop-i386.c +2 -0
- package/docker/install/wine-signal/signal-state.c +105 -0
- package/docker/install/wine-signal/tests/avx-registers.c +53 -0
- package/docker/install/wine-signal/tests/frame-and-handler.c +192 -0
- package/docker/install/wine-signal/tests/loader-i386.c +8 -0
- package/docker/install/wine-signal/tests/signal-return.c +47 -0
- package/docker/install/wine-signal/wine +4 -0
- package/docker/runner.ts +156 -0
- package/package.json +53 -4
- package/python/build.py +660 -0
- package/python/codesys_login.py +100 -0
- package/python/codesys_online.py +327 -0
- package/python/test_build.py +444 -0
- package/python/test_codesys_login.py +120 -0
- package/python/test_codesys_online.py +184 -0
- package/python/test_installer_packages.py +216 -0
- package/python/test_installer_verification.py +307 -0
- package/python/test_worker.py +142 -0
- package/python/worker.py +102 -0
- package/runtime/install.sh +74 -0
- package/src/__tests__/fixtures/xml/fb-simple.xml +40 -0
- package/src/__tests__/fixtures/xml/fb-state-machine.xml +86 -0
- package/src/__tests__/fixtures/xml/prg-cyclic.xml +44 -0
- package/src/artifacts.ts +77 -0
- package/src/build.ts +87 -0
- package/src/cli.ts +116 -0
- package/src/config.ts +12 -0
- package/src/controller-online.ts +297 -0
- package/src/controller-session.ts +298 -0
- package/src/diagnostics.ts +68 -0
- package/src/docker-build.ts +163 -0
- package/src/docker-context.ts +35 -0
- package/src/docker-run.ts +103 -0
- package/src/host/codesys-command.ts +45 -0
- package/src/host/codesys-host.ts +145 -0
- package/src/host/codesys-worker.ts +348 -0
- package/src/host/windows-path.ts +73 -0
- package/src/index.ts +43 -0
- package/src/io.ts +127 -0
- package/src/libraries.ts +166 -0
- package/src/package-path.ts +5 -0
- package/src/run.ts +133 -0
- package/src/runtime-status.ts +21 -0
- package/src/sources.ts +248 -0
- package/src/st/declarations.ts +229 -0
- package/src/st/lexer.ts +125 -0
- package/src/st/parse.ts +202 -0
- package/src/st/reader.ts +50 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Extract the 3.5.22.30 InstallShield payload (adapted from the Mac guide)."""
|
|
2
|
+
import ctypes
|
|
3
|
+
import mmap
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import struct
|
|
6
|
+
import sys
|
|
7
|
+
import zlib
|
|
8
|
+
|
|
9
|
+
library = ctypes.CDLL(str(Path(__file__).with_name("decode.so")))
|
|
10
|
+
library.decode.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_char_p, ctypes.c_size_t]
|
|
11
|
+
output = Path(sys.argv[2]).resolve()
|
|
12
|
+
output.mkdir(parents=True, exist_ok=True)
|
|
13
|
+
with open(sys.argv[1], "rb") as installer:
|
|
14
|
+
with mmap.mmap(installer.fileno(), 0, access=mmap.ACCESS_READ) as data:
|
|
15
|
+
position = data.find(b"ISSetupStream\0", 1300000)
|
|
16
|
+
if position < 0:
|
|
17
|
+
raise ValueError("Not the supported CODESYS 64 3.5.22.30 installer")
|
|
18
|
+
count, archive_type = struct.unpack_from("<HI", data, position + 14)
|
|
19
|
+
position += 46
|
|
20
|
+
for _ in range(count):
|
|
21
|
+
name_length, flags, length, compressed = struct.unpack_from("<II2xI8xH", data, position)
|
|
22
|
+
position += 48 if archive_type == 4 else 24
|
|
23
|
+
name = data[position:position + name_length].decode("utf-16le").rstrip("\0")
|
|
24
|
+
position += name_length
|
|
25
|
+
target = output / name.replace("\\", "/")
|
|
26
|
+
if not target.resolve().is_relative_to(output) or position + length > len(data):
|
|
27
|
+
raise ValueError("Invalid installer archive entry")
|
|
28
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
29
|
+
key = bytes(c ^ b"\x13\x35\x86\x07"[i % 4] for i, c in enumerate(name.encode()))
|
|
30
|
+
print(name, flush=True)
|
|
31
|
+
decompressor = zlib.decompressobj() if compressed else None
|
|
32
|
+
with target.open("wb") as destination:
|
|
33
|
+
for offset in range(0, length, 1048576):
|
|
34
|
+
block = ctypes.create_string_buffer(data[position + offset:position + min(offset + 1048576, length)])
|
|
35
|
+
size = len(block) - 1
|
|
36
|
+
if flags & 4:
|
|
37
|
+
library.decode(block, size, key, len(key))
|
|
38
|
+
destination.write(decompressor.decompress(block.raw[:size]) if decompressor else block.raw[:size])
|
|
39
|
+
if decompressor:
|
|
40
|
+
destination.write(decompressor.flush())
|
|
41
|
+
if not decompressor.eof:
|
|
42
|
+
raise ValueError("Incomplete compressed installer entry")
|
|
43
|
+
position += length
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#include <windows.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
#include <wchar.h>
|
|
5
|
+
|
|
6
|
+
/* Adapt the legacy package-manager protocol to the bundled metadata helper.
|
|
7
|
+
APPDOMAIN_MANAGER_* belongs to the old reflection helper, not helper 2. */
|
|
8
|
+
int wmain(int argc, wchar_t **argv) {
|
|
9
|
+
if (argc == 2 && !wcscmp(argv[1], L"-getAppDomainManagerAssembly")) {
|
|
10
|
+
fputs("Utilities, Version=3.5.22.30, Culture=neutral, PublicKeyToken=83380e73b2486719", stdout);
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
if (argc == 2 && !wcscmp(argv[1], L"-getAppDomainManagerType")) {
|
|
14
|
+
fputs("_3S.CoDeSys.Utilities.InstallerAppDomainManager", stdout);
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
wchar_t path[32768];
|
|
18
|
+
DWORD length = GetModuleFileNameW(NULL, path, 32768);
|
|
19
|
+
if (!length || length >= 32768) return 1;
|
|
20
|
+
wchar_t *name = wcsrchr(path, L'\\');
|
|
21
|
+
if (!name || name - path + 27 >= 32768) return 1;
|
|
22
|
+
wcscpy(name + 1, L"CoreInstallerSupport2.exe");
|
|
23
|
+
const wchar_t *args = GetCommandLineW();
|
|
24
|
+
if (*args == L'"') { args++; while (*args && *args != L'"') args++; if (*args) args++; }
|
|
25
|
+
else while (*args && *args != L' ' && *args != L'\t') args++;
|
|
26
|
+
size_t size = wcslen(path) + wcslen(args) + 4;
|
|
27
|
+
wchar_t *command = calloc(size, sizeof(wchar_t));
|
|
28
|
+
if (!command) return 1;
|
|
29
|
+
swprintf(command, size, L"\"%ls\"%ls", path, args);
|
|
30
|
+
SetEnvironmentVariableW(L"APPDOMAIN_MANAGER_ASM", NULL);
|
|
31
|
+
SetEnvironmentVariableW(L"APPDOMAIN_MANAGER_TYPE", NULL);
|
|
32
|
+
STARTUPINFOW startup = { .cb = sizeof(startup) };
|
|
33
|
+
PROCESS_INFORMATION process;
|
|
34
|
+
if (!CreateProcessW(path, command, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &process)) {
|
|
35
|
+
fwprintf(stderr, L"Cannot start CODESYS metadata helper: Windows error %lu\n", GetLastError());
|
|
36
|
+
free(command);
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
free(command);
|
|
40
|
+
CloseHandle(process.hThread);
|
|
41
|
+
DWORD result = 1;
|
|
42
|
+
if (WaitForSingleObject(process.hProcess, INFINITE) == WAIT_OBJECT_0)
|
|
43
|
+
GetExitCodeProcess(process.hProcess, &result);
|
|
44
|
+
CloseHandle(process.hProcess);
|
|
45
|
+
return (int)result;
|
|
46
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
# Keep fatal Windows exceptions visible without enabling routine Wine traces.
|
|
4
|
+
export WINEDEBUG=-all,err+seh
|
|
5
|
+
work=/tmp/codesys-setup
|
|
6
|
+
msi="$work/CODESYS 64 3.5.22.30.msi"
|
|
7
|
+
test -f "$msi"
|
|
8
|
+
# Use the same CLR configuration for installation and the verified compiler.
|
|
9
|
+
python3 - "$WINEPREFIX/drive_c/CODESYS-3.5.22.30/CODESYS/Common" <<'PY'
|
|
10
|
+
import pathlib, sys
|
|
11
|
+
for name in ("CODESYS.exe", "PackageManagerCLI.exe", "CoreInstallerSupport2.exe"):
|
|
12
|
+
path = pathlib.Path(sys.argv[1]) / (name + ".config")
|
|
13
|
+
text = path.read_text(encoding="utf-8-sig")
|
|
14
|
+
if "<runtime>" not in text:
|
|
15
|
+
raise ValueError("Missing CLR runtime configuration: " + name)
|
|
16
|
+
path.write_text(text.replace("<runtime>", '<runtime><gcConcurrent enabled="false" />', 1))
|
|
17
|
+
PY
|
|
18
|
+
mkdir "$work/streams"
|
|
19
|
+
(cd "$work/streams" && msiinfo export "$msi" ISSetupFile > "$work/setup-files.tsv")
|
|
20
|
+
python3 - "$msi" "$work/setup-files.tsv" "$WINEPREFIX/drive_c" <<'PY'
|
|
21
|
+
import csv, pathlib, subprocess, sys, zipfile
|
|
22
|
+
msi, table, output = sys.argv[1:]
|
|
23
|
+
packages = {
|
|
24
|
+
r"Packages\CODESYS Scripting 4.2.0.0.package": "scripting.package",
|
|
25
|
+
r"Packages\CODESYS RISC Front End 4.0.2.0.package": "risc.package",
|
|
26
|
+
r"Packages\CODESYS Code Generator ARM64 4.0.1.0.package": "arm64.package",
|
|
27
|
+
r"Packages\CODESYS Library Dependency Inspection 1.1.0.0.package": "library-inspection.package",
|
|
28
|
+
r"Packages\CODESYS Base Libraries 4.0.1.0.package": "base-libraries.package",
|
|
29
|
+
r"Packages\CODESYS Visualization Support 4.7.0.0.package": "visualization-support.package",
|
|
30
|
+
r"Packages\CODESYS Math Libraries 4.0.0.0.package": "math-libraries.package",
|
|
31
|
+
r"Packages\CODESYS Recipes 4.7.0.0.package": "recipes.package",
|
|
32
|
+
r"Packages\CODESYS Trace 4.4.0.0.package": "trace.package",
|
|
33
|
+
r"Packages\CODESYS Visualization 4.10.0.0.package": "visualization.package",
|
|
34
|
+
r"Packages\CODESYS Communication 4.8.0.0.package": "communication.package",
|
|
35
|
+
r"Packages\CODESYS Ethernet Adapter 4.2.0.0.package": "ethernet-adapter.package",
|
|
36
|
+
r"Packages\CODESYS EDS Import 4.3.0.0.package": "eds-import.package",
|
|
37
|
+
r"Packages\CODESYS NetX 4.1.0.0.package": "netx.package",
|
|
38
|
+
r"Packages\CODESYS EtherNetIP 4.9.1.0.package": "ethernetip.package",
|
|
39
|
+
r"Packages\CODESYS SoftMotion 4.20.2.0.package": "softmotion.package",
|
|
40
|
+
r"Packages\CODESYS Modbus 4.6.0.0.package": "modbus.package",
|
|
41
|
+
}
|
|
42
|
+
with open(table, newline="") as source:
|
|
43
|
+
for row in csv.DictReader(source, delimiter="\t"):
|
|
44
|
+
name = row["FileName"]
|
|
45
|
+
if name in packages:
|
|
46
|
+
target = pathlib.Path(output) / packages.pop(name)
|
|
47
|
+
with target.open("wb") as destination:
|
|
48
|
+
subprocess.run(["msiinfo", "extract", msi, row["Stream"]], stdout=destination, check=True)
|
|
49
|
+
with zipfile.ZipFile(target) as package:
|
|
50
|
+
if package.testzip() is not None:
|
|
51
|
+
raise ValueError("Corrupt package: " + name)
|
|
52
|
+
print("Extracted " + name, flush=True)
|
|
53
|
+
if packages:
|
|
54
|
+
raise ValueError("Missing bundled packages: " + ", ".join(packages))
|
|
55
|
+
PY
|
|
56
|
+
printf '%s\r\n' '@echo off' 'cd /d C:\CODESYS-3.5.22.30\CODESYS\Common' \
|
|
57
|
+
'set "packageComponents="' \
|
|
58
|
+
'if "%~1"=="visualization" set "packageComponents=--components=2;3;4"' \
|
|
59
|
+
'PackageManagerCLI.exe --profile="CODESYS V3.5 SP22 Patch 3" --install="C:\%~1.package" %packageComponents% --noConsole --verbose --cancelOnException --logFile="C:\package-install.log"' \
|
|
60
|
+
'set "packageStatus=%errorlevel%"' \
|
|
61
|
+
'if not "%packageStatus%"=="0" echo PackageManagerCLI Windows exit status: %packageStatus%' \
|
|
62
|
+
'exit /b %packageStatus%' > "$WINEPREFIX/drive_c/install-package.cmd"
|
|
63
|
+
# Symbol publishing also resolves AlarmManager and VisuShared. Visualization
|
|
64
|
+
# supplies those libraries and requires Communication to be installed first.
|
|
65
|
+
# Its official component IDs select Libraries, Visualization Profiles and License;
|
|
66
|
+
# the PlugIns component creates Windows shortcuts unsupported by Wine.
|
|
67
|
+
# Generated device trees need the Ethernet adapter, EDS converter and EtherNet/IP
|
|
68
|
+
# scanner; EtherNet/IP references NetX, which must be installed before it.
|
|
69
|
+
# Control for Linux SL requires SoftMotion's SM3_Basic and SM3_CNC libraries.
|
|
70
|
+
# Generated Modbus channels need the Modbus TCP devices and their editor plugin.
|
|
71
|
+
for package in scripting risc arm64 library-inspection base-libraries visualization-support math-libraries recipes trace communication visualization ethernet-adapter eds-import netx ethernetip softmotion modbus; do
|
|
72
|
+
if timeout --foreground 15m script -q -e -c "wine cmd /d /c 'C:\\install-package.cmd' '$package'" /dev/null; then
|
|
73
|
+
echo "Installed $package package"
|
|
74
|
+
else
|
|
75
|
+
status=$?
|
|
76
|
+
echo "Package $package installer exited with status $status"
|
|
77
|
+
python3 - "$WINEPREFIX/drive_c/package-install.log" <<'PY' || true
|
|
78
|
+
import pathlib, sys
|
|
79
|
+
path = pathlib.Path(sys.argv[1])
|
|
80
|
+
try:
|
|
81
|
+
if path.exists():
|
|
82
|
+
data = path.read_bytes()
|
|
83
|
+
text = data.decode('utf-16', errors='replace') if data.startswith(b'\xff\xfe') else data.decode(errors='replace')
|
|
84
|
+
print(text[-24000:])
|
|
85
|
+
except OSError as error:
|
|
86
|
+
print('Could not read package install log: ' + str(error), file=sys.stderr)
|
|
87
|
+
PY
|
|
88
|
+
exit "$status"
|
|
89
|
+
fi
|
|
90
|
+
done
|
|
91
|
+
wineserver -k
|
|
92
|
+
wineserver -w
|
|
93
|
+
rm -rf "$work" "$WINEPREFIX/drive_c/scripting.package" "$WINEPREFIX/drive_c/users/builder/Temp/"*
|
|
94
|
+
chmod -R a+rX "$WINEPREFIX"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
timeout --foreground 3m env WINEDLLOVERRIDES='mscoree,mshtml=' wine wineboot -u
|
|
4
|
+
timeout --foreground 40m winetricks -q dotnet48 vcrun2022 msxml6 win10
|
|
5
|
+
for exe in CODESYS.exe PackageManagerCLI.exe IPMCLI.exe PackageManager.exe \
|
|
6
|
+
LACUtil.exe ImportLibraryProfile.exe CoreInstallerSupport.exe CoreInstallerSupport2.exe \
|
|
7
|
+
DeletePlugInCache.exe RepairMenuConfig.exe Dependencies.exe PackageManagerSelfUpdater.exe \
|
|
8
|
+
VisualStylesEditor.exe Html5ControlEditor.exe; do
|
|
9
|
+
wine reg add "HKCU\\Software\\Wine\\AppDefaults\\$exe\\DllOverrides" /v '*security' /t REG_SZ /d native /f
|
|
10
|
+
done
|
|
11
|
+
wine regsvr32 /s oleaut32.dll
|
|
12
|
+
wine 'C:\windows\syswow64\regsvr32.exe' /s oleaut32.dll
|
|
13
|
+
wine reg add 'HKCU\Software\Microsoft\Avalon.Graphics' /v DisableHWAcceleration /t REG_DWORD /d 1 /f
|
|
14
|
+
wineserver -k
|
|
15
|
+
wineserver -w
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Verify the installed compiler and its symbol-publishing dependencies offline."""
|
|
2
|
+
from __future__ import print_function
|
|
3
|
+
|
|
4
|
+
import io
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
unicode
|
|
9
|
+
except NameError:
|
|
10
|
+
unicode = str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def fail_on_errors(engine):
|
|
14
|
+
errors = []
|
|
15
|
+
for category in engine.system.get_message_categories():
|
|
16
|
+
messages = engine.system.get_message_objects(
|
|
17
|
+
category, engine.Severity.Error | engine.Severity.FatalError,
|
|
18
|
+
)
|
|
19
|
+
for message in messages:
|
|
20
|
+
project = getattr(message, 'project', None)
|
|
21
|
+
location = unicode(project.path) if project is not None else unicode(category)
|
|
22
|
+
errors.append(location + ': ' + unicode(message.text))
|
|
23
|
+
if errors:
|
|
24
|
+
raise RuntimeError('CODESYS installation verification failed:\n' + '\n'.join(errors))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Controllers a build can target: the bundled ARM64 description for the local
|
|
28
|
+
# Virtual Control, and Control for Linux SL from its official package. Linux SL
|
|
29
|
+
# skips the reopen check: its SoftMotion libraries carry visualization templates
|
|
30
|
+
# whose System_VisuElem* placeholders resolve only through a project's
|
|
31
|
+
# visualization profile, which scripting cannot give a new project. Its compile
|
|
32
|
+
# and boot application still prove the device, code generator and libraries.
|
|
33
|
+
CONTROLLERS = (
|
|
34
|
+
(r'C:\codesys-device', 'codesys-verification', 4096, '0000 1008', '4.22.0.0', True),
|
|
35
|
+
(r'C:\codesys-device-linux-sl', 'codesys-verification-linux-sl', 4102, '0000 0005', '4.22.0.0', False),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def uses_byte_addressing(description):
|
|
40
|
+
"""CODESYS numbers %IW and %ID by element unless the device sets this target setting."""
|
|
41
|
+
return re.search(
|
|
42
|
+
r'name="byte-addressing"[^>]*>\s*<(?:\w+:)?value>\s*true\s*<', description, re.IGNORECASE,
|
|
43
|
+
) is not None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def verify_controller(engine, stem, kind, identifier, version, reopen):
|
|
47
|
+
from System import Guid
|
|
48
|
+
|
|
49
|
+
path = 'C:\\' + stem + '.project'
|
|
50
|
+
project = engine.projects.create(path, primary=True)
|
|
51
|
+
try:
|
|
52
|
+
project.add('Device', kind, identifier, version)
|
|
53
|
+
application = project.active_application
|
|
54
|
+
if application is None:
|
|
55
|
+
raise RuntimeError('Verification device did not create an Application')
|
|
56
|
+
program = application.create_program('PLC_PRG')
|
|
57
|
+
program.textual_declaration.replace(
|
|
58
|
+
"PROGRAM PLC_PRG\nVAR\n"
|
|
59
|
+
" {attribute 'symbol' := 'readwrite'}\n"
|
|
60
|
+
" Counter : UDINT;\nEND_VAR\n"
|
|
61
|
+
)
|
|
62
|
+
program.textual_implementation.replace('Counter := Counter + 1;\n')
|
|
63
|
+
task = application.create_task_configuration().create_task('MainTask')
|
|
64
|
+
task.kind_of_task = engine.KindOfTask.Cyclic
|
|
65
|
+
task.priority = '1'
|
|
66
|
+
task.interval_unit = 'ms'
|
|
67
|
+
task.interval = '20'
|
|
68
|
+
task.pous.add('PLC_PRG')
|
|
69
|
+
application.create_symbol_config(
|
|
70
|
+
True, True, Guid('{0141eb75-141b-4ea1-9a8c-75f952b22a6c}'),
|
|
71
|
+
)
|
|
72
|
+
project.save()
|
|
73
|
+
for category in engine.system.get_message_categories():
|
|
74
|
+
engine.system.clear_messages(category)
|
|
75
|
+
application.clean()
|
|
76
|
+
application.rebuild()
|
|
77
|
+
fail_on_errors(engine)
|
|
78
|
+
application.generate_code()
|
|
79
|
+
fail_on_errors(engine)
|
|
80
|
+
application.create_boot_application('C:\\' + stem + '.app', True, False)
|
|
81
|
+
fail_on_errors(engine)
|
|
82
|
+
project.save()
|
|
83
|
+
project.close()
|
|
84
|
+
project = None
|
|
85
|
+
if not reopen:
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
# Compilation can succeed before missing transitive libraries are
|
|
89
|
+
# reported. Reopening exercises library resolution on the saved project.
|
|
90
|
+
project = engine.projects.open(path, primary=True)
|
|
91
|
+
project.active_application.get_library_manager().get_libraries(recursive=True)
|
|
92
|
+
engine.system.delay(1000)
|
|
93
|
+
fail_on_errors(engine)
|
|
94
|
+
finally:
|
|
95
|
+
if project is not None:
|
|
96
|
+
project.close()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def verify(engine):
|
|
100
|
+
engine.system.script_prompt_handling = engine.ScriptPromptHandling.LogPrompts
|
|
101
|
+
for directory, _, _, _, _, _ in CONTROLLERS:
|
|
102
|
+
path = directory + r'\codesyscontrol.devdesc.xml'
|
|
103
|
+
with io.open(path, encoding='utf-8-sig') as description:
|
|
104
|
+
# tsPLC places and checks numeric I/O assuming element addressing.
|
|
105
|
+
if uses_byte_addressing(description.read()):
|
|
106
|
+
raise RuntimeError(path + ' sets byte-addressing; tsPLC supports element addressing only')
|
|
107
|
+
engine.device_repository.import_device(
|
|
108
|
+
path=path,
|
|
109
|
+
source=engine.device_repository.sources[0],
|
|
110
|
+
save_device_cache=True,
|
|
111
|
+
)
|
|
112
|
+
for _, stem, kind, identifier, version, reopen in CONTROLLERS:
|
|
113
|
+
verify_controller(engine, stem, kind, identifier, version, reopen)
|
|
114
|
+
# Generated device trees place these descriptions under the controller.
|
|
115
|
+
repository = engine.device_repository
|
|
116
|
+
for kind, identifier, version in ((110, '0000 0002', '4.2.0.0'), (100, '0000 100B', '4.9.0.0')):
|
|
117
|
+
if repository.get_device(repository.create_device_identification(kind, identifier, version)) is None:
|
|
118
|
+
raise RuntimeError('Missing EtherNet/IP device description {0} {1}'.format(kind, identifier))
|
|
119
|
+
print('CODESYS ARM64 and Linux SL compilation and symbol publishing, ARM64 project reopen: PASS')
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
if __name__ == '__main__':
|
|
123
|
+
import ctypes
|
|
124
|
+
import scriptengine
|
|
125
|
+
import traceback
|
|
126
|
+
|
|
127
|
+
native_exit = ctypes.windll.kernel32.ExitProcess
|
|
128
|
+
try:
|
|
129
|
+
verify(scriptengine)
|
|
130
|
+
except Exception:
|
|
131
|
+
traceback.print_exc()
|
|
132
|
+
native_exit(1)
|
|
133
|
+
native_exit(0)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
# Verify with the AMD64 Wine/CLR used by the compiler, after setup's FEX stage.
|
|
4
|
+
export WINEDEBUG=-all,err+seh
|
|
5
|
+
# Require fresh artifacts from this invocation, including on reused prefixes.
|
|
6
|
+
rm -f "$WINEPREFIX/drive_c/codesys-verification.project" \
|
|
7
|
+
"$WINEPREFIX/drive_c/codesys-verification.app" \
|
|
8
|
+
"$WINEPREFIX/drive_c/codesys-verification.crc"
|
|
9
|
+
printf '%s\r\n' '@echo off' 'cd /d C:\CODESYS-3.5.22.30\CODESYS\Common' \
|
|
10
|
+
'CODESYS.exe --profile="CODESYS V3.5 SP22 Patch 3" --noUI --textPrompts --runscript="C:\verify.py"' \
|
|
11
|
+
'exit /b %errorlevel%' > "$WINEPREFIX/drive_c/verify.cmd"
|
|
12
|
+
transcript="$WINEPREFIX/drive_c/codesys-verification.log"
|
|
13
|
+
if timeout --foreground 15m script -q -e -c "wine cmd /d /c 'C:\\verify.cmd'" "$transcript"; then
|
|
14
|
+
:
|
|
15
|
+
else
|
|
16
|
+
status=$?
|
|
17
|
+
echo "CODESYS verification exited with status $status; transcript: $transcript" >&2
|
|
18
|
+
exit "$status"
|
|
19
|
+
fi
|
|
20
|
+
# A Wine helper can assert while the main compiler still returns zero.
|
|
21
|
+
python3 - "$transcript" <<'PY'
|
|
22
|
+
import pathlib, re, sys
|
|
23
|
+
path = pathlib.Path(sys.argv[1])
|
|
24
|
+
text = path.read_bytes().decode(errors='replace')
|
|
25
|
+
text = re.sub(r'\x1b\[[0-?]*[ -/]*[@-~]', '', text).replace('\r', '')
|
|
26
|
+
assertion = re.search(r'^assertion failed \[[^\n]+\]:[^\n]*\n[ \t]*\(ThreadContext[^\n]*\)', text, re.M)
|
|
27
|
+
if assertion:
|
|
28
|
+
raise SystemExit('Wine translation aborted: ' + ' '.join(assertion.group().split()) + '. See ' + str(path))
|
|
29
|
+
PY
|
|
30
|
+
test -s "$WINEPREFIX/drive_c/codesys-verification.project"
|
|
31
|
+
test -s "$WINEPREFIX/drive_c/codesys-verification.app"
|
|
32
|
+
test -s "$WINEPREFIX/drive_c/codesys-verification.crc"
|
|
33
|
+
wineserver -k
|
|
34
|
+
wineserver -w
|