Skip to content

Commit

Permalink
Merge pull request #340 from shikokuchuo:windows
Browse files Browse the repository at this point in the history
Enable compilation of libfswatch under Windows MinGW
  • Loading branch information
emcrisostomo authored Feb 15, 2025
2 parents 0a8c9a2 + 3767582 commit 5c443d2
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 45 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/cmake-libfswatch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: CMake libfswatch on Windows MinGW

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release

jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: windows-latest

steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/setup-r@v2

- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_LIBS_ONLY=1

- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ set(CMAKE_CXX_EXTENSIONS OFF)

# Add option to choose between shared and static libraries
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
# Add option to build libfswatch only (without fswatch or tests)
option(BUILD_LIBS_ONLY "Build libfswatch only" OFF)

# include modules
include(FindGettext)
Expand Down Expand Up @@ -74,5 +76,7 @@ if (USE_NLS)
endif ()

add_subdirectory(libfswatch)
if (NOT BUILD_LIBS_ONLY)
add_subdirectory(fswatch/src)
add_subdirectory(test/src)
endif ()
46 changes: 22 additions & 24 deletions libfswatch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,30 +112,28 @@ endif (HAVE_PORT_H)

check_cxx_symbol_exists(FindFirstChangeNotification windows.h HAVE_WINDOWS_HEADER)

if (HAVE_WINDOWS_HEADER AND CYGWIN)
check_include_file_cxx(sys/cygwin.h HAVE_CYGWIN)

if (HAVE_CYGWIN)
set(LIBFSWATCH_HEADER_FILES
${LIBFSWATCH_HEADER_FILES}
src/libfswatch/c++/windows/win_directory_change_event.hpp
src/libfswatch/c++/windows/win_error_message.hpp
src/libfswatch/c++/windows/win_handle.hpp
src/libfswatch/c++/windows/win_paths.hpp
src/libfswatch/c++/windows/win_strings.hpp
src/libfswatch/c++/windows_monitor.hpp)

set(LIB_SOURCE_FILES
${LIB_SOURCE_FILES}
src/libfswatch/c++/windows/win_directory_change_event.cpp
src/libfswatch/c++/windows/win_error_message.cpp
src/libfswatch/c++/windows/win_handle.cpp
src/libfswatch/c++/windows/win_paths.cpp
src/libfswatch/c++/windows/win_strings.cpp
src/libfswatch/c++/windows_monitor.cpp)
set(HAVE_WINDOWS ON CACHE BOOL "Enable Windows support")
endif (HAVE_CYGWIN)
endif (HAVE_WINDOWS_HEADER AND CYGWIN)
if (HAVE_WINDOWS_HEADER)

set(LIBFSWATCH_HEADER_FILES
${LIBFSWATCH_HEADER_FILES}
src/libfswatch/c++/windows/win_directory_change_event.hpp
src/libfswatch/c++/windows/win_error_message.hpp
src/libfswatch/c++/windows/win_handle.hpp
src/libfswatch/c++/windows/win_paths.hpp
src/libfswatch/c++/windows/win_strings.hpp
src/libfswatch/c++/windows_monitor.hpp)

set(LIB_SOURCE_FILES
${LIB_SOURCE_FILES}
src/libfswatch/c++/windows/win_directory_change_event.cpp
src/libfswatch/c++/windows/win_error_message.cpp
src/libfswatch/c++/windows/win_handle.cpp
src/libfswatch/c++/windows/win_paths.cpp
src/libfswatch/c++/windows/win_strings.cpp
src/libfswatch/c++/windows_monitor.cpp)
set(HAVE_WINDOWS ON CACHE BOOL "Enable Windows support")

endif (HAVE_WINDOWS_HEADER)

if (APPLE)
check_include_file_cxx(CoreServices/CoreServices.h HAVE_FSEVENTS_FILE_EVENTS)
Expand Down
19 changes: 12 additions & 7 deletions libfswatch/src/libfswatch/c++/path_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ namespace fsw

try
{
for (const auto& entry : std::filesystem::directory_iterator(path))
for (const auto& entry : std::filesystem::directory_iterator(path))
entries.emplace_back(entry);
}
catch (const std::filesystem::filesystem_error& e)
}
catch (const std::filesystem::filesystem_error& e)
{
FSW_ELOGF(_("Error accessing directory: %s"), e.what());
}

return entries;
}

std::vector<std::filesystem::directory_entry> get_subdirectories(const std::filesystem::path& path)
{
std::vector<std::filesystem::directory_entry> entries;
Expand All @@ -52,10 +52,10 @@ namespace fsw

try
{
for (const auto& entry : std::filesystem::directory_iterator(path))
for (const auto& entry : std::filesystem::directory_iterator(path))
if (entry.is_directory()) entries.emplace_back(entry);
}
catch (const std::filesystem::filesystem_error& e)
}
catch (const std::filesystem::filesystem_error& e)
{
FSW_ELOGF(_("Error accessing directory: %s"), e.what());
}
Expand All @@ -79,10 +79,15 @@ namespace fsw

bool lstat_path(const std::string& path, struct stat& fd_stat)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
fsw_logf_perror(_("Cannot lstat %s (not implemented on Windows)"), path.c_str());
return false;
#else
if (lstat(path.c_str(), &fd_stat) == 0)
return true;

fsw_logf_perror(_("Cannot lstat %s"), path.c_str());
return false;
#endif
}
}
14 changes: 9 additions & 5 deletions libfswatch/src/libfswatch/c++/poll_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ namespace fsw

return true;
}

