Skip to content

Commit f30e21a

Browse files
committed
build: Add CMake-based build system
1 parent ea8f66b commit f30e21a

File tree

6 files changed

+335
-0
lines changed

6 files changed

+335
-0
lines changed

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

cmake/PrintConfigureSummary.cmake

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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("\n")
32+
if(PROJECT_IS_TOP_LEVEL)
33+
message("Configure summary")
34+
message("=================")
35+
else()
36+
message("minisketch configure summary")
37+
message("============================")
38+
endif()
39+
message("Build details:")
40+
if(HAVE_CLMUL)
41+
set(clmul_status "Enabled")
42+
else()
43+
set(clmul_status "Disabled")
44+
endif()
45+
message(" clmul fields ......................... ${clmul_status}")
46+
if(HAVE_CLZ)
47+
set(clz_status "Enabled")
48+
else()
49+
set(clz_status "Disabled")
50+
endif()
51+
message(" clz builtins ......................... ${clz_status}")
52+
message("Optional binaries:")
53+
message(" benchmark ........................... ${MINISKETCH_BUILD_BENCHMARK}")
54+
message(" tests ............................... ${MINISKETCH_BUILD_TESTS}")
55+
message("")
56+
if(CMAKE_CROSSCOMPILING)
57+
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
58+
else()
59+
set(cross_status "FALSE")
60+
endif()
61+
message("Cross compiling ....................... ${cross_status}")
62+
message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}")
63+
get_property(_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
64+
if(_is_multi_config)
65+
list(JOIN CMAKE_CONFIGURATION_TYPES ", " configs)
66+
message("Available build configurations ........ ${configs}")
67+
if(CMAKE_GENERATOR MATCHES "Visual Studio")
68+
set(default_config "Debug")
69+
else()
70+
list(GET CMAKE_CONFIGURATION_TYPES 0 default_config)
71+
endif()
72+
message("Default build configuration ........... ${default_config}")
73+
foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
74+
message("'${config}' build configuration:")
75+
print_flags_per_config("${config}" 2)
76+
endforeach()
77+
else()
78+
message("CMAKE_BUILD_TYPE ...................... ${CMAKE_BUILD_TYPE}")
79+
print_flags_per_config("${CMAKE_BUILD_TYPE}" 0)
80+
endif()
81+
unset(_is_multi_config)
82+
83+
message([=[
84+
85+
NOTE: The summary above may not exactly match the final applied build flags
86+
if any additional CMAKE_* or environment variables have been modified.
87+
To see the exact flags applied, build with the --verbose option.
88+
]=])
89+
90+
if(have_disabled_fields)
91+
message("")
92+
message(WARNING
93+
"Only compiling in support for field sizes: ${MINISKETCH_FIELDS}\n"
94+
"This means the library will lack support for other field sizes entirely.\n"
95+
)
96+
endif()
97+
endfunction()

cmake/SystemIntrospection.cmake

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
include_guard(GLOBAL)
2+
3+
include(CheckCXXSourceCompiles)
4+
include(CMakePushCheckState)
5+
cmake_push_check_state(RESET)
6+
7+
# Check for clmul instructions support.
8+
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
9+
set(CMAKE_REQUIRED_FLAGS "-mpclmul")
10+
endif()
11+
check_cxx_source_compiles("
12+
#include <immintrin.h>
13+
#include <stdint.h>
14+
15+
int main()
16+
{
17+
__m128i a = _mm_cvtsi64_si128((uint64_t)7);
18+
__m128i b = _mm_clmulepi64_si128(a, a, 37);
19+
__m128i c = _mm_srli_epi64(b, 41);
20+
__m128i d = _mm_xor_si128(b, c);
21+
uint64_t e = _mm_cvtsi128_si64(d);
22+
return e == 0;
23+
}
24+
" HAVE_CLMUL
25+
)
26+
if(HAVE_CLMUL)
27+
set(CLMUL_CXXFLAGS ${CMAKE_REQUIRED_FLAGS})
28+
endif()
29+
30+
# Check for working clz builtins.
31+
check_cxx_source_compiles("
32+
int main()
33+
{
34+
unsigned a = __builtin_clz(1);
35+
unsigned long b = __builtin_clzl(1);
36+
unsigned long long c = __builtin_clzll(1);
37+
}
38+
" HAVE_CLZ
39+
)
40+
41+
cmake_pop_check_state()

src/CMakeLists.txt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
include(GNUInstallDirs)
2+
3+
add_subdirectory(fields)
4+
5+
add_compile_definitions($<$<BOOL:${HAVE_CLZ}>:HAVE_CLZ>)
6+
7+
add_library(minisketch minisketch.cpp)
8+
target_link_libraries(minisketch PRIVATE minisketch_field_sources)
9+
10+
add_library(minisketch_verify EXCLUDE_FROM_ALL minisketch.cpp)
11+
target_compile_definitions(minisketch_verify
12+
PUBLIC
13+
MINISKETCH_VERIFY
14+
)
15+
target_link_libraries(minisketch_verify PRIVATE minisketch_field_sources)
16+
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
17+
target_compile_options(minisketch_verify
18+
PRIVATE
19+
/wd4702
20+
)
21+
endif()
22+
23+
if(MINISKETCH_BUILD_TESTS)
24+
add_executable(test-noverify test.cpp)
25+
target_link_libraries(test-noverify PRIVATE minisketch)
26+
add_test(NAME ${PROJECT_NAME}_test_noverify COMMAND test-noverify)
27+
28+
add_executable(test-verify test.cpp)
29+
target_link_libraries(test-verify PRIVATE minisketch_verify)
30+
add_test(NAME ${PROJECT_NAME}_test_verify COMMAND test-verify)
31+
endif()
32+
33+
if(MINISKETCH_BUILD_BENCHMARK)
34+
add_executable(bench bench.cpp)
35+
target_link_libraries(bench PRIVATE minisketch)
36+
endif()
37+
38+
if(MINISKETCH_INSTALL)
39+
install(TARGETS minisketch
40+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
41+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
42+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
43+
)
44+
install(FILES ${PROJECT_SOURCE_DIR}/include/minisketch.h
45+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
46+
)
47+
endif()

src/fields/CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
add_library(minisketch_field_sources INTERFACE)
2+
target_sources(minisketch_field_sources
3+
INTERFACE
4+
generic_1byte.cpp
5+
generic_2bytes.cpp
6+
generic_3bytes.cpp
7+
generic_4bytes.cpp
8+
generic_5bytes.cpp
9+
generic_6bytes.cpp
10+
generic_7bytes.cpp
11+
generic_8bytes.cpp
12+
)
13+
14+
if(HAVE_CLMUL)
15+
set(clmul_sources
16+
clmul_1byte.cpp
17+
clmul_2bytes.cpp
18+
clmul_3bytes.cpp
19+
clmul_4bytes.cpp
20+
clmul_5bytes.cpp
21+
clmul_6bytes.cpp
22+
clmul_7bytes.cpp
23+
clmul_8bytes.cpp
24+
)
25+
target_sources(minisketch_field_sources INTERFACE ${clmul_sources})
26+
set_property(SOURCE ${clmul_sources}
27+
DIRECTORY ${PROJECT_SOURCE_DIR}/src
28+
PROPERTY COMPILE_OPTIONS ${CLMUL_CXXFLAGS}
29+
)
30+
target_compile_definitions(minisketch_field_sources INTERFACE HAVE_CLMUL)
31+
endif()

0 commit comments

Comments
 (0)