Skip to content

Commit 1e44af0

Browse files
ConorWilliamsCopilot
authored andcommitted
[v4] Agents (#52)
* macros + format * add benchmark to lint * agents.md * tweaks to agents.md * fix typos * add .gemini * hide banner * Update .clang-format Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix comment --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 2cbdbb5 commit 1e44af0

9 files changed

Lines changed: 290 additions & 30 deletions

File tree

.clang-format

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,27 @@
22
Language: Cpp
33
ColumnLimit: 110
44
IndentPPDirectives: BeforeHash
5-
AlwaysBreakTemplateDeclarations : true
6-
PackConstructorInitializers : CurrentLine
5+
AlwaysBreakTemplateDeclarations: Yes
6+
PackConstructorInitializers: CurrentLine
77
AccessModifierOffset: -1
8-
IndentCaseLabels : true
8+
IndentCaseLabels: true
99
AllowShortLambdasOnASingleLine: Empty
1010
RequiresExpressionIndentation: OuterScope
11-
BinPackArguments : false
12-
BinPackParameters : false
13-
LambdaBodyIndentation : Signature
14-
PenaltyReturnTypeOnItsOwnLine : 1
11+
BinPackArguments: false
12+
# BinPackParameters: false
13+
LambdaBodyIndentation: Signature
14+
PenaltyReturnTypeOnItsOwnLine: 1
15+
16+
Macros:
17+
- LF_HOF(x)={x;}
18+
- LF_HOF(x,y)={x,y;}
19+
- LF_HOF(x,y,z)={x,y,z;}
20+
- LF_HOF(x,y,z,w)={x,y,z,w;}
21+
- LF_HOF(a,b,c,d,e)={a;}
22+
- LF_HOF(a,b,c,d,e,f)={a,b,c,d,e,f;}
1523

1624
SpaceBeforeParens: Custom
1725
SpaceBeforeParensOptions:
18-
AfterRequiresInClause: true
19-
AfterRequiresInExpression : true
26+
AfterRequiresInClause: true
27+
AfterRequiresInExpression: true
2028
...

.codespellrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ builtin = clear,rare,en-GB_to_en-US,names,informal,code
33
check-filenames =
44
check-hidden =
55
ignore-words-list = deque,warmup,stdio,copyable,combinate
6-
skip = */.git,*/build,*/prefix,*/vcpkg,*/_build,*/bench
6+
skip = */.git,*/build,*/.legacy
77
quiet-level = 2

.gemini/settings.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"context": {
3+
"fileName": "AGENTS.md"
4+
},
5+
"ui": {
6+
"hideBanner": true
7+
}
8+
}

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ jobs:
2525

2626
- name: Run clang-format
2727
run: |
28-
find src include test -name "*.cpp" -o -name "*.hpp" -o -name "*.cxx" | xargs clang-format --dry-run --Werror
28+
find src include test benchmark/src -name "*.cpp" -o -name "*.hpp" -o -name "*.cxx" | xargs clang-format --dry-run --Werror

.legacy/include/libfork/core/macro.hpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,6 @@
6161
#define LF_STATIC_CONST const
6262
#endif
6363

