Skip to content

Commit b1b208f

Browse files
committed
Squashed 'src/minisketch/' changes from ea8f66b1ea..f74b7e2bc2
f74b7e2bc2 Merge bitcoin-core/minisketch#75: build: Introduce CMake-based build system 850cc868d5 ci: Add GHA workflow with native Windows job 40d56708c8 doc: Add "Building with CMake" section to `README.md` a0c86c79a7 build: Add CMake-based build system git-subtree-dir: src/minisketch git-subtree-split: f74b7e2bc2e5e1a1360927934521216bee5f345c
1 parent bf25a09 commit b1b208f

File tree

7 files changed

+464
-1
lines changed

7 files changed

+464
-1
lines changed

.github/workflows/ci.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: CI
2+
on:
3+
pull_request:
4+
push:
5+
branches:
6+
- '**'
7+
tags-ignore:
8+
- '**'
9+
10+
concurrency:
11+
group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
windows-native:
16+
name: ${{ matrix.configuration.job_name }}
17+
# See: https://github.com/actions/runner-images#available-images.
18+
runs-on: windows-2025
19+
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
configuration:
24+
- job_name: 'x64 (MSVC): Windows (VS 2022)'
25+
build_configuration: 'Release'
26+
- job_name: 'x64 (MSVC): Windows (VS 2022, fields=32)'
27+
cmake_options: '-DMINISKETCH_FIELDS=32'
28+
build_configuration: 'Release'
29+
- job_name: 'x64 (MSVC): Windows (VS 2022, debug)'
30+
build_configuration: 'Debug'
31+
# TODO: Resolve the issue and re-enable benchmark.
32+
# See: https://github.com/bitcoin-core/minisketch/pull/96.
33+
skip_benchmark: true
34+
- job_name: 'x64 (MSVC): Windows (VS 2022, shared)'
35+
cmake_options: '-DBUILD_SHARED_LIBS=ON'
36+
build_configuration: 'Release'
37+
- job_name: 'x64 (clang-cl): Windows (VS 2022)'
38+
cmake_options: '-T ClangCL'
39+
build_configuration: 'Release'
40+
# TODO: Resolve the issue and re-enable benchmark.
41+
# See: https://github.com/bitcoin-core/minisketch/pull/96.
42+
skip_benchmark: true
43+
44+
steps:
45+
- name: Checkout
46+
uses: actions/checkout@v4
47+
48+
- name: Generate buildsystem
49+
env:
50+
CXXFLAGS: '/WX'
51+
run: cmake -B build -DMINISKETCH_BUILD_BENCHMARK=ON ${{ matrix.configuration.cmake_options }}
52+
53+
- name: Build
54+
run: cmake --build build --config ${{ matrix.configuration.build_configuration }}
55+
56+
- name: Binaries info
57+
shell: bash
58+
run: |
59+
cd build/bin/${{ matrix.configuration.build_configuration }}
60+
file * | grep "\.exe\|\.dll"
61+
62+
- name: Check
63+
working-directory: build
64+
run: ctest --output-on-failure -j $env:NUMBER_OF_PROCESSORS -C ${{ matrix.configuration.build_configuration }}
65+
66+
- name: Benchmark
67+
if: ${{ ! matrix.configuration.skip_benchmark }}
68+
working-directory: build
69+
run: bin\${{ matrix.configuration.build_configuration }}\bench.exe

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ stamp-h1
3333

