Sunday, October 11, 2026

Why are my builds slow? Using CMake’s Instrumentation FeatureCMake 4.2 dropped the experimental gate on a major new feature: the CMake Instrumentation API. This enables detailed tracking of the entire CMake workflow, including configure time, build execution, testing, and installation, and provides developers and teams with actionable insights into build performance. Support for automated, user-written scripts to handle instrumentation data make it easy to track performance data over time across different machines and environments.📝Kitware Inc
ClangIR and the cost of MLIRClangIR (CIR) is an MLIR dialect between the AST and LLVM IR, and in October 2026 the clang area team accepted building it by default . CIR is built on MLIR because each step along the way was locally reasonable, and together the steps locked MLIR in. The costs (build time, binary size, MLIR API churn) land largely on Clang contributors who neither chose MLIR nor use CIR. This post traces how CIR came to depend on MLIR, collects what the dependency costs, and uses an MLIR-free CIR as a thought experiment to separate the costs inherent to MLIR from those that can be reduced.📝MaskRay
C++26 Contracts: Introduction to Preconditions and PostconditionsIn the article about Standard Library hardening , we looked at checks for invalid Standard Library container access and other broken preconditions. I mentioned that those requirements are expressed in terms of “contracts”. But what about our code? In this post, we’ll explore contracts from C++26. We’ll start with a simple cassert , move the requirement into the function itself, and see how to check results. We’ll also look at declarations and definitions, compiler options, and a few details that can surprise you. Starting with an Assertion Let’s start with a small example: A header file first: // foo.h #include int get_value ( const std :: vector int >& values , std :: size_t index ); And the implementation: // foo.cpp #include "foo.h" // our function declaration... #include int get_value ( const std :: vector int >& values , std :: size_t index ) { assert ( index values . size ()); return values [ index ]; } The function expects a valid index. If the condition is false, assert prints a diagnostic message and terminates the program. However, this only happens when assertions are enabled. Defining NDEBUG disables the check and basically removes the check from the code. What are the issues with this simple approach? The requirement lives inside the implementation. Somebody reading only the declaration sees a vector and an index, without the relationship between them. Adding a Precondition With C++26 contracts, we can move that requirement from an assertion inside the function body to the function itself: int get_value ( const std :: vector int >& values , std :: size_t index ) pre ( index values . size ()) { return values [ index ]; } Notice the new pre(...) syntax after the parameter list. It introduces a precondition assertion : a condition expected to hold when entering the function. What’s more, we can add this precondition to the declaration: int get_value ( const std :: vector int >& values , std :: size_t index ) pre ( index values . size ()); The feature was introduced through P2900, Contracts for C++ . Let’s understand how it works and how it differs from assert . Why Use Contracts Instead of assert ? At first, pre(index might look like another way to write assert(index . Both express a condition that should be true. So what’s the benefit of using contracts? There are a few important differences: Requirements in declarations: We can put pre and post directly in the function declaration. This makes the requirements visible to anyone reading the API, without looking at the implementation. More flexible checking: Traditional assert is enabled or disabled through NDEBUG . Contracts define several evaluation semantics, including ignoring a check, reporting a violation and continuing, or terminating the program. The compiler implementation determines which semantics are available and how they can be selected. Preconditions and postconditions: Contracts distinguish between what the caller must provide and what the function promises to return. With assert , we would have to place checks manually inside the function body, including checks before different return statements. This also makes contracts useful for documenting APIs, even when runtime checking is disabled. A Complete Precondition Example Here’s a complete example (no header file for simplicity for now): #include #include int get_value ( const std :: vector int >& values , std :: size_t index ) pre ( index values . size ()) { return values [ index ]; } int main () { std :: vector int > values { 10 , 20 , 30 }; std :: println ( "{}" , get_value ( values , 1 )); // get_value(values, 10); // violates the precondition } The valid call prints: 20 And here’s the version for you to play with the problematic call uncommented: See at Compiler Explorer On GCC, I’m getting: Program returned: 134 Program stdout 20 Program stderr contract violation in function int get_value(const std::vector &, std::size_t) at /app/example.cpp:6: index Contracts on Declarations and Definitions For clarity, contracts can appear on a declaration, in a definition, or both: int get_value ( const std :: vector int >& values , std :: size_t index ) pre ( index values . size ()); The definition can then omit the contract specifier: int get_value ( const std :: vector int >& values , std :: size_t index ) { return values [ index ]; } The contract assertions are established by the function’s first declaration. A later declaration or definition may omit the contract specifiers, as above, or repeat the same sequence. A later declaration cannot introduce a different set of preconditions or postconditions. In practice, if a function is declared in a header, that first declaration is the natural place for its preconditions and postconditions. If you’re reading the API, it’s probably best to see all preconditions without looking inside the implementation. What’s more, contracts are associated with the function, but they are not part of the function type. Overload resolution, for example, does not distinguish functions based on their contracts. Contract Evaluation Semantics C++26 defines four evaluation semantics: Semantic What happens at runtime? Ignore The predicate is not evaluated. Observe A violation invokes the handler; execution continues if it returns normally. Enforce A violation invokes the handler; execution terminates if it returns normally. Quick-enforce A violation terminates execution without invoking the handler. The implementation determines which semantic applies. C++26 has no portable syntax for forcing an individual ordinary contract assertion to use one specific policy. These rules appear in the contract evaluation specification . With the ignore semantic, no runtime check is performed. With observe, a violation is reported, but execution continues if the handler returns normally. In our example, both policies can allow the program to reach values[index] with an invalid index, resulting in undefined behavior. Thus, adding pre(...) expresses the requirement, while the selected policy determines how checking responds. Compiling with GCC As of October 2026, only GCC 16 supports Contracts. We can use it with special compile flags: g++ -std = c++26 -fcontracts \ -fcontract-evaluation-semantic = enforce example.cpp With that policy, the invalid call invokes the violation handler. If the handler returns normally, execution terminates before the function body performs the invalid access. GCC’s default handler emits diagnostic information. See the GCC options documentation - contracts . GCC also allows us to replace the default contract-violation handler. For example, we can log a custom message when a violation is detected. The handler receives a std::contracts::contract_violation object, which provides information about the failed contract, including the predicate, location, and evaluation semantic. #include #include void handle_contract_violation ( const std :: contracts :: contract_violation & violation ) { std :: println ( stderr , "Contract violated: {}" , violation . comment ()); } See an example @Compiler Explorer Notice that replacing the handler doesn’t change what happens after it returns. With observe , execution continues. With enforce , the program terminates. Not every implementation is required to support replacing the handler, so this feature is implementation-defined. Adding a Postcondition So far, we’ve described what the caller must provide. We can also describe what a function promises when it returns normally. See this example: int clamp_value ( int value , const int low , const int high ) pre ( low high ) post ( result : result >= low && result high ) { if ( value low ) return low ; if ( value > high ) return high ; return value ; } There are two useful pieces here: pre(low checks that the bounds form a valid interval. post(result: ...) checks that the returned value lies inside that interval. The name result is ours to choose. It refers to the function’s result within that postcondition. What’s convenient is that the same postcondition covers every normal return path. We don’t have to repeat an assertion before each return . Here’s an example where I deliberately violated the postcondition: #include int clamp_value ( int value , const int low , const int high ) pre ( low high ) post ( result : result >= low && result high ) { if ( value low ) return low - 10 ; // if ( value > high ) return high ; return value ; } int main () { std :: print ( "{}" , clamp_value ( 10 , 20 , 30 )); } See @Compiler Explorer And on GCC I’m getting: contract violation in function int clamp_value(int, int, int) at /app/example.cpp:5: result >= low && result [assertion_kind: post, semantic: enforce, mode: predicate_false, terminating: yes] terminate called without an active exception Program terminated with signal SIGABRT (6) The precondition is fine, but the postcondition is broken. Const Parameters in Postconditions There’s also a detail in the parameter list: low and high are const . You will get the following error if you try making them non-const: source>:5:28: error: a value parameter used in a postcondition must be const 5 | post(result: result >= low && result When a postcondition uses a parameter passed by value, that parameter must have const type on every declaration. Our comparisons use both bounds this way. The parameter value is only used in the body, so this requirement doesn’t apply to it. Postconditions apply to normal exit; they do not check the result when the function body exits through an exception. See the function contract rules . Assertions Inside a Function For conditions inside an implementation, we have contract_assert : #include std :: size_t count_spaces ( std :: string_view text ) { std :: size_t count = 0 ; for ( char ch : text ) { if ( ch == ' ' ) ++ count ; } contract_assert ( count text . size ()); return count ; } The condition is simple, but it expresses a useful property: the number of spaces cannot exceed the number of characters. In a larger algorithm, such a check could describe a relationship between counters, an intermediate result, or the state after processing a block of data. Together, pre , post , and contract_assert cover function entry, normal exit, and points inside a function. Avoiding Mutation in Predicates One thing to watch during migration is mutation inside predicates: void process ( int count ) pre ( ++ count > 0 ) // error { } See @Compiler Explorer An error from GCC: error: increment of read-only location '(const int)count' 2 | pre(++count > 0) // error Contract predicates use special constification rules. In this example, count is treated as const inside the predicate, so ++count is rejected by the compiler. However, this does not make predicates completely free of side effects. For example, a predicate can still call a function that modifies global state. Since contract evaluation may be ignored, and side effects are not guaranteed even under checking semantics, predicates should not modify program state. Contracts Are Not Input Validation There’s another practical distinction: input validation. Suppose an index comes from a configuration file. If an invalid value requires an error message, that handling belongs in ordinary control flow: if ( index >= values . size ()) { std :: println ( "Invalid index: {}" , index ); return ; } std :: println ( "{}" , get_value ( values , index )); The validation handles an expected failure at the application boundary. The precondition documents the internal helper’s requirements. P2900 explicitly discusses this idea in: Principle 12: Contract Assertions Are Not Flow Control: While a contract assertion provides an algorithm to validate correctness, nothing about a contract assertion guarantees any particular runtime behavior associated with that syntactic construct. And more: Importantly, this aspect of Contracts is why contract assertions must not be used for error handling and input validation: If a function has in-contract requirements to report certain events as errors, that handling must be done with standard C++ control statements that are not optional, never with contract assertions. Considering Predicate Costs Finally, one note about performance implications. Our index comparison is cheap. A condition that verifies whether an entire collection is sorted needs to examine its elements. An expensive check may be useful during testing, but you should measure its effect on representative workloads. Summary C++26 contracts give us three ways to express assumptions and guarantees directly in the language: pre(...) describes conditions expected to hold when a function is entered, post(...) describes conditions expected to hold when a function returns normally, contract_assert(...) checks properties at specific points inside a function. Preconditions and postconditions are associated with the function through its declarations. In particular, the first declaration establishes the contract, which makes declarations in header files a natural place to document an API’s requirements. A contract assertion does not necessarily mean that a runtime check will always be performed. The selected evaluation semantic can ignore, observe, enforce, or quick-enforce the assertion. Code therefore shouldn’t depend on contract predicates for required application logic or side effects. Contracts also aren’t a replacement for normal input validation. Use regular control flow for errors that your program expects and needs to handle. References P2900, Contracts for C++ Contract assertions (since C++26) - cppreference.com - C++ Reference How C++26 Contracts Improve Correctness Without Sacrificing Performance | Citadel Securities How C++26 contracts work | Train IT Test Driving C++26 Contracts with GCC 16.1 | Fabian Koehler📝C++ Stories

