@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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -2
  3. package/dist/cli.js +1696 -0
  4. package/dist/cli.js.map +34 -0
  5. package/dist/index.js +1683 -0
  6. package/dist/index.js.map +31 -0
  7. package/dist/libraries.js +128 -0
  8. package/dist/libraries.js.map +10 -0
  9. package/docker/Dockerfile +173 -0
  10. package/docker/Dockerfile.dockerignore +18 -0
  11. package/docker/Dockerfile.source +15 -0
  12. package/docker/build-image +38 -0
  13. package/docker/codesys-build +5 -0
  14. package/docker/config.ts +8 -0
  15. package/docker/control-linux-sl/Dockerfile +38 -0
  16. package/docker/edge-gateway/Dockerfile +17 -0
  17. package/docker/entrypoint.sh +10 -0
  18. package/docker/install/NOTICE.md +21 -0
  19. package/docker/install/core.sh +36 -0
  20. package/docker/install/decode.c +12 -0
  21. package/docker/install/device/Runtime.ico +0 -0
  22. package/docker/install/device/Runtime.png +0 -0
  23. package/docker/install/device/codesyscontrol.devdesc.xml +1502 -0
  24. package/docker/install/extract.py +43 -0
  25. package/docker/install/helper-launcher.c +46 -0
  26. package/docker/install/install.sh +94 -0
  27. package/docker/install/prerequisites.sh +15 -0
  28. package/docker/install/verify.py +133 -0
  29. package/docker/install/verify.sh +34 -0
  30. package/docker/install/wine-ncrypt/COPYING.LIB +502 -0
  31. package/docker/install/wine-ncrypt/README.md +28 -0
  32. package/docker/install/wine-ncrypt/enable-oaep.py +34 -0
  33. package/docker/install/wine-ncrypt/main.c +619 -0
  34. package/docker/install/wine-ncrypt/oaep.patch +11 -0
  35. package/docker/install/wine-signal/README.md +22 -0
  36. package/docker/install/wine-signal/build.sh +10 -0
  37. package/docker/install/wine-signal/check.sh +34 -0
  38. package/docker/install/wine-signal/noop-i386.c +2 -0
  39. package/docker/install/wine-signal/signal-state.c +105 -0
  40. package/docker/install/wine-signal/tests/avx-registers.c +53 -0
  41. package/docker/install/wine-signal/tests/frame-and-handler.c +192 -0
  42. package/docker/install/wine-signal/tests/loader-i386.c +8 -0
  43. package/docker/install/wine-signal/tests/signal-return.c +47 -0
  44. package/docker/install/wine-signal/wine +4 -0
  45. package/docker/runner.ts +156 -0
  46. package/package.json +53 -4
  47. package/python/build.py +660 -0
  48. package/python/codesys_login.py +100 -0
  49. package/python/codesys_online.py +327 -0
  50. package/python/test_build.py +444 -0
  51. package/python/test_codesys_login.py +120 -0
  52. package/python/test_codesys_online.py +184 -0
  53. package/python/test_installer_packages.py +216 -0
  54. package/python/test_installer_verification.py +307 -0
  55. package/python/test_worker.py +142 -0
  56. package/python/worker.py +102 -0
  57. package/runtime/install.sh +74 -0
  58. package/src/__tests__/fixtures/xml/fb-simple.xml +40 -0
  59. package/src/__tests__/fixtures/xml/fb-state-machine.xml +86 -0
  60. package/src/__tests__/fixtures/xml/prg-cyclic.xml +44 -0
  61. package/src/artifacts.ts +77 -0
  62. package/src/build.ts +87 -0
  63. package/src/cli.ts +116 -0
  64. package/src/config.ts +12 -0
  65. package/src/controller-online.ts +297 -0
  66. package/src/controller-session.ts +298 -0
  67. package/src/diagnostics.ts +68 -0
  68. package/src/docker-build.ts +163 -0
  69. package/src/docker-context.ts +35 -0
  70. package/src/docker-run.ts +103 -0
  71. package/src/host/codesys-command.ts +45 -0
  72. package/src/host/codesys-host.ts +145 -0
  73. package/src/host/codesys-worker.ts +348 -0
  74. package/src/host/windows-path.ts +73 -0
  75. package/src/index.ts +43 -0
  76. package/src/io.ts +127 -0
  77. package/src/libraries.ts +166 -0
  78. package/src/package-path.ts +5 -0
  79. package/src/run.ts +133 -0
  80. package/src/runtime-status.ts +21 -0
  81. package/src/sources.ts +248 -0
  82. package/src/st/declarations.ts +229 -0
  83. package/src/st/lexer.ts +125 -0
  84. package/src/st/parse.ts +202 -0
  85. package/src/st/reader.ts +50 -0
