Skip to content

Add Windows installer infrastructure with GitHub Actions workflow#56

Merged
thiagoralves merged 12 commits into
developmentfrom
devin/1766858787-windows-installer
Dec 31, 2025
Merged

Add Windows installer infrastructure with GitHub Actions workflow#56
thiagoralves merged 12 commits into
developmentfrom
devin/1766858787-windows-installer

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

Add Windows installer infrastructure with GitHub Actions workflow

Summary

This PR adds the infrastructure to build a Windows installer for OpenPLC Runtime v4 using MSYS2 and Inno Setup. The installer bundles a complete MSYS2 environment with GCC, Python, and all dependencies so users can run the runtime on Windows without installing additional software.

Key components added:

  • GitHub Actions workflow (windows-installer.yml) - Triggers on version tags or manual dispatch, builds the installer and publishes to GitHub Releases
  • Inno Setup script (setup.iss) - Creates a per-user Windows installer (no admin rights required)
  • Windows launcher (StartOpenPLC.bat) - Starts the runtime inside the MSYS2 environment
  • MSYS2 provisioning script (provision-msys2.sh) - Installs required packages during CI build
  • Documentation (windows/README.md) - Explains the build process and troubleshooting

Updates to core scripts for MSYS2 compatibility:

  • Modified install.sh and start_openplc.sh to detect MSYS2/MinGW/Cygwin environments using uname -s
  • Skip root check on MSYS2 (not required/meaningful on Windows)
  • Added install_deps_msys2() function for pacman-based package installation
  • Handle runtime directory creation appropriately for MSYS2 (/run/runtime instead of /var/run/runtime)

Python dependency changes:

  • Made psutil optional in requirements.txt using environment marker (psutil; sys_platform != "cygwin") since psutil doesn't support MSYS2/Cygwin
  • Added graceful degradation in runtimemanager.py when psutil is unavailable

C code portability fixes using #ifdef blocks:

  • core/src/plc_app/utils/utils.c:
    • Added HAS_REALTIME_FEATURES macro to detect Linux vs MSYS2/Cygwin
    • mlockall()/MCL_CURRENT/MCL_FUTURE - disabled on MSYS2 (memory locking not available)
    • sched_setscheduler()/SCHED_FIFO - disabled on MSYS2 (real-time scheduling not available)
    • clock_nanosleep() with TIMER_ABSTIME - replaced with nanosleep() fallback on MSYS2
  • core/src/plc_app/scan_cycle_manager.c:
    • Added OPENPLC_CLOCK macro - uses CLOCK_MONOTONIC on MSYS2/Cygwin instead of Linux-specific CLOCK_MONOTONIC_RAW
  • core/src/CMakeLists.txt:
    • Added -Wno-cpp flag on MSYS2/Cygwin to suppress _POSIX_C_SOURCE redefinition warning from Python headers
    • Detection uses CMAKE_SYSTEM_NAME MATCHES "CYGWIN|MSYS"

Review & Testing Checklist for Human

This PR has not been tested on Windows/MSYS2 - all changes were developed based on analysis and iterative feedback. The following items need verification:

  • Test C compilation on MSYS2 - Delete build/ directory and run cmake .. && make. Verify no errors from mlockall, CLOCK_MONOTONIC_RAW, sched_setscheduler, or _POSIX_C_SOURCE redefinition
  • Verify CMake detection works - Check that CMAKE_SYSTEM_NAME MATCHES "CYGWIN|MSYS" actually triggers on MSYS2 (the -Wno-cpp flag should appear in compile commands)
  • Test install.sh on MSYS2 - Run ./install.sh and verify it detects MSYS2, skips root check, and completes successfully
  • Test PLC timing behavior - Upload a simple PLC program and verify scan cycle timing is acceptable with the nanosleep/CLOCK_MONOTONIC fallbacks
  • Test the generated installer - Trigger the GitHub Actions workflow manually, download the artifact, and test on a clean Windows machine

Recommended test plan:

  1. On a Windows machine with MSYS2 installed, clone the branch
  2. Delete any existing build/ directory
  3. Run ./install.sh in MSYS2 terminal - verify compilation completes without errors
  4. Run ./start_openplc.sh and verify the webserver starts at https://localhost:8443
  5. Upload a simple PLC program and verify it runs correctly
  6. Manually trigger the GitHub Actions workflow from the Actions tab
  7. Download and test the installer on a clean Windows machine

Notes

  • The is_msys2() shell detection uses uname -s to check for MSYS*/MINGW*/CYGWIN* patterns
  • The HAS_REALTIME_FEATURES and OPENPLC_CLOCK C macros use __CYGWIN__ and __MSYS__ preprocessor definitions
  • Without psutil, the runtime cannot detect already-running PLC processes - it will always start a new one
  • Real-time features (memory locking, SCHED_FIFO, CLOCK_MONOTONIC_RAW) are disabled on MSYS2 - this is acceptable for Windows testing use case
  • The sleep_until() fallback calculates relative sleep time from absolute target; may have slightly less precise timing
  • StartOpenPLC.bat only handles C:, D:, E: drive letters for path conversion

