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 $*
+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
-# Trigger update of version info (as required)
-wmakeBuildInfo -check || wrmo OpenFOAM/global/global.o 2>/dev/null
-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/src/OSspecific/MSwindows/Allwmake b/src/OSspecific/MSwindows/Allwmake
new file mode 100755
index 0000000000..24fb418826
--- /dev/null
+++ b/src/OSspecific/MSwindows/Allwmake
@@ -0,0 +1,12 @@
+#!/bin/sh
+cd ${0%/*} || exit 1 # Run from this directory
+targetType=libo # Preferred library type
+. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments $*
+
+#------------------------------------------------------------------------------
+unset COMP_FLAGS LINK_FLAGS
+
+# Make object (non-shared by default)
+wmake $targetType
+
+#------------------------------------------------------------------------------
diff --git a/src/OSspecific/MSwindows/MSwindows.C b/src/OSspecific/MSwindows/MSwindows.C
new file mode 100644
index 0000000000..30fb55792f
--- /dev/null
+++ b/src/OSspecific/MSwindows/MSwindows.C
@@ -0,0 +1,1288 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2004-2011, 2016-2019 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ | Copyright (C) 2011-2017 OpenFOAM Foundation
+ | Copyright (C) 2011 Symscape
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+#include "OSspecific.H"
+#include "MSwindows.H"
+#include "fileName.H"
+#include "fileStat.H"
+#include "DynamicList.H"
+#include "CStringList.H"
+#include "IOstreams.H"
+#include "Pstream.H"
+#undef DebugInfo // Windows name clash with OpenFOAM messageStream
+
+#include
+#include
+#include
+#include
+
+// Windows headers
+#define WIN32_LEAN_AND_MEAN
+#include
+#include // For _close
+#include
+
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+ defineTypeNameAndDebug(MSwindows, 0);
+}
+
+
+namespace Foam
+{
+ // Don't abort under windows, causes abort dialog to popup.
+ // Instead just exit with exitCode.
+ static void sigAbortHandler(int exitCode)
+ {
+ ::exit(exitCode);
+ }
+
+ static bool installAbortHandler()
+ {
+ // If it didn't succeed there's not much we can do,
+ // so don't check result.
+ ::signal(SIGABRT, &sigAbortHandler);
+ return true;
+ }
+
+ static bool const abortHandlerInstalled = installAbortHandler();
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace MSwindows
+{
+
+//- A simple directory contents iterator
+class directoryIterator
+{
+ HANDLE handle_;
+
+ bool exists_;
+
+ bool hidden_;
+
+ std::string item_;
+
+ //- Accept file/dir name
+ inline bool accept() const
+ {
+ return
+ (
+ item_.size() && item_ != "." && item_ != ".."
+ && (hidden_ || item_[0] != '.')
+ );
+ }
+
+
+public:
+
+ //- Construct for dirName, optionally allowing hidden files/dirs
+ directoryIterator(const fileName& dirName, bool allowHidden = false)
+ :
+ handle_(INVALID_HANDLE_VALUE),
+ exists_(false),
+ hidden_(allowHidden),
+ item_()
+ {
+ if (!dirName.empty())
+ {
+ WIN32_FIND_DATA findData;
+
+ handle_ = ::FindFirstFile((dirName/"*").c_str(), &findData);
+
+ if (good())
+ {
+ exists_ = true;
+ item_ = findData.cFileName;
+
+ // If first element is not acceptable, get another one
+ if (!accept())
+ {
+ next();
+ }
+ }
+ }
+ }
+
+
+ //- Destructor
+ ~directoryIterator()
+ {
+ close();
+ }
+
+
+ // Member Functions
+
+ //- Directory existed for opening
+ bool exists() const
+ {
+ return exists_;
+ }
+
+ //- Directory pointer is valid
+ bool good() const
+ {
+ return (INVALID_HANDLE_VALUE != handle_);
+ }
+
+ //- Close directory
+ void close()
+ {
+ if (good())
+ {
+ ::FindClose(handle_);
+ handle_ = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ //- The current item
+ const std::string& val() const
+ {
+ return item_;
+ }
+
+ //- Read next item, always ignoring "." and ".." entries.
+ // Normally also ignore hidden files/dirs (beginning with '.')
+ // Automatically close when it runs out of items
+ bool next()
+ {
+ if (good())
+ {
+ WIN32_FIND_DATA findData;
+
+ while (::FindNextFile(handle_, &findData))
+ {
+ item_ = findData.cFileName;
+
+ if (accept())
+ {
+ return true;
+ }
+ }
+ close(); // No more items
+ }
+
+ return false;
+ }
+
+
+ // Member Operators
+
+ //- Same as good()
+ operator bool() const
+ {
+ return good();
+ }
+
+ //- Same as val()
+ const std::string& operator*() const
+ {
+ return val();
+ }
+
+ //- Same as next()
+ directoryIterator& operator++()
+ {
+ next();
+ return *this;
+ }
+};
+
+} // End namespace MSwindows
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+std::string Foam::MSwindows::lastError()
+{
+ // Retrieve the system error message for the last-error code
+
+ // Based on an example at:
+ // http://msdn2.microsoft.com/en-us/library/ms680582(VS.85).aspx
+
+ LPVOID lpMsgBuf;
+ DWORD dw = GetLastError();
+
+ FormatMessage
+ (
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, // source
+ dw, // message-id
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // language-id
+ reinterpret_cast(&lpMsgBuf),
+ 0, NULL
+ );
+
+ const char* fmt = "Error %d: %s";
+
+ // Use snprintf with zero to establish the size (without '\0') required
+ std::string output;
+
+ int n = ::snprintf(nullptr, 0, fmt, static_cast(lpMsgBuf));
+
+ if (n > 0)
+ {
+ output.resize(n+1);
+
+ // Print directly into buffer
+ n = ::snprintf(&(output[0]), n+1, fmt, static_cast(lpMsgBuf));
+ output.resize(n);
+ }
+
+ LocalFree(lpMsgBuf);
+
+ return output;
+}
+
+
+std::string Foam::MSwindows::userName()
+{
+ const DWORD bufLen = 256;
+ TCHAR buf[bufLen];
+ DWORD len = bufLen;
+
+ if (::GetUserName(buf, &len))
+ {
+ return buf;
+ }
+
+ std::string str;
+
+ if
+ (
+ ERROR_INSUFFICIENT_BUFFER == ::GetLastError()
+ && len < 2048
+ )
+ {
+ // The len is with trailing '\0'
+ str.resize(len);
+
+ // Retrieve directly into buffer
+ ::GetUserName(&(str[0]), &len);
+
+ // Without trailing '\0'
+ str.resize(len-1);
+ }
+
+ return str;
+}
+
+
+pid_t Foam::pid()
+{
+ const DWORD processId = ::GetCurrentProcessId();
+ return processId;
+}
+
+
+pid_t Foam::ppid()
+{
+ // No equivalent under windows.
+
+ if (MSwindows::debug)
+ {
+ Info<< "ppid not supported under MSwindows" << endl;
+ }
+
+ return 0;
+}
+
+
+pid_t Foam::pgid()
+{
+ // No equivalent under windows.
+
+ if (MSwindows::debug)
+ {
+ Info<< "pgid not supported under MSwindows" << endl;
+ }
+
+ return 0;
+}
+
+
+bool Foam::env(const std::string& envName)
+{
+ // An empty envName => always false
+ return !envName.empty() &&
+ ::GetEnvironmentVariable(envName.c_str(), nullptr, 0);
+}
+
+
+Foam::string Foam::getEnv(const std::string& envName)
+{
+ std::string env;
+
+ const auto len = ::GetEnvironmentVariable(envName.c_str(), nullptr, 0);
+
+ if (len)
+ {
+ env.resize(len+1);
+ ::GetEnvironmentVariable(envName.c_str(), &(env[0]), len+1);
+
+ env.resize(len);
+ return fileName::validate(env);
+ }
+
+ return env;
+}
+
+
+bool Foam::setEnv
+(
+ const word& envName,
+ const std::string& value,
+ const bool overwrite
+)
+{
+ // Ignore an empty envName => always false
+ return
+ (
+ !envName.empty()
+ && ::SetEnvironmentVariable(envName.c_str(), value.c_str())
+ );
+}
+
+
+Foam::string Foam::hostName(bool)
+{
+ const DWORD bufLen = MAX_COMPUTERNAME_LENGTH + 1;
+ TCHAR buf[bufLen];
+ DWORD len = bufLen;
+
+ return ::GetComputerName(buf, &len) ? buf : string();
+}
+
+
+Foam::string Foam::domainName()
+{
+ // Could use ::gethostname and ::gethostbyname like POSIX.C, but would
+ // then need to link against ws_32. Prefer to minimize dependencies.
+
+ return string::null;
+}
+
+
+Foam::string Foam::userName()
+{
+ string name = Foam::getEnv("USERNAME");
+
+ if (name.empty())
+ {
+ name = MSwindows::userName();
+ }
+
+ return name;
+}
+
+
+bool Foam::isAdministrator()
+{
+ // Assume worst case
+ return true;
+}
+
+
+Foam::fileName Foam::home()
+{
+ fileName env = Foam::getEnv("HOME");
+
+ if (env.empty())
+ {
+ env = Foam::getEnv("USERPROFILE");
+ }
+
+ return env;
+}
+
+
+Foam::fileName Foam::home(const std::string& userName)
+{
+ return Foam::home();
+}
+
+
+Foam::fileName Foam::cwd()
+{
+ string path;
+ const DWORD len = ::GetCurrentDirectory(0, nullptr);
+
+ if (len)
+ {
+ path.resize(len+1);
+
+ ::GetCurrentDirectory(len+1, &(path[0]));
+
+ path.resize(len);
+
+ return fileName::validate(path);
+ }
+
+ FatalErrorInFunction
+ << "Couldn't get the current working directory"
+ << exit(FatalError);
+
+ return fileName();
+}
+
+
+Foam::fileName Foam::cwd(bool logical)
+{
+ return Foam::cwd();
+}
+
+
+bool Foam::chDir(const fileName& dir)
+{
+ // Ignore an empty dir name => always false
+ return !dir.empty() && ::SetCurrentDirectory(dir.c_str());;
+}
+
+
+bool Foam::mkDir(const fileName& pathName, const mode_t mode)
+{
+ // empty names are meaningless
+ if (pathName.empty())
+ {
+ return false;
+ }
+
+ bool ok = ::CreateDirectory(pathName.c_str(), NULL);
+
+ if (ok)
+ {
+ Foam::chMod(pathName, mode);
+ return true;
+ }
+
+ const DWORD error = ::GetLastError();
+ switch (error)
+ {
+ case ERROR_ALREADY_EXISTS:
+ {
+ ok = true;
+ break;
+ }
+
+ case ERROR_PATH_NOT_FOUND:
+ {
+ // Part of the path does not exist so try to create it
+ const fileName& parentName = pathName.path();
+
+ if (parentName.size() && mkDir(parentName, mode))
+ {
+ ok = mkDir(pathName, mode);
+ }
+ break;
+ }
+ }
+
+ if (!ok)
+ {
+ FatalErrorInFunction
+ << "Couldn't create directory: " << pathName
+ << " " << MSwindows::lastError()
+ << exit(FatalError);
+ }
+
+ return ok;
+}
+
+
+bool Foam::chMod(const fileName& name, const mode_t m)
+{
+ // Ignore an empty name => always false
+ return !name.empty() && _chmod(name.c_str(), m) == 0;
+}
+
+
+mode_t Foam::mode(const fileName& name, const bool followLink)
+{
+ // Ignore an empty name => always 0
+ if (!name.empty())
+ {
+ fileStat fileStatus(name, followLink);
+ if (fileStatus.valid())
+ {
+ return fileStatus.status().st_mode;
+ }
+ }
+
+ return 0;
+}
+
+
+// Windows equivalent to S_ISDIR
+#define ms_isdir(a) \
+ ((m != INVALID_FILE_ATTRIBUTES) && (m & FILE_ATTRIBUTE_DIRECTORY))
+
+// Windows equivalent to S_ISREG
+#define ms_isreg(s) \
+ ((m != INVALID_FILE_ATTRIBUTES) && !(m & FILE_ATTRIBUTE_DIRECTORY))
+
+
+Foam::fileName::Type Foam::type
+(
+ const fileName& name,
+ const bool /* followLink */
+)
+{
+ // Ignore an empty name => always UNDEFINED
+ if (name.empty())
+ {
+ return fileName::UNDEFINED;
+ }
+
+ const DWORD m = ::GetFileAttributes(name.c_str());
+
+ if (ms_isreg(m))
+ {
+ return fileName::FILE;
+ }
+ else if (ms_isdir(m))
+ {
+ return fileName::DIRECTORY;
+ }
+
+ return fileName::UNDEFINED;
+}
+
+
+// Local check for gz file
+static bool isGzFile(const std::string& name)
+{
+ const DWORD m = ::GetFileAttributes((name + ".gz").c_str());
+ return ms_isreg(m);
+}
+
+
+bool Foam::exists
+(
+ const fileName& name,
+ const bool checkGzip,
+ const bool followLink
+)
+{
+ // Ignore an empty name => always false
+ if (name.empty())
+ {
+ return false;
+ }
+
+ const DWORD m = ::GetFileAttributes(name.c_str());
+
+ return (ms_isdir(m) || ms_isreg(m) || (checkGzip && isGzFile(name)));
+}
+
+
+bool Foam::isDir(const fileName& name, const bool followLink)
+{
+ // Ignore an empty name => always false
+ if (name.empty())
+ {
+ return false;
+ }
+
+ const DWORD m = ::GetFileAttributes(name.c_str());
+
+ return ms_isdir(m);
+}
+
+
+bool Foam::isFile
+(
+ const fileName& name,
+ const bool checkGzip,
+ const bool followLink
+)
+{
+ // Ignore an empty name => always false
+ if (name.empty())
+ {
+ return false;
+ }
+
+ const DWORD m = ::GetFileAttributes(name.c_str());
+
+ return (ms_isreg(m) || (!ms_isdir(m) && checkGzip && isGzFile(name)));
+}
+
+
+off_t Foam::fileSize(const fileName& name, const bool followLink)
+{
+ // Ignore an empty name
+ if (!name.empty())
+ {
+ fileStat fileStatus(name, followLink);
+ if (fileStatus.valid())
+ {
+ return fileStatus.status().st_size;
+ }
+ }
+
+ return -1;
+}
+
+
+time_t Foam::lastModified(const fileName& name, const bool followLink)
+{
+ // Ignore an empty name
+ return name.empty() ? 0 : fileStat(name, followLink).modTime();
+}
+
+
+double Foam::highResLastModified(const fileName& name, const bool followLink)
+{
+ // Ignore an empty name
+ return name.empty() ? 0 : fileStat(name, followLink).dmodTime();
+}
+
+
+Foam::fileNameList Foam::readDir
+(
+ const fileName& directory,
+ const fileName::Type type,
+ const bool filtergz,
+ const bool followLink
+)
+{
+ // Initial filename list size
+ // also used as increment if initial size found to be insufficient
+ static constexpr int maxNnames = 100;
+
+ // Basic sanity: cannot strip '.gz' from directory names
+ const bool stripgz = filtergz && (type != fileName::DIRECTORY);
+ const word extgz("gz");
+
+ fileNameList dirEntries;
+
+ // Iterate contents (ignores an empty directory name)
+
+ MSwindows::directoryIterator dirIter(directory);
+
+ if (!dirIter.exists())
+ {
+ if (MSwindows::debug)
+ {
+ InfoInFunction
+ << "cannot open directory " << directory << endl;
+ }
+
+ return dirEntries;
+ }
+
+ if (MSwindows::debug)
+ {
+ InfoInFunction
+ << " : reading directory " << directory << endl;
+ }
+
+ label nFailed = 0; // Entries with invalid characters
+ label nEntries = 0; // Number of selected entries
+ dirEntries.resize(maxNnames);
+
+ // Process all the directory entries
+ for (/*nil*/; dirIter; ++dirIter)
+ {
+ const std::string& item = *dirIter;
+
+ // Validate filename without quotes, etc in the name.
+ // No duplicate slashes to strip - dirent will not have them anyhow.
+
+ const fileName name(fileName::validate(item));
+ if (name != item)
+ {
+ ++nFailed;
+ }
+ else if
+ (
+ (type == fileName::DIRECTORY)
+ || (type == fileName::FILE && !fileName::isBackup(name))
+ )
+ {
+ if ((directory/name).type() == type)
+ {
+ if (nEntries >= dirEntries.size())
+ {
+ dirEntries.resize(dirEntries.size() + maxNnames);
+ }
+
+ if (stripgz && name.hasExt(extgz))
+ {
+ dirEntries[nEntries++] = name.lessExt();
+ }
+ else
+ {
+ dirEntries[nEntries++] = name;
+ }
+ }
+ }
+ }
+
+ // Finalize the length of the entries list
+ dirEntries.resize(nEntries);
+
+ if (nFailed && MSwindows::debug)
+ {
+ std::cerr
+ << "Foam::readDir() : reading directory " << directory << nl
+ << nFailed << " entries with invalid characters in their name"
+ << std::endl;
+ }
+
+ return dirEntries;
+}
+
+
+bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink)
+{
+ // Make sure source exists - this also handles an empty source name
+ if (!exists(src))
+ {
+ return false;
+ }
+
+ fileName destFile(dest);
+
+ const fileName::Type srcType = src.type(followLink);
+
+ // Check type of source file.
+ if (srcType == fileName::FILE)
+ {
+ // If dest is a directory, create the destination file name.
+ if (destFile.type() == fileName::DIRECTORY)
+ {
+ destFile = destFile/src.name();
+ }
+
+ // Make sure the destination directory exists.
+ if (!isDir(destFile.path()) && !mkDir(destFile.path()))
+ {
+ return false;
+ }
+
+ // Open and check streams.
+ // - use binary mode to avoid any issues
+ std::ifstream srcStream(src, ios_base::in | ios_base::binary);
+ if (!srcStream)
+ {
+ return false;
+ }
+
+ // - use binary mode to avoid any issues
+ std::ofstream destStream(destFile, ios_base::out | ios_base::binary);
+ if (!destStream)
+ {
+ return false;
+ }
+
+ // Copy character data.
+ char ch;
+ while (srcStream.get(ch))
+ {
+ destStream.put(ch);
+ }
+
+ // Final check.
+ if (!srcStream.eof() || !destStream)
+ {
+ return false;
+ }
+ }
+ else if (srcType == fileName::DIRECTORY)
+ {
+ // If dest is a directory, create the destination file name.
+ if (destFile.type() == fileName::DIRECTORY)
+ {
+ destFile /= src.components().last();
+ }
+
+ // Make sure the destination directory extists.
+ if (!isDir(destFile) && !mkDir(destFile))
+ {
+ return false;
+ }
+
+ // Copy files
+ fileNameList files = readDir(src, fileName::FILE, false, followLink);
+ for (const fileName& item : files)
+ {
+ if (MSwindows::debug)
+ {
+ Info<< "Copying : " << src/item
+ << " to " << destFile/item << endl;
+ }
+
+ // File to file.
+ Foam::cp(src/item, destFile/item);
+ }
+
+ // Copy sub directories.
+ fileNameList dirs = readDir
+ (
+ src,
+ fileName::DIRECTORY,
+ false,
+ followLink
+ );
+
+ for (const fileName& item : dirs)
+ {
+ if (MSwindows::debug)
+ {
+ Info<< "Copying : " << src/item
+ << " to " << destFile << endl;
+ }
+
+ // Dir to Dir.
+ Foam::cp(src/item, destFile);
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Foam::ln(const fileName& src, const fileName& dst)
+{
+ // links are poorly supported, or need adminstrator privileges.
+ // Skip for now.
+
+ if (MSwindows::debug)
+ {
+ Info<< "MSwindows does not support ln - softlinking" << endl;
+ }
+
+ return false;
+}
+
+
+bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
+{
+ if (MSwindows::debug)
+ {
+ Info<< "Move : " << src << " to " << dst << endl;
+ }
+
+ // Ignore an empty names => always false
+ if (src.empty() || dst.empty())
+ {
+ return false;
+ }
+
+
+ if
+ (
+ dst.type() == fileName::DIRECTORY
+ && src.type(followLink) != fileName::DIRECTORY
+ )
+ {
+ const fileName dstName(dst/src.name());
+
+ return 0 == std::rename(src.c_str(), dstName.c_str());
+ }
+
+ return 0 == std::rename(src.c_str(), dst.c_str());
+}
+
+
+bool Foam::mvBak(const fileName& src, const std::string& ext)
+{
+ // Ignore an empty name or extension => always false
+ if (src.empty() || ext.empty())
+ {
+ return false;
+ }
+
+ if (exists(src, false))
+ {
+ const int maxIndex = 99;
+ char index[3];
+
+ for (int n = 0; n <= maxIndex; n++)
+ {
+ fileName dstName(src + "." + ext);
+ if (n)
+ {
+ sprintf(index, "%02d", n);
+ dstName += index;
+ }
+
+ // avoid overwriting existing files, except for the last
+ // possible index where we have no choice
+ if (!exists(dstName, false) || n == maxIndex)
+ {
+ return (0 == std::rename(src.c_str(), dstName.c_str()));
+ }
+ }
+ }
+
+ // fall-through: nothing to do
+ return false;
+}
+
+
+bool Foam::rm(const fileName& file)
+{
+ if (MSwindows::debug)
+ {
+ Info<< "Removing : " << file << endl;
+ }
+
+ // Ignore an empty name => always false
+ if (file.empty())
+ {
+ return false;
+ }
+
+
+ // If removal of plain file name failed, try with .gz
+
+ return
+ (
+ 0 == std::remove(file.c_str())
+ || 0 == std::remove((file + ".gz").c_str())
+ );
+}
+
+
+bool Foam::rmDir(const fileName& directory, const bool silent)
+{
+ // Iterate contents (ignores an empty directory name)
+ // Also retain hidden files/dirs for removal
+
+ MSwindows::directoryIterator dirIter(directory, true);
+
+ if (!dirIter.exists())
+ {
+ if (!silent)
+ {
+ WarningInFunction
+ << "cannot open directory " << directory << endl;
+ }
+ }
+
+ if (MSwindows::debug)
+ {
+ InfoInFunction
+ << " : removing directory " << directory << endl;
+ }
+
+
+ // Process each directory entry, counting any errors encountered
+ label nErrors = 0;
+
+ for (/*nil*/; dirIter; ++dirIter)
+ {
+ const std::string& item = *dirIter;
+
+ // Allow invalid characters (spaces, quotes, etc),
+ // otherwise we cannot remove subdirs with these types of names.
+ // -> const fileName path = directory/name; <-
+
+ const fileName path(fileName::concat(directory, item));
+
+ if (path.type(false) == fileName::DIRECTORY)
+ {
+ if (!rmDir(path, true)) // Only report errors at the top-level
+ {
+ ++nErrors;
+ }
+ }
+ else
+ {
+ if (!rm(path))
+ {
+ ++nErrors;
+ }
+ }
+ }
+
+ if (nErrors)
+ {
+ if (!silent)
+ {
+ WarningInFunction
+ << "failed to remove directory " << directory << nl
+ << "could not remove " << nErrors << " sub-entries" << endl;
+ }
+ }
+ else
+ {
+ if (!::RemoveDirectory(directory.c_str()))
+ {
+ ++nErrors;
+ if (!silent)
+ {
+ WarningInFunction
+ << "failed to remove directory " << directory << endl;
+ }
+ }
+ }
+
+ return !nErrors;
+}
+
+
+unsigned int Foam::sleep(const unsigned int sec)
+{
+ ::Sleep(1000*sec); // in milliseconds
+
+ return 0;
+}
+
+
+void Foam::fdClose(const int fd)
+{
+ if (::_close(fd) != 0)
+ {
+ FatalErrorInFunction
+ << "close error on " << fd << endl
+ << abort(FatalError);
+ }
+}
+
+
+bool Foam::ping
+(
+ const std::string& destName,
+ const label destPort,
+ const label timeOut
+)
+{
+ // Appears that socket calls require adminstrator privileges.
+ // Skip for now.
+
+ if (MSwindows::debug)
+ {
+ Info<< "MSwindows does not support ping" << endl;
+ }
+
+ return false;
+}
+
+
+bool Foam::ping(const std::string& host, const label timeOut)
+{
+ return ping(host, 222, timeOut) || ping(host, 22, timeOut);
+}
+
+
+int Foam::system(const std::string& command, const bool bg)
+{
+ if (MSwindows::debug && bg)
+ {
+ InfoInFunction
+ << "MSwindows does not support background (fork) tasks" << endl;
+ }
+
+ return std::system(command.c_str());
+}
+
+
+int Foam::system(const CStringList& command, const bool bg)
+{
+ if (command.empty())
+ {
+ // Treat an empty command as a successful no-op.
+ // For consistency with POSIX (man sh) behaviour for (sh -c command),
+ // which is what is mostly being replicated here.
+ return 0;
+ }
+
+ const int count = command.size();
+
+ std::string cmd;
+
+ for (int i = 0; i < count; ++i)
+ {
+ if (i) cmd += ' ';
+ cmd += command[i];
+ }
+
+ return system(cmd, bg);
+}
+
+
+int Foam::system(const UList& command, const bool bg)
+{
+ if (command.empty())
+ {
+ // Treat an empty command as a successful no-op.
+ return 0;
+ }
+
+ const int count = command.size();
+
+ std::string cmd;
+
+ for (int i = 0; i < count; ++i)
+ {
+ if (i) cmd += ' ';
+ cmd += command[i];
+ }
+
+ return system(cmd, bg);
+}
+
+
+// Explicitly track loaded libraries, rather than use
+// EnumerateLoadedModules64 and have to link against
+// Dbghelp.dll
+// Details at http://msdn.microsoft.com/en-us/library/ms679316(v=vs.85).aspx
+
+static std::unordered_map libsLoaded;
+
+
+void* Foam::dlOpen(const fileName& libName, const bool check)
+{
+ if (MSwindows::debug)
+ {
+ std::cout
+ << "dlOpen(const fileName&)"
+ << " : dlopen of " << libName << std::endl;
+ }
+
+ // Map "libXX.so" and "libXX" to "libXX.dll"
+
+ fileName winLibName(libName.lessExt().ext("dll"));
+ void* handle = ::LoadLibrary(winLibName.c_str());
+
+ if (handle)
+ {
+ libsLoaded[handle] = libName.lessExt();
+ }
+ else if (check)
+ {
+ WarningInFunction
+ << "dlopen error : " << MSwindows::lastError()
+ << endl;
+ }
+
+ if (MSwindows::debug)
+ {
+ std::cout
+ << "dlOpen(const fileName&)"
+ << " : dlopen of " << libName
+ << " handle " << handle << std::endl;
+ }
+
+ return handle;
+}
+
+
+bool Foam::dlClose(void* const handle)
+{
+ if (MSwindows::debug)
+ {
+ std::cout
+ << "dlClose(void*)"
+ << " : dlclose of handle " << handle << std::endl;
+ }
+
+ const bool ok = ::FreeLibrary(static_cast(handle));
+
+ if (ok)
+ {
+ libsLoaded.erase(handle);
+ }
+
+ return ok;
+}
+
+
+void* Foam::dlSymFind(void* handle, const std::string& symbol, bool required)
+{
+ if (!required && (!handle || symbol.empty()))
+ {
+ return nullptr;
+ }
+
+ if (MSwindows::debug)
+ {
+ std::cout
+ << "dlSymFind(void*, const std::string&, bool)"
+ << " : dlsym of " << symbol << std::endl;
+ }
+
+ // Get address of symbol, or nullptr on failure
+ void* fun =
+ reinterpret_cast
+ (
+ ::GetProcAddress(static_cast(handle), symbol.c_str())
+ );
+
+ // Any error?
+ if (!fun && required)
+ {
+ WarningInFunction
+ << "Cannot lookup symbol " << symbol << " : "
+ << MSwindows::lastError() << endl;
+ }
+
+ return fun;
+}
+
+
+Foam::fileNameList Foam::dlLoaded()
+{
+ DynamicList libs(libsLoaded.size());
+
+ for (const auto& item : libsLoaded)
+ {
+ libs.append(item.second);
+ }
+
+ if (MSwindows::debug)
+ {
+ std::cout
+ << "dlLoaded()"
+ << " : determined loaded libraries :" << libs.size() << std::endl;
+ }
+
+ return libs;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OSspecific/MSwindows/MSwindows.H b/src/OSspecific/MSwindows/MSwindows.H
new file mode 100644
index 0000000000..e0f7c317b2
--- /dev/null
+++ b/src/OSspecific/MSwindows/MSwindows.H
@@ -0,0 +1,69 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ | Copyright (C) 2011 Symscape
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Namespace
+ Foam::MSwindows
+
+Description
+ OS-specific functions implemented for MS-windows.
+
+SourceFiles
+ MSwindows.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef MSwindows_H
+#define MSwindows_H
+
+#include "className.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace MSwindows
+{
+ //- Declare namespace and its debug switch
+ NamespaceName("MSwindows");
+
+ //- The last Windows API error from GetLastError
+ std::string lastError();
+
+ //- The user-name from Windows API GetUserName
+ std::string userName();
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OSspecific/MSwindows/Make/files b/src/OSspecific/MSwindows/Make/files
new file mode 100644
index 0000000000..964f34106e
--- /dev/null
+++ b/src/OSspecific/MSwindows/Make/files
@@ -0,0 +1,21 @@
+MSwindows.C
+
+cpuInfo/cpuInfo.C
+memInfo/memInfo.C
+
+signals/sigFpe.C
+signals/sigInt.C
+signals/sigQuit.C
+signals/sigSegv.C
+signals/sigStopAtWriteNow.C
+signals/sigWriteNow.C
+signals/timer.C
+
+fileStat/fileStat.C
+
+/* Without inotify */
+fileMonitor/fileMonitor.C
+
+printStack/dummyPrintStack.C
+
+LIB = $(FOAM_LIBBIN)/libOSspecific
diff --git a/src/OSspecific/MSwindows/Make/options b/src/OSspecific/MSwindows/Make/options
new file mode 100644
index 0000000000..3f86d412a6
--- /dev/null
+++ b/src/OSspecific/MSwindows/Make/options
@@ -0,0 +1 @@
+EXE_INC = $(COMP_FLAGS)
diff --git a/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C
new file mode 100644
index 0000000000..d20330b78e
--- /dev/null
+++ b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C
@@ -0,0 +1,68 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+#include "cpuInfo.H"
+#include "IOstreams.H"
+
+#include
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::cpuInfo::cpuInfo()
+:
+ vendor_id(),
+ model_name(),
+ cpu_family(-1),
+ model(-1),
+ cpu_MHz(0),
+ siblings(0),
+ cpu_cores(std::thread::hardware_concurrency())
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+void Foam::cpuInfo::write(Ostream& os) const
+{
+ if (!vendor_id.empty())
+ {
+ os.writeEntry("vendor_id", vendor_id);
+ }
+ if (!model_name.empty())
+ {
+ os.writeEntry("model_name", model_name);
+ }
+
+ os.writeEntryIfDifferent("cpu_family", -1, cpu_family);
+ os.writeEntryIfDifferent("model", -1, model);
+ os.writeEntryIfDifferent("cpu_MHz", 0, cpu_MHz);
+ os.writeEntryIfDifferent("cpu_cores", 0, cpu_cores);
+ os.writeEntryIfDifferent("siblings", 0, siblings);
+}
+
+
+// ************************************************************************* //
diff --git a/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H
new file mode 100644
index 0000000000..1dbba0b6ee
--- /dev/null
+++ b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H
@@ -0,0 +1,111 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Class
+ Foam::cpuInfo
+
+Description
+ General CPU characteristics.
+
+ If the machine has multiple cpus/cores, only the characteristics
+ of the first core are used.
+
+Note
+ Windows variant only provides the number of cores.
+
+SourceFiles
+ cpuInfo.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cpuInfo_H
+#define cpuInfo_H
+
+#include
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declarations
+class Ostream;
+
+/*---------------------------------------------------------------------------*\
+ Class cpuInfo Declaration
+\*---------------------------------------------------------------------------*/
+
+class cpuInfo
+{
+ // Private data
+
+ // Various bits from /proc/cpuinfo
+
+ std::string vendor_id;
+ std::string model_name;
+ int cpu_family;
+ int model;
+ float cpu_MHz;
+ int siblings;
+ int cpu_cores;
+
+
+ // Private Member Functions
+
+ //- Parse /proc/cpuinfo
+ void parse();
+
+ //- No copy construct
+ cpuInfo(const cpuInfo&) = delete;
+
+ //- No copy assignment
+ void operator=(const cpuInfo&) = delete;
+
+public:
+
+ // Constructors
+
+ //- Construct and populate with information
+ cpuInfo();
+
+ //- Destructor
+ ~cpuInfo() = default;
+
+
+ // Member Functions
+
+ //- Write content as dictionary entries
+ void write(Ostream& os) const;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OSspecific/MSwindows/cpuTime/cpuTime.H b/src/OSspecific/MSwindows/cpuTime/cpuTime.H
new file mode 100644
index 0000000000..3af1aa192e
--- /dev/null
+++ b/src/OSspecific/MSwindows/cpuTime/cpuTime.H
@@ -0,0 +1,40 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Typedef
+ Foam::cpuTime
+
+Description
+ Selection of preferred clock mechanism for the elapsed cpu time.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cpuTime_H
+#define cpuTime_H
+
+#include "cpuTimeCxx.H"
+#include "cpuTimeFwd.H"
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H b/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H
new file mode 100644
index 0000000000..bc7d1885f3
--- /dev/null
+++ b/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H
@@ -0,0 +1,48 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Typedef
+ Foam::cpuTime
+
+Description
+ Selection of preferred clock mechanism for the elapsed cpu time.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cpuTimeFwd_H
+#define cpuTimeFwd_H
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+ class cpuTimeCxx;
+
+ typedef cpuTimeCxx cpuTime;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C
new file mode 100644
index 0000000000..425a0c333d
--- /dev/null
+++ b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C
@@ -0,0 +1,625 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2010-2011, 2018 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ | Copyright (C) 2011-2016 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+#include "fileMonitor.H"
+#include "IOstreams.H"
+#include "Pstream.H"
+#include "PackedList.H"
+#include "PstreamReduceOps.H"
+#include "OSspecific.H"
+#include "regIOobject.H" // for fileModificationSkew symbol
+
+#ifdef _WIN32
+#undef FOAM_USE_INOTIFY
+#endif
+
+#ifdef FOAM_USE_INOTIFY
+ #include
+ #include
+ #include
+ #include
+ #define EVENT_SIZE ( sizeof (struct inotify_event) )
+ #define EVENT_LEN (EVENT_SIZE + 16)
+ #define EVENT_BUF_LEN ( 1024 * EVENT_LEN )
+#endif
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+const Foam::Enum
+<
+ Foam::fileMonitor::fileState
+>
+Foam::fileMonitor::fileStateNames_
+({
+ { fileState::UNMODIFIED, "unmodified" },
+ { fileState::MODIFIED, "modified" },
+ { fileState::DELETED, "deleted" },
+});
+
+
+namespace Foam
+{
+ defineTypeNameAndDebug(fileMonitor, 0);
+
+ //- Reduction operator for PackedList of fileState
+ class reduceFileStates
+ {
+ public:
+ unsigned int operator()(const unsigned int x, const unsigned int y)
+ const
+ {
+ // x,y are sets of 2bits representing fileState
+
+ unsigned int mask = 3u;
+ unsigned int shift = 0;
+ unsigned int result = 0;
+
+ while (mask)
+ {
+ // Combine state
+ unsigned int xState = (x & mask) >> shift;
+ unsigned int yState = (y & mask) >> shift;
+
+ // Combine and add to result. Combine is such that UNMODIFIED
+ // wins.
+ unsigned int state = min(xState, yState);
+ result |= (state << shift);
+
+ shift += 2;
+ mask <<= 2;
+ }
+ return result;
+ }
+ };
+
+ //- Combine operator for PackedList of fileState
+ class combineReduceFileStates
+ {
+ public:
+ void operator()(unsigned int& x, const unsigned int y) const
+ {
+ x = reduceFileStates()(x, y);
+ }
+ };
+
+
+
+ //- Internal tracking via stat(3p) or inotify(7)
+ class fileMonitorWatcher
+ {
+ public:
+
+ const bool useInotify_;
+
+ // For inotify
+
+ //- File descriptor for the inotify instance
+ int inotifyFd_;
+
+ //- Current watchIDs and corresponding directory id
+ DynamicList