DEV Community

Roy J. Wignarajah
Roy J. Wignarajah

Posted on

How I Added Continuous Integration (CI) to a C++ Project

Managing Project Complexity with CI Pipelines

For this week in my Open Source Class we looked into adding Continuous Integration pipelines to our projects. Last week I added unit tests using the Google Test testing framework. However, at this point, testing will only run if me and other developers remember to run them. What if someone forgets to run the tests before pushing new code or merging a pull request, or what if new code breaks those tests?

Continuous Integration

Continuous Integration, or CI, is one method of ensuring that new or modified code does not break our tests. With CI, a project can be automatically built and tested whenever something is pushed to a repo or when a pull request is made. This is done continually and helps monitor the effect of code changes.

GitHub Actions - GitHub's CI service

CI requires dedicated machines to checkout our code, built it and run tests. We can either setup our own machines, or we can provision a CI cloud provider to do this for us. GitHub actually provides its own CI service, GitHub Actions, that lets you automate workflows to GitHub repo events, like making a pull request or merging to a main branch.

Lab Exercise - Add a CI Workflow

For this lab exercise I used GitHub actions to add a CI workflow. Based on the language(s) used in your repo, GitHub will suggest possible workflows:

Image description

Workflow Templates - MSBuild-based projects (for Visual Studio)

I used a workflow template for MSBuild-based projects. When doing this lab exercise I referred to this video by TheCherno, who used the same template for his Hazel Game Engine developed using Visual Studio. The Microsoft Build Engine, MSBuild, is what Visual Studio uses to load and build managed projects. Since I'm also developing my project using Visual Studio, this template seemed like the best option.

Fine-Tuning my First CI Workflow

After adding the workflow template, I had a couple hiccups that I had to solve.

MSBUILD : Error MSB1050 - Cause

After adding the template, my first build failed due to the following error:

Image description

MSBUILD : error MSB1050: Specify which project or solution file
to use because the folder "." contains more than
one project or solution file.
Enter fullscreen mode Exit fullscreen mode

This error made sense. The root of my project has multiple solution (.sln) and project (.vcxproj) files.

MSBUILD : Error MSB1050 - Solution

I solved this issue by specifying the project file containing my solution:

Cannot Locate Executable (.exe) - Cause

I wanted to add a job to my workflow that builds and runs the Google Test solution, testLibrary, but couldn't locate the executable:

Image description

Cannot Locate Executable (.exe) - Solution

I knew running msbuild would create an executable that would run my tests, but I didn't know where to locate it. I found this stackoverflow post that taught me how to locate the executable.
In short:

  • msbuild generates a folder containing the executable file.
  • by running ls in the workflow, I was able to locate the testLibrary.exe executable and run it from my workflow:

Final Workflow file

In the end, my final workflow file was similar to the original template but with a few jobs added to suit my needs.

Adding Tests to a Classmate's project

For this lab exercise I had the opportunity to add unit tests to a classmate's project and experience their CI workflow. For this exercise I worked on go-go-web by kliu57. Go-Go Web is written in Python and uses the pytest testing framework. This was my first time writing tests for pytest, but I found the pytest docs helpful. However, more helpful was the information provided in the associated issue and the tests already written, which helped me write the test I needed in the author's preferences.

My Thoughts on adding CI to a C++ project

Before starting this exercise, I was intimidated by this task. I was aware of the value of adding it, but I was scared adding CI would take hours. Adding CI itself didn't take very long (although debugging my workflow did). However, I've now added a valuable tool that will always provide value to my project's development and save time, and I think I'll have a better time adding CI in the future.

Future Changes

Two optional objectives for this exercise were to add my linter to my CI workflow and to set up a Dev Container in GitHub Codespaces that would make it simple for new developers to work on my project.

I chose to skip these changes for now due to class commitments. However, I plan to add these in the future.

Top comments (0)