Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
00ef6eb
add module file for scope and modular example
JeffGarland May 30, 2025
a932580
run clang-format on new source
JeffGarland May 30, 2025
a6ffc6e
formatting for humans in example
JeffGarland May 30, 2025
8000dfd
initial draft of module test even though cant cmake compile yet
JeffGarland May 31, 2025
e619449
attempt to emulate exemplar modules PR
JeffGarland May 31, 2025
7e7c3f4
Update CMakeLists.txt
JeffGarland May 31, 2025
5f1d499
Update tests/CMakeLists.txt
JeffGarland May 31, 2025
eb84105
working version of module.test - woohoo!
JeffGarland May 31, 2025
451ce8e
Update tests/CMakeLists.txt
JeffGarland May 31, 2025
aff35b1
remove special case logic for module.test
JeffGarland May 31, 2025
914483d
reinstate catch2 into module test file, cleanup test
JeffGarland May 31, 2025
e1d97e9
adopt ClausK's ci updates for cmake, compiler
JeffGarland May 31, 2025
f4f1f48
adjust review-dog error level, maybe?
JeffGarland May 31, 2025
17694cd
fix logic of module.test
JeffGarland May 31, 2025
99bb50f
exclude compilers that dont support modules from compiling module.test
JeffGarland May 31, 2025
b1b04b1
Update tests/CMakeLists.txt reviewdog
JeffGarland May 31, 2025
ad6ccdf
Update tests/module.test.cpp
JeffGarland May 31, 2025
618c043
minor spacing in cmake
JeffGarland May 31, 2025
9639523
revert the gnu workflow to 13 and 14 until 15 is available
JeffGarland May 31, 2025
c9f385d
explicit changes to module support based on compiler versions
JeffGarland May 31, 2025
78afde7
more module scan tweaks
JeffGarland May 31, 2025
ef85c4d
Update tests/CMakeLists.txt
JeffGarland May 31, 2025
4c77cca
Update CMakeLists.txt
JeffGarland May 31, 2025
4ed6f55
add cmake debugging for version
JeffGarland May 31, 2025
8a95605
module test of clang-19 looks good, adding to supported
JeffGarland Jun 1, 2025
d30afca
update comment on modules support
JeffGarland Jun 1, 2025
6a6ee76
update the readme.md for modules information.
JeffGarland Jun 2, 2025
54d2d74
minor doc tweak
JeffGarland Jun 13, 2025
0f4fd2e
revert modules back to clang-20 to see if CI cleans-up
JeffGarland Jun 14, 2025
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
8 changes: 4 additions & 4 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: Setup build environment
uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0"
cmakeVersion: "~3.28.0"
ninjaVersion: "^1.11.1"
- name: Setup MSVC
if: startsWith(matrix.presets.platform, 'windows')
Expand Down Expand Up @@ -80,7 +80,7 @@ jobs:
- name: Install Ninja
uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0"
cmakeVersion: "~4.0.0"
ninjaVersion: "^1.11.1"
- name: Setup MSVC
if: startsWith(matrix.platform.os, 'windows')
Expand Down Expand Up @@ -139,7 +139,7 @@ jobs:
- name: Setup build environment
uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0"
cmakeVersion: "~3.28.0"
ninjaVersion: "^1.11.1"
- name: Print installed softwares
run: |
Expand Down Expand Up @@ -183,7 +183,7 @@ jobs:
- name: Setup build environment
uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0"
cmakeVersion: "~4.0.0"
ninjaVersion: "^1.11.1"
- name: Install Compiler
id: install-compiler
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ jobs:
with:
tool_name: pre-commit
level: warning
reviewdog_flags: "-fail-level=none"
reviewdog_flags: "-fail-level=error"
64 changes: 52 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

cmake_minimum_required(VERSION 3.25)
cmake_minimum_required(VERSION 3.28)