watched_file_info pwfi = previous_data->tracked_files[path];
vector<fsw_event_flag> flags;

if (mtime > pwfi.mtime)
{
flags.push_back(fsw_event_flag::Updated);
}
}

if (ctime > pwfi.ctime)
{
Expand Down Expand Up @@ -139,6 +139,9 @@ namespace fsw
return;
}

#if defined(_WIN32) && !defined(__CYGWIN__)
fsw_log_perror("Poll monitor on Windows requires Cygwin");
#else
if (!accept_path(path)) return;

// TODO: C++17 doesn't standardize access to ctime, so we need to keep
Expand All @@ -149,6 +152,7 @@ namespace fsw
if (!add_path(path, fd_stat, fn)) return;
if (!recursive) return;
if (!S_ISDIR(fd_stat.st_mode)) return;
#endif

const auto entries = get_directory_entries(path);

Expand All @@ -157,7 +161,7 @@ namespace fsw
scan(entry.path(), fn);
}
}
catch (const std::filesystem::filesystem_error& e)
catch (const std::filesystem::filesystem_error& e)
{
// Handle errors, such as permission issues or non-existent paths
FSW_ELOGF(_("Filesystem error: %s"), e.what());
Expand All @@ -183,7 +187,7 @@ namespace fsw

void poll_monitor::collect_data()
{
path_visitor fn = std::bind(&poll_monitor::intermediate_scan_callback,
path_visitor fn = std::bind(&poll_monitor::intermediate_scan_callback,
this,
std::placeholders::_1,
std::placeholders::_2);
Expand All @@ -200,7 +204,7 @@ namespace fsw

void poll_monitor::collect_initial_data()
{
path_visitor fn = std::bind(&poll_monitor::initial_scan_callback,
path_visitor fn = std::bind(&poll_monitor::initial_scan_callback,
this,
std::placeholders::_1,
std::placeholders::_2);
Expand Down
21 changes: 21 additions & 0 deletions libfswatch/src/libfswatch/c++/windows/win_paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "win_paths.hpp"
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#else
#include <windows.h>
#include <vector>
#endif
#include "../libfswatch_exception.hpp"
#include "../../gettext_defs.h"

Expand All @@ -26,6 +31,7 @@ namespace fsw
{
wstring posix_to_win_w(string path)
{
#ifdef __CYGWIN__
void * raw_path = cygwin_create_path(CCP_POSIX_TO_WIN_W, path.c_str());
if (raw_path == nullptr) throw libfsw_exception(_("cygwin_create_path could not allocate memory to convert the path."));

Expand All @@ -34,10 +40,18 @@ namespace fsw
free(raw_path);

return win_path;
#else
int pathlen = (int) path.length() + 1;
int buflen = MultiByteToWideChar(CP_ACP, 0, path.c_str(), pathlen, 0, 0);
std::vector<wchar_t> buf(buflen);
MultiByteToWideChar(CP_ACP, 0, path.c_str(), pathlen, buf.data(), buflen);
return std::wstring(buf.data());
#endif
}

string win_w_to_posix(wstring path)
{
#ifdef __CYGWIN__
void * raw_path = cygwin_create_path(CCP_WIN_W_TO_POSIX, path.c_str());
if (raw_path == nullptr) throw libfsw_exception(_("cygwin_create_path could not allocate memory to convert the path."));

Expand All @@ -46,6 +60,13 @@ namespace fsw
free(raw_path);

return posix_path;
#else
int pathlen = (int)path.length() + 1;
int buflen = WideCharToMultiByte(CP_ACP, 0, path.c_str(), pathlen, 0, 0, 0, 0);
std::vector<char> buf(buflen);
WideCharToMultiByte(CP_ACP, 0, path.c_str(), pathlen, buf.data(), buflen, 0, 0);
return std::string(buf.data());
#endif
}
}
}
13 changes: 7 additions & 6 deletions libfswatch/src/libfswatch/c++/windows/win_strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,26 @@
*/
#include "win_strings.hpp"
#include <windows.h>
#include <vector>

namespace fsw
{
namespace win_strings
{
using namespace std;

string wstring_to_string(wchar_t * s)
string wstring_to_string(wchar_t *s)
{
int buf_size = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char buf[buf_size];
WideCharToMultiByte(CP_UTF8, 0, s, -1, buf, buf_size, NULL, NULL);
std::vector<char> buf(buf_size);
WideCharToMultiByte(CP_UTF8, 0, s, -1, buf.data(), buf_size, NULL, NULL);

return string(buf);
return std::string(buf.data());
}

string wstring_to_string(const wstring & s)
string wstring_to_string(const wstring &s)
{
return wstring_to_string((wchar_t *)s.c_str());
return wstring_to_string((wchar_t *) s.c_str());
}
}
}
6 changes: 3 additions & 3 deletions libfswatch/src/libfswatch/c/libfswatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ extern "C"
* returns FSW_OK, otherwise the initialization routine failed and the library
* should not be usable.
*/
FSW_STATUS fsw_init_library();
FSW_STATUS fsw_init_library(void);

/**
* This function creates a new monitor session using the specified monitor
Expand Down Expand Up @@ -195,12 +195,12 @@ extern "C"
/**
* Gets the last error code.
*/
FSW_STATUS fsw_last_error();
FSW_STATUS fsw_last_error(void);

/**
* Check whether the verbose mode is active.
*/
bool fsw_is_verbose();
bool fsw_is_verbose(void);

/**
* Set the verbose mode.
Expand Down

0 comments on commit 5c443d2

Please sign in to comment.