This article is a part of a collection about open supply DevOps instruments for C/C++ improvement. If you construct up your venture from the start on a strong toolchain, you’ll profit from a quicker and safer improvement. Aside from that, will probably be simpler so that you can get others concerned in your venture. In this text, I’ll put together a C/C++ construct system based mostly on CMake and VSCodium. As ordinary, the associated instance code is obtainable on GitHub.
I’ve examined the steps described on this article. This is an answer for all platforms.
Why CMake?
CMake is a construct system generator that creates the Makefile in your venture. What sounds easy at first look could be fairly complicated at second look. At a excessive altitude, you outline the person elements of your venture (executables, libraries), compiling choices (C/C++ customary, optimizations, structure), the dependencies (header, libraries), and the venture construction on file stage. This info will get made out there to CMake within the file CMakeLists.txt
utilizing a particular description language. When CMake processes this file, it routinely detects the put in compilers in your programs and creates a working Makefile.
In addition, the configuration described within the CMakeLists.txt
could be learn by many editors like QtCreator, VSCodium/VSCode, or Visual Studio.
Sample program
Our pattern program is a straightforward command-line device: It takes an integer as an argument and outputs numbers randomly shuffled within the vary from one to the offered enter worth.
$ ./Producer 10
3 8 2 7 9 1 5 10 6 4
In the most important()
operate of our executable, we simply course of the enter parameter and exit this system if nobody worth (or a worth that may’t be processed) is offered.
producer.cpp
int most important(int argc, char** argv){if (argc != 2) {
std::cerr << "Enter the number of elements as argument" << std::endl;
return -1;
}int vary = 0;
attempt{
vary = std::stoi(argv[1]);
}catch (const std::invalid_argument&){
std::cerr << "Error: Cannot parse "" << argv[1] << "" ";
return -1;
}catch (const std::out_of_range&) {
std::cerr << "Error: " << argv[1] << " is out of range";
return -1;
}if (vary <= 0) {
std::cerr << "Error: Zero or negative number provided: " << argv[1];
return -1;
}std::stringstream information;
std::cout << Generator::generate(information, vary).rdbuf();
}
The precise work will get executed within the Generator, which is compiled and linked as a static library to our Producer
executable.
Generator.cpp
std::stringstream &Generator::generate(std::stringstream &stream, const int vary) {
std::vector<int> information(vary);
std::iota(information.start(), information.finish(), 1);std::random_device rd;
std::mt19937 g(rd());std::shuffle(information.start(), information.finish(), g);
for (const auto n : information) {
stream << std::to_string(n) << " ";
}return stream;
}
The operate generate
takes a reference to a std::stringstream and an integer as an argument. Based on the worth n of the integer vary
, a vector of integers within the vary of 1 to n is made and afterward shuffled. The values within the shuffled vector are then transformed right into a string and pushed into the stringstream
. The operate returns the identical stringstream
reference as handed as argument.
Top-level CMakeLists.txt
The top-level CMakeLists.txt is the entry level of our venture. There could be a number of CMakeLists.txt
recordsdata in subdirectories (for instance, libraries or different executables related to the venture). We begin by going step-by-step over the top-level CMakeLists.txt
.
The first traces inform us in regards to the model of CMake, which is required to course of the file, the venture identify, and its variations, in addition to the supposed C++ customary.
cmake_minimum_required(VERSION 3.14)venture(CPP_Testing_Sample VERSION 1.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
We inform CMake to look into the subdirectory Generator
with the next line. This subdirectory consists of all info to construct the Generator
library and incorporates a CMakeLists.txt
for its personal. We’ll get to that shortly.
add_subdirectory(Generator)
Now we come to an absolute particular function: CMake Modules. Loading modules can lengthen CMake performance. In our venture, we load the module FetchContent, which allows us to obtain exterior sources, in our case GoogleTest when CMake is run.
embody(FetchContent)FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/bb9216085fbbf193408653ced9e73c61e7766e80.zip
)
FetchContent_MakeAvailable(googletest)
In the subsequent half, we do what we’d normally do in an abnormal Makefile: Specify which binary to construct, their associated supply recordsdata, libraries which ought to be linked to, and the directories by which the compiler can discover the header recordsdata.
add_executable(Producer Producer.cpp)target_link_libraries(Producer PUBLIC Generator)
target_include_directories(Producer PUBLIC "${PROJECT_BINARY_DIR}")
With the next assertion, we get CMake to create a file within the construct folder known as compile_commands.json
. This file exposes the compile choices for each single file of the venture. Loaded in VSCodium, this file tells the IntelliSense function the place to seek out the header recordsdata (see documentation).
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
The final half defines the exams for our venture. The venture makes use of the beforehand loaded GoogleTest framework. The entire matter of unit exams shall be a part of a separate article.
enable_testing()add_executable(unit_test unit_test.cpp)
target_link_libraries(unit_test gtest_main)
embody(GoogleTest)
gtest_discover_tests(unit_test)
Library stage CMakeLists.txt
Now we have a look at the CMakeLists.txt file within the subdirectory Generator
containing the eponymous library. This CMakeLists.txt
is way shorter, and apart from the unit test-related instructions, it incorporates solely two statements.
add_library(Generator STATIC Generator.cpp Generator.h)target_include_directories(Generator INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
With add_library(...)
we outline a brand new construct goal: The static Generator
library. With the assertion target_include_directories(...)
, we add the present subdirectory to the search path for header recordsdata for different construct targets. We additionally specify the scope of this property to be of kind INTERFACE
: This signifies that the property will solely have an effect on construct targets that hyperlink in opposition to this library, not the library itself.
Get began with VSCodium
With the data out there within the CMakeLists.txt
, IDEs like VSCodium can configure the construct system accordingly. If you have not already expertise with VSCodium or VS Code, this instance venture is an efficient place to begin. First, go to their website and obtain the most recent set up bundle in your system. Open VSCodium and navigate to the Extensions tab.
To correctly construct, debug and check the venture, seek for the next extensions and set up them.
If not already executed, clone the repository by clicking on Clone Git Repository on the beginning web page.
Or manually by typing:
git clone https://github.com/hANSIc99/cpp_testing_sample.git
Afterward, try the tag devops_1 both by typing:
git checkout tags/devops_1
Or by clicking on the most important department button (pink field) and choosing the tag from the drop-down menu (yellow field).
Once you open the repository’s root folder inside VSCodium, the CMake Tools
extensions detect the CMakeLists.txt
file and instantly scan your system for appropriate compilers. You can now click on on the Build button on the backside of the display screen (pink field) to begin the construct course of. You may change the compiler by clicking on the realm on the backside (yellow field) mark, which exhibits the presently lively compiler.
To begin debugging the Producer
executable, click on on the debugger image (yellow field) and select Debug Producer (inexperienced field) from the drop-down menu.
As beforehand talked about, the Producer
executable expects the variety of components as a command-line argument. The command-line argument could be specified within the file .vscode/launch.json.
Alright, you at the moment are in a position to construct and debug the venture.
Conclusion
Thanks to CMake, the above steps ought to work it doesn’t matter what OS you are working. Especially with the CMake-related extensions, VSCodium turns into a strong IDE. I did not point out the Git integration of VSCodium as a result of you’ll be able to already discover many sources on the internet. I hope you see that offering a correct CMake configuration makes it a lot simpler for others to construct, use and contribute to your venture. In a future article, I’ll have a look at unit exams and CMake’s testing utility ctest
.