Have an amazing solution built in RAD Studio? Let us know. Looking for discounts? Visit our Special Offers page!
C++

How Exotic Is C++Builder 13?

C++Builder is often treated as something of an exotic species within the wider C++ world. Sometimes that is said with a smile, sometimes quite seriously. Behind it lies a more fundamental question: how much does a development environment still belong to the C++ ecosystem when many of the libraries, tools, and workflows that have become commonplace elsewhere are not readily available?

For me, that question goes deeper than it may appear at first.

C and C++ are not merely two programming languages among many. A significant part of modern IT infrastructure is built directly or indirectly on them. Operating systems, databases, network stacks, compilers, graphics systems, runtimes, cryptography, and countless foundational libraries would hardly exist in the form we know today without this ecosystem.

Projects such as curl, zlib, OpenSSL, PostgreSQL, Skia, or Boost are therefore not simply optional tools that happen to be useful in a project. Many of them are part of the technical foundation on which other frameworks, programming languages, and applications are built.

This is also where I see one of the defining strengths of C++. The language spans an enormous range. I can work close to the operating system, memory, and hardware, use established C APIs directly, and at the same time build highly abstract models with templates, Concepts, Ranges, and generic architectures.

That breadth is sometimes underestimated because abstraction is more strongly associated with other languages. I think that distinction is misleading. Modern C++ abstractions do not have to hide behind Python or other high level languages. The real strength is that I can stay within one language from low level infrastructure all the way to highly abstract application models, without crossing a language boundary where I suddenly lose control over types, memory, runtime behaviour, or the underlying system.

Our own adecc library is one example of that approach. It connects modern C++ concepts with data access, models, and user interfaces at an abstraction level where much of the traditional boilerplate can disappear. But this only becomes truly interesting when those abstractions do not remain in an isolated world of their own and can instead connect directly to the existing IT landscape.

That is why access to the Open Source ecosystem matters so much.

If I can use curl, OpenSSL, PostgreSQL, XML parsers, PDF libraries, graphics systems, and the many other building blocks directly and under my own control, I gain more than individual features. I gain the ability to connect my own abstractions to a substantial part of the existing IT world.

And that is exactly where this story began.

It started with a livestream

In the first week of August, during one of my C++ livestreams, we were working on a Visual Studio project and needed curl, zlib, and nlohmann-json. In that environment, the task was almost unremarkable. The libraries were configured quickly, integrated, and we could have simply moved on.

Instead, the discussion turned to C++Builder 13.

Why was the same process not equally straightforward there? Why had an infrastructure that had become normal in other C++ environments not become equally natural for C++Builder? And if C++Builder carries C++ in its name and now uses a modern Clang based toolchain, should the surrounding C++ world not be just as reachable?

My immediate answer was quite clear: these libraries belong in GetIt Package Management and should be provided and maintained by Embarcadero.

That view became even stronger when looking at the Embarcadero ecosystem itself. Delphi is by no means detached from this technical foundation. Embarcadero frameworks and libraries also use technologies originating in the C and C++ world, sometimes directly, sometimes through ports into Delphi, and sometimes in mixed forms.

There is nothing inherently wrong with that. If anything, it demonstrates how fundamental this infrastructure is. But it also raises an obvious question for me: why should a C++Builder developer access an original C or C++ library through a Delphi layer when the library can be used directly in C++?

If a library provides an established C or C++ API, I want to use its types, documentation, examples, and community directly. I want to follow new versions of the original project instead of depending on when an additional abstraction layer catches up.

The discussion in the stream therefore became more than a question of convenience. It led to a much simpler and harder question: was my expectation technically realistic?

Before asking Embarcadero to provide these libraries, I wanted to know whether they could actually be built with the current toolchain.

That became the first project.

August: proving that it can be done

The purpose of that first project was deliberately narrow. It was meant to demonstrate whether current Open Source libraries could be built reliably with C++Builder 13 and its bcc64x toolchain.

I was not trying to create a new package manager, nor was I trying to build a permanent Third Party infrastructure. The goal was evidence.

That sounds simple. It was not.

Porting large Open Source libraries requires much more than selecting a compiler and pressing a build button. You need to understand build systems, follow CMake logic, analyse compiler detection, inspect platform branches, understand dependencies, generated sources, and sometimes several nested build systems. At some point, you also need enough experience in C and C++ to recognise that the error message shown at the end of a build may be several conceptual layers away from the actual cause.

This is not work every C++Builder developer should have to do, and it is not work every developer needs to be able to do. Quite the opposite. A developer who needs a database, a graphics library, or a cryptography component should be able to use it without first becoming an expert in the complete build machinery behind it.

But if I wanted to prove that the route was technically open, I first had to do that work myself.

