Skip to content

Commit c1d2207

Browse files
Fix Clang build, add Clang CI, warnings-as-errors
1 parent 1a8f389 commit c1d2207

File tree

13 files changed

+178
-72
lines changed

13 files changed

+178
-72
lines changed

.github/workflows/ci.yml

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,26 @@ jobs:
1818
run: make format-check PYTHON_RUN="uv run --group=format"
1919

2020
build-alpine:
21-
name: Build on Alpine 3.20
21+
strategy:
22+
matrix:
23+
alpine_version:
24+
- 3.21
25+
- 3.20
26+
- 3.19
27+
# This arg is formatted in this way so that it is easily understandable in
28+
# the GitHub Actions web interface
29+
vcpkg_arg: &vcpkg_arg
30+
- use_vcpkg=false
31+
- use_vcpkg=true
32+
name: Build on Alpine
2233
runs-on: ubuntu-latest
2334
steps:
2435
- *checkout
2536
- name: Run Build
26-
run: bash tools/earthly.sh +build-alpine --use_vcpkg=false
37+
run: |
38+
bash tools/earthly.sh +build-alpine \
39+
--alpine_version=${{matrix.alpine_version}} \
40+
--${{matrix.vcpkg_arg}}
2741
2842
build-gcc-matrix:
2943
strategy:
@@ -34,12 +48,29 @@ jobs:
3448
- 14.3.0
3549
- 13.4.0
3650
- 12.5.0
51+
3752
runs-on: ubuntu-latest
3853
name: "Build with GCC"
3954
steps:
4055
- *checkout
4156
- name: Build
4257
run: |
4358
bash tools/earthly.sh +build-gcc \
44-
--gcc_version=${{matrix.gcc_version}} \
45-
--test=false
59+
--gcc_version=${{matrix.gcc_version}}
60+
61+
build-clang-matrix:
62+
strategy:
63+
fail-fast: true
64+
matrix:
65+
version_arg:
66+
- clang_major_version=20
67+
- clang_major_version=19
68+
# vcpkg_arg: *vcpkg_arg
69+
runs-on: ubuntu-latest
70+
name: Build with Clang
71+
steps:
72+
- *checkout
73+
- name: Build
74+
run: |
75+
bash tools/earthly.sh +build-clang \
76+
--${{matrix.version_arg}}

CMakeLists.txt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ if(AMONGOC_USE_PMM)
1515
pmm(VCPKG REVISION 2024.08.23)
1616
endif()
1717

18+
# A toggle to enable warnings-as-errors. We don't use CMAKE_COMPILE_WARNING_AS_ERROR,
19+
# because we don't want to enable -Werror on dependencies that we might be importing
20+
# and building
21+
option(AMONGOC_COMPILE_WARNING_AS_ERROR "Treat compiler warnings as errors" FALSE)
22+
1823
# Set up `find_package()` to trigger FetchContent for certain deps
1924
include(DeclareFetchContentDeps)
2025

@@ -160,7 +165,11 @@ target_link_libraries(amongoc
160165
$<BUILD_INTERFACE:asio::asio>
161166
$<BUILD_INTERFACE:neo::fun>
162167
OpenSSL::SSL
163-
)
168+
)
169+
170+
# Toggle warnings-as-errors
171+
set_property(TARGET amongoc PROPERTY COMPILE_WARNING_AS_ERROR "${AMONGOC_COMPILE_WARNING_AS_ERROR}")
172+
164173
if(BUILD_TESTING)
165174
# Add Catch integrations
166175
include(Catch)
@@ -173,15 +182,20 @@ if(BUILD_TESTING)
173182
$<BUILD_INTERFACE:asio::asio>
174183
$<BUILD_INTERFACE:neo::fun>
175184
Boost::container
176-
)
185+
)
177186
target_include_directories(amongoc-test PRIVATE src)
178-
catch_discover_tests(amongoc-test DISCOVERY_MODE PRE_TEST
187+
catch_discover_tests(
188+
amongoc-test
189+
DISCOVERY_MODE PRE_TEST
179190
PROPERTIES
180191
SKIP_REGULAR_EXPRESSION ":[0-9]+: SKIPPED:"
181192
TIMEOUT 5
182-
)
193+
)
183194
target_compile_features(amongoc-test PRIVATE cxx_std_23)
184195

196+
# Also add -Werror to the test target, if requested for amongoc
197+
set_property(TARGET amongoc-test PROPERTY COMPILE_WARNING_AS_ERROR "${AMONGOC_COMPILE_WARNING_AS_ERROR}")
198+
185199
# A test case that simply invokes each BSON API
186200
add_executable(bson-use-test tests/use-bson.test.c)
187201
target_link_libraries(bson-use-test PRIVATE amongoc::amongoc)

