From 0d672c21ec185652cf88cb7c2190afbff7e31cc9 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Sun, 28 Apr 2019 13:36:50 +0200
Subject: [PATCH] COMP: add wmake rules for mingw (#1238)

---
 doc/cross-compile-mingw.md          | 131 ++++++++++++++++++++++++++++
 etc/config.csh/settings             |   7 ++
 etc/config.sh/mpi                   |  14 +++
 etc/config.sh/settings              |  11 +++
 src/Allwmake                        |  27 ++++--
 wmake/makefiles/general             |   8 ++
 wmake/rules/linux64Mingw/c          |  28 ++++++
 wmake/rules/linux64Mingw/c++        |  35 ++++++++
 wmake/rules/linux64Mingw/c++Debug   |   2 +
 wmake/rules/linux64Mingw/c++Opt     |   4 +
 wmake/rules/linux64Mingw/c++Prof    |   2 +
 wmake/rules/linux64Mingw/cDebug     |   2 +
 wmake/rules/linux64Mingw/cOpt       |   2 +
 wmake/rules/linux64Mingw/cProf      |   2 +
 wmake/rules/linux64Mingw/general    |  19 ++++
 wmake/rules/linux64Mingw/mplibMSMPI |   3 +
 16 files changed, 292 insertions(+), 5 deletions(-)
 create mode 100644 doc/cross-compile-mingw.md
 create mode 100644 wmake/rules/linux64Mingw/c
 create mode 100644 wmake/rules/linux64Mingw/c++
 create mode 100644 wmake/rules/linux64Mingw/c++Debug
 create mode 100644 wmake/rules/linux64Mingw/c++Opt
 create mode 100644 wmake/rules/linux64Mingw/c++Prof
 create mode 100644 wmake/rules/linux64Mingw/cDebug
 create mode 100644 wmake/rules/linux64Mingw/cOpt
 create mode 100644 wmake/rules/linux64Mingw/cProf
 create mode 100644 wmake/rules/linux64Mingw/general
 create mode 100644 wmake/rules/linux64Mingw/mplibMSMPI

diff --git a/doc/cross-compile-mingw.md b/doc/cross-compile-mingw.md
new file mode 100644
index 0000000000..d98dfa8f7c
--- /dev/null
+++ b/doc/cross-compile-mingw.md
@@ -0,0 +1,131 @@
+Notes for cross-compiling with mingw.
+
+On openSUSE use the packages:
+```
+mingw64-cross-binutils
+mingw64-cross-cpp
+mingw64-cross-gcc
+mingw64-cross-gcc-c++
+mingw64-filesystem
+mingw64-headers
+mingw64-runtime
+
+mingw64-libwinpthread1
+mingw64-winpthreads-devel
+
+mingw64-libfftw3
+mingw64-fftw3-devel
+```
+
+This setup is missing zlib, so download that manually and compile as a
+*static* library.
+
+```
+CC="$(wmake -show-c) CFLAGS="$(wmake -show-cflags) ./configure --static
+```
+
+The resulting output files (zconf.h zlib.h) and (libz.a) either need
+to be installed in system locations where OpenFOAM can find it, or if
+they are to be shipped directly with OpenFOAM, they can also be placed
+in the `src/OpenFOAM/include` and `platforms/XXX/lib` paths.
+
+When using the cross-compiled executables and libraries, additional
+runtime libraries are required. On openSUSE these are provided by the
+packages:
+```
+mingw64-libgcc_s_seh1
+mingw64-libstdc++6
+```
+
+In a few locations within OpenFOAM, flex is used to generate code. The
+generated C++ code requires the `FlexLexer.h` header file.
+This is normally located under `/usr/include/FlexLexer.h`, which will
+be ignored by the cross-compiler.
+
+As a fairly ugly hack, a copy of this file can be made in a standard
+project include location. For example,
+
+```
+mkdir src/OpenFOAM/lnInclude
+cp /usr/include/FlexLexer.h src/OpenFOAM/lnInclude
+```
+
+
+The last point to consider when cross-compiling is the behaviour of
+the OpenFOAM tools used during compilation. These are found under
+`wmake/src`. When these are compiled they will create executables that
+work on the target platform (Windows), but *not* on the host platform.
+
+The workaround:
+
+1. Activate the native OpenFOAM environment (Linux with system gcc)
+and use that to compile the build tools
+```
+wmake/src/Allmake
+```
+This can be skipped if you already have an existing OpenFOAM build.
+
+2. Activate the OpenFOAM for cross-compiling (Linux with mingw)
+and use that to compile the build tools
+```
+wmake/src/Allmake
+```
+
+3. Copy the contents of the native platform build tools into the
+cross-compilation platform directory. For example,
+```
+cp wmake/platforms/linux64Gcc/* wmake/platforms/linux64Mingw/
+```
+
+The `wmake/platforms/linux64Mingw/` directory should now contain
+native and cross-compiled tools:
+```
+dirToString
+wmkdep
+wmkdepend
+
+dirToString.exe
+wmkdep.exe
+wmkdepend.exe
+```
+
+The native tools are the one that will (automatically) be used
+throughout the balance of the cross-compilation process.
+
+
+Adjust paths for third-party sources. Eg, in `etc/config.sh/FFTW` you
+may wish to have the following:
+```
+fftw_version=fftw-system
+export FFTW_ARCH_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw
+```
+
+
+The settings for cross-compilation are normally defined in the
+`etc/pref.sh` file with contents like this:
+
+```
+# For mingw cross-compile
+
+export WM_COMPILER=Mingw
+export WM_MPLIB=MSMPI
+
+export WM_LABEL_SIZE=32
+# other settings...
+```
+
+
+Additional adjustments may be required in some other places. For example
+in `etc/config.sh/FFTW`
+```
+fftw_version=fftw-system
+export FFTW_ARCH_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw
+```
+
+
+Known limitations (2019-05-01)
+
+- No CGAL support (ie, no foamyHexMesh)
+- No ParaView plugin, runTimepostProcessing
+- reacting EulerFoam solvers have too many interdependencies and do
+  not yet compile.
diff --git a/etc/config.csh/settings b/etc/config.csh/settings
index 12b2bd1182..3c8486b21f 100644
--- a/etc/config.csh/settings
+++ b/etc/config.csh/settings
@@ -227,6 +227,13 @@ setenv FOAM_RUN "$WM_PROJECT_USER_DIR/run"
 # Default to system compiler
 if (! $?WM_COMPILER_TYPE ) setenv WM_COMPILER_TYPE system
 
+# Cross-compiling
+switch ("$WM_COMPILER")
+case Mingw*:
+    setenv WM_OSTYPE MSwindows
+    breaksw
+endsw
+
 # Adjustments for non-gcc compilers
 switch ("$WM_COMPILER")
 case Clang*:  # Clang compiler suite
diff --git a/etc/config.sh/mpi b/etc/config.sh/mpi
index 52c8826d88..6b3f98fb34 100644
--- a/etc/config.sh/mpi
+++ b/etc/config.sh/mpi
@@ -321,6 +321,20 @@ INTELMPI*)
     _foamAddPath    "$MPI_ARCH_PATH/intel64/bin"
     _foamAddLib     "$MPI_ARCH_PATH/intel64/lib"
     ;;
