Skip to content

Commit

Permalink
[C++] Fix Windows 32 bits compile and runtime failures (#11082)
Browse files Browse the repository at this point in the history
### 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 #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.
  • Loading branch information
BewareMyPower committed Jun 25, 2021
1 parent eafe7dd commit c8fe1e8
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 7 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/ci-cpp-build-windows.yaml
Expand Up @@ -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
Expand Down
8 changes: 3 additions & 5 deletions pulsar-client-cpp/README.md
Expand Up @@ -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,

Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion pulsar-client-cpp/lib/CMakeLists.txt
Expand Up @@ -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)
Expand Down
12 changes: 11 additions & 1 deletion pulsar-client-cpp/lib/checksum/crc32c_sse42.cc
Expand Up @@ -19,18 +19,27 @@
#if BOOST_VERSION >= 105500
#include <boost/predef.h>
#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 <assert.h>
#include <stdlib.h>
#include "lib/checksum/crc32c_sw.h"

#if BOOST_ARCH_X86_64
#include <nmmintrin.h> // SSE4.2
#include <wmmintrin.h> // 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 <intrin.h>
Expand Down Expand Up @@ -82,6 +91,7 @@ bool crc32c_initialize() {
DEBUG_PRINTF1("has_pclmulqdq = %d\n", has_pclmulqdq);
initialized = true;
}

return has_sse42;
}

Expand Down Expand Up @@ -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

0 comments on commit c8fe1e8

Please sign in to comment.