Skip to content

feat(compat.openssl): add Windows support via VC-WIN64A + nmake sourc… - #211

Open
FarnaHerry wants to merge 3 commits into
mcpplibs:mainfrom
FarnaHerry:feat/openssl-windows-source-build
Open

feat(compat.openssl): add Windows support via VC-WIN64A + nmake sourc…#211
FarnaHerry wants to merge 3 commits into
mcpplibs:mainfrom
FarnaHerry:feat/openssl-windows-source-build

Conversation

@FarnaHerry

Copy link
Copy Markdown
Collaborator

Summary

Adds Windows support to compat.openssl — the last major package in the index still
marked "windows deferred". OpenSSL is built from the same source tarball the other
platforms use, through Windows' only x64 configuration path:
perl Configure VC-WIN64A + nmake, producing MSVC-ABI static
libssl.lib / libcrypto.lib.

This is the missing link that unblocks compat.libmysqlclient on Windows — its
mcpp.toml already has the Windows build segment written (win_timers.cc,
-lws2_32, …); openssl was the one dependency it couldn't resolve. This PR
intentionally does not add libmysqlclient's windows xpm line; that's the follow-up.

Changes (pkgs/c/compat.openssl.lua, +192/−6)

  1. xpm: add a windows entry — same source tarball / sha256 as linux/macosx;
    only the build path differs.

  2. mcpp: add windows ldflags

    windows = { ldflags = { "-Llib", "-llibssl", "-llibcrypto",
                            "-lws2_32", "-lcrypt32", "-ladvapi32", "-luser32" } },

    Naming matters: the MSVC static libs are libssl.lib / libcrypto.lib, and
    lld-link's -lX looks for X.lib, so -lssl would fail — they must be
    -llibssl / -llibcrypto. Static libcrypto's own system deps
    (winsock / crypt / registry / windowing) are listed explicitly, mirroring how the
    linux leg lists -ldl / -lpthread.

  3. install() routes Windows to _install_windows() instead of erroring out.

  4. _install_windows() + helpers — generates one .bat that runs the whole build
    inside a single vcvars64 environment (Configure → nmake → install_sw), verifies
    libssl.lib / libcrypto.lib, and writes the anchor TU. Helpers:
    find_vcvars() (vswhere, then well-known VS paths),
    resolve_perl_windows() / perl_usable_windows() (Strawberry-first, with the
    extra module probe), win_dirname() (xpkg has no path.dirname).
    Build config: no-shared no-dso no-tests no-apps no-engine no-asm.

Pitfalls for maintainers (all found on real hardware)