For that reason, I did not restrict the experiment to a few convenient examples. Boost 1.92 was part of the first round, as were OpenGL, SDL2, and Raylib. Skia made the challenge considerably more demanding, because Skia is not simply one library in a list. It brings a complex landscape of internal and external dependencies, additional tools, and its own assumptions about compilers, platforms, and build systems.

By the end of August, we had successfully built more than twenty libraries, while the actual Open Source landscape involved was considerably larger once internal dependencies were counted.

The route to that point was anything but smooth.

There were highs, when a library finally built cleanly after hours or days of investigation and confirmed that the underlying idea was sound, and there were lows, when I spent many hours on failures that initially made very little sense.

Some of the most frustrating cases were those in which a project correctly detected Borland or Embarcadero related macros and then did exactly the wrong thing. Old compatibility code would activate a compiler specific path that had been written for a completely different generation of toolchain.

At first glance, that looks reasonable. The project sees Borland or Embarcadero and selects the corresponding branch. Only when you follow the toolchain history and the preprocessor logic in detail does it become clear that modern bcc64x is technically far closer to current Clang than to the historic compilers for which those paths were written.

I spent many hours in exactly those situations, occasionally questioning assumptions and sometimes discarding approaches that had looked promising at first. But that also made every successful build more meaningful, because each one confirmed that the fundamental problem was not C++ itself and not the basic capability of the compiler.

The difficulty was often the weight of history.

And that was precisely why I wanted to complete the proof.

I did not want to accept the idea that C++Builder should be considered exotic simply because access to the surrounding library world was more difficult than with other toolchains. I believed that modern C++Builder technically belongs in the C++ ecosystem, and I wanted to demonstrate that with real projects, not with toy examples.

By the end of August, that proof existed for me.

C++Builder is not fundamentally cut off from the modern Open Source world. Many projects need adaptations, some build systems require corrections, and some assumptions in the source do not fit the real toolchain, but the ecosystem is reachable.

That made the project more than a personal experiment.

It became a call for action to Embarcadero.

I did not only talk about it publicly. I wrote emails and received replies. I do not want to discuss that communication here, because the central point is more important than the individual responses.

The technical proof was there.

It can be done.

For me, that means there is no fundamental technical reason why a maintained offering could not emerge in the future, whether through GetIt or through another suitable infrastructure.

I still believe that this point matters strategically. Direct access to the modern C and C++ Open Source ecosystem is not simply about adding more packages. It affects how naturally C++Builder can position itself within the wider C++ world.

That was the first conclusion.

The second was less comfortable.

The proof worked.

The structure did not.

September: from evidence to reproducibility

By the end of August, the first project had accumulated CMake adjustments, special parameters, batch files, patches, helper tools, and project specific treatments. That was acceptable for an evidence project, because its purpose was to prove that the route was technically open.

It was not acceptable as a long term solution.

There is a fundamental difference between building a library successfully once and being able to reproduce the same result months later, on another machine, after a version change, and from the same defined prerequisites.

Evidence had to become reproducibility.

That is where the second project began in September.

I could have waited to see whether something would eventually emerge elsewhere from the evidence project, but I did not want to. We needed this infrastructure for our own projects, and the first project had already shown that the technical basis existed.

So I started again.

Not by extending the old scripts, but by designing a system for reproducible builds.

That system became the BuildEngine.

The BuildEngine: not just a build script

The BuildEngine itself was written with C++Builder and already uses parts of the same Open Source world whose integration had triggered the whole discussion.

At its core is a finite state machine, but the FSM is only one part of the architecture.

Each library moves through a defined sequence of states, beginning with a verified download and continuing through source preparation, patching, configuration, build, test, installation, publication, and documentation. The system therefore no longer describes a list of commands. It models state, dependencies, and the evidence that determines whether a state is valid.

At the same time, the engine was designed to execute work concurrently.

Multiple workers process independent tasks in parallel, while a separate thread analyses the output produced by the different build systems and reduces it to a controlled console representation. When the underlying build system supports parallel execution, the BuildEngine uses that as well, and the same applies to test suites that can be executed concurrently.

This gives the system several layers of parallelism, but without surrendering control over what is happening.

Testing became equally important to me.

Whenever a project provides upstream tests, we run them. I was never satisfied merely because a library happened to compile and link. If tests failed, I wanted to understand why. A test was only excluded when there was a clear technical reason why it could not meaningfully run in our environment, for example because it was genuinely Linux specific.

That insistence cost time, sometimes a great deal of it, but it changed the quality of the result. A successful build tells me that the compiler accepted the code. A successful upstream test suite tells me much more about whether the resulting library behaves as its authors intended.

And yet, all of this initially remained hidden behind a very simple surface.

The BuildEngine was a console application.

When appearance becomes more important than architecture

That apparently simple fact triggered another kind of discussion.

