Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{cpp,hpp,h}]
[*.{cpp,hpp}]
indent_style = space
indent_size = 4
max_line_length = 100
Expand All @@ -22,7 +22,7 @@ indent_size = 2
[*.sh]
indent_style = space
indent_size = 2
end_of_line = lf
max_line_length = 100

[*.md]
indent_style = space
Expand Down
44 changes: 35 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- "**.cpp"
- "**/CMakeLists.txt"
- "cmake/**"
- ".github/workflows/ci.yml"

permissions: {}

Expand All @@ -16,34 +17,59 @@ concurrency:
cancel-in-progress: true

jobs:
sanitize:
name: Sanitize
runs-on: ubuntu-latest
permissions:
contents: read # checkout

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Configure
run: cmake --preset asan

- name: Build
run: cmake --build --preset asan

- name: Test
run: ctest --preset asan

check:
name: Check (${{ matrix.os }})
name: Check (${{ matrix.name }})
runs-on: ${{ matrix.os }}
permissions:
contents: read
contents: read # checkout
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
include:
- { os: ubuntu-latest, cxx: g++, name: linux-gcc }
- { os: ubuntu-latest, cxx: clang++, name: linux-clang }
- { os: macos-latest, name: apple-clang }
- { os: windows-latest, name: windows-msvc }

steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Configure
env:
CXX_STD: "20"
CXX_COMPILER: ${{ matrix.cxx }}
shell: bash
run: cmake -B build -DCMAKE_BUILD_TYPE=Release -DANYHOW_BUILD_TESTS=ON "-DCMAKE_CXX_STANDARD=$CXX_STD"
run: cmake --preset ci "${CXX_COMPILER:+-DCMAKE_CXX_COMPILER=$CXX_COMPILER}"

- name: Lint
if: matrix.os == 'ubuntu-latest'
if: matrix.os == 'ubuntu-latest' && matrix.cxx == 'clang++'
run: find tests -name '*.cpp' | xargs clang-tidy -p build

- name: Build
run: cmake --build build --config Release
run: cmake --build --preset ci

- name: Test
run: ctest --test-dir build --build-config Release --output-on-failure
run: ctest --preset ci
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
contents: write # create GitHub release and upload assets
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Build directories ###
build/
build-asan/
out/
cmake-build-*/

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to this project.

## [0.2.0] - 2026-07-08

### Added

- `ANYHOW_ENSURE` stringification (embedding failing condition as a string in the error message)

## [0.1.0] - 2026-06-16

### Added
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.22)
project(
anyhow-cpp
VERSION 0.1.0
VERSION 0.2.0
DESCRIPTION "Rust's anyhow, ported to C++20."
LANGUAGES CXX)

Expand Down
69 changes: 69 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"version": 3,
"configurePresets": [
{
"name": "dev",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_STANDARD": "20",
"ANYHOW_BUILD_TESTS": "ON"
}
},
{
"name": "asan",
"inherits": "dev",
"binaryDir": "${sourceDir}/build-asan",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_CXX_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer"
}
},
{
"name": "ci",
"inherits": "dev",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{
"name": "dev",
"configurePreset": "dev"
},
{
"name": "asan",
"configurePreset": "asan"
},
{
"name": "ci",
"configurePreset": "ci",
"configuration": "Release"
}
],
"testPresets": [
{
"name": "dev",
"configurePreset": "dev",
"output": {
"outputOnFailure": true
}
},
{
"name": "asan",
"configurePreset": "asan",
"output": {
"outputOnFailure": true
}
},
{
"name": "ci",
"configurePreset": "ci",
"configuration": "Release",
"output": {
"outputOnFailure": true
}
}
]
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ include(FetchContent)
FetchContent_Declare(
anyhow-cpp
GIT_REPOSITORY https://github.com/MihaiStreames/anyhow-cpp.git
GIT_TAG v0.1.0
GIT_TAG v0.2.0
)
FetchContent_MakeAvailable(anyhow-cpp)

Expand Down
Empty file modified scripts/pin-actions.sh
100644 → 100755
Empty file.
20 changes: 15 additions & 5 deletions src/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,23 @@
/// Early-return a failure.
#define ANYHOW_BAIL(msg, ...) return ::anyhow::fail(msg __VA_OPT__(, ) __VA_ARGS__)