Link to Devin run: https://app.devin.ai/sessions/64ffd9e3ddb84cc08e3e414b5296e07d
Requested by: Thiago Alves (thiago.alves@autonomylogic.com) / @thiagoralves

- Add Inno Setup script (setup.iss) for creating Windows installer
- Add MSYS2 provisioning script for CI builds
- Add Windows launcher batch file (StartOpenPLC.bat)
- Add GitHub Actions workflow for automated installer builds
- Workflow triggers on version tags and manual dispatch
- Installer bundles pre-provisioned MSYS2 with GCC, Python, and dependencies
- Per-user installation (no admin rights required)
- Creates Start Menu shortcuts automatically

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration Bot and others added 11 commits December 28, 2025 01:51
- Add is_msys2() function to detect MSYS2/MinGW/Cygwin environments
- Skip root check on MSYS2 (not required/meaningful on Windows)
- Add install_deps_msys2() function for pacman-based package installation
- Handle runtime directory creation appropriately for MSYS2
- Update check_installation() message to not suggest sudo on MSYS2

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Add environment marker to requirements.txt to skip psutil on cygwin platforms
- Add conditional import with HAS_PSUTIL flag in runtimemanager.py
- Gracefully degrade when psutil is not available:
  - find_running_process() returns None (cannot detect existing processes)
  - is_runtime_alive() and stop() handle subprocess.Popen only
- Log informational message when psutil is not available

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Add conditional compilation for Linux-specific real-time features:
  - mlockall/MCL_CURRENT/MCL_FUTURE (memory locking)
  - sched_setscheduler/SCHED_FIFO (real-time scheduling)
  - clock_nanosleep with TIMER_ABSTIME (absolute time sleep)
- Use HAS_REALTIME_FEATURES macro to detect platform support
- Provide fallback implementations for MSYS2/Cygwin:
  - sleep_until() uses nanosleep with relative time calculation
  - set_realtime_priority() and lock_memory() log info message and return
- Add -Wno-error=cpp flag on Cygwin/MSYS2 to handle _POSIX_C_SOURCE
  redefinition warning from Python headers

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Use CMAKE_SYSTEM_NAME MATCHES instead of CYGWIN/MSYS variables
- Use -Wno-error to disable all warnings-as-errors on MSYS2/Cygwin
- The -Werror=format-security is still applied after -Wno-error

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Add OPENPLC_CLOCK macro to use CLOCK_MONOTONIC on MSYS2/Cygwin
  (CLOCK_MONOTONIC_RAW is Linux-specific)
- Use proper #ifdef blocks instead of CMake -Wno-error workaround
- Change CMake from -Wno-error to -Wno-cpp to only suppress the
  _POSIX_C_SOURCE redefinition warning from Python headers

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Wrap Python.h includes with GCC diagnostic push/pop to suppress
  the _POSIX_C_SOURCE redefinition warning on MSYS2/Cygwin
- Fix applied to python_plugin_bridge.h and plugin_driver.c
- Remove CMake -Wno-cpp workaround since the fix is now in the code
- This is more robust than CMake platform detection which was unreliable

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Use WIN32 AND UNIX detection which is more reliable than CMAKE_SYSTEM_NAME
- WIN32 AND UNIX is true on MSYS2/Cygwin but not on native Windows or Linux
- Keep GCC diagnostic pragmas in Python.h includes as additional safety
- The -Wno-error flag comes after -Werror to properly override it

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Wrap priority inheritance mutex code with conditional compilation
- Use __CYGWIN__ and __MSYS__ preprocessor definitions for detection
- On MSYS2/Cygwin, use a regular mutex without priority inheritance
- Priority inheritance is a Linux-specific feature not available on MSYS2

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- Patch ssl.SSLSocket.recv to handle EAGAIN/EWOULDBLOCK (errno 11) errors
- On non-Linux platforms, return empty bytes instead of raising exception
- This fixes 'Resource temporarily unavailable' error on MSYS2/Cygwin
- Same fix as applied in OpenPLC_v3 commit 3ac3252

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
- GitHub Actions workflow now uses install.sh instead of manual dependency installation
- provision-msys2.sh now delegates to install.sh for consistent installation
- This ensures all MSYS2-specific fixes in install.sh are used during CI builds

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
@thiagoralves thiagoralves merged commit 3fab6c7 into development Dec 31, 2025
1 check passed
@thiagoralves thiagoralves deleted the devin/1766858787-windows-installer branch December 31, 2025 02:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant