Using CMake with C++ Builder
Contents
CMake Command-Line Support
RAD Studio includes support for building CMake projects on the command line using RAD Studio's C++ Compilers. You can compile for Windows or for other platforms from Windows. CMake supports RAD Studio’s Clang-enhanced compilers: BCC64 for 64-bit Windows and BCC32X for 32-bit Windows. RAD Studio also supports using Ninja with CMake. This allows for fast parallel compilation.
Installing CMake and Ninja
CMake
Download and install CMake 3.19.4. Use the binary installer, since it can optionally add CMake to the system path. Make sure you select that option during the installation.
CMake files are located in C:\Program Files (x86)\Embarcadero\Studio\23.0\cmake
. However, to prevent errors in the build process, you need to move one file manually. Follow the steps below to do this:
- Locate your CMake installation folder and the Modules\Platform subfolder. E.g.
C:\Program Files\CMake\Modules\Platform
- Locate the
Windows-Embarcadero.cmake
file and make a backup. - Copy
Windows-Embarcadero.cmake
from theStudio\23.0\cmake\Modules
folder and overwrite the version in the CMake Modules directory.
We have greatly extended the inbuilt CMake support for the Windows compilers and you need to use this file to build successfully.
Ninja
Download and install Ninja. You will need to add it to the system path manually.
How to use CMake
CMake builds based on a text file called CMakeLists.txt that tells CMake which files to build. You can find more information in their developer documentation. We also recommend Jeff Preshing’s blog series on CMake: How to Build a CMake-based Project and Learn CMake’s Scripting Language in 15 Minutes.
To use CMake, you need the following files:
- C++ source you want to build: Many C++ files and headers.
- CMakeLists.txt file: Defines the project name, tells it to find all source files, and builds them in one executable, library, package, etc. See below for several sample files. More advanced CMakeLists.txt files specify several projects.
- (Optionally) Batch script to drive CMake: Use the batch script (*.bat) to contain several commands. CMake can create a large number of files, and you can use the batch file to create a subfolder where all output including CMake’s files are placed. This blog post on using bcc32c with CMake has more details.
- Run the batch script from the command line to generate the executable file along with many other files in the specified subfolder.
Incremental Links
FromRAD StudioSidney 10.4, you should not have any issues related to incremental links when using CMake + Ninja to build a static library.
For older versions, if the dependency information is not generated during the build, set the CMAKE_DEPFILE_FLAGS_CXX
variable in CMakeLists.txt
as it follows:
For clang compilers:
set(CMAKE_DEPFILE_FLAGS_CXX "-MD -MT <OBJECT> -MF <DEPFILE>"
For the classic compiler:
set(CMAKE_DEPFILE_FLAGS_CXX "-md -mo\"<DEPFILE>\"")
Building using CMake
Start a RAD Studio command prompt from the Start menu, or by opening a command prompt and executing rsvars.bat in the RAD Studio \bin folder.
CMake looks for a CMakeLists.txt file. See below for information on creating one of these for a project.
Targeting Windows
To target Win32:
cmake -DCMAKE_C_COMPILER=bcc32x.exe -DCMAKE_CXX_COMPILER=bcc32x.exe -G Ninja <directory>
[1]
To target Win64:
cmake -DCMAKE_C_COMPILER=bcc64.exe -DCMAKE_CXX_COMPILER=bcc64.exe -G Ninja <directory>
[1]
Then,
ninja
To invoke Ninja to do the actual build.
Other command-line flags
- -G”Borland Makefiles” to use old-fashioned make to build.
- -DCMAKE_BUILD_TYPE_INIT=Release to target debug or release builds.
- -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON for easier to debug output.
- --debug-output to put CMake in debug mode.
For example:
cmake -DCMAKE_C_COMPILER=bcc32x.exe -DCMAKE_CXX_COMPILER=bcc32x.exe -DCMAKE_BUILD_TYPE_INIT=Release -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -G "Borland Makefiles" --debug-output -v ..
To use the Win32 compiler, release build, some verbose and debugging flags, and build using make, with CMakeLists.txt located in the parent folder.
C++ Builder-specific support in a CMakeLists.txt
Targets
Using CMake, you can create executables, DLLs, static libraries, and packages.
set_embt_target(FMX)
set_embt_target(VCL)
set_embt_target(Package)
set_embt_target(DynamicRuntime)
Or combinations:
set_embt_target(VCL DynamicRuntime)
Macros and variables
There are a number of macros and variables for Windows. This sample CMakeLists.txt shows several of them:
cmake_minimum_required(VERSION 3.9)
set(APP "FMXApp")
set(CMAKE_BUILD_TYPE "DEBUG")
set(EMBT_PROJECT_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/Project_${APP}")
project (${APP})
# Create a sources variable with a link to all cpp files to compile
file(GLOB SOURCES
"src/*.h"
"src/*.cpp"
)
set_embt_target("FMX")
if(EMBT_TARGET STREQUAL Windows)
add_executable (${APP} WIN32 ${SOURCES})
install(TARGETS ${APP} RUNTIME DESTINATION bin)
else()
add_fmx_app("${SOURCES}")
endif()
Manifests
To add a Manifest, you must create a resource file that includes:
#pragma code_page(65001)
124 "name.manifest"
Also, you can post-process with the Windows SDK tool manifest mt.exe:
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.manifest\" -outputresource:\"$<TARGET_FILE:${PROJECT_NAME}>\")
Example CMakeLists.txt file
For a project called Example, with source files in the same folder, a very minimal CMakeLists.txt file is:
cmake_minimum_required (VERSION 3.10)
project (Example)
file(GLOB Example_SRC
"*.h"
"*.cpp"
)
add_executable(Example ${Example_SRC})
This specifies the minimum version (3.10); the project name; that it uses all available .cpp and .h files, and compiles them all into Example.exe.
“Glob”-ing all files together is quick and easy, but is not a recommended best practice; instead, it is better to specify the files you want to use. You can specify .cpp files and headers, but one minimal example specifying .cpp files is:
cmake_minimum_required (VERSION 3.10)
project (Example)
add_executable(Example main.cpp foo.cpp bar.cpp)
Sample CMakeLists.txt: VCL app
cmake_minimum_required(VERSION 3.9)
project (VCLApp)
set_embt_target(VCL DynamicRuntime)
add_executable (VCLApp WIN32 src/VCLApplication.cpp src/Project1.cpp)
install(TARGETS VCLApp
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
)
Sample CMakeLists.txt: FMX app
cmake_minimum_required(VERSION 3.9)
project (FMXApp)
set_embt_target(FMX)
add_executable (FMXApp WIN32 src/FMXSample.cpp src/FMXProj.cpp)
install(TARGETS FMXApp RUNTIME DESTINATION bin)
project(SharedLibrary)
set(SharedLibrary_headers SharedLibrary.h)
set(SharedLibrary_sources SharedLibrary.cpp)
add_library(SharedLibrary SHARED SharedLibrary.h SharedLibrary.cpp)
install(TARGETS SharedLibrary
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
)
Sample CMakeLists.txt: Static Library
project(StaticLibrary)
set(StaticLibrary_headers StaticLibrary.h)
set(StaticLibrary_sources StaticLibrary.cpp)
add_library(StaticLibrary STATIC StaticLibrary.h StaticLibrary.cpp)
install(TARGETS StaticLibrary
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
)
Sample CMakeLists.txt: Package
cmake_minimum_required(VERSION 3.9)
project (PackageExample)
set_embt_target(Package)
add_library(PackageExample SHARED PackageExample.cpp)
install(TARGETS PackageExample
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
)
Sample CMakeLists.txt: Resources
cmake_minimum_required(VERSION 3.9)
project (myapp)
set(SYSTEM_SOURCES ${SYSTEM_SOURCES} myapp.rc )
set(StrTableRes_SRCS resource.h myapp.cpp)
ADD_EXECUTABLE(myapp WIN32 ${SYSTEM_SOURCES} ${StrTableRes_SRCS} )