Earthfile

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,37 @@
11
VERSION 0.8
22

3+
# Tweak the default container registry used for pulling system images.
34
ARG --global default_container_registry = "docker.io"
45

56
build-gcc:
67
ARG --required gcc_version
78
FROM $default_container_registry/gcc:$gcc_version
9+
ARG warnings_as_errors=true
810
DO --pass-args +BOOTSTRAP_BUILD_INSTALL_EXPORT \
9-
--build_deps "perl pkg-config linux-libc-dev curl zip unzip ccache" \
10-
--third_deps "libfmt-dev libboost-url1.81-dev libboost-container1.81-dev libssl-dev"
11+
--warnings_as_errors=$warnings_as_errors \
12+
--build_deps "ccache" \
13+
--vcpkg_bs_deps "build-essential perl git pkg-config linux-libc-dev curl zip unzip"
14+
15+
build-clang:
16+
ARG --required clang_version_major
17+
FROM $default_container_registry/ubuntu:24.04
18+
DO +INIT
19+
# Required for the LLVM installer:
20+
RUN __install lsb-release software-properties-common gnupg
21+
RUN curl -Ls https://apt.llvm.org/llvm.sh -o llvm.sh && \
22+
bash llvm.sh "$clang_version_major"
23+
ENV CC=clang-$clang_version_major
24+
ENV CXX=clang++-$clang_version_major
25+
ARG warnings_as_errors=true
26+
DO --pass-args +BOOTSTRAP_BUILD_INSTALL_EXPORT \
27+
--warnings_as_errors=$warnings_as_errors \
28+
--build_deps "ccache" \
29+
--vcpkg_bs_deps "build-essential perl git pkg-config linux-libc-dev curl zip unzip"
1130

1231
build-alpine:
13-
FROM $default_container_registry/alpine:3.20
32+
ARG alpine_version=3.20
33+
FROM $default_container_registry/alpine:$alpine_version
34+
ARG warnings_as_errors=true
1435
DO --pass-args +BOOTSTRAP_BUILD_INSTALL_EXPORT \
1536
--build_deps "build-base git cmake gcc g++ ninja make ccache python3" \
1637
--vcpkg_bs_deps "pkgconfig linux-headers perl bash tar zip unzip curl" \
@@ -19,8 +40,6 @@ build-alpine:
1940
build-debian:
2041
FROM $default_container_registry/debian:12
2142
DO --pass-args +BOOTSTRAP_BUILD_INSTALL_EXPORT \
22-
# Spec test generation requires a Python newer than what is on Debian 12
23-
--BUILD_SPEC_TESTS=FALSE \
2443
--build_deps "build-essential cmake git ninja-build python3 ccache" \
2544
--vcpkg_bs_deps "perl pkg-config linux-libc-dev curl zip unzip" \
2645
--third_deps "libfmt-dev libboost-url1.81-dev libboost-container1.81-dev libssl-dev"
@@ -69,14 +88,16 @@ run:
6988
# Miscellaneous system init
7089
INIT:
7190
FUNCTION
72-
COPY --chmod=755 tools/__install /usr/local/bin/__install
91+
COPY --chmod=755 tools/__install tools/__bool tools/__boolstr /usr/local/bin/
7392
RUN __install curl
7493
ARG uv_version = "0.8.15"
7594
ARG uv_install_sh_url = "https://astral.sh/uv/$uv_version/install.sh"
76-
RUN (curl -LsSf "$uv_install_sh_url" || wget -qO- "$uv_install_sh_url") \
77-
| env UV_UNMANAGED_INSTALL=/opt/uv sh - \
78-
&& ln -s /opt/uv/uv /usr/local/bin/uv \
79-
&& uv --version
95+
IF ! uv --version
96+
RUN (curl -LsSf "$uv_install_sh_url" || wget -qO- "$uv_install_sh_url") \
97+
| env UV_UNMANAGED_INSTALL=/opt/uv sh - \
98+
&& ln -s /opt/uv/uv /usr/local/bin/uv \
99+
&& uv --version
100+
END
80101

81102
BOOTSTRAP_BUILD_INSTALL_EXPORT:
82103
FUNCTION
@@ -97,10 +118,10 @@ BOOTSTRAP_DEPS:
97118
RUN __install $build_deps
98119
# Switch behavior based on whether we use vcpkg
99120
ARG use_vcpkg=true
100-
IF ! $use_vcpkg
121+
IF ! __bool $use_vcpkg
101122
# No vcpkg. Install system dependencies
102-
ARG third_deps
103-
RUN __install $third_deps
123+
COPY tools/ci/install-third-deps.sh /
124+
RUN bash /install-third-deps.sh
104125
# Install system deps for testing, if needed
105126
ARG test_deps
106127
ARG test=true
@@ -126,7 +147,7 @@ BOOTSTRAP_DEPS:
126147
# Running CMake now will prepare our dependencies without configuring the rest of the project
127148
CACHE ~/.cache/vcpkg
128149
ARG launcher
129-
RUN $launcher uv run --with=cmake~=3.20 --with=ninja cmake -S $src_tmp -B $src_tmp/_build/vcpkg-bootstrapping
150+
RUN $launcher uv run --with=cmake~=3.20 --with=ninja cmake -G Ninja -S $src_tmp -B $src_tmp/_build/vcpkg-bootstrapping
130151
END
131152

