Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ else()
set_property(TARGET ${TARGET_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_options(${TARGET_NAME} PRIVATE "${LINK_ARG}")
target_link_libraries(${TARGET_NAME} ${ESPP_EXTERNAL_LIBS})
if(WIN32)
target_link_libraries(${TARGET_NAME} winmm)
endif()
target_compile_features(${TARGET_NAME} PRIVATE cxx_std_20)

# install build output and headers
Expand Down
8 changes: 6 additions & 2 deletions lib/espp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,13 @@ if(MSVC)
list(APPEND ESPP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/wcswidth.c)
endif()

# if we're on Windows, we need to link against ws2_32
# On Windows link against ws2_32 (sockets) and winmm (timeBeginPeriod, used by
# the TimerResolution helper in espp.hpp). Centralizing these here keeps linkage
# consistent across the static library, tests, and the _espp module, and works
# on all Windows toolchains (MSVC, MinGW, clang) rather than relying on
# MSVC-only #pragma comment(lib, ...).
if(WIN32)
set(ESPP_EXTERNAL_LIBS ws2_32)
set(ESPP_EXTERNAL_LIBS ws2_32 winmm)
else()
set(ESPP_EXTERNAL_LIBS pthread)
endif()
Expand Down
12 changes: 10 additions & 2 deletions lib/espp.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
#include "espp.hpp"

#ifdef _MSC_VER
#pragma comment(lib, "Ws2_32.lib")
// The Windows system libraries this needs (Ws2_32, winmm) are linked via CMake
// (see lib/espp.cmake, which sets ESPP_EXTERNAL_LIBS for WIN32), so no
// #pragma comment(lib, ...) is needed here - keeping the link spec in one place
// keeps it consistent across the static library, the tests, and the _espp
// Python module, and works on all Windows toolchains (not just MSVC).

#ifdef _WIN32
// Global instance that raises the multimedia timer resolution to 1 ms for the
// lifetime of the program (see TimerResolution in espp.hpp).
TimerResolution timer_resolution{};
#endif
27 changes: 27 additions & 0 deletions lib/include/espp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include "socket_msvc.hpp"

#ifdef _MSC_VER
// windows.h is a C++ header and must not be wrapped in extern "C"; only the C
// header (wcswidth) needs it.
#include <windows.h>
extern "C" {
// NOTE: needed for tabulate
#include "wcswidth.h"
Comment thread
finger563 marked this conversation as resolved.
Expand Down Expand Up @@ -64,3 +67,27 @@ extern "C" {
#include "state_base.hpp"

#include <tabulate/markdown_exporter.hpp>

// The timer-resolution helper uses the Windows multimedia timer API
// (timeBeginPeriod), which is available on all Windows toolchains (MSVC, MinGW,
// clang), so guard on _WIN32 rather than _MSC_VER. winmm is linked via CMake
// (see lib/espp.cmake / pc/CMakeLists.txt).
#ifdef _WIN32

#include <mmsystem.h>
#include <windows.h>

// we want to ensure that the timer resolution is set to 1ms, otherwise the
// timer will not be accurate. To do this we need to call timeBeginPeriod(1) at
// the start of the program and timeEndPeriod(1) at the end of the program.
class TimerResolution {
public:
TimerResolution() { timeBeginPeriod(1); }
~TimerResolution() { timeEndPeriod(1); }
};

// we create a global instance of the TimerResolution class to ensure that the
// timer resolution is set to 1ms for the duration of the program.
extern TimerResolution timer_resolution;

#endif
7 changes: 7 additions & 0 deletions pc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ MACRO(GEN_TESTS curdir)
PRIVATE espp_pc
PRIVATE ${ESPP_EXTERNAL_LIBS}
)
# /WHOLEARCHIVE is an MSVC/link.exe flag (gate on MSVC, not WIN32, so
# MinGW/clang Windows builds don't receive it). It ensures the whole archive
# is linked in, otherwise the Windows timer-period adjustment code (from
# espp.hpp) is stripped and the timer runs at a max of ~64 Hz.
if(MSVC)
target_link_options(${TEST_NAME} PRIVATE "/WHOLEARCHIVE:espp_pc.lib")
endif()
ENDFOREACH()
ENDMACRO()

Expand Down