@@ -0,0 +1,173 @@
1
+ # Build with --platform=linux/amd64; CODESYS and its CLR are x86-64.
2
+ ARG SETUP_BASE=base
3
+ ARG SETUP_PLATFORM=linux/amd64
4
+ ARG INSTALLER_SOURCE=installer-download
5
+ FROM oven/bun:1.4.3 AS bun
6
+
7
+ FROM ubuntu:24.04 AS tools
8
+ ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 LC_ALL=C.UTF-8 \
9
+ WINEDEBUG=-all WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--disable-gpu
10
+ RUN dpkg --add-architecture i386 && apt-get -o Acquire::Retries=3 update && apt-get -o Acquire::Retries=3 install -y --no-install-recommends \
11
+ ca-certificates curl gnupg xvfb xauth cabextract unzip p7zip-full \
12
+ gcc gcc-mingw-w64-x86-64-posix python3 msitools util-linux fonts-liberation \
13
+ && mkdir -p /etc/apt/keyrings \
14
+ && curl -fsSL https://dl.winehq.org/wine-builds/winehq.key | gpg --dearmor -o /etc/apt/keyrings/winehq.gpg \
15
+ && printf '%s\n' 'deb [signed-by=/etc/apt/keyrings/winehq.gpg] https://dl.winehq.org/wine-builds/ubuntu/ noble main' > /etc/apt/sources.list.d/winehq.list \
16
+ && rm -rf /var/lib/apt/lists/*
17
+ # 11.19 includes the Wine fix for page alignment under QEMU/Rosetta (Wine bug 58084).
18
+ # Pin every Wine package: apt otherwise resolves the dependencies to the newest release.
19
+ RUN apt-get -o Acquire::Retries=3 update && apt-get -o Acquire::Retries=3 install -y --no-install-recommends \
20
+ winehq-devel=11.19~noble-1 wine-devel=11.19~noble-1 wine-devel-amd64=11.19~noble-1 wine-devel-i386:i386=11.19~noble-1 \
21
+ && curl -fsSL https://raw.githubusercontent.com/Winetricks/winetricks/20260125/src/winetricks -o /usr/local/bin/winetricks \
22
+ && chmod +x /usr/local/bin/winetricks && rm -rf /var/lib/apt/lists/*
23
+ COPY --from=bun /usr/local/bin/bun /usr/local/bin/bun
24
+ RUN userdel ubuntu && useradd --create-home --uid 1000 builder \
25
+ && mkdir /opt/wine-template /home/builder/.cache \
26
+ && chown builder:builder /opt/wine-template /home/builder/.cache
27
+ FROM tools AS base
28
+ COPY docker/install/decode.c docker/install/helper-launcher.c /opt/codesys-install/
29
+ RUN gcc -shared -fPIC -nostdlib -Wl,--no-undefined -O2 /opt/codesys-install/decode.c -o /opt/codesys-install/decode.so \
30
+ && x86_64-w64-mingw32-gcc -municode -Wall -Wextra -O2 -static \
31
+ /opt/codesys-install/helper-launcher.c -o /opt/codesys-install/CoreInstallerSupport.exe
32
+
33
+ # ARM setup uses FEX for 32-bit prerequisites that fault under Rosetta.
34
+ # Compilation is verified later under AMD64 Wine; FEX runs only setup.
35
+ FROM --platform=${SETUP_PLATFORM} ubuntu:24.04 AS arm-setup
36
+ ENV DEBIAN_FRONTEND=noninteractive
37
+ RUN apt-get -o Acquire::Retries=3 update \
38
+ && apt-get -o Acquire::Retries=3 install -y --no-install-recommends \
39
+ software-properties-common xvfb xauth cabextract unzip curl util-linux \
40
+ && add-apt-repository -y ppa:fex-emu/fex \
41
+ && apt-get -o Acquire::Retries=3 update \
42
+ && apt-get -o Acquire::Retries=3 install -y --no-install-recommends \
43
+ fex-emu-armv8.2=2610-1~n gcc python3 msitools p7zip-full fonts-liberation \
44
+ && rm -rf /var/lib/apt/lists/*
45
+ COPY --from=base /usr /opt/fex-rootfs/usr
46
+ COPY --from=base /lib /opt/fex-rootfs/lib
47
+ COPY --from=base /lib64 /opt/fex-rootfs/lib64
48
+ COPY --from=base /bin /opt/fex-rootfs/bin
49
+ COPY --from=base /sbin /opt/fex-rootfs/sbin
50
+ COPY --from=base /etc /opt/fex-rootfs/etc
51
+ COPY --from=base /opt/wine-devel /opt/fex-rootfs/opt/wine-devel
52
+ COPY --from=base /usr/local/bin/winetricks /usr/local/bin/winetricks
53
+ COPY --from=base /opt/codesys-install /opt/codesys-install
54
+ ENV FEX_ROOTFS=/opt/fex-rootfs WINEDLLPATH=/opt/fex-rootfs/opt/wine-devel/lib/wine \
55
+ WINE64=wine LANG=C.UTF-8 LC_ALL=C.UTF-8 WINEDEBUG=-all
56
+ RUN rm -f /opt/fex-rootfs/etc/resolv.conf /opt/fex-rootfs/etc/hosts /opt/fex-rootfs/etc/hostname \
57
+ && ln -s /opt/fex-rootfs/opt/wine-devel /opt/wine-devel \
58
+ && printf '#!/bin/sh\nexec FEX /opt/wine-devel/bin/wine "$@"\n' > /usr/local/bin/wine \
59
+ && printf '#!/bin/sh\nexec FEX /opt/wine-devel/bin/wineserver "$@"\n' > /usr/local/bin/wineserver \
60
+ && chmod +x /usr/local/bin/wine /usr/local/bin/wineserver \
61
+ && gcc -shared -fPIC -nostdlib -Wl,--no-undefined -O2 /opt/codesys-install/decode.c -o /opt/codesys-install/decode.so \
62
+ && userdel ubuntu && useradd --create-home --uid 1000 builder \
63
+ && mkdir /opt/wine-template /home/builder/.cache \
64
+ && chown builder:builder /opt/wine-template /home/builder/.cache
65
+
66
+ FROM scratch AS installer-download
67
+ # The archive URL serves this exact release without Store credentials.
68
+ ADD --chmod=0644 --checksum=sha256:06f8abceffffbeb23edbc909e0f06133b47d6708bf66799b5699bc08daa01c19 \
69
+ https://store-archive.codesys.com/ftp_download/3S/CODESYS/300000/3.5.22.30/CODESYS%2064%203.5.22.30.exe /codesys.exe
70
+
71
+ FROM scratch AS linux-sl-package
72
+ # Builds can target Control for Linux SL; only its device description is installed.
73
+ ADD --chmod=0644 --checksum=sha256:c34d1d9293f23c92e0130a2a9c61da1500892c6023006b85c0dcdba102b29f9a \
74
+ https://store-archive.codesys.com/ftp_download/3S/LinuxSL/2302000005/4.22.0.0/CODESYS%20Control%20for%20Linux%20SL%204.22.0.0.package /linux-sl.package
75
+
76
+ FROM ${SETUP_BASE} AS installer-local
77
+ RUN --mount=type=bind,from=installer,source=codesys.exe,target=/tmp/codesys.exe \
78
+ echo '06f8abceffffbeb23edbc909e0f06133b47d6708bf66799b5699bc08daa01c19 /tmp/codesys.exe' | sha256sum --check - \
79
+ && cp /tmp/codesys.exe /codesys.exe && chmod 644 /codesys.exe
80
+
81
+ FROM ${INSTALLER_SOURCE} AS installer-file
82
+
83
+ FROM ${SETUP_BASE} AS linux-sl-device
84
+ RUN --mount=type=bind,from=linux-sl-package,source=/linux-sl.package,target=/tmp/linux-sl.package \
85
+ unzip -j -d /linux-sl-device /tmp/linux-sl.package \
86
+ 'Devices/AddOns/CODESYS Control for Linux SL/linux/4.22.0.0/*'
87
+
88
+ FROM ${SETUP_BASE} AS init
89
+ RUN arch=$(dpkg --print-architecture) \
90
+ && curl -fsSL --retry 3 "https://github.com/krallin/tini/releases/download/v0.19.0/tini-$arch" -o "/tmp/tini-$arch" \
91
+ && curl -fsSL --retry 3 "https://github.com/krallin/tini/releases/download/v0.19.0/tini-$arch.sha256sum" -o /tmp/tini.sha256sum \
92
+ && (cd /tmp && sha256sum -c tini.sha256sum) \
93
+ && install -m 755 "/tmp/tini-$arch" /usr/local/bin/tini
94
+
95
+ FROM base AS runtime-init
96
+ RUN curl -fsSL --retry 3 'https://github.com/krallin/tini/releases/download/v0.19.0/tini-amd64' -o /tmp/tini-amd64 \
97
+ && curl -fsSL --retry 3 'https://github.com/krallin/tini/releases/download/v0.19.0/tini-amd64.sha256sum' -o /tmp/tini.sha256sum \
98
+ && (cd /tmp && sha256sum -c tini.sha256sum) \
99
+ && install -m 755 /tmp/tini-amd64 /usr/local/bin/tini
100
+
101
+ FROM ${SETUP_BASE} AS prerequisites
102
+ COPY docker/install/prerequisites.sh /opt/codesys-install/prerequisites.sh
103
+ USER builder
104
+ ENV WINEPREFIX=/opt/wine-template HOME=/home/builder WINEARCH=win64
105
+ RUN --mount=type=bind,from=installer,source=winetricks,target=/tmp/download-cache \
106
+ --mount=type=cache,id=codesys-winetricks-20260125,target=/home/builder/.cache/winetricks,uid=1000,gid=1000 \
107
+ cp -Rn /tmp/download-cache/. /home/builder/.cache/winetricks/ \
108
+ && xvfb-run -a /opt/codesys-install/prerequisites.sh
109
+
110
+ FROM prerequisites AS webview
111
+ RUN curl --fail --location --retry 3 --connect-timeout 30 --max-time 600 \
112
+ 'https://go.microsoft.com/fwlink/p/?LinkId=2124701' -o /tmp/webview2.exe \
113
+ && xvfb-run -a timeout --foreground 10m wine /tmp/webview2.exe /silent /install \
114
+ && wineserver -k && wineserver -w && rm /tmp/webview2.exe
115
+
116
+ FROM webview AS core
117
+ COPY --chmod=755 docker/install/core.sh docker/install/extract.py /opt/codesys-install/
118
+ RUN --mount=type=bind,from=installer-file,source=/codesys.exe,target=/tmp/codesys.exe \
119
+ xvfb-run -a /opt/codesys-install/core.sh /tmp/codesys.exe
120
+
121
+ FROM core AS installed
122
+ COPY --from=init /usr/local/bin/tini /usr/local/bin/tini
123
+ COPY docker/install/install.sh /opt/codesys-install/
124
+ # Wine starts orphaned helpers; BuildKit RUN needs the same reaping as docker run --init.
125
+ RUN tini -s -g -- xvfb-run -a /opt/codesys-install/install.sh
126
+
127
+ # Build the Wine-only signal adapter independently of the expensive setup cache.
128
+ FROM base AS wine-signal-compat
129
+ RUN apt-get -o Acquire::Retries=3 update \
130
+ && apt-get -o Acquire::Retries=3 install -y --no-install-recommends libc6-dev \
131
+ && rm -rf /var/lib/apt/lists/*
132
+ COPY docker/install/wine-signal /opt/codesys-install/wine-signal
133
+ RUN /opt/codesys-install/wine-signal/build.sh /opt/tsplc-wine-compat
134
+
135
+ # Only the installed prefix leaves setup. After observed managed faults under FEX,
136
+ # the compiler uses AMD64 Wine without setup's FEX wrappers, rootfs or environment.
137
+ FROM base AS builder
138
+ COPY --from=installed --chown=builder:builder /opt/wine-template /opt/wine-template
139
+ COPY --from=wine-signal-compat /opt/tsplc-wine-compat /opt/tsplc-wine-compat
140
+ COPY --chmod=755 docker/install/wine-signal/wine /usr/local/bin/wine
141
+ USER root
142
+ COPY docker/install/wine-ncrypt /opt/codesys-install/wine-ncrypt
143
+ RUN python3 /opt/codesys-install/wine-ncrypt/enable-oaep.py \
144
+ /opt/wine-devel/lib/wine/x86_64-windows/ncrypt.dll \
145
+ /opt/wine-template/drive_c/windows/system32/ncrypt.dll
146
+ COPY --chmod=755 docker/install/verify.sh /opt/codesys-install/verify.sh
147
+ COPY --from=runtime-init /usr/local/bin/tini /usr/local/bin/tini
148
+ # Verification imports the controller descriptions; changing it keeps the package install cached.
149
+ COPY --chown=builder:builder docker/install/verify.py /opt/wine-template/drive_c/verify.py
150
+ COPY --chown=builder:builder docker/install/device /opt/wine-template/drive_c/codesys-device
151
+ COPY --from=linux-sl-device --chown=builder:builder /linux-sl-device /opt/wine-template/drive_c/codesys-device-linux-sl
152
+ USER builder
153
+ ENV WINEPREFIX=/opt/wine-template HOME=/home/builder WINEARCH=win64
154
+ RUN tini -s -g -- xvfb-run -a /opt/codesys-install/verify.sh
155
+ USER root
156
+ WORKDIR /opt/codesys-build
157
+ COPY package.json ./
158
+ RUN bun install --production \
159
+ && mkdir -p /node_modules/@tsplc \
160
+ && ln -s /opt/codesys-build /node_modules/@tsplc/build
161
+ COPY shared-config /opt/tsplc-config
162
+ RUN ln -s /opt/codesys-build/node_modules /opt/tsplc-config/node_modules
163
+ RUN ln -s /opt/tsplc-config /node_modules/@tsplc/config
164
+ COPY src ./src
165
+ RUN bun build src/index.ts --target=node --packages=external --outdir dist
166
+ COPY python ./python
167
+ COPY docker/entrypoint.sh docker/runner.ts docker/config.ts ./docker/
168
+ RUN chmod +x docker/entrypoint.sh
169
+ ENV WINEPREFIX=/tmp/codesys-wine HOME=/tmp/codesys-home WINEARCH=win64 \
170
+ WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--disable-gpu
171
+ WORKDIR /workspace
172
+ ENTRYPOINT ["/opt/codesys-build/docker/entrypoint.sh"]
173
+ CMD ["--help"]
@@ -0,0 +1,18 @@
1
+ **
2
+ !package.json
3
+ !bun.lock
4
+ !src
5
+ !src/**
6
+ src/**/*.test.ts
7
+ src/__tests__
8
+ !python
9
+ !python/build.py
10
+ !python/worker.py
11
+ !python/codesys_online.py
12
+ !python/codesys_login.py
13
+ !docker
14
+ !docker/**
15
+ docker/.installer
16
+
17
+ !shared-config
18
+ !shared-config/**
@@ -0,0 +1,15 @@
1
+ # Refresh tsPLC code without reinstalling an already verified vendor compiler.
2
+ ARG BUILDER_IMAGE=tsplc-build:latest
3
+ FROM ${BUILDER_IMAGE}
4
+ USER root
5
+ WORKDIR /opt/codesys-build
6
+ COPY src /opt/codesys-build/src
7
+ COPY python /opt/codesys-build/python
8
+ COPY docker/runner.ts docker/entrypoint.sh docker/config.ts /opt/codesys-build/docker/
9
+ COPY runtime /opt/codesys-build/runtime
10
+ COPY shared-config /opt/tsplc-config
11
+ RUN bun build src/index.ts --target=node --packages=external --outdir dist \
12
+ && chmod +x /opt/codesys-build/docker/entrypoint.sh
13
+ WORKDIR /workspace
14
+ ENTRYPOINT ["/opt/codesys-build/docker/entrypoint.sh"]
15
+ CMD ["--help"]
@@ -0,0 +1,38 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ installer=
4
+ installer_source=installer-download
5
+ if [ "$#" -gt 1 ]; then
6
+ echo 'Usage: docker/build-image [ /path/to/CODESYS-64-3.5.22.30.exe ]' >&2
7
+ echo 'Downloads the official installer automatically when no file is supplied.' >&2
8
+ exit 2
9
+ fi
10
+ if [ "$#" -eq 1 ]; then
11
+ installer=$1
12
+ installer_source=installer-local
13
+ test -f "$installer" || { echo "Installer not found: $installer" >&2; exit 1; }
14
+ fi
15
+ root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
16
+ context=$(mktemp -d)
17
+ source_context=
18
+ trap 'rm -rf "$context"; if [ -n "$source_context" ]; then rm -rf "$source_context"; fi' EXIT HUP INT TERM
19
+ if [ -n "$installer" ]; then
20
+ cp "$installer" "$context/codesys.exe"
21
+ fi
22
+ mkdir "$context/winetricks"
23
+ if [ -n "${CODESYS_WINETRICKS_CACHE:-}" ]; then
24
+ test -d "$CODESYS_WINETRICKS_CACHE" || { echo 'CODESYS_WINETRICKS_CACHE must be a directory.' >&2; exit 1; }
25
+ cp -R "$CODESYS_WINETRICKS_CACHE/." "$context/winetricks/"
26
+ fi
27
+ case $(docker info --format '{{.OSType}}/{{.Architecture}}') in
28
+ linux/aarch64|linux/arm64) setup_base=arm-setup; setup_platform=linux/arm64 ;;
29
+ linux/x86_64|linux/amd64) setup_base=base; setup_platform=linux/amd64 ;;
30
+ *) echo 'The builder requires a Linux Docker server on ARM64 or AMD64.' >&2; exit 1 ;;
31
+ esac
32
+ source_context=$(bun -e 'import { pathToFileURL } from "node:url"; const { prepareDockerContext } = await import(pathToFileURL(process.argv[1]).href); console.log(await prepareDockerContext());' "$root/src/docker-context.ts")
33
+ # FEX handles ARM setup's 32-bit prerequisites; the compiler runtime stays AMD64.
34
+ docker build --platform linux/amd64 \
35
+ --build-arg "SETUP_BASE=$setup_base" --build-arg "SETUP_PLATFORM=$setup_platform" \
36
+ --build-arg "INSTALLER_SOURCE=$installer_source" --progress plain \
37
+ --build-context "installer=$context" \
38
+ -f "$source_context/docker/Dockerfile" -t "${CODESYS_BUILD_IMAGE:-tsplc-build:latest}" "$source_context"
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ # Keep the shell entrypoint on the same shared config and artifact protocol.
4
+ root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
5
+ exec bun "$root/src/cli.ts" "$@"
@@ -0,0 +1,8 @@
1
+ import { resolveConfig, type ResolvedConfig } from "../src/config.ts";
2
+
3
+ /** Only the Docker entrypoint disables dispatch after validating its request. */
4
+ export function resolveContainerConfig(input: unknown, configFile: string): ResolvedConfig {
5
+ const config = resolveConfig(input, configFile);
6
+ if (config.codesys.wine) config.codesys.wine.debug = "-all,err+seh";
7
+ return { ...config, docker: undefined };
8
+ }
@@ -0,0 +1,38 @@
1
+ # CODESYS Control for Linux SL, the line controller's runtime. CODESYS ships it only as an
2
+ # amd64 package, so this image lays it out like the Virtual Control image tsPLC deploys to.
3
+ FROM debian:12-slim AS package
4
+ RUN apt-get update && apt-get install -y --no-install-recommends unzip
5
+ ADD --checksum=sha256:c34d1d9293f23c92e0130a2a9c61da1500892c6023006b85c0dcdba102b29f9a \
6
+ https://store-archive.codesys.com/ftp_download/3S/LinuxSL/2302000005/4.22.0.0/CODESYS%20Control%20for%20Linux%20SL%204.22.0.0.package /linux-sl.package
7
+ RUN unzip -j /linux-sl.package 'Delivery/linux/codesyscontrol_linux_4.22.0.0_amd64.deb' -d /deb \
8
+ && dpkg-deb -x /deb/codesyscontrol_linux_4.22.0.0_amd64.deb /runtime
9
+
10
+ FROM debian:12-slim
11
+ COPY --from=package /runtime/etc/codesyscontrol /etc/codesyscontrol
12
+ COPY --from=package /runtime/opt/codesys /opt/codesys
13
+ COPY --from=package /runtime/var/opt/codesys /var/opt/codesys
14
+ COPY --from=package /runtime/var/opt/codesyscontrolapi /var/opt/codesyscontrolapi
15
+ # No CodeMeter daemon runs here, so don't wait 60 s for one; the runtime starts in demo mode (about 2 hours).
16
+ RUN groupadd codesyscontrolapi && sed -i \
17
+ -e 's|^FileReference.1=.*|FileReference.1=/conf/codesyscontrol/CODESYSControl_User.cfg|' \
18
+ -e 's|^InitLicenseFile.0=.*|EnableNetLicenses=1\nInstallCmActContainer=-1\nInstallLegacyCmActContainer=-1\nTimeoutWaitForCmRuntime=1|' \
19
+ /etc/codesyscontrol/CODESYSControl.cfg
20
+ COPY <<'EOF' /opt/codesys/scripts/startup.sh
21
+ #!/bin/sh
22
+ set -eu
23
+ if [ ! -f /conf/codesyscontrol/.docker_initialized ]; then
24
+ cp /etc/codesyscontrol/CODESYSControl.cfg /etc/codesyscontrol/CODESYSControl_User.cfg /conf/codesyscontrol/
25
+ touch /conf/codesyscontrol/.docker_initialized
26
+ fi
27
+ if [ ! -f /data/codesyscontrol/.docker_initialized ]; then
28
+ cp -a /var/opt/codesys/. /data/codesyscontrol/
29
+ touch /data/codesyscontrol/.docker_initialized
30
+ fi
31
+ cd /data/codesyscontrol
32
+ exec /opt/codesys/bin/codesyscontrol.bin /conf/codesyscontrol/CODESYSControl.cfg
33
+ EOF
34
+ RUN chmod +x /opt/codesys/scripts/startup.sh
35
+ ENV LD_LIBRARY_PATH=/opt/codesys/lib
36
+ VOLUME /conf/codesyscontrol /data/codesyscontrol
37
+ EXPOSE 4840 11740
38
+ ENTRYPOINT ["/opt/codesys/scripts/startup.sh"]
@@ -0,0 +1,17 @@
1
+ # CODESYS Edge Gateway for Linux: the gateway the builder container logs in to a controller
2
+ # through. Its container config logs to stdout; it keeps no state worth a volume.
3
+ FROM debian:12-slim AS package
4
+ RUN apt-get update && apt-get install -y --no-install-recommends unzip
5
+ ADD --checksum=sha256:1fdce370441cffd2849d68f075a197e1830998e875f6f239fb625b96b94a6f28 \
6
+ https://store-archive.codesys.com/ftp_download/3S/EdgeGatewayLinux/000120/4.22.0.0/CODESYS%20Edge%20Gateway%20for%20Linux%204.22.0.0.package /edge.package
7
+ RUN unzip -j /edge.package 'Delivery/edgeamd64/codesysedge_edgeamd64_4.22.0.0_amd64.deb' -d /deb \
8
+ && dpkg-deb -x /deb/codesysedge_edgeamd64_4.22.0.0_amd64.deb /gateway
9
+
10
+ FROM debian:12-slim
11
+ COPY --from=package /gateway/etc/codesysedge /etc/codesysedge
12
+ COPY --from=package /gateway/opt/codesysedge /opt/codesysedge
13
+ COPY --from=package /gateway/var/opt/codesysedge /var/opt/codesysedge
14
+ ENV LD_LIBRARY_PATH=/opt/codesysedge/lib
15
+ WORKDIR /var/opt/codesysedge
16
+ EXPOSE 1217
17
+ ENTRYPOINT ["/opt/codesysedge/bin/codesysedge.bin", "/etc/codesysedge/GatewayvControl.cfg"]
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ mkdir -p "$HOME"
4
+ if [ "$#" -eq 0 ] || [ "$1" = '--help' ] || [ "$1" = '-h' ]; then
5
+ exec bun /opt/codesys-build/docker/runner.ts "$@"
6
+ fi
7
+ # Every job gets its own writable prefix. The installed image is immutable and
8
+ # arbitrary host UIDs can write their build artifacts without root-owned files.
9
+ cp -R --no-preserve=ownership /opt/wine-template "$WINEPREFIX"
10
+ exec xvfb-run -a bun /opt/codesys-build/docker/runner.ts "$@"
@@ -0,0 +1,21 @@
1
+ The installer extractor (`extract.py`, `decode.c`), package metadata adapter
2
+ (`helper-launcher.c`), and Linux ARM64 device description come from
3
+ https://github.com/livingforjesus/codesys-macos-install-guide at commit
4
+ 1c6337991e68e4dbcdc89e43035e230aa600e5d2. The extractor is adapted for Linux
5
+ and takes explicit input/output paths. The adapter is unchanged.
6
+ On Linux, the bundled add-ons are extracted from the MSI's `ISSetupFile`
7
+ streams; `msiextract` only exposes the regular installed files.
8
+
9
+ CODESYS and Microsoft prerequisites retain their vendor licenses. The official
10
+ CODESYS installer is downloaded from the official CODESYS archive during image
11
+ creation and checked against the pinned SHA-256 of the tested installer. An
12
+ optional local copy must match the same checksum. No installer or installed IDE
13
+ is included in this source repository. The device description is for CODESYS
14
+ Virtual Control for Linux ARM64 SL 4.22.0.0, matching the supplied example.
15
+ The CODESYS Control for Linux SL 4.22.0.0 device description is extracted
16
+ during image creation from its official package, downloaded from the same
17
+ archive and checked against a pinned SHA-256; no part of it is included here.
18
+
19
+ Wine 11.19's NCrypt OAEP forwarding repair, original component source,
20
+ equivalent source patch and LGPL license are in `wine-ncrypt/`.
21
+ This provider repair leaves the original CODESYS and .NET assemblies unchanged.
@@ -0,0 +1,36 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ work=/tmp/codesys-setup
4
+ common="$WINEPREFIX/drive_c/CODESYS-3.5.22.30/CODESYS/Common"
5
+ python3 /opt/codesys-install/extract.py "$1" "$work"
6
+ msi="$work/CODESYS 64 3.5.22.30.msi"
7
+ test -f "$msi"
8
+ set +e
9
+ timeout --foreground 20m wine msiexec /i "$msi" /qn /norestart \
10
+ 'INSTALLDIR=C:\CODESYS-3.5.22.30' \
11
+ 'ADDLOCAL=Basic,CODESYS,CDS_Exe_x64,Compatibility,OEMCustomization_CDS,Only_x64,SubFeature' \
12
+ CDS_INSTALL_SERVICES=0 CDS_INSTALL_NOPACK=1 AgreeToLicense=Yes CDSAgreeToReadMe=Yes \
13
+ '/L*v' 'C:\codesys-core-install.log'
14
+ status=$?
15
+ set -e
16
+ if [ "$status" -ne 0 ]; then
17
+ echo "CODESYS MSI exited with status $status"
18
+ python3 - "$WINEPREFIX/drive_c/codesys-core-install.log" <<'PY'
19
+ import pathlib, sys
20
+ data = pathlib.Path(sys.argv[1]).read_bytes()
21
+ text = data.decode('utf-16') if data.startswith(b'\xff\xfe') else data.decode(errors='replace')
22
+ lines = text.splitlines()
23
+ print('\n'.join(lines[:25]))
24
+ for index, line in enumerate(lines):
25
+ if 'Return value 3' in line or 'Return value 0' in line or 'Error ' in line:
26
+ print('\n'.join(lines[max(0, index - 20):index + 2]))
27
+ PY
28
+ exit 1
29
+ fi
30
+ test -f "$common/CODESYS.exe"
31
+ mv "$common/CoreInstallerSupport.exe" "$common/CoreInstallerSupport.exe.wine-original"
32
+ mv "$common/CoreInstallerSupport.exe.config" "$common/CoreInstallerSupport.exe.config.wine-original"
33
+ cp /opt/codesys-install/CoreInstallerSupport.exe "$common/CoreInstallerSupport.exe"
34
+ cp "$common/CoreInstallerSupport2.exe.config" "$common/CoreInstallerSupport.exe.config"
35
+ wineserver -k
36
+ wineserver -w
@@ -0,0 +1,12 @@
1
+ #include <stddef.h>
2
+
3
+ /* InstallShield swaps each byte's nibbles, XORs the name-derived key byte,
4
+ then inverts the bits. The repeated key sequence restarts every 1024 bytes. */
5
+ void decode(unsigned char *data, size_t data_length, const unsigned char *key, size_t key_length) {
6
+ for (size_t index = 0; index < data_length; index++) {
7
+ const unsigned char byte = data[index];
8
+ const unsigned char swapped_nibbles = (unsigned char)((byte << 4) | (byte >> 4));
9
+ const unsigned char key_byte = key[(index % 1024) % key_length];
10
+ data[index] = (unsigned char)~(key_byte ^ swapped_nibbles);
11
+ }
12
+ }