Skip to content

Commit 31d063d

Browse files
andyclaude
andcommitted
Merge remote-tracking branch 'origin/main' into wip/227-bs-arrows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PFPK14wBcLD1s4dYUowpP4
2 parents 01af2df + 6519e80 commit 31d063d

140 files changed

Lines changed: 3075 additions & 252 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/build.yml‎

Lines changed: 178 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ on:
5050
workflow_dispatch:
5151
inputs:
5252
only:
53-
description: "Run just this job (debian, vendored-inventor, ubuntu, rocky, fedora, macos); empty runs all"
53+
description: "Run just this job (debian, vendored-inventor, ubuntu, rocky, fedora, macos, windows); empty runs all"
5454
required: false
5555
default: ""
5656

@@ -427,3 +427,180 @@ jobs:
427427
name: macos-app-run-${{ matrix.arch }}
428428
path: macos-app-run/
429429
if-no-files-found: ignore
430+
431+
# Windows client (#133), experimental: MSYS2 UCRT64 toolchain, the same
432+
# package set as tests/windows/README.md. Never turns the workflow red.
433+
windows:
434+
if: ${{ github.event_name != 'workflow_dispatch' || inputs.only == '' || inputs.only == 'windows' }}
435+
name: Windows (MSYS2 UCRT64)
436+
runs-on: windows-latest
437+
timeout-minutes: 120
438+
continue-on-error: true
439+
steps:
440+
# LF in the checkout: fixtures and shell scripts must not get CRLF.
441+
- run: git config --global core.autocrlf false
442+
443+
- uses: actions/checkout@v4
444+
445+
- uses: msys2/setup-msys2@v2
446+
with:
447+
msystem: UCRT64
448+
update: false
449+
cache: true
450+
install: >-
451+
base git
452+
mingw-w64-ucrt-x86_64-apr-util mingw-w64-ucrt-x86_64-ccache mingw-w64-ucrt-x86_64-cmake
453+
mingw-w64-ucrt-x86_64-coin mingw-w64-ucrt-x86_64-freetype
454+
mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gcc-fortran
455+
mingw-w64-ucrt-x86_64-glib2 mingw-w64-ucrt-x86_64-libjpeg-turbo
456+
mingw-w64-ucrt-x86_64-libssh mingw-w64-ucrt-x86_64-mosquitto
457+
mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-pkgconf
458+
mingw-w64-ucrt-x86_64-python mingw-w64-ucrt-x86_64-wxwidgets3.2-msw
459+
mingw-w64-ucrt-x86_64-xerces-c
460+
461+
# The build is ~20 minutes cold; ccache makes a rerun after a small
462+
# change a few.
463+
- uses: actions/cache@v4
464+
with:
465+
path: .ccache
466+
key: ccache-windows-${{ github.run_id }}
467+
restore-keys: ccache-windows-
468+
469+
- name: Configure
470+
shell: msys2 {0}
471+
env:
472+
CCACHE_DIR: ${{ github.workspace }}/.ccache
473+
CCACHE_MAXSIZE: 600M
474+
run: |
475+
cmake -G Ninja -B build -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE=Release -DECCE_REQUIRE_LIBSSH=ON \
476+
-DECCE_HOME_DIR="$PWD/stage/ecce" -DCMAKE_INSTALL_PREFIX="$PWD/stage/ecce"
477+
478+
- name: Build
479+
shell: msys2 {0}
480+
env:
481+
CCACHE_DIR: ${{ github.workspace }}/.ccache
482+
CCACHE_MAXSIZE: 600M
483+
# -k 0: report every failing file, not only the first few.
484+
run: cmake --build build -- -k 0
485+
486+
- name: Tests
487+
id: tests
488+
shell: msys2 {0}
489+
continue-on-error: true
490+
run: |
491+
cd build
492+
ctest -R 'transport_process|fragreaders|fragreaders_de|parsers' --output-on-failure --timeout 600 \
493+
| tee ../ctest.log
494+
exit "${PIPESTATUS[0]}"
495+
496+
- name: Install to a staging tree
497+
shell: msys2 {0}
498+
run: |
499+
cmake --install build > install.log 2>&1 || { tail -30 install.log; exit 1; }
500+
ls stage/ecce stage/ecce/bin
501+
502+
# The shell the job scripts run with, next to the apps (#133).
503+
- name: Bundle the POSIX shell
504+
shell: msys2 {0}
505+
run: packaging/windows/bundle-shell.sh "$PWD/stage/ecce" "$(cygpath -m /)"
506+
507+
# MinGW runtime DLLs and the broker, then Perl and Python, so the tree
508+
# runs with no MSYS2 on the machine.
509+
- name: Bundle the runtime
510+
shell: msys2 {0}
511+
run: |
512+
packaging/windows/bundle-runtime.sh "$PWD/stage/ecce"
513+
cp packaging/windows/ecce.cmd packaging/windows/make-shortcuts.ps1 stage/ecce/
514+
515+
- name: Download cache (Strawberry Perl, Python, wxPython)
516+
uses: actions/cache@v4
517+
with:
518+
path: ${{ runner.temp }}/ecce-dl
519+
key: windows-tools-${{ hashFiles('packaging/windows/bundle-tools.ps1') }}
520+
521+
- name: Bundle Perl and Python
522+
shell: pwsh
523+
run: packaging/windows/bundle-tools.ps1 -Install stage\ecce -Cache "$env:RUNNER_TEMP\ecce-dl"
524+
525+
- name: Zip the install tree
526+
shell: pwsh
527+
run: |
528+
$v = (Get-Content data/client/config/Version -TotalCount 1).Trim()
529+
New-Item -ItemType Directory -Force dist | Out-Null
530+
Compress-Archive -Path stage\ecce -DestinationPath "dist\ECCE-windows-$v.zip"
531+
Get-ChildItem dist | Format-Table Name, Length
532+
$d = "$env:RUNNER_TEMP\unpacked"
533+
Remove-Item -Recurse -Force $d -ErrorAction SilentlyContinue
534+
Expand-Archive "dist\ECCE-windows-$v.zip" $d
535+
"unpacked: $((Get-ChildItem $d -Recurse -File | Measure-Object Length -Sum).Sum / 1MB) MB" | Tee-Object -Append $env:GITHUB_STEP_SUMMARY
536+
Get-ChildItem "$d\ecce" | Format-Table Name
537+
# launchjob is a test driver, not part of the package.
538+
Copy-Item build\launchjob.exe "$d\ecce\bin\"
539+
540+
# Local job end to end from the unpacked zip, with System32 as the only
541+
# PATH outside it (tests/windows/launch_local.py): no MSYS2 involved.
542+
- name: Local jobs (complete, cancel)
543+
id: localjobs
544+
shell: pwsh
545+
continue-on-error: true
546+
run: |
547+
$r = "$env:RUNNER_TEMP\unpacked\ecce"
548+
New-Item -ItemType Directory -Force localjobs | Out-Null
549+
$sys = "$env:SystemRoot\System32;$env:SystemRoot"
550+
$env:Path = $sys
551+
$env:WINTEST_HOME = $r
552+
$env:WINTEST_BASE_PATH = "$r\bin;$r\usr\bin;$r\python;$r\strawberry\perl\site\bin;$r\strawberry\perl\bin;$r\strawberry\c\bin;$sys"
553+
$env:Path = $env:WINTEST_BASE_PATH
554+
& "$r\usr\bin\bash.exe" -c 'echo "$PATH"; command -v mosquitto mosquitto_sub perl python3; ls -l "$ECCE_HOME/bin/mosquitto.exe"' 2>&1 | Tee-Object localjobs\probe.log
555+
$env:Path = $sys
556+
$rc = 0
557+
foreach ($c in "complete", "cancel") {
558+
& "$r\python\python3.exe" tests/windows/launch_local.py $c --build "$r\bin" --state "$PWD\localjobs\state-$c" 2>&1 | Tee-Object "localjobs\$c.log"
559+
"$c rc=$LASTEXITCODE" | Tee-Object -Append localjobs\summary.txt
560+
if ($LASTEXITCODE -ne 0) { $rc = 1 }
561+
}
562+
Get-Content localjobs\summary.txt >> $env:GITHUB_STEP_SUMMARY
563+
exit $rc
564+
565+
# Does it run? (#133) Starts the unpacked apps on the runner's desktop
566+
# (PATH: the package and System32 only) and screenshots them. Allowed
567+
# to fail; see summary.txt.
568+
- name: Start the apps
569+
id: apps
570+
shell: pwsh
571+
continue-on-error: true
572+
timeout-minutes: 20
573+
run: |
574+
$env:Path = "$env:SystemRoot\System32;$env:SystemRoot"
575+
tests\windows\ci-run.ps1 -Stage "$env:RUNNER_TEMP\unpacked" -Out windows-run
576+
Get-Content windows-run\summary.txt >> $env:GITHUB_STEP_SUMMARY
577+
578+
- uses: actions/upload-artifact@v4
579+
if: always()
580+
with:
581+
name: ECCE-windows-zip
582+
path: dist/*.zip
583+
if-no-files-found: ignore
584+
585+
- uses: actions/upload-artifact@v4
586+
if: always()
587+
with:
588+
name: windows-run
589+
path: |
590+
windows-run/
591+
localjobs/
592+
ctest.log
593+
install.log
594+
if-no-files-found: ignore
595+
596+
# continue-on-error steps show green; say what really happened, and
597+
# fail this (experimental) job when any of them did.
598+
- name: Verdict
599+
if: always()
600+
shell: bash
601+
run: |
602+
{ echo '### Windows'
603+
echo "- ctest: ${{ steps.tests.outcome }}"
604+
echo "- local jobs: ${{ steps.localjobs.outcome }}"
605+
echo "- start the apps: ${{ steps.apps.outcome }}"; } >> "$GITHUB_STEP_SUMMARY"
606+
[ "${{ steps.tests.outcome }}${{ steps.localjobs.outcome }}${{ steps.apps.outcome }}" = successsuccesssuccess ]

‎CMakeLists.txt‎

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ endif()
9797
# "...-NOTFOUND" rather than erroring, which only surfaces later as a
9898
# baffling "Found relative path while evaluating include directories"
9999
# CMake generate-step error. Confirmed via a real macOS CI run.
100+
# PATH_SUFFIXES covers prefixes such as MSYS2's /ucrt64 (#133).
100101
find_path(FREETYPE_UNQUALIFIED_INCLUDE_DIR ftoutln.h
102+
PATH_SUFFIXES freetype2/freetype
101103
PATHS /usr/include/freetype2/freetype /usr/include/freetype
102104
/opt/homebrew/include/freetype2/freetype
103105
/usr/local/include/freetype2/freetype)
@@ -137,6 +139,21 @@ if(ECCE_USE_COIN)
137139
find_library(COIN_LIBRARY Coin REQUIRED)
138140
endif()
139141

142+
if(WIN32)
143+
# MSYS2's Coin is a DLL; moiv is a static library of ours. GL/gl.h pulls in
144+
# <windows.h>, whose full form drags in rpcndr.h's `byte`, ambiguous with
145+
# std::byte under `using namespace std`; and its min/max macros break
146+
# std::min/std::max. _POSIX_THREAD_SAFE_FUNCTIONS declares gmtime_r and
147+
# localtime_r (#133).
148+
add_compile_definitions(COIN_DLL CHEMKIT_NOT_DLL WIN32_LEAN_AND_MEAN NOMINMAX
149+
_POSIX_THREAD_SAFE_FUNCTIONS=200112L)
150+
# PosixCompat.H in every C++ file: it supplies the POSIX calls and strips
151+
# the windows.h macros (ERROR, OPAQUE, ...) that wx pulls in first.
152+
# win32compat/ stands in for the <sys/wait.h>-style headers MinGW lacks.
153+
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:SHELL:-include ${CMAKE_SOURCE_DIR}/include/util/PosixCompat.H>")
154+
include_directories(${CMAKE_SOURCE_DIR}/include/win32compat)
155+
endif()
156+
140157
if(APPLE)
141158
# ~90 files across the tree spell OpenGL headers the Linux/X11 way
142159
# ("GL/gl.h", "GL/glu.h") -- Apple's own OpenGL framework headers live
@@ -173,6 +190,10 @@ function(ecce_library name)
173190
endforeach()
174191
add_library(${name} STATIC ${_srcs})
175192
target_include_directories(${name} PRIVATE ${XercesC_INCLUDE_DIRS})
193+
if(WIN32)
194+
# The libraries reference each other in cycles; GNU ld needs them repeated.
195+
set_target_properties(${name} PROPERTIES LINK_INTERFACE_MULTIPLICITY 3)
196+
endif()
176197
endfunction()
177198

178199
# --- src/util -> libecceutil.a ---
@@ -189,6 +210,10 @@ target_compile_definitions(ecceutil PRIVATE ECCE_VERSION=\"${ECCE_VERSION_RAW}\"
189210
# Messaging (src/util/jms) is MQTT 5 on libmosquitto.
190211
pkg_check_modules(MOSQUITTO REQUIRED IMPORTED_TARGET libmosquitto)
191212
target_link_libraries(ecceutil PUBLIC PkgConfig::MOSQUITTO)
213+
if(WIN32)
214+
# POSIX regex (libtre) and Winsock, which libssh's callers use directly.
215+
target_link_libraries(ecceutil PUBLIC regex ws2_32)
216+
endif()
192217
193218
# ------------------------------------------------------------------------
194219
# Where an installed ECCE lives, and where its ecce-<app> wrappers go.
@@ -226,6 +251,9 @@ ecce_library(eccetdat
226251
# --- src/dsm -> 5 separate libraries, matching the old per-subdir mapping ---
227252
ecce_library(eccexml src/dsm/chemistry src/dsm/xml)
228253
ecce_library(eccecipc src/dsm/cipc)
254+
if(WIN32)
255+
target_link_libraries(eccecipc PUBLIC ws2_32)
256+
endif()
229257
find_package(OpenSSL REQUIRED)
230258
target_link_libraries(eccecipc PUBLIC OpenSSL::SSL OpenSSL::Crypto)
231259
ecce_library(eccedav src/dsm/dav)
@@ -268,6 +296,7 @@ endif()
268296
# this codebase) live one level down - both are needed.
269297
# Same Homebrew-path gap as FREETYPE_UNQUALIFIED_INCLUDE_DIR above.
270298
find_path(FREETYPE_ROOT_INCLUDE_DIR ft2build.h
299+
PATH_SUFFIXES freetype2
271300
PATHS /usr/include/freetype2 /usr/include
272301
/opt/homebrew/include/freetype2
273302
/usr/local/include/freetype2)
@@ -414,7 +443,13 @@ function(ecce_app name dir)
414443
if(ECCE_APP_GL)
415444
target_link_libraries(${name} PRIVATE OpenGL::GL OpenGL::GLU)
416445
endif()
417-
target_link_libraries(${name} PRIVATE ${ECCE_APP_LINK} ${XercesC_LIBRARIES})
446+
if(WIN32)
447+
# The static libraries reference each other in cycles; GNU ld rescans a group.
448+
target_link_libraries(${name} PRIVATE
449+
"$<LINK_GROUP:RESCAN,${ECCE_APP_LINK}>" ${XercesC_LIBRARIES})
450+
else()
451+
target_link_libraries(${name} PRIVATE ${ECCE_APP_LINK} ${XercesC_LIBRARIES})
452+
endif()
418453
endfunction()
419454
420455
# --- apps with no wx dependency ---
@@ -442,7 +477,9 @@ target_link_libraries(mocomp PRIVATE
442477
eccedsi eccedav eccecipc eccefaces eccexml eccetdat eccedsi eccexml ecceutil
443478
${XercesC_LIBRARIES})
444479
# flock(1) for the session scripts where util-linux is absent (macOS).
445-
add_executable(ecce-flock src/apps/flock/ecce-flock.c)
480+
if(NOT WIN32) # the Windows client has no session scripts (#133)
481+
add_executable(ecce-flock src/apps/flock/ecce-flock.c)
482+
endif()
446483
# The server half of "ecce -admin" on a -remote client (SiteRequest).
447484
add_executable(ecce-site-admin src/apps/siteadmin/ecce-site-admin.C)
448485
target_link_libraries(ecce-site-admin PRIVATE eccetdat ecceutil)
@@ -742,6 +779,7 @@ install(PROGRAMS
742779
${CMAKE_SOURCE_DIR}/packaging/gateway/ecce-gateway-status
743780
${CMAKE_SOURCE_DIR}/packaging/gateway/ecce-gateway-reap
744781
${CMAKE_SOURCE_DIR}/packaging/gateway/ecce-find-mosquitto
782+
${CMAKE_SOURCE_DIR}/packaging/windows/ecce-broker-win
745783
${CMAKE_SOURCE_DIR}/packaging/nwchem/ecce-nwchem-datadir
746784
DESTINATION bin
747785
COMPONENT client)
@@ -771,7 +809,7 @@ install(FILES ${CMAKE_BINARY_DIR}/systemd/ecce-broker.service
771809
# file (a central server's broker, ecce-gateway-start). Needs mosquitto's
772810
# plugin header and apr-util, whose apr_password_validate reads htpasswd's
773811
# hash formats.
774-
if(NOT APPLE) # macOS runs no central server
812+
if(NOT APPLE AND NOT WIN32) # macOS and Windows run no central server
775813
pkg_check_modules(APRUTIL REQUIRED IMPORTED_TARGET apr-util-1)
776814
find_path(MOSQUITTO_PLUGIN_INCLUDE_DIR mosquitto_plugin.h REQUIRED)
777815
add_library(ecce_users_auth MODULE src/mqttauth/ecce_users_auth.c)
@@ -906,8 +944,21 @@ set(ECCE_GUI_APPS
906944
mddynamics mdenergy mdoptimize mdprepare msgdialog metadyn organizer
907945
passdialog hostkeydialog pertable polyed solvate builder vizthumbnail)
908946
set(ECCE_CLI_APPS
909-
load_tgbs ecmd eccejobmaster eccejobstore ecce-localdata ecce-flock ecce-site-admin mocomp
947+
load_tgbs ecmd eccejobmaster eccejobstore ecce-localdata ecce-site-admin mocomp
910948
autosym getfrag genmol genmollat cleansym symops)
949+
if(NOT WIN32)
950+
list(APPEND ECCE_CLI_APPS ecce-flock)
951+
endif()
952+
953+
if(WIN32)
954+
# GUI subsystem: no console window opens behind the apps. The command-line
955+
# programs (ECCE_CLI_APPS, the parsers) keep theirs.
956+
foreach(_app ${ECCE_GUI_APPS})
957+
if(TARGET ${_app})
958+
set_target_properties(${_app} PROPERTIES WIN32_EXECUTABLE ON)
959+
endif()
960+
endforeach()
961+
endif()
911962

912963
install(TARGETS ${ECCE_GUI_APPS} ${ECCE_CLI_APPS} RUNTIME DESTINATION bin
913964
COMPONENT client)
@@ -1691,10 +1742,12 @@ add_executable(session_key_test tests/session/session_key_test.C)
16911742
target_link_libraries(session_key_test PRIVATE ecceutil)
16921743
add_test(NAME session-key COMMAND session_key_test
16931744
${CMAKE_SOURCE_DIR}/packaging/gateway/ecce-session-lib.sh)
1745+
if(NOT WIN32) # POSIX-only test programs
16941746
add_executable(session_lease_test tests/session/session_lease_test.C)
16951747
target_link_libraries(session_lease_test PRIVATE ecceutil)
16961748
add_test(NAME session-lease COMMAND session_lease_test
16971749
${CMAKE_SOURCE_DIR}/packaging/gateway/ecce-session-lib.sh)
1750+
endif()
16981751
add_test(NAME session-display-gate COMMAND bash
16991752
${CMAKE_SOURCE_DIR}/tests/session/display_gate.sh ${CMAKE_SOURCE_DIR})
17001753
set_tests_properties(session-display-gate PROPERTIES SKIP_RETURN_CODE 77)
@@ -1703,6 +1756,7 @@ set_tests_properties(session-display-gate PROPERTIES SKIP_RETURN_CODE 77)
17031756
# socket; checks delivery, not just acknowledgement. "auth" is the same on
17041757
# a TCP broker with two accounts and the shipped access rules. SKIPs (77)
17051758
# without the mosquitto binary.
1759+
if(NOT WIN32)
17061760
add_executable(mqtt_test tests/mqtt/mqtt_test.C)
17071761
target_include_directories(mqtt_test PRIVATE ${XercesC_INCLUDE_DIRS})
17081762
target_link_libraries(mqtt_test PRIVATE ecceutil ${XercesC_LIBRARIES})
@@ -1714,6 +1768,7 @@ if(TARGET ecce_users_auth)
17141768
set_tests_properties(mqtt-auth-plugin PROPERTIES TIMEOUT 120 SKIP_RETURN_CODE 77)
17151769
endif()
17161770
set_tests_properties(mqtt mqtt-auth PROPERTIES TIMEOUT 120 SKIP_RETURN_CODE 77)
1771+
endif()
17171772

17181773
# tests/tls -- https data-server client (#236): pinned certificate, CA mode
17191774
# with host-name check, certificate rejection, no fallback to plain http.
@@ -1923,10 +1978,18 @@ if(PYTHON3_EXECUTABLE)
19231978
set_tests_properties(filedsi PROPERTIES TIMEOUT 300)
19241979

19251980
# tests/transport -- DirectTransport against a real /bin/sh (#204).
1926-
add_executable(testTransport tests/transport/testTransport.C)
1927-
target_link_libraries(testTransport PRIVATE eccercmd ecceutil)
1928-
add_test(NAME transport COMMAND testTransport)
1929-
set_tests_properties(transport PROPERTIES TIMEOUT 120)
1981+
if(NOT WIN32)
1982+
add_executable(testTransport tests/transport/testTransport.C)
1983+
target_link_libraries(testTransport PRIVATE eccercmd ecceutil)
1984+
add_test(NAME transport COMMAND testTransport)
1985+
set_tests_properties(transport PROPERTIES TIMEOUT 120)
1986+
endif()
1987+
1988+
# Process launch (POSIX fork/exec and the Windows CreateProcess path, #133).
1989+
add_executable(testWinProcess tests/transport/testWinProcess.C)
1990+
target_link_libraries(testWinProcess PRIVATE eccercmd ecceutil)
1991+
add_test(NAME transport_process COMMAND testWinProcess)
1992+
set_tests_properties(transport_process PROPERTIES TIMEOUT 180)
19301993

19311994
# RCommand on a local machine against results recorded from the old pty
19321995
# path (#204).
@@ -1994,6 +2057,9 @@ if(PYTHON3_EXECUTABLE)
19942057
eccewxguicomm eccewxgui eccecomm eccercmd eccedsi eccedav eccecipc
19952058
eccefaces eccexml eccetdat ecceutil ${wxWidgets_LIBRARIES}
19962059
${XercesC_LIBRARIES})
2060+
if(WIN32) # GNU ld resolves static libraries in order (#133)
2061+
target_link_libraries(tailwindow PRIVATE "$<LINK_GROUP:RESCAN,eccewxguicomm;eccewxgui;eccecomm;eccercmd;eccedsi;eccedav;eccecipc;eccefaces;eccexml;eccetdat;ecceutil>" ${XercesC_LIBRARIES})
2062+
endif()
19972063
add_test(NAME transport_tail_window
19982064
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tests/transport/tail_window_test.sh
19992065
$<TARGET_FILE:tailwindow> ${CMAKE_CURRENT_SOURCE_DIR})

‎docs/claude/services/index.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,6 @@ what the deployment mode needs (GETTING_STARTED, "Deployment modes"):
4747
- [Waiting for login: a lost monitor parks the job, session start catches it up](waiting-for-login.md)
4848
- [Test suites get a per-run state directory, ports and X display](test-suites-isolate-per-run.md)
4949
- [Full builds and long suites go to radium/tellurium via tools/offload](long-suites-go-to-offload-hosts.md)
50+
- [Windows local jobs: paths in sh scripts, the job id, Strawberry perl, the broker](windows-local-jobs-pitfalls.md)
5051
- [A remote view rides ECCE's own login, not an ssh of its own (Tail)](remote-views-use-ecces-own-login.md)
5152
- [A calculation's molecule and basis properties are stored below it](calculation-properties-live-below-it.md)

0 commit comments

Comments
 (0)