3434
test*
3535
bench
36+
37+
# CMake build directories.
38+
/*build*

CMakeLists.txt

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
cmake_minimum_required(VERSION 3.22)
2+
3+
#=============================
4+
# Project / Package Metadata
5+
#=============================
6+
project(minisketch
7+
VERSION 0.0.1
8+
DESCRIPTION "A library for BCH-based set reconciliation"
9+
HOMEPAGE_URL "https://github.com/bitcoin-core/minisketch"
10+
LANGUAGES CXX
11+
)
12+
13+
# ============================================================
14+
# Project Initialization
15+
# ============================================================
16+
enable_testing()
17+
include(CTestUseLaunchers)
18+
19+
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
20+
21+
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
22+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
23+
endif()
24+
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
25+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
26+
endif()
27+
if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
28+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
29+
endif()
30+
31+
# Prevent include directories from parent project from leaking into this one.
32+
set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES "")
33+
34+
#=============================
35+
# Language Setup
36+
#=============================
37+
if(DEFINED CMAKE_CXX_STANDARD)
38+
if(CMAKE_CXX_STANDARD EQUAL 98 OR CMAKE_CXX_STANDARD LESS 11)
39+
message(FATAL_ERROR "This project requires at least C++11")
40+
endif()
41+
else()
42+
set(CMAKE_CXX_STANDARD 11)
43+
endif()
44+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
45+
if(NOT DEFINED CMAKE_CXX_EXTENSIONS)
46+
set(CMAKE_CXX_EXTENSIONS OFF)
47+
endif()
48+
49+
#=============================
50+
# Configurable Options
51+
#=============================
52+
option(MINISKETCH_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL})
53+
if(NOT PROJECT_IS_TOP_LEVEL)
54+
mark_as_advanced(MINISKETCH_INSTALL)
55+
endif()
56+
57+
option(MINISKETCH_BUILD_TESTS "Build tests." ON)
58+
option(MINISKETCH_BUILD_BENCHMARK "Build benchmark." OFF)
59+
60+
set(supported_fields "")
61+
set(have_enabled_fields NO)
62+
set(have_disabled_fields NO)
63+
foreach(i RANGE 2 64)
64+
list(APPEND supported_fields ${i})
65+
endforeach()
66+
if(NOT DEFINED MINISKETCH_FIELDS)
67+
set(MINISKETCH_FIELDS ${supported_fields} CACHE STRING "Semicolon-separated list of field sizes to build. Default=all. Available sizes: ${supported_fields}.")
68+
endif()
69+
foreach(field IN LISTS supported_fields)
70+
if(field IN_LIST MINISKETCH_FIELDS)
71+
set(have_enabled_fields YES)
72+
else()
73+
set(have_disabled_fields YES)
74+
add_compile_definitions(DISABLE_FIELD_${field})
75+
endif()
76+
endforeach()
77+
if(NOT have_enabled_fields)
78+
message(FATAL_ERROR "No field sizes are enabled.")
79+
endif()
80+
unset(have_enabled_fields)
81+
unset(supported_fields)
82+
83+
#=============================
84+
# Build Options
85+
#=============================
86+
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
87+
88+
if(MSVC)
89+
add_compile_options(/Zc:__cplusplus)
90+
endif()
91+
92+
if(MINGW)
93+
add_link_options(-static)
94+
endif()
95+
96+
#=============================
97+
# Diagnostics Options
98+
#=============================
99+
if(MSVC)
100+
# For both MSVC's cl.exe and clang-cl compilers.
101+
add_compile_options(/W3) # Production quality warning level. Enables -Wall Clang's core option.
102+
else()
103+
add_compile_options(-Wall)
104+
endif()
105+
106+
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
107+
add_compile_options(/wd4060) # Disable warning C4060 "switch statement contains no 'case' or 'default' labels".
108+
add_compile_options(/wd4065) # Disable warning C4065 "switch statement contains 'default' but no 'case' labels".
109+
add_compile_options(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned".
110+
add_compile_options(/wd4244) # Disable warning C4244 "conversion from 'type1' to 'type2', possible loss of data".
111+
else()
112+
add_compile_options(-Wundef)
113+
endif()
114+
115+
#=============================
116+
# Main Processing
117+
#=============================
118+
include(SystemIntrospection)
119+
add_subdirectory(src)
120+
121+
include(PrintConfigureSummary)
122+
print_configure_summary()

README.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Below we compare the PinSketch algorithm (which `libminisketch` is an implementa
6666
* **Difference type:** PinSketch can only compute the symmetric difference from a merged sketch, while CPISync and IBLT can distinguish which side certain elements were missing on. When the decoder has access to one of the sets, this generally doesn't matter, as he can look up each of the elements in the symmetric difference with one of the sets.
6767
* **Secure sketch:** Whether the sketch satisfies the definition of a secure sketch<sup>[[1]](#myfootnote1)</sup>, which implies a minimal amount about a set can be extracted from a sketch by anyone who does not know most of the elements already. This makes the algorithm appropriate for applications like fingerprint authentication.
6868

69-
## Building
69+
## Building with Autotools
7070

7171
The build system is very rudimentary for now, and [improvements](https://github.com/bitcoin-core/minisketch/pulls) are welcome.
7272

@@ -78,6 +78,44 @@ cd minisketch
7878
./autogen.sh && ./configure && make
7979
```
8080

81+
## Building with CMake
82+
83+
To maintain a pristine source tree, CMake encourages performing an out-of-source build by using a separate dedicated build directory.
84+
85+
### Building on POSIX systems
86+
87+
The following commands will produce the same `libminisketch.a` file as in the example [above](#building-with-autotools):
88+
89+
```bash
90+
cmake -B build -DCMAKE_CXX_FLAGS="-g -O2" # Generate a build system in subdirectory "build"
91+
cmake --build build # Run the actual build process
92+
ctest --test-dir build # Run the test suite
93+
sudo cmake --install build # Install the library into the system (optional)
94+
```
95+
96+
Run `cmake -B build -LH` or `ccmake -B build` to see the full list of configurable build options.
97+
98+
### Cross compiling
99+
100+
The following example works on modern Ubuntu/Debian systems:
101+
102+
```bash
103+
sudo apt install g++-mingw-w64-x86-64-posix
104+
cmake -B build -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++-posix
105+
cmake --build build
106+
```
107+
108+
### Building on Windows
109+
110+
The following example assumes the use of Visual Studio 2022 and CMake v3.21 or newer.
111+
112+
In "Developer Command Prompt for VS 2022":
113+
114+
```cmd
115+
cmake -B build
116+
cmake --build build --config Release
117+
```
118+
81119
## Usage
82120

83121
In this section Alice and Bob are trying to find the difference between their sets.

cmake/PrintConfigureSummary.cmake

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
include_guard(GLOBAL)
2+
3+
function(indent_message header content indent_num)
4+
if(indent_num GREATER 0)
5+
string(REPEAT " " ${indent_num} indentation)
6+
string(REPEAT "." ${indent_num} tail)
7+
string(REGEX REPLACE "${tail}$" "" header "${header}")
8+
endif()
9+
message("${indentation}${header} ${content}")
10+
endfunction()
11+
12+
# Print compiler's flags on best-effort. Include the abstracted
13+
# CMake flags that we touch ourselves.
14+
function(print_flags_per_config config indent_num)
15+
string(STRIP "${CMAKE_CXX_COMPILER_ARG1} ${CMAKE_CXX_FLAGS}" combined_cxx_flags)
16+
string(TOUPPER "${config}" config_uppercase)
17+
string(STRIP "${combined_cxx_flags} ${CMAKE_CXX_FLAGS_${config_uppercase}}" combined_cxx_flags)
18+
string(STRIP "${combined_cxx_flags} ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION}" combined_cxx_flags)
19+
if(CMAKE_POSITION_INDEPENDENT_CODE)
20+
string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${CMAKE_CXX_COMPILE_OPTIONS_PIC})
21+
endif()
22+
if(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY AND CMAKE_CXX_VISIBILITY_PRESET)
23+
string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY}${CMAKE_CXX_VISIBILITY_PRESET})
24+
endif()
25+
get_directory_property(compile_options COMPILE_OPTIONS)
26+
string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${compile_options})
27+
indent_message("CXXFLAGS .............................." "${combined_cxx_flags}" ${indent_num})
28+
endfunction()
29+
30+
function(print_configure_summary)
31+
message("")
32+
if(PROJECT_IS_TOP_LEVEL)
33+
message("Configure summary")
34+
message("=================")
35+
else()
36+
message("minisketch configure summary")
37+
message("============================")
38+
endif()
39+
if(BUILD_SHARED_LIBS)
40+
set(library_type "Shared")
41+
else()
42+
set(library_type "Static")
43+
endif()
44+
message("Library type .......................... ${library_type}")
45+
message("Build options:")
46+
if(have_disabled_fields)
47+
set(filed_sizes "${MINISKETCH_FIELDS}")
48+
else()
49+
set(filed_sizes "All")
50+
endif()
51+
message(" field sizes ........................ ${filed_sizes}")
52+
if(HAVE_CLMUL)
53+
set(clmul_status "Enabled")
54+
else()
55+
set(clmul_status "Disabled")
56+
endif()
57+
message(" clmul fields ........................ ${clmul_status}")
58+
if(CMAKE_CXX_STANDARD GREATER_EQUAL 20)
59+
set(clz_status "C++20")
60+
elseif(HAVE_CLZ)
61+
set(clz_status "Compiler builtin")
62+
else()
63+
set(clz_status "Default")
64+
endif()
65+
message(" clz implementation .................. ${clz_status}")
66+
message("Optional binaries:")
67+
message(" benchmark ........................... ${MINISKETCH_BUILD_BENCHMARK}")
68+
message(" tests ............................... ${MINISKETCH_BUILD_TESTS}")
69+
message("")
70+
if(CMAKE_CROSSCOMPILING)
71+
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
72+
else()
73+
set(cross_status "FALSE")
74+
endif()
75+
message("Cross compiling ....................... ${cross_status}")
76+
message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}")
77+
get_property(_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
78+
if(_is_multi_config)
79+
list(JOIN CMAKE_CONFIGURATION_TYPES ", " configs)
80+
message("Available build configurations ........ ${configs}")
81+
if(CMAKE_GENERATOR MATCHES "Visual Studio")
82+
set(default_config "Debug")
83+
else()
84+
list(GET CMAKE_CONFIGURATION_TYPES 0 default_config)
85+
endif()
86+
message("Default build configuration ........... ${default_config}")
87+
foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
88+
message("'${config}' build configuration:")
89+
print_flags_per_config("${config}" 2)
90+
endforeach()
91+
else()
92+
message("CMAKE_BUILD_TYPE ...................... ${CMAKE_BUILD_TYPE}")
93+
print_flags_per_config("${CMAKE_BUILD_TYPE}" 0)
94+
endif()
95+
unset(_is_multi_config)
96+
97+
message([=[
98+
99+
NOTE: The summary above may not exactly match the final applied build flags
100+
if any additional CMAKE_* or environment variables have been modified.
101+
To see the exact flags applied, build with the --verbose option.]=]
102+
)
103+
104+
if(have_disabled_fields AND PROJECT_IS_TOP_LEVEL)
105+
message("")
106+
message(WARNING
107+
"Only compiling in support for field sizes: ${MINISKETCH_FIELDS}\n"
108+
"This means the library will lack support for other field sizes entirely.\n"
109+
)
110+
endif()
111+
message("")
112+
endfunction()

0 commit comments

Comments
 (0)