These are why the Windows path looks the way it does:

  1. The xpkg hook env on Windows is missing os.rm and path.dirname. Calling
    os.rm throws attempt to call a nil value and would take the whole install()
    down, so it's invoked through pcall. path.join exists but path.dirname
    doesn't — win_dirname() hand-rolls it.
  2. OpenSSL's Configure needs Locale::Maketext::Simple (via Params::Check →
    IPC::Cmd). Git-for-Windows' MSYS perl doesn't ship it and dies deep inside
    Configure. The existing perl_usable() module check (Config/FindBin/File::Path/…)
    does not include this module and would wrongly accept MSYS perl, so the Windows
    probe explicitly requires Locale::Maketext::Simple. Strawberry Perl
    (scoop perl or C:\Strawberry) is required.
  3. os.exec("bash -c …") silently does nothing in the Windows hook env. It
    returns true but the command never runs (probed directly: target file not
    produced, vswhere output empty). So the Windows branch cannot reuse the shared
    run() helper — it drives the build via os.exec("cmd /c <bat> > <log> 2>&1")
    instead.
  4. vcvars does NOT crash on real Windows — the old note is stale. The prior
    comment claimed "running vcvars in ANY form takes the whole process chain down".
    Tested on Windows 11 + VS 2022/18: cmd /c "vcvars64.bat & set" runs fine (also
    invoked from bash) and dumps INCLUDE/LIB/PATH correctly. That crash was specific
    to the old xlings hook env (almost certainly the same bash -c no-op as feat: add mcpplibs.tinyhttps 0.2.1 + mcpplibs.llmapi 0.2.4 #3), not
    a property of Windows.

→ Could a maintainer update the now-outdated note in
.agents/docs/2026-08-05-openssl-windows-todo.md (the "vcvars takes down the process
chain" claim) accordingly?

Verification (this machine, full chain)

  1. Manual recipe: perl Configure VC-WIN64A no-shared no-tests no-asm --prefix=… --libdir=lib + nmakelibcrypto.lib (48MB) + libssl.lib (10MB).
  2. clang-cl links libssl.lib + libcrypto.lib + ws2_32 + crypt32 + advapi32 + user32 → minimal test exe prints OpenSSL 3.5.1.
  3. Full mcpp build from scratch: downloads the 50MB tarball → builds inside the
    install() hook → compiles the anchor → links → exe prints
    linked: OpenSSL 3.5.1 1 Jul 2025. ✅

Known limitations

  • no-asm: Windows builds default to pure-C (no NASM dependency). Functionally
    identical, slightly slower. Can be revisited if a xim:nasm-style build dep ever
    lands.
  • Spaces in paths: cmd /c splices paths directly; the standard layout
    (C:\Users\<name>\…) is space-free. Usernames with spaces would need quoting the
    bat path — can be patched later.
  • vswhere output is empty in the hook env (same bash -c no-op as feat: add mcpplibs.tinyhttps 0.2.1 + mcpplibs.llmapi 0.2.4 #3), so
    find_vcvars primarily uses the known-path fallback; vswhere is a bonus, not a
    dependency.

Follow-up

  • compat.libmysqlclient: add the windows xpm line and verify (its Windows build
    segment is already in place). Next PR, gated on this one.

…e build

The last major package still marked "windows deferred". Unblocks the
Windows leg of compat.libmysqlclient, whose mcpp.toml is already wired
for it; openssl was the only missing dependency there.

- xpm: add a windows entry reusing the shared source tarball (same sha256)
- mcpp: add windows ldflags. lld-link resolves `-lX` to `X.lib`, so the
  MSVC-built static libs must be spelled `-llibssl`/`-llibcrypto`; the
  static libcrypto system deps (ws2_32, crypt32, advapi32, user32) are
  listed explicitly, the same way the linux leg lists -ldl/-lpthread.
- install(): route windows to _install_windows() instead of erroring out.
- _install_windows(): one generated .bat runs under a single vcvars64
  invocation and does Configure VC-WIN64A no-shared no-dso no-tests
  no-apps no-engine no-asm + nmake + install_sw, then verifies
  libssl.lib/libcrypto.lib exist and writes the anchor TU. Helpers:
  find_vcvars (vswhere, then known paths), resolve_perl_windows /
  perl_usable_windows, win_dirname.

Pitfalls found on real hardware, baked into the implementation:
- the xpkg hook env on Windows has no os.rm (must be pcall'd) and no
  path.dirname (hand-rolled win_dirname)
- OpenSSL Configure needs Locale::Maketext::Simple, which MSYS perl
  (Git-for-Windows) lacks; the existing module probe would wrongly accept
  it, so the windows check requires Strawberry Perl
- os.exec("bash -c ...") silently returns true WITHOUT running the command
  in the Windows hook env, so the windows build drives
  `cmd /c <bat> > <log> 2>&1` directly instead of reusing the shared run()
- vcvars (cmd /c "vcvars64.bat & set") works fine on Windows 11 + VS
  2022/18; the old "takes the whole process chain down" note was a
  hook-env artifact, not a property of Windows
@FarnaHerry

Copy link
Copy Markdown
Collaborator Author

@Sunrisepeak

@Sunrisepeak

Copy link
Copy Markdown
Member

FARNA-HERRY-OFF\farna added 2 commits August 16, 2026 20:03
compat.openssl now builds on Windows (VC-WIN64A + nmake), so the
tests/examples/openssl member no longer has to be a no-op main() there.
Declare the dependency and HAVE_OPENSSL on all three platforms; tls.cpp
compiles its real TLS-context + SHA-256 checks on Windows as well.

Verified on Windows (llvm/clang toolchain, MSVC-built libssl.lib +
libcrypto.lib): `mcpp test -p openssl` → tls ... ok (1 passed, 0 failed).
Windows CI failed `mcpp test -p openssl` at install(): find_vcvars ran
vswhere through `os.exec("bash -c …")`, which this hook's Windows
environment silently swallows (returns true, runs nothing), so vswhere's
output file was never written. The search then fell back to hardcoded
vcvars64.bat paths that only covered Community editions — and GitHub
Actions runners carry VS **Enterprise**, so the toolset was never found.

- find_vcvars: drive vswhere through a generated .bat under `cmd /c`
  (the same pattern _install_windows uses), which actually executes and
  is edition-agnostic; keep the hardcoded fallback but expand it to
  Enterprise/BuildTools across the 2022 (17) / 18 (2026) product lines.
- perl_usable_windows: the old probe ran perl via `bash -c`, which also
  no-ops — it accepted ANY perl, including the MSYS perl that lacks
  Locale::Maketext::Simple and dies inside Configure. Probe perl through
  a generated .bat under `cmd /c` and require it to print a marker only
  when the modules load; MSYS perl on PATH now correctly fails the probe.

Verified on hardware: the generated vswhere .bat returns the install
path (and the matching vcvars64.bat), and the perl probe prints `ok` for
Strawberry (scoop) perl while MSYS perl fails it with the missing-module
error. Descriptor still parses with the pinned CI client (2026.8.10.3).
@FarnaHerry

Copy link
Copy Markdown
Collaborator Author

@Sunrisepeak 这次应该好了

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.

2 participants