Build and Integrate libraries having different build process seamlessly into CMake


Heavy title, right? Then before setting the context for this article, I will break down the title first.
And we will start with CMake.
What is CMake?
As you know, for a compiled language, we need compilers to compile them into machine code which then executes on the machine.
For a single file, this process could be quite straightforward and you can directly do that via CLI and voila, a working executable.
But when the project is huge and you need to dynamically link libraries, doing all the steps in CLI could be tiring, to make your life easy you would like to have a build system in place, which handles all the things.
Hopefully we are clear so far, feel free to re-read any portion before moving forward.
You also might be aware that there are many operating system and the build tools are different in all of them. Like Make in Unix and MSBuild in Windows. And it is a task to maintain build scripts for each platform.
Thus, CMake that part for us. We write a single build script and it generates the respective build scripts depending on the platform/tool and that tool then run that build script to build the executable.
What do I mean by libraries with different build process?
I think, the statement “Libraries with different build process” itself conveys what it means but I am going to use this section to provide a little more detail and context.
One of the most popular C++ Library utilised by most of the C++ projects is Boost, and it has it’s own build system Build.Boost, which generates bjam which then builds the boost.
And, another example could be OpenSSL, it uses a perl script (Configure) to generate makefiles which then builds the openssl. It also a headache(or maybe not) if we are building it in Window. You can read about that here. (self-promotion)
Recently, both of these libraries have started adding support for CMake but it’s still an ongoing effort and old build process is preferred.
Stitching it all Together
The objective here is to use CMake to build our project .which utilises libraries like boost, openssl which have their own build processes and build those libraries together while building our project in a single step.
I hope, now, we all understand the “title” of this article and objective of this article more clearly.
So, the next question is, how are we going to do that with CMake?
Building a Library with CMake
Let’s assume we are building Boost with CMake and we will create a CMakeLists.txt to do that.
CMakeLists.txt is a configuration file use to define how a project should be built, tested and installed.
Another thing, maybe not so important for you, I quickly want to mention is python template file i.e., .py.in
It is a python file which contains variables which gets replaced during build process. And as you have guessed, this also helps us configuring python file as per platform on which the build process is running.
Okay, now, to the main dish…
Since, there is different build system i.e., Build.Boost which builds Boost, we need to have a script which executes those steps and build Boost for us, so we are going to use a python script for that.
We will execute the python file and it will produce the files likelibboost_chrono.a
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build-boost.py.in ${CMAKE_CURRENT_BINARY_DIR}/build-boost.py @ONLY) add_custom_command(OUTPUT ${BOOST_LIBS} # ${BOOST_LIBS} is variable for the static files i.e., libboost_chrono.a etc COMMAND python -u ${CMAKE_CURRENT_BINARY_DIR}/build-boost.py COMMENT "Building boost libs" VERBATIM )
Create a custom target and make it depend on these static libraries
Create an Interface library and make it depend on the custom target, so that static libraries will be built first before anything which uses them.
add_custom_target(${TARGET_BOOST_STATIC_LIBS} DEPENDS ${BOOST_LIBS}) add_library(${ARC} INTERFACE) add_dependencies(${ARC} ${TARGET_BOOST_STATIC_LIBS})
Here, Interface Library is just an abstraction layer.
Link the static libraries with interface, so that any other part of the project can link to these libraries when they link to interface library.
Also, set headers, preprocessor definitions ,and required compilation options.
target_link_libraries(${ARC} INTERFACE ${BOOST_LIBS}) target_include_directories(${ARC} SYSTEM INTERFACE ${BOOST}) target_compile_definitions(${ARC} INTERFACE ${BOOST_PREPROCESSOR_DEFINITIONS}) target_compile_options(${ARC} INTERFACE ${BOOST_COMPILE_OPTIONS})
Interface library is an abstraction layer, not actual library and it provides any part of the project access to the boost static libraries, headers, preprocessors and compile options — It encapsulates all the complexity of using the library and these settings are packaged together and automatically propagated.
Summary
To build any library having it’s own build process via CMake, use a script (I used python script) which builds the library. Then, create a Interface library using CMake and link the compiled static libraries to it and set the headers, preprocessors definition and compile options as well, so that any part of the project can access the library via the Interface library without worrying about anything else.
FAQs
Why can't Interface library directly depends on static boost library, why there is a need for target?
Then if a target is built, and it is dependent on boost library, why are we linking it to the Interface library?
Subscribe to my newsletter
Read articles from Saurabh Singh Gautam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Saurabh Singh Gautam
Saurabh Singh Gautam
Software Engineer with 3+ years of experience in the tech industry. Proven ability to design, develop, and deliver high-quality software solutions. Expertise in a variety of programming languages and technologies, including C++, C#, Java, Azure, ReactJS. Strong problem-solving and analytical skills. Passionate about cyber security, artificial intelligence, and software engineering. Always looking for new ways to learn and grow. Strong advocate for diversity and inclusion in the tech industry, and I am always looking for ways to make the industry more welcoming to everyone.