132153
COPY_SRC:
@@ -144,19 +165,21 @@ BUILD:
144165
CACHE ~/.cache/ccache
145166
# Toggle testing
146167
ARG test=true
147-
LET __test=$(echo $test | tr [:lower:] [:upper:])
148-
ARG BUILD_SPEC_TESTS=TRUE
168+
# Enable -Werror
169+
ARG warnings_as_errors=false
149170
# Toggle PMM in the build
150171
ARG use_vcpkg=true
151-
LET __use_vcpkg=$(echo "$use_vcpkg" | tr "[:lower:]" "[:upper:]")
172+
# The configurations to build (semicolon-separated list)
173+
ARG configs=Debug
152174
# Configure
153175
RUN $launcher make test \
154176
LAUNCHER='uv run --group=build' \
155-
CONFIGS="Debug" \
177+
CONFIGS="$configs" \
156178
TEST_CONFIG="Debug" \
157-
USE_PMM=$__use_vcpkg \
158179
INSTALL_PREFIX=$install_prefix \
159-
BUILD_TESTING=$__test
180+
USE_PMM=$(__boolstr $use_vcpkg) \
181+
WARNINGS_AS_ERRORS=$(__boolstr $warnings_as_errors) \
182+
BUILD_TESTING=$(__boolstr $test)
160183
IF test "$install_prefix" != ""
161184
FOR conf IN Debug # Release RelWithDebInfo
162185
RUN $launcher make install-fast LAUNCHER='uv run --group=build' INSTALL_PREFIX=$install_prefix INSTALL_CONFIG=$conf

Makefile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# *** Build Parameters ***
22
# Whether to use PMM for the build process
3-
USE_PMM := TRUE
3+
USE_PMM := true
44
# Whether to build tests
5-
BUILD_TESTING := TRUE
5+
BUILD_TESTING := true
66
# Sanitizers to request (Comma-separated list)
77
SANITIZE :=
88
# The configurations to build (Semicolon-separated, or "all")
@@ -11,6 +11,8 @@ CONFIGS := Debug
1111
TEST_CONFIG := Debug
1212
# Set the CMAKE_INSTALL_PREFIX and the `--prefix` arg for installs
1313
INSTALL_PREFIX :=
14+
# Treat compiler warnings as errors (Sets COMPILE_WARNING_AS_ERROR on amongoc)
15+
WARNINGS_AS_ERRORS := false
1416

1517
# *** Execution Parameters ***
1618
# Set the LAUNCHER parameter to prefix all executed commands
@@ -55,6 +57,7 @@ configure:
5557
-B "$(BUILD_DIR)" \
5658
-D CMAKE_CROSS_CONFIGS="$(CONFIGS)" \
5759
-D CMAKE_DEFAULT_CONFIGS=all \
60+
-D AMONGOC_COMPILE_WARNING_AS_ERROR=$(WARNINGS_AS_ERRORS) \
5861
-D AMONGOC_USE_PMM=$(USE_PMM) \
5962
-D BUILD_TESTING=$(BUILD_TESTING) \
6063
-D MONGO_SANITIZE="$(SANITIZE)" \
@@ -92,10 +95,10 @@ package-fast:
9295
rm -r -- "$(CPACK_OUT)/_CPack_Packages"
9396

9497
format-check:
95-
$(PYTHON_RUN) tools/format.py --mode=check
98+
uv run --group=format --isolated $(PYTHON_RUN) tools/format.py --mode=check
9699

97100
format:
98-
$(PYTHON_RUN) tools/format.py
101+
uv run --group=format --isolated $(PYTHON_RUN) tools/format.py
99102

100103
packages:
101104
bash $(THIS_DIR)/tools/earthly.sh -a +build-multi/ _build/pkgs

