-
Notifications
You must be signed in to change notification settings - Fork 57
build: Introduce CMake-based build system #75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
name: CI | ||
on: | ||
pull_request: | ||
push: | ||
branches: | ||
- '**' | ||
tags-ignore: | ||
- '**' | ||
|
||
concurrency: | ||
group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
windows-native: | ||
name: ${{ matrix.configuration.job_name }} | ||
# See: https://github.com/actions/runner-images#available-images. | ||
runs-on: windows-2025 | ||
|
||
strategy: | ||
fail-fast: false | ||
matrix: | ||
configuration: | ||
- job_name: 'x64 (MSVC): Windows (VS 2022)' | ||
build_configuration: 'Release' | ||
- job_name: 'x64 (MSVC): Windows (VS 2022, fields=32)' | ||
cmake_options: '-DMINISKETCH_FIELDS=32' | ||
build_configuration: 'Release' | ||
- job_name: 'x64 (MSVC): Windows (VS 2022, debug)' | ||
build_configuration: 'Debug' | ||
# TODO: Resolve the issue and re-enable benchmark. | ||
# See: https://github.com/bitcoin-core/minisketch/pull/96. | ||
skip_benchmark: true | ||
- job_name: 'x64 (MSVC): Windows (VS 2022, shared)' | ||
cmake_options: '-DBUILD_SHARED_LIBS=ON' | ||
build_configuration: 'Release' | ||
- job_name: 'x64 (clang-cl): Windows (VS 2022)' | ||
cmake_options: '-T ClangCL' | ||
build_configuration: 'Release' | ||
# TODO: Resolve the issue and re-enable benchmark. | ||
# See: https://github.com/bitcoin-core/minisketch/pull/96. | ||
skip_benchmark: true | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: Generate buildsystem | ||
env: | ||
CXXFLAGS: '/WX' | ||
run: cmake -B build -DMINISKETCH_BUILD_BENCHMARK=ON ${{ matrix.configuration.cmake_options }} | ||
|
||
- name: Build | ||
run: cmake --build build --config ${{ matrix.configuration.build_configuration }} | ||
|
||
- name: Binaries info | ||
shell: bash | ||
run: | | ||
cd build/bin/${{ matrix.configuration.build_configuration }} | ||
file * | grep "\.exe\|\.dll" | ||
|
||
- name: Check | ||
working-directory: build | ||
run: ctest --output-on-failure -j $env:NUMBER_OF_PROCESSORS -C ${{ matrix.configuration.build_configuration }} | ||
|
||
- name: Benchmark | ||
if: ${{ ! matrix.configuration.skip_benchmark }} | ||
working-directory: build | ||
run: bin\${{ matrix.configuration.build_configuration }}\bench.exe |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,3 +33,6 @@ stamp-h1 | |
|
||
test* | ||
bench | ||
|
||
# CMake build directories. | ||
/*build* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
cmake_minimum_required(VERSION 3.22) | ||
|
||
#============================= | ||
# Project / Package Metadata | ||
#============================= | ||
project(minisketch | ||
VERSION 0.0.1 | ||
DESCRIPTION "A library for BCH-based set reconciliation" | ||
HOMEPAGE_URL "https://github.com/bitcoin-core/minisketch" | ||
LANGUAGES CXX | ||
) | ||
|
||
# ============================================================ | ||
# Project Initialization | ||
# ============================================================ | ||
enable_testing() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is superior to Some other developers, namely @purpleKarrot, disagree. |
||
include(CTestUseLaunchers) | ||
|
||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) | ||
|
||
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) | ||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) | ||
endif() | ||
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) | ||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) | ||
endif() | ||
if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) | ||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) | ||
endif() | ||
|
||
# Prevent include directories from parent project from leaking into this one. | ||
set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES "") | ||
Comment on lines
+31
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See similar code in the # Prevent include directories from parent project from leaking into this one.
set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES "") |
||
|
||
#============================= | ||
# Language Setup | ||
#============================= | ||
if(DEFINED CMAKE_CXX_STANDARD) | ||
if(CMAKE_CXX_STANDARD EQUAL 98 OR CMAKE_CXX_STANDARD LESS 11) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hah! Stupid CMake :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Y2K problem :) |
||
message(FATAL_ERROR "This project requires at least C++11") | ||
endif() | ||
else() | ||
set(CMAKE_CXX_STANDARD 11) | ||
endif() | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
if(NOT DEFINED CMAKE_CXX_EXTENSIONS) | ||
set(CMAKE_CXX_EXTENSIONS OFF) | ||
endif() | ||
|
||
#============================= | ||
# Configurable Options | ||
#============================= | ||
option(MINISKETCH_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL}) | ||
if(NOT PROJECT_IS_TOP_LEVEL) | ||
mark_as_advanced(MINISKETCH_INSTALL) | ||
endif() | ||
|
||
option(MINISKETCH_BUILD_TESTS "Build tests." ON) | ||
option(MINISKETCH_BUILD_BENCHMARK "Build benchmark." OFF) | ||
|
||
set(supported_fields "") | ||
set(have_enabled_fields NO) | ||
set(have_disabled_fields NO) | ||
foreach(i RANGE 2 64) | ||
list(APPEND supported_fields ${i}) | ||
endforeach() | ||
if(NOT DEFINED MINISKETCH_FIELDS) | ||
set(MINISKETCH_FIELDS ${supported_fields} CACHE STRING "Semicolon-separated list of field sizes to build. Default=all. Available sizes: ${supported_fields}.") | ||
endif() | ||
foreach(field IN LISTS supported_fields) | ||
if(field IN_LIST MINISKETCH_FIELDS) | ||
set(have_enabled_fields YES) | ||
else() | ||
set(have_disabled_fields YES) | ||
add_compile_definitions(DISABLE_FIELD_${field}) | ||
endif() | ||
endforeach() | ||
if(NOT have_enabled_fields) | ||
message(FATAL_ERROR "No field sizes are enabled.") | ||
endif() | ||
unset(have_enabled_fields) | ||
unset(supported_fields) | ||
|
||
#============================= | ||
# Build Options | ||
#============================= | ||
set(CMAKE_CXX_VISIBILITY_PRESET hidden) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feature actually requires a bit more work to get right. It is currently not working correctly in the autotools build either, so it can be done in a separate PR. |
||
|
||
if(MSVC) | ||
add_compile_options(/Zc:__cplusplus) | ||
endif() | ||
|
||
if(MINGW) | ||
add_link_options(-static) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should port this functionality. Instead we should use the CMake shared/static selection machinery. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This affects only benchmark/test binaries and allows to run them on the build system via Wine when building either a static library or a shared one. UPD. It also links There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider
or
|
||
endif() | ||
|
||
#============================= | ||
# Diagnostics Options | ||
#============================= | ||
if(MSVC) | ||
# For both MSVC's cl.exe and clang-cl compilers. | ||
add_compile_options(/W3) # Production quality warning level. Enables -Wall Clang's core option. | ||
else() | ||
add_compile_options(-Wall) | ||
endif() | ||
|
||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") | ||
add_compile_options(/wd4060) # Disable warning C4060 "switch statement contains no 'case' or 'default' labels". | ||
add_compile_options(/wd4065) # Disable warning C4065 "switch statement contains 'default' but no 'case' labels". | ||
add_compile_options(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". | ||
add_compile_options(/wd4244) # Disable warning C4244 "conversion from 'type1' to 'type2', possible loss of data". | ||
else() | ||
add_compile_options(-Wundef) | ||
endif() | ||
|
||
#============================= | ||
# Main Processing | ||
#============================= | ||
include(SystemIntrospection) | ||
add_subdirectory(src) | ||
|
||
include(PrintConfigureSummary) | ||
print_configure_summary() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
include_guard(GLOBAL) | ||
|
||
function(indent_message header content indent_num) | ||
if(indent_num GREATER 0) | ||
string(REPEAT " " ${indent_num} indentation) | ||
string(REPEAT "." ${indent_num} tail) | ||
string(REGEX REPLACE "${tail}$" "" header "${header}") | ||
endif() | ||
message("${indentation}${header} ${content}") | ||
endfunction() | ||
|
||
# Print compiler's flags on best-effort. Include the abstracted | ||
# CMake flags that we touch ourselves. | ||
function(print_flags_per_config config indent_num) | ||
string(STRIP "${CMAKE_CXX_COMPILER_ARG1} ${CMAKE_CXX_FLAGS}" combined_cxx_flags) | ||
string(TOUPPER "${config}" config_uppercase) | ||
string(STRIP "${combined_cxx_flags} ${CMAKE_CXX_FLAGS_${config_uppercase}}" combined_cxx_flags) | ||
string(STRIP "${combined_cxx_flags} ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION}" combined_cxx_flags) | ||
if(CMAKE_POSITION_INDEPENDENT_CODE) | ||
string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${CMAKE_CXX_COMPILE_OPTIONS_PIC}) | ||
endif() | ||
if(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY AND CMAKE_CXX_VISIBILITY_PRESET) | ||
string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY}${CMAKE_CXX_VISIBILITY_PRESET}) | ||
endif() | ||
get_directory_property(compile_options COMPILE_OPTIONS) | ||
string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${compile_options}) | ||
indent_message("CXXFLAGS .............................." "${combined_cxx_flags}" ${indent_num}) | ||
endfunction() | ||
|
||
function(print_configure_summary) | ||
message("") | ||
if(PROJECT_IS_TOP_LEVEL) | ||
message("Configure summary") | ||
message("=================") | ||
else() | ||
message("minisketch configure summary") | ||
message("============================") | ||
endif() | ||
if(BUILD_SHARED_LIBS) | ||
set(library_type "Shared") | ||
else() | ||
set(library_type "Static") | ||
endif() | ||
message("Library type .......................... ${library_type}") | ||
message("Build options:") | ||
if(have_disabled_fields) | ||
set(filed_sizes "${MINISKETCH_FIELDS}") | ||
else() | ||
set(filed_sizes "All") | ||
endif() | ||
message(" field sizes ........................ ${filed_sizes}") | ||
if(HAVE_CLMUL) | ||
set(clmul_status "Enabled") | ||
else() | ||
set(clmul_status "Disabled") | ||
endif() | ||
message(" clmul fields ........................ ${clmul_status}") | ||
if(CMAKE_CXX_STANDARD GREATER_EQUAL 20) | ||
set(clz_status "C++20") | ||
elseif(HAVE_CLZ) | ||
set(clz_status "Compiler builtin") | ||
else() | ||
set(clz_status "Default") | ||
endif() | ||
message(" clz implementation .................. ${clz_status}") | ||
message("Optional binaries:") | ||
message(" benchmark ........................... ${MINISKETCH_BUILD_BENCHMARK}") | ||
message(" tests ............................... ${MINISKETCH_BUILD_TESTS}") | ||
message("") | ||
if(CMAKE_CROSSCOMPILING) | ||
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}") | ||
else() | ||
set(cross_status "FALSE") | ||
endif() | ||
message("Cross compiling ....................... ${cross_status}") | ||
message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}") | ||
get_property(_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||
if(_is_multi_config) | ||
list(JOIN CMAKE_CONFIGURATION_TYPES ", " configs) | ||
message("Available build configurations ........ ${configs}") | ||
if(CMAKE_GENERATOR MATCHES "Visual Studio") | ||
set(default_config "Debug") | ||
else() | ||
list(GET CMAKE_CONFIGURATION_TYPES 0 default_config) | ||
endif() | ||
message("Default build configuration ........... ${default_config}") | ||
foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) | ||
message("'${config}' build configuration:") | ||
print_flags_per_config("${config}" 2) | ||
endforeach() | ||
else() | ||
message("CMAKE_BUILD_TYPE ...................... ${CMAKE_BUILD_TYPE}") | ||
print_flags_per_config("${CMAKE_BUILD_TYPE}" 0) | ||
endif() | ||
unset(_is_multi_config) | ||
|
||
message([=[ | ||
|
||
NOTE: The summary above may not exactly match the final applied build flags | ||
if any additional CMAKE_* or environment variables have been modified. | ||
To see the exact flags applied, build with the --verbose option.]=] | ||
) | ||
|
||
if(have_disabled_fields AND PROJECT_IS_TOP_LEVEL) | ||
message("") | ||
message(WARNING | ||
"Only compiling in support for field sizes: ${MINISKETCH_FIELDS}\n" | ||
"This means the library will lack support for other field sizes entirely.\n" | ||
) | ||
endif() | ||
message("") | ||
endfunction() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
cmake_minimum_required()
command does two things:Rationale for point 1:
Rationale for point 2:
From Professional CMake: A Practical Guide, 21st Edition, Section 13.1:
Some other developers, namely @ryanofsky and @purpleKarrot, disagree.
See: bitcoin-core/libmultiprocess#163.