If this page is useful, please consider donating a coffee

Saturday, October 10, 2026

Friday, October 9, 2026

Thursday, October 8, 2026

CMake: Making Hard Things EasyAt CppCon 2026, I gave a talk called “CMake: Making Hard Things Easy” about how CMake handles build-system complexity so developers can focus on their software. This article shares practical takeaways from that talk. We started CMake for ITK 26 years ago. Researchers needed to use medical image segmentation and registration algorithms across different platforms without becoming experts in every compiler and linker. The idea was to capture that expertise in the build system so everyone could benefit from it. I wrote about those early days in Happy Birthday CMake!. Today, we take it for granted that we have build tools that can create static or shared libraries and link applications to them on Linux, Windows, or macOS.📝Kitware Inc
Introducing the QML Live Preview MCP Tool for Agentic Development of Embedded DevicesAgents Edit QML, But Don’t See the Result Without Building, Compiling, and Running AI agents can make many UI changes in a single iteration. AI agents edit files, maybe run a build, and then report success. Every change can costs a full rebuild and relaunch, or it goes unchecked by the developer. Qt's QML Live Preview MCP tool makes autonomous AI agent work transparent for the developer at a low token expense: it runs the app and hot reloads changed QML files, without a rebuild and without a restart.📝Qt Blog

Wednesday, October 7, 2026

Tuesday, October 6, 2026