A very exciting feature in C++Builder 10.2.3 is support for using CMake with our compilers. Let's dig in!
This post is the first in a series on CMake, and will cover:
You can think of CMake as a platform-independent, compiler-independent, project format for C++ apps and libraries.
CMake uses a file called CMakeLists.txt. This is a plain text, human-editable, description of a project: the files that need to be built, the project name(s), dependencies, etc. Here's an example:
cmake_minimum_required (VERSION 3.10)
add_executable(MyProjectName one.cpp two.cpp three.cpp)
This is a simple example. A CMakeLists.txt file is more akin to the project group in C++Builder than a project, because it can specify several projects, dependencies among them, etc.
This is completely compiler-independent. CMake knows how to build the above project as well with cc on Solaris as gcc on Linux as clang on Mac. Naturally, sometimes you do need to set vendor- or platform-specific settings, and you can do that as well. We do, for example to specify linking against the VCL or FMX runtime, which is very specific to C++Builder, or to link with the dynamic runtime, which has equivalents for other compilers but is still specific to us in implementation.
CMake has good documentation, but I think it's a bit opaque if you don't already know CMake. Personally, I recommend reading Jeff Pershing's blog series on CMake: How to Build a CMake-Based Project and Learn CMake's Scripting Language in 15 Minutes. There's a wealth of well-explained material there that will make you a CMake expert in no time.
Many third-party open source C++ libraries come packaged as CMake projects. In the past, to use these you'd have to create a C++Builder project for them, which is manual work. Now, you can just build them on the command line right away.
This makes it significantly easier for you to use other common libraries in your projects.
One secondary item is that we support using Ninja with CMake. This allows parallel building. We already support parallel compilation in C++Builder, but I'll cover Ninja in a followup blog post.
We have added: Support for using CMake to build with all of C++Builder's Clang-based command-line compilers: for Win32, Win64, iOS32, iOS64, and Android.
(You could already use CMake with the classic compiler.)
If you do not do this final step, you will get a rather puzzling error message when running CMake, something like:
-- Check for working C compiler: C:/Program Files (x86)/Embarcadero/Studio/19.0/bin/bcc64.exe -- broken
CMake Error at C:/Program Files/CMake/share/cmake-3.11/Modules/CMakeTestCCompiler.cmake:52 (message):
The C compiler
"C:/Program Files (x86)/Embarcadero/Studio/19.0/bin/bcc64.exe"
is not able to compile a simple test program.
It fails with the following output:
[ -- Long compiler command line omitted -- ]
error: invalid integral value 'd' in '-Od'
CMake will not be able to correctly generate this project.
If you see this, copy over Windows-Embarcadero.cmake as above. We hope that soon, perhaps 10.3, we will be able to support CMake out of the box without needing to ship an updated configuration file.
Above, I showed a very simple CMakeLists.txt to demonstrate the concept. Let's look at one for a real project. This is for a FireMonkey Windows application I built for CodeRage last year.
cmake_minimum_required (VERSION 3.10)
add_executable(Mazes CppMazes.cpp Algorithms.cpp Cell.cpp DistanceDijkstra.cpp
Looks very similar, doesn't it? There is one addition: an Embarcadero-specific line, set_embt_target. This macro specifies whether to link with the VCL or FMX, the dynamic runtime, or as a package. These can be combined and are listed in our documentation.
If you are building a VCL application, just write,
Which does not link against the dynamic runtime (because it was not specified) but does link against the VCL.
In normal CMake projects, you need to specify WIN32 in the add_executable call, which specifies that it is not a console app (ie sets a PE flag and uses WinMain.) If you specify the VCL or FMX, you don't need to do this; we automatically do. You can override it and specify console if you need.
Want to find more - how to build a shared library, or a package, or...? We have six sample CMakeLists.txt files in our documentation.
All the above is just background - all you really need to know is here, two command lines!
You have CMake installed and you have a CMakeLists.txt file. Building is very straightforward: call cmake, specifying that you want to use bcc64 or bcc32x as the C and C++ compiler. That's it. CMake automatically looks for the CMakeLists.txt file, and based on the compiler you specify knows if it's Win32 or Win64.
cmake -DCMAKE_C_COMPILER=bcc32x.exe -DCMAKE_CXX_COMPILER=bcc32x.exe -G Ninja
cmake -DCMAKE_C_COMPILER=bcc64.exe -DCMAKE_CXX_COMPILER=bcc64.exe -G Ninja
This will run CMake and use the Ninja generator, that is, generate the files that Ninja needs to build. More on Ninja or using other generators in another post. This process only need to be run once; you can run it again to update when your project changes, such as adding a new file. You do not need to run it every time to build, just once.
To build, call ninja:
That's it. Simple! You will see ninja build for a short while, and find the executable in your base folder.
More info about targeting iOS and Android in the next post, tomorrow!
Using CMake is actually really simple. Install it, make sure there is a CMakeLists.txt file, and call cmake. Thereafter, build with a single word: ninja.
This lets you build third party C++ libraries easily: download and run cmake. Or, you can build your own projects if you write a CMakeLists.txt file. Not only does this make it really easy to use other C++ libraries or code, but there are other benefits to using generators like ninja too (speed, for example.) Compatibility and being able to integrate well with the wider C++ world is very important to us, making it easy for you to use libraries and code from elsewhere, and easy for people to use C++Builder. We're very excited to support CMake -- and have much more to tell you!
Don't forget to read what else is new in 10.2.3.