Some critics of C++ looked at the console interface and immediately associated it with legacy technology. A console program, in that reading, was old fashioned almost by definition.

I found that reaction revealing.

Behind that console was a state driven system with multiple workers, layered parallelism, asynchronous output analysis, dependency tracking, automated patching, testing, evidence evaluation, and reproducible creation of an entire Third Party landscape.

But none of that is visible if the first judgement is made from the surface alone.

That distinction mattered to me because it reflected a broader tension around C++ itself. C++ is sometimes judged by its visible traditions rather than by what modern C++ can actually express and what systems built with it can actually do.

For me, content matters more than facade.

Still, the criticism had one useful effect.

It made me ask how much of the BuildEngine world should remain hidden.

And that is where the Server and Manager came from.

Making the system visible

The BuildEngine Server became possible for exactly the same reason the BuildEngine itself had become possible: by using the libraries we had already brought into our own controlled ecosystem.

That is important to me, because the Server is not merely a web frontend that happens to sit beside the build system. It is itself another proof that the libraries we built are usable in real applications.

For the HTTP and server side, we can use boost::beast, together with curl, OpenSSL, nlohmann-json, and pugixml. Compression and archive handling build on zlib, other compression libraries, and libarchive. Markdown processing uses cmark-gfm, while syntax highlighting, Mermaid, and MathJax are integrated through the corresponding JavaScript packages.

The result is therefore more than a server displaying web content. It is a working integration of the Open Source stack that the BuildEngine has created.

That closes another part of the loop: the libraries are no longer only artefacts produced by the system, they are becoming the foundation on which the next generation of tools is built.

The Server exposes the information created by the BuildEngine in a form that can be navigated, inspected, reused, and distributed.

One part of that is documentation.

The server processes Markdown and integrates syntax highlighting, Mermaid diagrams, and MathJax, while adding table of contents functionality, navigation, and a dedicated print view. Build instructions, architectural documentation, licences, technical explanations, diagrams, and formulas can therefore become part of one coherent documentation environment.

That may look like presentation, but it serves a deeper purpose. Reproducibility is not only about binary artefacts. It is also about making the knowledge around those artefacts available and understandable.

The Server also exposes a REST API over the library landscape.

That makes the information accessible to other tools, because libraries, versions, dependencies, and metadata are no longer locked into one user interface. The server can already package selected libraries together with their dependencies and provide the resulting bundle as a download.

The BuildEngine Manager addresses another part of the problem.

It is deliberately written with the VCL as its user interface.

That choice is intentional. I do not want to hide C++Builder behind some unrelated frontend technology. If the environment is capable of modern C++ development, then the surrounding tools should be able to demonstrate that directly.

One of the Manager’s tasks is to work with security findings. It reads information about known security issues, allows CVEs and other findings to be reviewed and classified, and stores those assessments so they can be distributed together with the information about the affected libraries.

That is an area where a graphical interface is genuinely useful. A build system can collect and correlate security information automatically, but deciding whether a finding is relevant, accepted, mitigated, or requires action is ultimately a human judgement.

The Manager provides that layer.

This is also where the interaction around the project became especially interesting.

On one side were C++Builder developers who were not interested in theoretical debates about whether the ecosystem should exist. They wanted solutions. They needed usable libraries, predictable builds, and a path that did not force every developer to rediscover the same toolchain problems.

On the other side were critics of C++ who were quick to judge the visible facade, while the architecture and the amount of engineering underneath remained invisible to them.

Both reactions influenced the project in different ways.

The first group confirmed why the work was necessary.

The second reminded me that good engineering is not always self explanatory.

Solving the real integration problems

The deeper I went into the libraries, the clearer the recurring technical patterns became.

A substantial part of the integration problems does not arise because C++Builder is fundamentally unable to compile a library, but because a project classifies the toolchain incorrectly.

bcc64x is based on Clang. At the same time, compatibility definitions and structures exist that resemble GNU or MinGW environments. Some projects detect one of these characteristics and immediately conclude that they are dealing with MinGW, after which they activate a build path that does not actually match the environment.

The real combination is more interesting. We have a modern Clang compiler, a GNU like C++ standard library environment, and at the same time the Windows runtime and UCRT. There are also specific characteristics in the environment shipped by Embarcadero, including problematic imports that we already correct in a controlled way during bootstrap.

For that reason, a central adaptation takes place before individual library builds begin. Its purpose is not to turn bcc64x into MinGW, but to prevent third party projects from forcing the toolchain into the wrong branch based on individual compatibility markers.

The same principle applies to historic Borland support in library sources. Existing compatibility code is sometimes exactly what breaks a modern build, because it describes a compiler generation that no longer resembles current bcc64x.

Once those patterns were understood, I could stop treating every failure as an isolated problem.

They became part of the infrastructure.

Patches, XML, and controlled build definitions

There are still libraries that require actual source changes.

