Skip to content

Native build on Windows - #3309

Open
yorickreum wants to merge 2 commits into
NanoComp:masterfrom
yorickreum:windows-native-build
Open

yorickreum wants to merge 2 commits into
NanoComp:masterfrom
yorickreum:windows-native-build

Conversation

@yorickreum

Copy link
Copy Markdown
Contributor

Turns out that not much needs to be adjusted to be able to build and run MEEP natively on Windows (with MYSY2 UCRT64)... All required changes are in the first commit, the second commit adds a Windows CI runner.

Addresses #385

Comment thread python/tests/test_mpb.py
@yorickreum
yorickreum force-pushed the windows-native-build branch 2 times, most recently from 09fb2f0 to 787c086 Compare September 15, 2026 09:15
Comment thread python/Makefile.am
Comment thread python/Makefile.am
$(srcdir)/adjoint/utils.py

PY_PKG_FILES = $(INIT_PY) $(HL_IFACE) .libs/_meep.so
PY_PKG_FILES = $(INIT_PY) $(HL_IFACE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is replaced by the explicit cp below?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The built name (.dll) and the importable name (.pyd) differ on Windows, so it needs its own cp with a rename. On Unix both are .so.

Comment thread src/meepgeom.cpp Outdated
// An absolute Windows path begins with a drive letter, e.g. "C:\dir\eps.h5";
// that colon is part of the path, not the "file.h5:dataname" separator.
if (dataname == fname + 1 && isalpha((unsigned char)fname[0])) dataname = NULL;
#endif

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should do

char *dataname = strstr(fname, ".h5:");
if (dataname) { *(dataname + 3) = 0; dataname += 4; }

instead. That will handle the Windows case, and will also behave better on operating systems where a colon is a valid part of a filename.

(It assumes that the HDF5 file ends with .h5, which isn't strictly necessary but should be a near-universal practice?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. That sounds fair. I now split at the first .h5: or .hdf5:, so .hdf5 files still work, and dropped the #ifdef _WIN32.

@stevengj

Copy link
Copy Markdown
Collaborator

Thanks for working on this, overall it looks very reasonable.

Yorick Reum added 2 commits September 26, 2026 12:09
Apart from a colon in an epsilon-input-file path, none are reachable on Linux
or macOS, so they have gone unnoticed; four are latent bugs rather than build
breakage.

Source:

* output_directory.cpp: Windows mkdir() takes one argument, and its remove()
  fails on directories, so nftw() aborted and delete_directory() removed
  nothing at all.
* meepgeom.cpp: epsilon-input-file was split at its last ':', so
  "C:\dir\eps.h5" became the filename "C" and the failed H5Fopen aborted.
  It is now split after a ".h5:" or ".hdf5:" extension, which also keeps
  colons in Unix paths part of the filename.
* mympi.cpp: _GNU_SOURCE came after <cstdlib>, too late to declare
  vasprintf() on mingw-w64.
* tests/h5test.cpp: POSIX sync() does not exist there, breaking the C++ test
  suite's compile.

Build:

* Windows DLLs may not contain undefined symbols; without -no-undefined
  libtool silently emits a static archive.
* PYTHON_LIBS was referenced but never set.  Empty is right on Unix, where
  modules take their symbols from the interpreter; on Windows they must link
  the Python library.  Module suffixes (.so vs .pyd) are chosen per host too.
* _mpb linked only libpympb, relying on transitive resolution Windows does
  not permit.  Both modules use -avoid-version now, as no platform imports a
  versioned extension module.
* sphere-quad.h's rule ignored $(EXEEXT).
* TESTS_ENVIRONMENT built PYTHONPATH from $(abs_top_builddir): an MSYS
  "/c/..." path joined with ":", neither readable by native Python.
* test_mpb.py passed a path as an re.sub() replacement, where backslashes are
  escapes.

A native build also needs lt_cv_deplibs_check_method=pass_all; libctl,
harminv, mpb and libGDSII need their own fixes.
Builds and tests Meep on windows-latest via MSYS2.  No dependency needs
patching: harminv is built static, MPB already carries -no-undefined, and the
one libctl omits is supplied on the make command line.  The reasoning behind
the less obvious choices -- UCRT64 over MINGW64, pass_all, libctl from a
release tarball, and vendoring the runtime DLLs beside _meep.pyd -- is in
comments in the workflow.
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.

3 participants