Science and technology

Arrange a construct system with CMake and VSCodium

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.

Most Popular

To Top