project(
beman.scope
Expand All @@ -9,6 +9,19 @@ project(
VERSION 0.0.1
)

# gersemi: off
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If more than 60% of the CMake file is ignored, we might as well remove the cmake formatter.

Copy link
Member Author

@JeffGarland JeffGarland Jun 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other cmake files. I have a bunch of clang-format exclusions as well -- that doesn't mean I want it all turned off.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pro removing the formatter, it's too wrong too often to really be useful


# Modules opt in only on compilers that support g++-15 and clang-20+
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20)
set(CMAKE_CXX_SCAN_FOR_MODULES 1)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15)
set(CMAKE_CXX_SCAN_FOR_MODULES 1)
elseif()
set(CMAKE_CXX_SCAN_FOR_MODULES 0)
endif()

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# [CMAKE.SKIP_TESTS]
option(
BEMAN_SCOPE_BUILD_TESTS
Expand All @@ -29,35 +42,61 @@ option(
${PROJECT_IS_TOP_LEVEL}
)

add_library(beman.scope INTERFACE)
message(
"Compiler is: ${CMAKE_CXX_COMPILER_ID} version: ${CMAKE_CXX_COMPILER_VERSION}"
)
message(
"cmake is: ${CMAKE_VERSION} modules scan : ${CMAKE_CXX_SCAN_FOR_MODULES}"
)

if(CMAKE_CXX_SCAN_FOR_MODULES)
add_library(beman.scope)
target_sources(
beman.scope
PUBLIC
FILE_SET HEADERS
BASE_DIRS include
FILES include/beman/scope/scope.hpp
PUBLIC
FILE_SET CXX_MODULES
BASE_DIRS include
FILES include/beman/scope/beman.scope.cppm
)
else()
add_library(beman.scope INTERFACE)
target_sources(
beman.scope
INTERFACE
FILE_SET HEADERS
BASE_DIRS include
FILES include/beman/scope/scope.hpp
)
endif()

add_library(beman::scope ALIAS beman.scope)

# gersemi: off
set_target_properties(
beman.scope
PROPERTIES
VERIFY_INTERFACE_HEADER_SETS ON
EXPORT_NAME scope
)

target_sources(
beman.scope
INTERFACE
FILE_SET HEADERS
BASE_DIRS include
FILES include/beman/scope/scope.hpp
)
include(GNUInstallDirs)

install(
TARGETS beman.scope
EXPORT beman.scope-targets
COMPONENT beman.scope
EXPORT beman.scope-targets

FILE_SET CXX_MODULES
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILE_SET HEADERS
)

# gersemi: on

if(BEMAN_SCOPE_INSTALL_CONFIG_FILE_PACKAGE)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

write_basic_package_version_file(
Expand All @@ -77,6 +116,7 @@ if(BEMAN_SCOPE_INSTALL_CONFIG_FILE_PACKAGE)
EXPORT beman.scope-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/beman.scope
NAMESPACE beman::
CXX_MODULES_DIRECTORY cxx-modules
COMPONENT beman.scope
)
endif()
Expand Down
30 changes: 23 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,32 @@ Full runnable examples can be found in `examples/`.
## Integrate beman.scope into your project

Beman.scope is a header-only library that currently relies on TS implementations
and is thus currently available only on GCC13 and up, or Clang 19 and up -- in C++20 mode.
and is thus currently available only on g++-13 and up, or clang 19 and up -- in C++20 mode.

Note that modules support is currently tested only on clang++-19 and above and g++-15.

As a header only library no building is required to use in a project -- simply make
the `include` directory available add add the following to your source.

```cpp
#include <beman/scope/scope.hpp>

//modular version

import beman.scope;
```
Withmodules import needs to be after any includes to avoid compilation errors.

## Building beman.scope

Building is only required to run tests and examples.
Building is only required to run tests and examples. All compilers build and
run `include` based tests. Compilers known to support modules are automatically
detected added to tests.

### Build Dependencies

The library itself has no build dependencies other than Catch2 for testing
and cmake.
The library itself has no build dependencies other than Catch2 for testing.
And for building cmake and ninja. Makefiles are supported in non-modular builds.

Build-time dependencies:

Expand All @@ -110,14 +119,21 @@ Build-time dependencies:
- CMake defaults to "Unix Makefiles" on POSIX systems
- `catch2` for building tests

### How to build beman.scope
### How to build beman.scope tests and examples

from root of repo:

```shell
cmake --workflow --preset gcc-debug
mkdir build; cd build;
cmake .. -DCMAKE_CXX_COMPILER=g++-15 -DCMAKE_CXX_STANDARD=26 -G=Ninja
ninja -j 5 -v; ctest
```

or using cmake presets
```shell
cmake --workflow --preset gcc-release
cmake --install build/gcc-release --prefix /opt/beman.scope
```

# License

Source is licensed with the Apache 2.0 license with LLVM exceptions
Expand Down
42 changes: 42 additions & 0 deletions examples/scope-module.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// This example uses c++20 modules with beman.scope
//
// The following are by hand instructions for compiling with g++-15
// first line generates gcm.cache file for standard headers - one time only
// g++-15 -std=c++26 -O2 -fmodules -fsearch-include-path -fmodule-only -c bits/std.cc
// g++-15 -std=c++26 -O2 -fmodules -fmodule-only -c ${scope_top}/include/beman/scope/beman.scope.cppm
// g++-15 -std=c++26 -fmodules scope-module.cpp
//
// prints:
// --> scope start
// construct noisy
// --> scope end
// destroy noisy
// scope exit: true success: true fail: false

import std;
import beman.scope;

// clang-format off
struct noisy_resource {
noisy_resource() { std::print( "construct noisy\n" ); }
~noisy_resource() { std::print( "destroy noisy\n" ); }
};

int main() {

bool exit_ran, success_ran, fail_ran = false;
{
std::print("--> scope start\n");
beman::scope::scope_exit _([&exit_ran] { exit_ran = true; });
beman::scope::scope_success _([&success_ran] { success_ran = true; });
beman::scope::scope_fail _([&fail_ran] { fail_ran = true; });
auto resource_ptr = beman::scope::unique_resource(new noisy_resource(),
// Cleanup function
[](noisy_resource* ptr) { delete ptr; });
std::print("--> scope end\n");
} // Normal scope exit

std::print("scope exit: {} success: {} fail: {} \n", exit_ran, success_ran, fail_ran);
}
15 changes: 15 additions & 0 deletions include/beman/scope/beman.scope.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// create the beman.scope.gcm in gcm.cache directory
// g++-15 -std=c++26 -O2 -fmodules -fmodule-only -c ${scopetop}/include/beman/scope/beman.scope.cppm
module;

#include "scope.hpp"

export module beman.scope;

export namespace beman::scope {
using ::beman::scope::scope_exit;
using ::beman::scope::scope_fail;
using ::beman::scope::scope_success;
using ::beman::scope::unique_resource;
} // namespace beman::scope
7 changes: 6 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(Catch2)

set(ALL_TESTNAMES scope_success scope_exit scope_fail unique_resource)
# module tests will only compile with gcc15 or clang20 and above
if(CMAKE_CXX_SCAN_FOR_MODULES)
set(ALL_TESTNAMES scope_success scope_exit scope_fail unique_resource module)
else()
set(ALL_TESTNAMES scope_success scope_exit scope_fail unique_resource)
endif()

message("Tests to be built: ${ALL_TESTNAMES}")

Expand Down
37 changes: 37 additions & 0 deletions tests/module.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#define CATCH_CONFIG_MAIN
#include <catch2/catch_all.hpp>

// for g++-15 the order is important -- import after includes
import beman.scope;

struct DummyResource {
bool& cleaned;

DummyResource(bool& flag) : cleaned(flag) { cleaned = false; }

bool is_clean() const { return cleaned; }
};

TEST_CASE("module-test", "[scope_module_test]") {
bool exit_ran, success_ran, fail_ran = false;
bool cleaned = true;
{
// clang-format off
beman::scope::scope_exit _se([&exit_ran] { exit_ran = true; });
beman::scope::scope_success _ss([&success_ran] { success_ran = true; });
beman::scope::scope_fail _sf([&fail_ran] { fail_ran = true; });
auto resource_ptr = beman::scope::unique_resource(new DummyResource(cleaned),
[](DummyResource* ptr) { ptr->cleaned =true; delete ptr; });
REQUIRE(cleaned == false);
REQUIRE(resource_ptr->is_clean() == false);
// clang-format on
} // Normal scope exit

REQUIRE(exit_ran == true);
REQUIRE(success_ran == true);
REQUIRE(fail_ran == false);
REQUIRE(cleaned == true);

}
Loading