64-
// clang-format off
65-
66-
/**
67-
* @brief Use like `BOOST_HOF_RETURNS` to define a function/lambda with all the noexcept/requires/decltype specifiers.
68-
*
69-
* This macro is not truly variadic but the ``...`` allows commas in the macro argument.
70-
*/
71-
#define LF_HOF_RETURNS(...) noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) requires requires { __VA_ARGS__; } { return __VA_ARGS__;}
72-
73-
// clang-format on
74-
7564
/**
7665
* @brief __[public]__ Detects if the compiler has exceptions enabled.
7766
*

AGENTS.md

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# Libfork Copilot Instructions
2+
3+
## Project Overview
4+
5+
**libfork** is a continuation-stealing coroutine-tasking library implementing
6+
strict fork-join parallelism using C++20 coroutines.
7+
8+
- **Type**: C++ library with module/`import std` support
9+
- **Languages**: C++23
10+
11+
## Critical Build Requirements
12+
13+
### Compiler & Module Support
14+
15+
This project **requires C++23 `import std`** and **MUST** use the appropriate
16+
toolchain file:
17+
18+
- **MacOS**: Use `-DCMAKE_TOOLCHAIN_FILE=cmake/llvm-brew-toolchain.cmake`
19+
- **Linux**: Use `-DCMAKE_TOOLCHAIN_FILE=cmake/gcc-brew-toolchain.cmake`
20+
21+
**Common Error**: Without the toolchain file, CMake will fail.
22+
23+
**Always include the toolchain file** in configure commands.
24+
25+
### Dependencies (Homebrew)
26+
27+
Make sure Homebrew is installed and `brew` is in your `PATH`:
28+
29+
```bash
30+
brew --version
31+
```
32+
33+
**Required for building/testing:**
34+
35+
- `cmake`
36+
- `ninja`
37+
- `catch2`
38+
- `google-benchmark`
39+
- `clang-format`
40+
- `codespell`
41+
42+
If on MacOS, also require:
43+
44+
- `llvm`
45+
46+
If on Linux, also require:
47+
48+
- `gcc`
49+
- `binutils`
50+
51+
Install all at once (MacOS):
52+
53+
```bash
54+
brew install cmake ninja catch2 google-benchmark clang-format codespell llvm
55+
```
56+
57+
Install all at once (Linux):
58+
59+
```bash
60+
brew install cmake ninja catch2 google-benchmark clang-format codespell gcc binutils
61+
```
62+
63+
## Build & Test Workflow
64+
65+
### 1. Configure
66+
67+
Always use presets with the toolchain file:
68+
69+
```bash
70+
cmake --preset <preset-name> -DCMAKE_TOOLCHAIN_FILE=cmake/<toolchain>.cmake
71+
```
72+
73+
**Relevant available presets** (from `CMakePresets.json`):
74+
75+
- `ci-hardened` - Debug build with warnings and hardening flags
76+
- `ci-release` - Optimized release build
77+
78+
All presets enable developer mode (`libfork_DEV_MODE=ON`) and use Ninja generator.
79+
80+
You should use the `ci-hardened` preset for development/testing and
81+
`ci-release` for benchmarking.
82+
83+
### 2. Build
84+
85+
```bash
86+
cmake --build --preset <preset-name>
87+
```
88+
89+
**Build warnings** (expected and safe):
90+
91+
- "It is recommended to build benchmarks in Release mode" - only relevant for `ci-hardened`
92+
- CMake experimental `import std;` warning - expected for C++23 modules
93+
94+
### 3. Test
95+
96+
```bash
97+
ctest --preset <preset-name>
98+
```
99+
100+
All tests should pass. If tests fail, check that:
101+
102+
- Configuration used the correct toolchain file
103+
- Build completed without errors
104+
- Any changes you have made are correct
105+
106+
## Linting & Validation
107+
108+
The CI runs two linting tools that you should run before committing:
109+
110+
### codespell (spelling)
111+
112+
```bash
113+
codespell
114+
```
115+
116+
Config: `.codespellrc` (ignores: build/, .git/, etc.)
117+
Should produce no output if passing.
118+
119+
### clang-format (code formatting)
120+
121+
```bash
122+
find src include test benchmark/src -name "*.cpp" -o -name "*.hpp" -o -name "*.cxx" | xargs clang-format --dry-run --Werror
123+
```
124+
125+
Config: `.clang-format` (110 column limit, specific style)
126+
Should produce no output if passing.
127+
128+
**To auto-fix formatting**:
129+
130+
```bash
131+
find src include test benchmark/src -name "*.cpp" -o -name "*.hpp" -o -name "*.cxx" | xargs clang-format -i
132+
```
133+
134+
## Project Structure
135+
136+
### Source Layout
137+
138+
```sh
139+
libfork/
140+
├── cmake/ # CMake utilities
141+
├── include/libfork/**/*.hpp # Public headers
142+
├── src/**/ # Module and source files
143+
│ ├── *.cxx # Module files
144+
│ └── *.cpp # Source files
145+
├── test/src/**/ # Test suite (Catch2)
146+
│ └── *.cpp # Test source files
147+
├── benchmark/src/ # Benchmarking suite (google-benchmark)
148+
│ └── libfork_benchmark/ # Merged source/header files for benchmarks
149+
│ └── fib/ # Each benchmark in its own sub-directory
150+
│ ├── *.hpp # Benchmark header files
151+
│ └── *.cpp # Benchmark source files
152+
├── .github/workflows/ # CI workflows
153+
│ ├── linux.yml # Linux builds
154+
│ ├── macos.yml # MacOS builds
155+
│ ├── lint.yml # Linting
156+
│ └── linear.yml # Enforces linear history (no merge commits)
157+
└── CMakeLists.txt # Main build configuration
158+
```
159+
160+
## Workflows
161+
162+
### Workflow Command Pattern
163+
164+
All workflows follow this pattern:
165+
166+
```yaml
167+
- Install Dependencies: brew install ...
168+
- Configure: cmake --preset <preset> -DCMAKE_TOOLCHAIN_FILE=<toolchain>.cmake
169+
- Build: cmake --build --preset <preset>
170+
- Test: ctest --preset <preset>
171+
```
172+
173+
## Common Development Tasks
174+
175+
### Making Code Changes
176+
177+
1. **Modify source files** in `src/`, `include/`, `test/`, or `benchmark/`
178+
2. **Rebuild**: `cmake --build --preset <your-preset>`
179+
3. **Test**: `ctest --preset <your-preset>`
180+
4. **Lint**: Run codespell and clang-format checks
181+
182+
#### Adding/removing files from `src/` or `include/`
183+
184+
- Update the root `CMakeLists.txt` with new/removed files.
185+
186+
#### Adding/removing files from `benchmark/src/`
187+
188+
- Update `benchmark/CMakeLists.txt` with new/removed files.
189+
190+
### Adding Tests
191+
192+
Strive to add tests for new features/bug fixes.
193+
194+
- Add `.cpp` files to `test/src/`
195+
- Tests auto-discovered by CMake (GLOB_RECURSE)
196+
- Links against `libfork::libfork` and `Catch2::Catch2WithMain`
197+
- Uses `cxx_std_23` feature requirement
198+
199+
### Modifying Build Configuration
200+
201+
**Warning**: Module-related changes are complex. Test thoroughly with clean builds.
202+
203+
## Troubleshooting
204+
205+
### Build Failures
206+
207+
**Problem**: Configuration/Build fails after adding/removing files or modifying CMakeLists.txt
208+
**Solution**: Try a clean build directory:
209+
210+
```bash
211+
rm -rf build/
212+
```
213+
214+
**Problem**: "compiler does not provide a way to discover the import graph"
215+
**Solution**: Add `-DCMAKE_TOOLCHAIN_FILE=cmake/llvm-brew-toolchain.cmake` to configure
216+
217+
**Problem**: "Could not find 'brew' executable"
218+
**Solution**: Install Homebrew
219+
220+
**Problem**: "Could not automatically find libc++.modules.json"
221+
**Solution**: Ensure LLVM is installed via Homebrew; toolchain auto-detects the path
222+
223+
### Linting Failures
224+
225+
**Problem**: clang-format errors
226+
**Solution**: Run fix command above to auto-format code
227+
228+
**Problem**: codespell errors
229+
**Solution**: Fix typos or add to ignore list in `.codespellrc` if false positive

include/libfork/macros.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@
99
* however, only macros that are marked as __[public]__ should be consumed.
1010
*/
1111

12+
// =============== Utility =============== //
13+
14+
// clang-format off
15+
16+
/**
17+
* @brief Use like `BOOST_HOF_RETURNS` to define a function/lambda with all the noexcept/decltype specifiers.
18+
*
19+
* This macro is not truly variadic but the ``...`` allows commas in the macro argument.
20+
*/
21+
#define LF_HOF(...) noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__;}
22+
23+
// clang-format on
24+
25+
/**
26+
* @brief Use like `std::forward` to perfectly forward an expression.
27+
*/
28+
#define LF_FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
29+
1230
// =============== Inlining/optimization =============== //
1331

1432
/**

src/core/promise.cxx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
module;
22
#include <version>
3+
4+
#include "libfork/macros.hpp"
35
export module libfork.core:promise;
46

57
import std;
68

79
namespace lf {
810

9-
export template <typename T>
10-
struct promise {
11-
auto test() -> std::string_view { return "hi"; }
12-
};
11+
// =============== Frame =============== //
1312

1413
struct frame_type {
1514
frame_type *parent;
1615
};
1716

1817
static_assert(std::is_standard_layout_v<frame_type>);
1918

19+
// =============== Frame-mixin =============== //
20+
21+
struct mixin_frame {
22+
auto self(this auto &&self) LF_HOF(LF_FWD(self).frame)
23+
};
24+
25+
static_assert(std::is_empty_v<mixin_frame>);
26+
27+
// =============== Promises =============== //
28+
2029
template <typename T>
2130
struct promise_type;
2231

2332
template <>
24-
struct promise_type<void> {
33+
struct promise_type<void> : mixin_frame {
2534
frame_type frame;
2635
};
2736

@@ -34,7 +43,7 @@ static_assert(std::is_standard_layout_v<promise_type<void>>);
3443
#endif
3544

3645
template <typename T>
37-
struct promise_type {
46+
struct promise_type : mixin_frame {
3847
frame_type frame;
3948
T *return_address;
4049
};

test/src/promise.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33
import libfork.core;
44

55
TEST_CASE("Promise test", "[promise]") {
6-
lf::promise<int> p;
7-
REQUIRE(p.test() == "hi");
6+
// TODO:
87
}

0 commit comments

Comments
 (0)