+
+MSMPI)
+    export FOAM_MPI=msmpi
+    _foamEtc -config  mpi-msmpi                 # <- Adjustments (optional)
+
+    # Respect MPI_ARCH_PATH if set to a valid directory (eg, user adjustments)
+    if [ ! -d "$MPI_ARCH_PATH" ]
+    then
+        export MPI_ARCH_PATH=$WM_THIRD_PARTY_DIR/platforms/$WM_ARCH$WM_COMPILER/$FOAM_MPI
+    fi
+
+    # _foamAddPath    "$MPI_ARCH_PATH/bin"
+    _foamAddLib     "$MPI_ARCH_PATH/lib/x64"
+    ;;
 esac
 
 
diff --git a/etc/config.sh/settings b/etc/config.sh/settings
index af61276c83..f44dec25c8 100644
--- a/etc/config.sh/settings
+++ b/etc/config.sh/settings
@@ -227,6 +227,17 @@ export FOAM_RUN="$WM_PROJECT_USER_DIR/run"
 # Default to system compiler
 : ${WM_COMPILER_TYPE:=system}; export WM_COMPILER_TYPE
 
+# Cross-compiling
+case "$WM_COMPILER" in
+(Mingw*)
+    export WM_OSTYPE=MSwindows
+    export WM_CC="$(wmake -show-c)"
+    export WM_CXX="$(wmake -show-cxx)"
+    export WM_CFLAGS="$(wmake -show-cflags)"
+    export WM_CXXFLAGS="$(wmake -show-cxxflags)"
+    ;;
+esac
+
 # Adjust for non-gcc compilers
 case "$WM_COMPILER" in
 Clang*)    # Clang compiler suite
