From c8fe1e89469228a59967b8716cada0fcf63315e1 Mon Sep 17 00:00:00 2001 From: Yunze Xu Date: Fri, 25 Jun 2021 08:59:13 +0800 Subject: [PATCH] [C++] Fix Windows 32 bits compile and runtime failures (#11082) ### Motivation C++ source code cannot be compiled successfully for Windows 32-bit build. The compile error is: > fatal error C1021: invalid preprocessor command 'warning' It's because `#warning` preprocessor directive is not supported by MSVC compilers. And even if the related code was remove and the build succeeded, a example producer program would crash. This bug is introduced from https://github.com/apache/pulsar/pull/6129. It's because hardware CRC32 implementation on Windows is only provided for 64-bit programs. However, the `__cpuid` check in `crc32_initialize()` still returns true for 32-bit build, so finally it went here: ```c++ uint32_t crc32c(uint32_t init, const void *buf, size_t len, const chunk_config *config) { // SSE 4.2 extension for hw implementation are not present abort(); } ``` The `abort()` call will terminate the process. ### Modifications - Use `#pragma message()` to replace `#warning` if the compiler is MSVC. - Fallback to software implementation of CRC32 checksum algorithm if the hardware implementation is not supported. - Add the workflow to build Windows 32-bit C++ library. - Fix the wrong document about how to build it for Windows 32-bit. --- .github/workflows/ci-cpp-build-windows.yaml | 7 +++++++ pulsar-client-cpp/README.md | 8 +++----- pulsar-client-cpp/lib/CMakeLists.txt | 2 +- pulsar-client-cpp/lib/checksum/crc32c_sse42.cc | 12 +++++++++++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-cpp-build-windows.yaml b/.github/workflows/ci-cpp-build-windows.yaml index 6384968741d6d..c524fdc4b0ca6 100644 --- a/.github/workflows/ci-cpp-build-windows.yaml +++ b/.github/workflows/ci-cpp-build-windows.yaml @@ -52,6 +52,13 @@ jobs: suffix: 'windows-win64' generator: 'Visual Studio 16 2019' arch: '-A x64' + - name: 'Windows x86' + os: windows-latest + triplet: x86-windows + vcpkg_dir: 'C:\vcpkg' + suffix: 'windows-win32' + generator: 'Visual Studio 16 2019' + arch: '-A Win32' steps: - name: checkout diff --git a/pulsar-client-cpp/README.md b/pulsar-client-cpp/README.md index f489c3d3aa7c9..61f6dff441485 100644 --- a/pulsar-client-cpp/README.md +++ b/pulsar-client-cpp/README.md @@ -189,13 +189,13 @@ ${PULSAR_PATH}/pulsar-client-cpp/perf/perfConsumer It's highly recommended to use `vcpkg` for C++ package management on Windows. It's easy to install and well supported by Visual Studio (2015/2017/2019) and CMake. See [here](https://github.com/microsoft/vcpkg#quick-start-windows) for quick start. -Take 64 bits Windows as an example, you only need to run +Take Windows 64-bit library as an example, you only need to run ```bash vcpkg install --feature-flags=manifests --triplet x64-windows ``` -> NOTE: The default triplet is `x86-windows`, see [here](https://github.com/microsoft/vcpkg/blob/master/docs/users/triplets.md) for more details. +> NOTE: For Windows 32-bit library, change `x64-windows` to `x86-windows`, see [here](https://github.com/microsoft/vcpkg/blob/master/docs/users/triplets.md) for more details about the triplet concept in Vcpkg. The all dependencies, which are specified by [vcpkg.json](vcpkg.json), will be installed in `vcpkg_installed/` subdirectory, @@ -214,10 +214,8 @@ cmake --build ./build --config Release Then all artifacts will be built into `build` subdirectory. -> NOTE: +> NOTE: For Windows 32-bit, you need to use `-A Win32` and `-DVCPKG_TRIPLET=x86-windows`. > -> 1. Change `Release` to `Debug` if you want to build a debug version library. -> 2. For 32 bits Windows, you need to use `-A Win32` and `-DVCPKG_TRIPLET=x32-windows`. #### Install dependencies manually diff --git a/pulsar-client-cpp/lib/CMakeLists.txt b/pulsar-client-cpp/lib/CMakeLists.txt index 2e540b2dfd554..96d7283c4b600 100644 --- a/pulsar-client-cpp/lib/CMakeLists.txt +++ b/pulsar-client-cpp/lib/CMakeLists.txt @@ -150,7 +150,7 @@ elseif(BUILD_STATIC_LIB) # Install regular libpulsar.a target_link_libraries(pulsarStatic ${COMMON_LIBS}) install(TARGETS pulsarStatic DESTINATION lib) -endif(LINK_STATIC) +endif() if (BUILD_STATIC_LIB) install(TARGETS pulsarStatic DESTINATION lib) diff --git a/pulsar-client-cpp/lib/checksum/crc32c_sse42.cc b/pulsar-client-cpp/lib/checksum/crc32c_sse42.cc index 89349a7e03e33..5126ec971be6c 100644 --- a/pulsar-client-cpp/lib/checksum/crc32c_sse42.cc +++ b/pulsar-client-cpp/lib/checksum/crc32c_sse42.cc @@ -19,18 +19,27 @@ #if BOOST_VERSION >= 105500 #include #else +#if _MSC_VER +#pragma message("Boost version is < 1.55, disable CRC32C") +#else #warning "Boost version is < 1.55, disable CRC32C" #endif +#endif #include #include +#include "lib/checksum/crc32c_sw.h" #if BOOST_ARCH_X86_64 #include // SSE4.2 #include // PCLMUL #else +#ifdef _MSC_VER +#pragma message("BOOST_ARCH_X86_64 is not defined, CRC32C will be disabled") +#else #warning "BOOST_ARCH_X86_64 is not defined, CRC32C will be disabled" #endif +#endif #ifdef _MSC_VER #include @@ -82,6 +91,7 @@ bool crc32c_initialize() { DEBUG_PRINTF1("has_pclmulqdq = %d\n", has_pclmulqdq); initialized = true; } + return has_sse42; } @@ -251,7 +261,7 @@ uint32_t crc32c(uint32_t init, const void *buf, size_t len, const chunk_config * uint32_t crc32c(uint32_t init, const void *buf, size_t len, const chunk_config *config) { // SSE 4.2 extension for hw implementation are not present - abort(); + return crc32c_sw(init, buf, len); // fallback to the software implementation } #endif