/// Early-return a failure if `cond` is false.
#define ANYHOW_ENSURE(cond, msg, ...) \
#define ANYHOW_ENSURE_IMPL_MSG(cond, ...) \
do { \
if (!(cond)) \
ANYHOW_BAIL(msg __VA_OPT__(, ) __VA_ARGS__); \
if (!(cond)) { \
ANYHOW_BAIL(__VA_ARGS__); \
} \
} while (0)

#define ANYHOW_ENSURE_IMPL_(cond) ANYHOW_ENSURE_IMPL_MSG(cond, "Condition failed: " #cond)

// i couldn't come up with a better solution than this
// VA_OPT(MSG) token-pastes into ANYHOW_ENSURE_IMPL_MSG when message given
// otherwise ANYHOW_ENSURE_IMPL_

/// Early-return a failure if `cond` is false.
#define ANYHOW_ENSURE(cond, ...) \
ANYHOW_ENSURE_IMPL_##__VA_OPT__(MSG)(cond __VA_OPT__(, ) __VA_ARGS__)

// opt-in short aliases
// define ANYHOW_SHORT_MACROS before including to enable

Expand All @@ -54,6 +64,6 @@
#define TRY_CATCH(expr, cleanup) ANYHOW_TRY_CATCH(expr, cleanup)
#define TRY_ASSIGN(var_out, expr) ANYHOW_TRY_ASSIGN(var_out, expr)
#define BAIL(msg, ...) ANYHOW_BAIL(msg __VA_OPT__(, ) __VA_ARGS__)
#define ENSURE(cond, msg, ...) ANYHOW_ENSURE(cond, msg __VA_OPT__(, ) __VA_ARGS__)
#define ENSURE(cond, ...) ANYHOW_ENSURE(cond __VA_OPT__(, ) __VA_ARGS__)

#endif
10 changes: 4 additions & 6 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,18 @@ set(BUILD_GMOCK
CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

# Unit tests ###

# Unit tests
set(ANYHOW_TEST_SOURCES test_expected.cpp test_context.cpp test_fmt.cpp
test_scope_guard.cpp test_macros.cpp test_failure.cpp)

add_executable(anyhow-tests ${ANYHOW_TEST_SOURCES})

target_link_libraries(anyhow-tests PRIVATE anyhow::anyhow GTest::gtest_main)
target_compile_features(anyhow-tests PRIVATE cxx_std_20)
set_target_properties(anyhow-tests PROPERTIES CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON)
target_compile_definitions(anyhow-tests PRIVATE ANYHOW_SHORT_MACROS)

# __VA_OPT__ is C++20 but MSVC requires an explicit conformance flag to enable
# it
if(MSVC)
target_compile_options(anyhow-tests PRIVATE /Zc:preprocessor)
endif()
Expand All @@ -34,8 +33,7 @@ target_include_directories(anyhow-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
include(GoogleTest)
gtest_discover_tests(anyhow-tests)

# Fuzz target (clang libFuzzer only) ###

# Fuzz target (clang libFuzzer only)
option(ANYHOW_BUILD_FUZZ
"Build libFuzzer fuzz targets (requires clang + -fsanitize=fuzzer)" OFF)

Expand Down
12 changes: 12 additions & 0 deletions tests/test_macros.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ static anyhow::Expected<int> ensure_fails(int val) {
return {val};
}

static anyhow::Expected<int> ensure_no_msg(int val) {
ANYHOW_ENSURE(val > 0);
return {val};
}

TEST(Macros, TryPropagatesFailure) {
auto res = try_propagate();

Expand Down Expand Up @@ -114,3 +119,10 @@ TEST(Macros, EnsureFailsWhenCondFalse) {
EXPECT_EQ(res.failure().error.message, "must be positive");
EXPECT_EQ(res.failure().error.domain, "validation");
}

TEST(Macros, EnsureAutoMessage) {
auto res = ensure_no_msg(-1);
ASSERT_TRUE(res.failed());
EXPECT_EQ(res.failure().error.message, "Condition failed: val > 0");
EXPECT_EQ(res.failure().error.domain, "");
}
Loading