diff --git a/src/Allwmake b/src/Allwmake
index 30f3ab8386..5797c9eeda 100755
--- a/src/Allwmake
+++ b/src/Allwmake
@@ -20,11 +20,28 @@ wmakeLnInclude -u OSspecific/"${WM_OSTYPE:-POSIX}"
 
 OSspecific/"${WM_OSTYPE:-POSIX}"/Allwmake $targetType $*
 
-Pstream/Allwmake $targetType $*
-
-# Trigger update of version info (as required)
-wmakeBuildInfo -check || wrmo OpenFOAM/global/global.o 2>/dev/null
-wmake $targetType OpenFOAM
+case "$WM_COMPILER" in
+Mingw*)
+    # Pstream/OpenFOAM cyclic dependency
+    # 1st pass: link as Pstream as single .o object
+    WM_MPLIB=dummy Pstream/Allwmake libo
+    FOAM_LINK_DUMMY_PSTREAM=libo wmake $targetType OpenFOAM
+
+    # 2nd pass: link Pstream.dll against libOpenFOAM.dll
+    Pstream/Allwmake $targetType $*
+
+    # Relink libOpenFOAM.dll against libPstream.dll
+    wrmo OpenFOAM/global/global.o 2>/dev/null
+    wmake $targetType OpenFOAM
+    ;;
+*)
+    Pstream/Allwmake $targetType $*
+
+    # Trigger update of version info (as required)
+    wmakeBuildInfo -check || wrmo OpenFOAM/global/global.o 2>/dev/null
+    wmake $targetType OpenFOAM
+    ;;
+esac
 
 wmake $targetType fileFormats
 wmake $targetType surfMesh
diff --git a/wmake/makefiles/general b/wmake/makefiles/general
index 74d6518cd4..21bc05efdf 100644
--- a/wmake/makefiles/general
+++ b/wmake/makefiles/general
@@ -163,11 +163,19 @@ objects: $(OBJECTS) | silent
 .PHONY: libso
 libso: $(LIB)$(EXT_SO) | silent
 
+ifeq ("$(WM_OSTYPE)","MSwindows")
+$(LIB)$(EXT_SO): $(OBJECTS)
+	@$(WM_SCRIPTS)/makeTargetDir $(LIB)
+	$(call QUIET_MESSAGE,ld,$(LIB)$(EXT_SO))
+	$E $(LINKLIBSO) $(OBJECTS) -L$(LIB_PLATFORMS) \
+	    $(PROJECT_LIBS) $(LIB_LIBS) $(GLIB_LIBS) -o $(LIB)$(EXT_SO)
+else
 $(LIB)$(EXT_SO): $(OBJECTS)
 	@$(WM_SCRIPTS)/makeTargetDir $(LIB)
 	$(call QUIET_MESSAGE,ld,$(LIB)$(EXT_SO))
 	$E $(LINKLIBSO) $(OBJECTS) -L$(LIB_PLATFORMS) \
 	    $(LIB_LIBS) $(GLIB_LIBS) -o $(LIB)$(EXT_SO)