Those changes are not manual fixes.

Necessary patches are part of the build definition. They are versioned, verified, and applied automatically, so the system knows which modification belongs to which library version and under which conditions it is required.

A working source tree is therefore no longer the result of personal memory or manual editing. It can be reconstructed from defined sources.

The same principle applies to workflow.

I did not want the second project to become another collection of ever growing scripts, so the processes and parameters of the individual libraries are described declaratively in XML.

The description defines where a package comes from, which version is used, how the download is verified, which dependencies exist, which preparation steps are required, which patches are applied, and how the individual phases are executed.

A second XML description defines the complete build landscape.

The system is deliberately not restricted to CMake. The real Open Source world uses different build systems, so the BuildEngine also works with Meson and MPC, while Python and Perl become controlled parts of the environment wherever a project requires them.

I did not want to write a CMake engine.

I wanted an engine capable of reproducing an Open Source landscape.

A library is more than a binary

The project also changed my understanding of when a library is actually finished.

At the beginning, a successful link was an achievement.

That is no longer enough.

After the build, artefacts are installed and published into a defined structure. Licence information is discovered and added, source origins and versions remain traceable, and an SBOM is generated.

In a professional environment, that is essential. As soon as a CVE appears, it is not enough to know that OpenSSL is used somewhere. I need to know which version is present, where it came from, and which components depend on it.

That information belongs to the artefact.

The same is true for documentation.

Where it is useful and technically possible, Doxygen documentation is generated directly from the exact source revision used to create the library, so the documentation belongs to the artefact rather than pointing to some unrelated current version on the internet.

The finite state machine also makes sure that this work is not repeated without reason.

A successful build is evidence in its own right. If the source has not changed and the relevant downstream states remain valid, rebuilding everything would be pointless. Reproducibility does not mean doing everything again every time. It means being able to explain precisely why an existing state is still valid, or why it must be recreated.

That concept became one of the most important parts of the BuildEngine.

From a build system to a usable ecosystem

The more than twenty libraries from the August evidence project have now grown into a stack of more than forty libraries. The landscape spans networking, cryptography, compression, databases, XML processing, graphics, PDF processing, and further infrastructure, including the corresponding dependencies and supporting tools.

For me, that breadth matters because it turns the original proof into something much more practical.

The libraries are not left behind as demonstration artefacts. The BuildEngine ecosystem uses its own Third Party stack, and the Server is perhaps the clearest example of that transition, because it is itself built from the libraries that the whole project set out to make available.

That closes one loop.

But not yet the most important one.

The original discussion in the livestream was not about how interesting it would be to build libraries.

It was about how a C++Builder developer could simply use them.

And that is where the StackBuilder comes in.

Closing the gap: from builds to ready to use packages

The StackBuilder takes the published artefacts and assembles defined Third Party stacks for concrete projects.

A project can specify not only which libraries it needs, but also which exact versions belong to its build environment. The resulting stack can be packaged, distributed, and integrated into a repository in a controlled way.

That finally closes the gap from the original discussion.

The developer no longer needs to know how Boost, OpenSSL, PostgreSQL, Skia, or any of their dependencies were built. The difficult work has already happened upstream, under controlled and reproducible conditions.

What reaches the project is a ready to use package.

The repository knows which Third Party stack it expects. The stack can be provided in a defined form, restored when needed, and integrated directly into the build.

That is the point where the whole story comes full circle.

In early August, the question was why a Visual Studio project could use established C++ libraries almost naturally while the same experience was missing in C++Builder.

The first project proved that the libraries can be built.

The second project turned that knowledge into reproducible infrastructure.

The Server and Manager made the landscape visible, inspectable, manageable, and, importantly, demonstrated that the libraries themselves could already serve as the foundation for real applications.

The StackBuilder now turns the result into what developers actually need: finished, defined, directly integrable Third Party packages.

And for me, that is still the central point of the entire project.

C++Builder should not be treated as an outsider to the C++ world simply because the path into that world has been harder than it should be. The compiler belongs there. The libraries can be built. The infrastructure can be created. The remaining question is how naturally that world is made available to developers.

That is why the original call for action to Embarcadero still stands.

The work should not have to be repeated independently by every C++Builder developer. Those developers need solutions, and they should get them.

For now, we have built our own path from verified source to reproducible build, from tested artefact to documentation and security metadata, and from published library to repository ready Third Party stack.

There will be more information about that very soon.


C++Builder

Why not download a free trial of C++Builder and see why we think it’s the best version we’ve ever produced?

RAD Studio 13.2 Florence Now Available! Kai 1.1.1 Now Available! What's Coming in RAD Studio 13.2 Florence

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.

Start Free Trial   Upgrade Today

   Free Delphi Community Edition   Free C++Builder Community Edition

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

IN THE ARTICLES