include/bson/doc.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,11 @@ class document {
402402

403403
using enable_trivially_relocatable = document;
404404

405-
#if !mlib_audit_allocator_passing()
405+
#if mlib_allocator_default_constructible()
406406
document() noexcept
407-
: document(allocator_type(mlib_default_allocator)) {}
407+
: document(allocator_type()) {}
408408
explicit document(bson_view v)
409-
: document(v, allocator_type(mlib_default_allocator)) {}
409+
: document(v, allocator_type()) {}
410410
#endif
411411

412412
~document() { _del(); }

include/mlib/alloc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ mlib_extern_c_end();
108108

109109
#if mlib_is_cxx()
110110

111+
#ifndef mlib_allocator_default_constructible
112+
#define mlib_allocator_default_constructible() !mlib_audit_allocator_passing()
113+
#endif
114+
111115
namespace mlib {
112116

113117
/**
@@ -121,6 +125,11 @@ class allocator {
121125
using value_type = T;
122126
using pointer = value_type*;
123127

128+
#if mlib_allocator_default_constructible()
129+
allocator() noexcept
130+
: _alloc(::mlib_default_allocator) {}
131+
#endif
132+
124133
// Construct around an existing mlib_allocator object
125134
constexpr allocator(mlib_allocator a) noexcept
126135
: _alloc(a) {}

include/mlib/config.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@
191191
* @brief Macro that should be used to toggle convenience APIs that will
192192
* pass default allocators.
193193
*/
194-
#define mlib_audit_allocator_passing() 1
194+
#define mlib_audit_allocator_passing() 0
195195
#endif // mlib_audit_allocator_passing
196196

197197
#ifdef __GNUC__
@@ -263,6 +263,10 @@
263263
MLIB_IF_GCC(mlib_pragma(GCC diagnostic ignored Warning)) \
264264
mlib_static_assert(true, "")
265265

266+
#define mlib_clang_warning_disable(Warning) \
267+
MLIB_IF_CLANG(mlib_pragma(clang diagnostic ignored Warning)) \
268+
mlib_static_assert(true, "")
269+
266270
#define mlib_gnu_warning_disable(Warning) \
267271
MLIB_IF_GNU_LIKE(mlib_pragma(GCC diagnostic ignored Warning)) \
268272
mlib_static_assert(true, "")
@@ -342,7 +346,7 @@
342346
#define MLIB_ARGC_PICK(Prefix, ...) \
343347
MLIB_PASTE_3(Prefix, _argc_, MLIB_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
344348

345-
MLIB_LANG_PICK()([[noreturn]]) mlib_constexpr void mlib_unreachable() mlib_noexcept {
349+
MLIB_LANG_PICK()([[noreturn]]) static inline void mlib_unreachable() mlib_noexcept {
346350
MLIB_IF_GNU_LIKE(__builtin_unreachable();)
347351
MLIB_IF_MSVC(__assume(0);)
348352
}

src/amongoc/status.test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ TEST_CASE("Status/Okay") {
1010
CHECK(st.category == &amongoc_generic_category);
1111

1212
bool took_else = false;
13-
amongoc_if_error (st, _) {
13+
amongoc_if_error (st, _ [[maybe_unused]]) {
1414
FAIL_CHECK("Did not expect an error");
1515
} else {
1616
took_else = true;
@@ -23,7 +23,7 @@ TEST_CASE("Status/From an Error") {
2323
CHECK(st.category == &amongoc_generic_category);
2424
CHECK(st.code == EIO);
2525
bool took_err = false;
26-
amongoc_if_error (st, _) {
26+
amongoc_if_error (st, _ [[maybe_unused]]) {
2727
took_err = true;
2828
} else {
2929
FAIL_CHECK("Did not take the error branch");

src/amongoc/uri.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include <mlib/alloc.h>
1010

1111
#include <boost/url.hpp>
12-
#include <fmt/chrono.h> // Enable duration formatting
12+
// XXX: We would like to format date types, but a Clang bug prevents it from
13+
// working. Disable that for now.
14+
// #include <fmt/chrono.h> // Enable duration formatting
1315
#include <neo/tokenize.hpp>
1416
#include <neo/utility.hpp>
1517

@@ -201,14 +203,21 @@ result<connection_uri> connection_uri::parse(std::string_view
201203
return [=](I ival) -> I {
202204
if (ival < min or ival > max) {
203205
warn.fire(defer_convert([&] {
204-
return uri_warning_event(
205-
format(alloc,
206-
"URI parameter “{}”: Value {} is outside the supported range "
207-
"(min: {}, max: {})",
208-
std::string_view(qp.key),
209-
ival,
210-
min,
211-
max));
206+
if constexpr (fmt::is_formattable<I>::value) {
207+
return uri_warning_event(format(
208+
alloc,
209+
"URI parameter “{}”: Value {} is outside the supported range "
210+
"(min: {}, max: {})",
211+
std::string_view(qp.key),
212+
ival,
213+
min,
214+
max));
215+
} else {
216+
return uri_warning_event(
217+
format(alloc,
218+
"URI parameter “{}” is outside the supported range",
219+
std::string_view(qp.key)));
220+
}
212221
}));
213222
}
214223
return std::clamp(ival, min, max);

0 commit comments

Comments
 (0)