+endif
 
 .PHONY: lib
 lib: $(LIB).a | silent
diff --git a/wmake/rules/linux64Mingw/c b/wmake/rules/linux64Mingw/c
new file mode 100644
index 0000000000..48013b3d7b
--- /dev/null
+++ b/wmake/rules/linux64Mingw/c
@@ -0,0 +1,28 @@
+include $(GENERAL_RULES)/Gcc/c
+
+cARCH       = -m64
+
+cc          = x86_64-w64-mingw32-gcc
+
+include $(RULES)/c$(WM_COMPILE_OPTION)
+
+cFLAGS      = $(cARCH) $(GFLAGS) $(cWARN) $(cOPT) $(cDBUG) $(LIB_HEADER_DIRS)
+
+ctoo        = $(WM_SCHEDULER) $(cc) $(cFLAGS) -c $< -o $@
+
+LINK_LIBS   = $(cDBUG)
+
+LINKLIBSO   = $(cc) $(cARCH) \
+    -Wl,--output-def=$(LIB).def \
+    -Wl,--out-implib,$(LIB).dll.a \
+    -Wl,--no-undefined \
+    -Wl,--enable-runtime-pseudo-reloc \
+    -Wl,--enable-auto-import \
+    -Wl,--enable-auto-image-base \
+    -Wl,--strip-all \
+    -shared
+
+LINKEXE     = $(cc) $(cARCH) \
+    -Wl,--enable-auto-import \
+    -Wl,--strip-all \
+    -Wl,--force-exe-suffix
diff --git a/wmake/rules/linux64Mingw/c++ b/wmake/rules/linux64Mingw/c++
new file mode 100644
index 0000000000..c4939e019a
--- /dev/null
+++ b/wmake/rules/linux64Mingw/c++
@@ -0,0 +1,35 @@
+include $(GENERAL_RULES)/Gcc/c++
+
+c++ARCH     = -m64
+
+# With gnu++11 (not c++11) to ensure __STRICT_ANSI__ is not defined
+CC          = x86_64-w64-mingw32-g++ -std=gnu++11
+
+include $(RULES)/c++$(WM_COMPILE_OPTION)
+
+c++FLAGS    = $(c++ARCH) $(GFLAGS) $(c++WARN) $(c++OPT) $(c++DBUG) $(ptFLAGS) $(LIB_HEADER_DIRS)
+
+Ctoo        = $(WM_SCHEDULER) $(CC) $(c++FLAGS) -c $< -o $@
+cxxtoo      = $(Ctoo)
+cctoo       = $(Ctoo)
+cpptoo      = $(Ctoo)
+
+LINK_LIBS   = $(c++DBUG)
+
+# Using "-Wl,--no-undefined,--enable-runtime-pseudo-reloc"
+# does not forgive undefined symbols during linking
+
+LINKLIBSO   = $(CC) $(c++FLAGS) \
+    -Wl,--output-def=$(LIB).def \
+    -Wl,--out-implib=$(LIB).dll.a \
+    -Wl,--no-undefined \
+    -Wl,--enable-runtime-pseudo-reloc \
+    -Wl,--enable-auto-import \
+    -Wl,--enable-auto-image-base \
+    -Wl,--strip-all \
+    -shared
+
+LINKEXE     = $(CC) $(c++FLAGS) \
+    -Wl,--enable-auto-import \
+    -Wl,--strip-all \
+    -Wl,--force-exe-suffix
diff --git a/wmake/rules/linux64Mingw/c++Debug b/wmake/rules/linux64Mingw/c++Debug
new file mode 100644
index 0000000000..0dae74f2bf
--- /dev/null
+++ b/wmake/rules/linux64Mingw/c++Debug
@@ -0,0 +1,2 @@
+c++DBUG     = -gstabs3 -DFULLDEBUG
+c++OPT      = -O0 -fdefault-inline
diff --git a/wmake/rules/linux64Mingw/c++Opt b/wmake/rules/linux64Mingw/c++Opt
new file mode 100644
index 0000000000..35b3083a56
--- /dev/null
+++ b/wmake/rules/linux64Mingw/c++Opt
@@ -0,0 +1,4 @@
+c++DBUG     = -DNDEBUG
+c++OPT      = -O3
+
+ROUNDING_MATH = -frounding-math
diff --git a/wmake/rules/linux64Mingw/c++Prof b/wmake/rules/linux64Mingw/c++Prof
new file mode 100644
index 0000000000..faa2711c7e
--- /dev/null
+++ b/wmake/rules/linux64Mingw/c++Prof
@@ -0,0 +1,2 @@
+c++DBUG     = -gstabs3 -pg
+c++OPT      = -O2
diff --git a/wmake/rules/linux64Mingw/cDebug b/wmake/rules/linux64Mingw/cDebug
new file mode 100644
index 0000000000..687db6d2d5
--- /dev/null
+++ b/wmake/rules/linux64Mingw/cDebug
@@ -0,0 +1,2 @@
+cDBUG       = -gstabs3 -DFULLDEBUG
+cOPT        = -O1 -finline-functions
diff --git a/wmake/rules/linux64Mingw/cOpt b/wmake/rules/linux64Mingw/cOpt
new file mode 100644
index 0000000000..5031d6a49b
--- /dev/null
+++ b/wmake/rules/linux64Mingw/cOpt
@@ -0,0 +1,2 @@
+cDBUG       = -DNDEBUG
+cOPT        = -O3
diff --git a/wmake/rules/linux64Mingw/cProf b/wmake/rules/linux64Mingw/cProf
new file mode 100644
index 0000000000..5e2634d844
--- /dev/null
+++ b/wmake/rules/linux64Mingw/cProf
@@ -0,0 +1,2 @@
+cDBUG       = -gstabs3 -pg
+cOPT        = -O2
diff --git a/wmake/rules/linux64Mingw/general b/wmake/rules/linux64Mingw/general
new file mode 100644
index 0000000000..b63818537a
--- /dev/null
+++ b/wmake/rules/linux64Mingw/general
@@ -0,0 +1,19 @@
+# Need -D_WIN32 -D__MINGW32__ if host cpp is used
+#CPP     = /lib/cpp -traditional-cpp -D_WIN32 -D__MINGW32__ $(GFLAGS)
+
+CPP     = x86_64-w64-mingw32-cpp -traditional-cpp $(GFLAGS)
+LD      = x86_64-w64-mingw32-ld
+AR      = x86_64-w64-mingw32-ar
+RANLIB  = x86_64-w64-mingw32-ranlib
+
+PROJECT_LIBS = -l$(WM_PROJECT) -L$(FOAM_LIBBIN)/dummy -lPstream
+
+include $(GENERAL_RULES)/standard
+
+include $(DEFAULT_RULES)/c
+include $(DEFAULT_RULES)/c++
+
+EXT_SO  = .dll
+EXT_EXE = .exe
+
+# -----------------------------------------------------------------------------
diff --git a/wmake/rules/linux64Mingw/mplibMSMPI b/wmake/rules/linux64Mingw/mplibMSMPI
new file mode 100644
index 0000000000..abaef71ef9
--- /dev/null
+++ b/wmake/rules/linux64Mingw/mplibMSMPI
@@ -0,0 +1,3 @@
+PFLAGS     = -DMPICH_SKIP_MPICXX -DOMPI_SKIP_MPICXX
+PINC       = -I$(MPI_ARCH_PATH)/include
+PLIBS      = -L$(MPI_ARCH_PATH)/lib -L$(MPI_ARCH_PATH)/lib/x64 -lmsmpi
-- 
GitLab