Using CMake with C++ Builder

From RAD Studio
Jump to: navigation, search

Overview

CMake is the de facto standard for creating and managing third-party C++ libraries, widely adopted due to its flexibility and cross-platform capabilities.

The integration of CMake support with the new Window 64-bit Modern C++ toolchain allows you to build third-party C++ libraries easily, especially taking advantage of the new toolchain's compatibility with modern C++ libraries. In addition, you can also build your own apps with CMake.

Building Third-Party Libraries

To build third-party libraries using CMake, run from the RAD Studio Command Prompt (64-bit) to ensure that the product's bin64 folder is in the path, and make sure that ”cmake” is also included in the PATH environment variable. Finally, ensure that Ninja is installed and included in the PATH.

  • CMake is available from the GetIt package manager. Use this version, which has been changed to support the C++Builder toolchain.
  • Ninja is available from https://ninja-build.org/. It is a single EXE distributable; place it anywhere on your PATH.

When building using an existing CMakeList.txt file, use the following CMake options:

-DCMAKE_SYSTEM_NAME=Windows

-DCMAKE_SYSTEM_PROCESSOR=x86_64

-DCMAKE_CROSSCOMPILING=OFF

-DCMAKE_BUILD_TYPE=Release

-DCMAKE_INSTALL_PREFIX=<install dir>

-DCMAKE_ASM_COMPILER=bcc64x

-DCMAKE_C_COMPILER=bcc64x

-DCMAKE_CXX_COMPILER=bcc64x

Most of these are self-explanatory: Windows, 64-bit Intel, not cross-compiling (i.e., yes, targeting Win64), a Release build, and use bcc64x, the new compiler. A CMake install folder is where the final build artifacts are placed once built to separate them from intermediate build files.

Then use the following commands:

cmake -G Ninja -S <source dir> -B <build dir> -Wno-dev <cmake options>

cmake --build <build dir> --config Release

cmake --install <build dir> --config Release

Building C++ Builder Projects

CMake has evolved significantly over the years, and modern CMake now revolves around the concept of “targets”. These targets encapsulate compilation rules, dependencies, and properties, providing a clean and modular approach to managing compilations.

The new implementation in C++Builder fully embraces this modern CMake paradigm. RAD Studio integrates support for managing targets in C++Builder from the target, ensuring that developers can take full advantage of CMake's powerful features. This modernization aligns C++Builder with current industry standards, making it easier for developers to manage complex build configurations and integrate with third-party libraries.

Limitations

  • C++Builder projects are only compatible with the Ninja generator.
  • C++Builder custom components are unavailable in Delphi projects. Because a C++Builder component project does not generate a .DCP or .DCU files, the custom control (.BPL) files created with C++Builder do not appear in the Tool Palette for Delphi projects.
  • CMake cannot generate the *.res resource file because it depends on various internal project settings, such as the icon, product information, and other settings. In addition, the IDE can use tools such as Single Icon during the compilation process. Therefore, the user must build the project at least once through the IDE and use the generated .res file located in the output folder. The same applies to *.tbd files for Active X projects.

Packages

Packages should be treated as libraries because the new Win64x toolchain, as well as CMake internally, uses the -l<name> option for libraries, which can also be applied to packages. For example, if you have Package1.lib (static) and Package1.bpi (dynamic), passing the library name “Package1”.

Set-up C++Builder Target

The previous implementation of CMake used a macro called “set_embt_target”. In the new implementation, a function with the same name is used; however, the first argument is now the project target, allowing multiple targets in the same project.

Below is the declaration of the new function:

set_embt_target(<target> [RTL | VCL | FMX | Package | DynamicRuntime | Unicode])

Samples

The following is a VCL Application (Static Linking):

cmake_minimum_required(VERSION 3.30)

project(MyProject)

file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/*.cpp")

add_executable(Project1 WIN32 ${SOURCES})

set_embt_target(Project1 VCL)

target_include_directories(Project1 PRIVATE "${CMAKE_SOURCE_DIR}")

target_link_libraries(Project1 PRIVATE "${CMAKE_SOURCE_DIR}/Project1.res")

install(TARGETS Project1

       RUNTIME DESTINATION bin

       ARCHIVE DESTINATION lib

       LIBRARY DESTINATION lib

)

The following is an FMX Application (Dynamic Linking) sample:

cmake_minimum_required(VERSION 3.30)

project(MyProject)

file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/*.cpp")

add_executable(Project1 WIN32 ${SOURCES})

set_embt_target(Project1 FMX DynamicRuntime)

target_include_directories(Project1 PRIVATE "${CMAKE_SOURCE_DIR}")

target_link_libraries(Project1 PRIVATE "${CMAKE_SOURCE_DIR}/Project1.res")

install(TARGETS Project1

       RUNTIME DESTINATION bin

       ARCHIVE DESTINATION lib

       LIBRARY DESTINATION lib

)

The sample below shows a Console app using RTL (Static Linking):

cmake_minimum_required(VERSION 3.30)

project(MyProject)

file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/*.cpp")

add_executable(Project1 ${SOURCES})

set_embt_target(Project1 RTL)

target_include_directories(Project1 PRIVATE "${CMAKE_SOURCE_DIR}")

target_link_libraries(Project1 PRIVATE "${CMAKE_SOURCE_DIR}/Project1.res")

install(TARGETS Project1

       RUNTIME DESTINATION bin

       ARCHIVE DESTINATION lib

       LIBRARY DESTINATION lib

)

The example below is for a VCL Package:

cmake_minimum_required(VERSION 3.30)

project(MyProject)

file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/*.cpp")

add_library(Package1 SHARED ${SOURCES})

add_library(Package1_static STATIC ${SOURCES})

set_target_properties(Package1_static PROPERTIES OUTPUT_NAME "Package1")

set_embt_target(Package1 VCL Package)

set_embt_target(Package1_static VCL Package)

target_include_directories(Package1 PRIVATE "${CMAKE_SOURCE_DIR}")

target_include_directories(Package1_static PRIVATE "${CMAKE_SOURCE_DIR}")

target_link_libraries(Package1 PRIVATE "${CMAKE_SOURCE_DIR}/Package1.res")

install(TARGETS Package1 Package1_static

       RUNTIME DESTINATION bin

       ARCHIVE DESTINATION lib

       LIBRARY DESTINATION lib

)

Demos

Our GitHub page contains several demo scripts for building common third-party libraries. These require our CMake to be installed from GetIt, Ninja, plus git, and, for one demo, Python installed locally.

From our GitHub demos, navigate to CPP\CMake and invoke any batch file from a RAD Studio Command Prompt (x64) with the above tools on the path.

For more information, read:

See Also