diff --git a/.github/workflows/test-build-cygwin.yml b/.github/workflows/test-build-cygwin.yml new file mode 100644 index 0000000000..d4554e5bef --- /dev/null +++ b/.github/workflows/test-build-cygwin.yml @@ -0,0 +1,96 @@ +name: Test on Cygwin +on: + workflow_dispatch: + release: + type: ["published"] + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + SHELLOPTS: igncr + CYGWIN_NOWINPATH: 1 + CHERE_INVOKING: 1 + ESMF_DIR: /cygdrive/d/a/esmf/esmf + ESMF_BOPT: O + ESMF_OPTLEVEL: 2 + ESMF_COMM: mpiuni + ESMF_COMPILER: gfortran + ESMF_TESTSHAREDOBJ: ON + ESMF_RANLIB: ranlib + ESMF_LAPACK: system + ESMF_LAPACK_LIBPATH: /usr/lib + ESMF_LAPACK_LIBS: -llapack -lblas + NETCDF: /usr + ESMF_NETCDF: split + ESMF_NETCDF_INCLUDE: /usr/include + ESMF_NETCDF_LIBPATH: /usr/lib + ESMF_CXX: g++ + ESMF_CXXCOMPILEOPTS: "-g -O2" + ESMF_F90: gfortran + ESMF_F90COMPILEOPTS: "-g -O2" + ESMF_INSTALL_PREFIX: /tmp/fakeroot/usr + ESMF_INSTALL_DOCDIR: share/doc/esmf + +jobs: + cygwin_build_test: + runs-on: windows-latest + steps: + - run: git config --global core.autocrlf input + - uses: actions/checkout@v3 + with: + submodules: recursive + - uses: cygwin/cygwin-install-action@v4 + with: + platform: x86_64 + install-dir: 'C:\tools\cygwin' + packages: >- + openmpi gcc-core gcc-fortran gcc-g++ libnetcdf-devel libnetcdf-fortran-devel + perl make bash dash + liblapack-devel cmake libyaml-devel + python39-devel python39-pip python39-numpy python39-pytest + - name: Set Windows PATH + uses: egor-tensin/cleanup-path@v3 + with: + dirs: 'C:\tools\cygwin\bin;C:\tools\cygwin\lib\lapack' + - name: Check location + run: | + C:\tools\cygwin\bin\dash.exe -c "echo PWD; pwd; echo ESMF_DIR=${ESMF_DIR}" + - name: Build ESMF + run: | + C:\tools\cygwin\bin\dash.exe -c "/usr/bin/make all" + - name: Build ESMPy + env: + ESMFMKFILE: "${ESMF_DIR}/esmf.mk" + run: | + C:\tools\cygwin\bin\dash.exe -c "cd src/addon/esmpy; python -m pip install ." + - name: Check ESMF + run: | + C:\tools\cygwin\bin\dash.exe -c "/usr/bin/make check" + - name: Install ESMF + run: | + C:\tools\cygwin\bin\dash.exe -c "/usr/bin/make install" + - name: List ESMF Installed files + run: | + C:\tools\cygwin\bin\dash.exe -c "/usr/bin/find /tmp/fakeroot" + - name: Print esmf.mk + run: | + C:\tools\cygwin\bin\dash.exe -c "/usr/bin/find /tmp/fakeroot -name esmf.mk -exec cat {} +" + - name: ESMF Installcheck + env: + ESMFMKFILE: "/tmp/fakeroot/usr/lib/libO/Cygwin.gfortran.64.mpiuni.default/esmf.mk" + run: | + C:\tools\cygwin\bin\dash.exe -c "/usr/bin/make installcheck" + - name: Check ESMPy + env: + ESMFMKFILE: "/tmp/fakeroot/usr/lib/libO/Cygwin.gfortran.64.mpiuni.default/esmf.mk" + run: | + C:\tools\cygwin\bin\dash.exe -c "/usr/bin/python -m pip install pytest" + C:\tools\cygwin\bin\dash.exe -c "cd src/addon/esmpy; /usr/bin/make download test_all" diff --git a/build/common.mk b/build/common.mk index 3380b31741..89a311d4ba 100644 --- a/build/common.mk +++ b/build/common.mk @@ -1735,6 +1735,9 @@ ifdef ESMF_PIO ESMF_CPPFLAGS += -DESMF_PIO=1 ifneq ($(origin ESMF_PIO_LIBS), environment) ESMF_PIO_LIBS = -lpioc +ifeq ($(ESMF_OS),Cygwin) +ESMF_PIO_LIBS += $(ESMF_NETCDF_LIBS) +endif endif ifdef ESMF_PIO_INCLUDE ESMF_CXXCOMPILEPATHSTHIRD += -I$(ESMF_PIO_INCLUDE) @@ -4101,7 +4104,11 @@ $(ESMF_LOCOBJDIR)/%.o : %.cpp .F90.$(ESMF_SL_SUFFIX): $(ESMF_F90COMPILEFREECPP_CMD) $(ESMF_SO_F90COMPILEOPTS) $< - $(ESMF_F90LINKER) $(ESMF_SO_F90LINKOPTS) $(ESMF_F90LINKOPTS) $(ESMF_F90LINKPATHS) $(ESMF_F90LINKRPATHS) -o $@ $*.o $(ESMF_F90ESMFLINKLIBS) + if [ $(ESMF_SL_SUFFIX) != "dll.a" ] ; then \ + $(ESMF_F90LINKER) $(ESMF_SO_F90LINKOPTS) $(ESMF_F90LINKOPTS) $(ESMF_F90LINKPATHS) $(ESMF_F90LINKRPATHS) -o $@ $*.o $(ESMF_F90ESMFLINKLIBS); \ + else \ + $(ESMF_F90LINKER) $(ESMF_SO_F90LINKOPTS) $(ESMF_F90LINKOPTS) $(ESMF_F90LINKPATHS) -shared -o $(@:.dll.a=.dll) -Wl,--out-implib=$@ -Wl,--export-all-symbols -Wl,--whole-archive $*.o -Wl,--no-whole-archive $(ESMF_F90ESMFLINKLIBS); \ + fi; .F90.$(ESMF_LIB_SUFFIX): $(ESMF_F90COMPILEFREECPP_CMD) $< @@ -4201,12 +4208,20 @@ shared: echo Converting $$NEXTLIB.a to $$NEXTLIB.$(ESMF_SL_SUFFIX) ;\ mkdir tmp_$$NEXTLIB ;\ cd tmp_$$NEXTLIB ;\ - $(ESMF_AREXTRACT) ../$$NEXTLIB.$(ESMF_LIB_SUFFIX) ;\ - echo $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB.$(ESMF_SL_SUFFIX) *.o $(ESMF_SL_LIBLIBS) ;\ - $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB.$(ESMF_SL_SUFFIX) *.o $(ESMF_SL_LIBLIBS) ;\ - echo Converting $$NEXTLIB.$(ESMF_SL_SUFFIX) to $$NEXTLIB\_fullylinked.$(ESMF_SL_SUFFIX) ;\ - echo $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB\_fullylinked.$(ESMF_SL_SUFFIX) *.o $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) $(ESMF_CXXLINKRPATHS) $(ESMF_CXXLINKLIBS) ;\ - $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB\_fullylinked.$(ESMF_SL_SUFFIX) *.o $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) $(ESMF_CXXLINKRPATHS) $(ESMF_CXXLINKLIBS) ;\ + $(ESMF_AREXTRACT) ../$$NEXTLIB.$(ESMF_LIB_SUFFIX) ;\ + if [ "${ESMF_SL_SUFFIX}" != "dll.a" ] ; then \ + echo $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB.$(ESMF_SL_SUFFIX) *.o $(ESMF_SL_LIBLIBS) ;\ + $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB.$(ESMF_SL_SUFFIX) *.o $(ESMF_SL_LIBLIBS) ;\ + echo Converting $$NEXTLIB.$(ESMF_SL_SUFFIX) to $$NEXTLIB\_fullylinked.$(ESMF_SL_SUFFIX) ;\ + echo $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB\_fullylinked.$(ESMF_SL_SUFFIX) *.o $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) $(ESMF_CXXLINKRPATHS) $(ESMF_CXXLINKLIBS) ;\ + $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/$$NEXTLIB\_fullylinked.$(ESMF_SL_SUFFIX) *.o $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) $(ESMF_CXXLINKRPATHS) $(ESMF_CXXLINKLIBS) ;\ + else \ + echo $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/"cyg$${NEXTLIB#lib}.dll" -Wl,--out-implib=$(ESMF_LDIR)/$$NEXTLIB\.dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import \ + -Wl,--whole-archive *.o -Wl,--no-whole-archive $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) $(ESMF_CXXLINKRPATHS) $(ESMF_CXXLINKLIBS) ;\ + $(ESMF_SL_LIBLINKER) $(ESMF_SL_LIBOPTS) -o $(ESMF_LDIR)/"cyg$${NEXTLIB#lib}\.dll" -Wl,--out-implib=$(ESMF_LDIR)/$$NEXTLIB\.dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import \ + -Wl,--whole-archive *.o -Wl,--no-whole-archive $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) $(ESMF_CXXLINKRPATHS) $(ESMF_CXXLINKLIBS) ;\ + ls $(ESMF_LDIR) ; \ + fi ;\ cd .. ;\ $(ESMF_RM) -r tmp_$$NEXTLIB ;\ fi ;\ diff --git a/build_config/Cygwin.gfortran.default/build_rules.mk b/build_config/Cygwin.gfortran.default/build_rules.mk index d915f6222c..6a88aff7cd 100644 --- a/build_config/Cygwin.gfortran.default/build_rules.mk +++ b/build_config/Cygwin.gfortran.default/build_rules.mk @@ -9,6 +9,7 @@ ESMF_F90DEFAULT = gfortran ESMF_CXXDEFAULT = g++ ESMF_CDEFAULT = gcc +ESMF_CXXCOMPILECPPFLAGS+= -D_BSD_SOURCE -D_POSIX_C_SOURCE=199309L ############################################################ # Default MPI setting. @@ -115,8 +116,8 @@ ESMF_CXXOPTFLAG_G += -Wall -Wextra -Wno-unused ############################################################ # Cygwin 1.5.24 does not yet support POSIX IPC (memory mapped files) -# -ESMF_CXXCOMPILECPPFLAGS += -DESMF_NO_POSIXIPC +# Cygwin 3.4.9 might +# ESMF_CXXCOMPILECPPFLAGS += -DESMF_NO_POSIXIPC ############################################################ # Fortran symbol convention diff --git a/makefile b/makefile index 0867bc74e3..dccbad69cf 100644 --- a/makefile +++ b/makefile @@ -819,6 +819,10 @@ install: envdump cp -f $(ESMF_MODDIR)/*.mod $(ESMF_INSTALL_MODDIR_ABSPATH) mkdir -p $(ESMF_INSTALL_LIBDIR_ABSPATH) cp -f $(ESMF_LIBDIR)/libesmf*.* $(ESMF_INSTALL_LIBDIR_ABSPATH) +ifeq ($(ESMF_OS),Cygwin) + mkdir -p $(ESMF_INSTALL_BINDIR_ABSPATH) + cp -f $(ESMF_LIBDIR)/cygesmf*.* $(ESMF_INSTALL_BINDIR_ABSPATH) +endif ifeq ($(ESMF_PIO),internal) cp -f $(ESMF_LIBDIR)/libpioc.* $(ESMF_INSTALL_LIBDIR_ABSPATH) diff --git a/src/addon/esmpy/src/esmpy/api/constants.py b/src/addon/esmpy/src/esmpy/api/constants.py index 8d9c88927d..2734151bd7 100644 --- a/src/addon/esmpy/src/esmpy/api/constants.py +++ b/src/addon/esmpy/src/esmpy/api/constants.py @@ -34,9 +34,10 @@ # ESMF OS _ESMF_OS = None -(_ESMF_OS_DARWIN, +(_ESMF_OS_CYGWIN, + _ESMF_OS_DARWIN, _ESMF_OS_LINUX, - _ESMF_OS_UNICOS) = (-5,-4,-3) + _ESMF_OS_UNICOS) = (-6, -5,-4,-3) # ESMF_NETCDF _ESMF_NETCDF = False diff --git a/src/addon/esmpy/src/esmpy/interface/loadESMF.py b/src/addon/esmpy/src/esmpy/interface/loadESMF.py index f664efec53..53b951b6de 100644 --- a/src/addon/esmpy/src/esmpy/interface/loadESMF.py +++ b/src/addon/esmpy/src/esmpy/interface/loadESMF.py @@ -51,6 +51,7 @@ # investigate esmf.mk libsdir = None + appsdir = None esmfos = None esmfabi = None esmfcomm = None @@ -62,6 +63,8 @@ for line in MKFILE: if 'ESMF_LIBSDIR' in line: libsdir = line.split("=")[1] + elif 'ESMF_APPSDIR' in line: + appsdir = line.split("=", 1)[1].strip() elif 'ESMF_OS:' in line: esmfos = line.split(":")[1] elif 'ESMF_ABI:' in line: @@ -113,8 +116,10 @@ constants._ESMF_OS = constants._ESMF_OS_LINUX elif "Unicos" in esmfos: constants._ESMF_OS = constants._ESMF_OS_UNICOS +elif "Cygwin" in esmfos: + constants._ESMF_OS = constants._ESMF_OS_CYGWIN else: - raise ValueError("Unrecognized ESMF_OS setting!") + raise ValueError(f"Unrecognized ESMF_OS setting: {esmfos:s}!") # set _ESMF_ABI for 32/64 switching if "64" in esmfabi: @@ -148,6 +153,8 @@ try: if constants._ESMF_OS == constants._ESMF_OS_DARWIN: _ESMF = np.ctypeslib.load_library('libesmf_fullylinked',libsdir) + elif constants._ESMF_OS == constants._ESMF_OS_CYGWIN: + _ESMF = np.ctypeslib.load_library('cygesmf.dll', appsdir) else: _ESMF = ct.CDLL(os.path.join(libsdir,'libesmf_fullylinked.so'), mode=ct.RTLD_GLOBAL)