> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/continuous-integration/troubleshooting-and-resources/tutorials-and-code-samples/ci-c.md).

# C/C++

You can build and test C and C++ applications on [Harness Cloud](/continuous-integration/use-harness-ci/use-harness-ci/set-up-build-infrastructure/use-harness-cloud-build-infrastructure.md) or a [self-managed Kubernetes cluster](/continuous-integration/use-harness-ci/use-harness-ci/set-up-build-infrastructure/k8s-build-infrastructure.md) build infrastructure. This guide uses a Linux platform, but you can also use macOS and Windows platforms with Harness.

This guide assumes you've [created a Harness CI pipeline](/continuous-integration/use-harness-ci/use-harness-ci/prep-ci-pipeline-components.md).

### Install dependencies <a href="#install-dependencies" id="install-dependencies"></a>

Use [Run steps](/continuous-integration/use-harness-ci/use-harness-ci/run-step-settings.md) to install dependencies in the build environment.

You can run any commands in Run steps as long as the necessary binaries are available on the host machine or the referenced container image. For example, you can run cURL commands, build commands for CMake, Ninja, or MSBuild, or any other commands you might otherwise run on the command line.

In the following YAML example, the Run step runs a Python script to get dependencies for a C++ project. It uses a [matrix looping strategy](/harness-ai/use-harness-platform/pipelines/looping-strategies/looping-strategies-matrix-repeat-and-parallelism.md) to cycle through each dependency.

{% tabs %}
{% tab title="Harness Cloud" %}

```yaml
- step:
    type: Run
    name: Fetch Deps
    identifier: Fetch_Deps
    spec:
      shell: Sh
      command: python3 build/getdeps.py fetch --no-tests <+matrix.deps>
    failureStrategies: []
    strategy:
      matrix:
        deps:
          - ninja
          - cmake
          - zlib
          - zstd
          - boost
          - double-conversion
          - fmt
          - gflags
          - glog
          - googletest
          - libevent
        maxConcurrency: 1
```

{% endtab %}

{% tab title="Self-managed" %}

```yaml
- step:
    type: Run
    name: Fetch Deps
    identifier: Fetch_Deps
    spec:
      connectorRef: YOUR_IMAGE_REGISTRY_CONNECTOR
      image: python:latest
      shell: Sh
      command: python3 build/getdeps.py fetch --no-tests <+matrix.deps>
    failureStrategies: []
    strategy:
      matrix:
        deps:
          - ninja
          - cmake
          - zlib
          - zstd
          - boost
          - double-conversion
          - fmt
          - gflags
          - glog
          - googletest
          - libevent
        maxConcurrency: 1
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
In addition to Run steps, [Plugin steps](/continuous-integration/use-harness-ci/use-harness-ci/use-drone-plugins/explore-ci-plugins.md) are also useful for installing dependencies.

You can use [Background steps](/continuous-integration/use-harness-ci/use-harness-ci/manage-dependencies/background-step-settings.md) to run dependent services that are needed by multiple steps in the same stage.
{% endhint %}

### Cache dependencies <a href="#cache-dependencies" id="cache-dependencies"></a>

{% tabs %}
{% tab title="Cache Intelligence" %}
Cache your C and C++ dependencies with [Cache Intelligence](/continuous-integration/use-harness-ci/use-harness-ci/caching-ci-data/cache-intelligence.md).

Add `caching.enabled.true` to your `stage.spec`:

```yaml
- stage:
    spec:
      caching:
        enabled: true
```

{% endtab %}

{% tab title="Save and Restore Cache steps" %}
You can use built-in steps to:

* [Save and Restore Cache from S3](/continuous-integration/use-harness-ci/use-harness-ci/caching-ci-data/saving-cache.md)
* [Save and Restore Cache from GCS](/continuous-integration/use-harness-ci/use-harness-ci/caching-ci-data/save-cache-in-gcs.md)

Here's an example of a pipeline with **Save Cache to S3** and **Restore Cache from S3** steps.

```yaml
            steps:
              - step:
                  type: RestoreCacheS3
                  name: Restore Cache From S3
                  identifier: Restore_Cache_From_S3
                  spec:
                    connectorRef: AWS_Connector
                    region: us-east-1
                    bucket: your-s3-bucket
                    key: cache-{{ checksum "pom.xml" }}
                    archiveFormat: Tar
              - step:
                  type: Run
                  ...
              - step:
                  type: BuildAndPushDockerRegistry
                  ...
              - step:
                  type: SaveCacheS3
                  name: Save Cache to S3
                  identifier: Save_Cache_to_S3
                  spec:
                    connectorRef: AWS_Connector
                    region: us-east-1
                    bucket: your-s3-bucket
                    key: cache-{{ checksum "pom.xml" }}
                    sourcePaths:
                      - /root/.m2
                    archiveFormat: Tar
```

{% endtab %}
{% endtabs %}

### Build and run tests <a href="#build-and-run-tests" id="build-and-run-tests"></a>

You can use **Run** steps to [run tests in CI pipelines](/continuous-integration/use-harness-ci/use-harness-ci/run-tests/run-tests-in-ci.md).

{% tabs %}
{% tab title="Harness cloud" %}

```yaml
- step:
    type: Run
    name: build and test
    identifier: build and test
    spec:
      shell: Sh
      command: |-
        cmake -S . -B build
        ctest --test-dir $FILES --output-junit /target/reports/test_output.xml
```

{% endtab %}

{% tab title="Self-managed" %}

```yaml
- step:
    type: Run
    name: build and test
    identifier: build and test
    spec:
      connectorRef: YOUR_IMAGE_REGISTRY_CONNECTOR
      image: gradle:alpine
      shell: Sh
      command: |
        cmake -S . -B build
        ctest --test-dir $FILES --output-junit /target/reports/test_output.xml
```

{% endtab %}
{% endtabs %}

#### Visualize test results <a href="#visualize-test-results" id="visualize-test-results"></a>

If you want to [view test results in Harness](/continuous-integration/use-harness-ci/use-harness-ci/run-tests/viewing-tests.md), make sure your test commands produce reports in JUnit XML format and that your steps include the `reports` specification.

```yaml
reports:
  type: JUnit
  spec:
    paths:
      - target/reports/*.xml
```

#### Test splitting <a href="#test-splitting" id="test-splitting"></a>

Harness CI supports [test splitting (parallelism)](/continuous-integration/use-harness-ci/use-harness-ci/run-tests/speed-up-ci-test-pipelines-using-parallelism.md) in **Run** steps.

### Specify version <a href="#specify-version" id="specify-version"></a>

{% tabs %}
{% tab title="Harness Cloud" %}
CLang and GNU C++ are pre-installed on Harness Cloud runners. For details about all available tools and versions, go to [Platforms and image specifications](/continuous-integration/use-harness-ci/use-harness-ci/set-up-build-infrastructure/use-harness-cloud-build-infrastructure.md#platforms-and-image-specifications).

If you want to use a different compiler or a specific version of a compiler, you can use a **Run** step to install it, for example:

```yaml
- step:
    type: Run
    name: install
    identifier: install
    spec:
      shell: Sh
      command: |
        sudo apt update
        sudo apt install g++-12
```

{% endtab %}

{% tab title="Self-managed" %}
You can use a **Run** step to install compilers, such as CLang or GNU C++, if they are not already installed on your host machine, for example:

```yaml
- step:
    type: Run
    name: install
    identifier: install
    spec:
      connectorRef:
      image:
      shell: Sh
      command: |
        sudo apt update
        sudo apt install g++
```

{% endtab %}
{% endtabs %}

### Full pipeline examples <a href="#full-pipeline-examples" id="full-pipeline-examples"></a>

Here's a YAML example of a pipeline that builds a C application and pushes the image to Docker Hub.

This pipeline uses [Harness Cloud build infrastructure](/continuous-integration/use-harness-ci/use-harness-ci/set-up-build-infrastructure/use-harness-cloud-build-infrastructure.md) and [Cache Intelligence](/continuous-integration/use-harness-ci/use-harness-ci/caching-ci-data/cache-intelligence.md).

<details>

<summary>Pipeline YAML</summary>

```yaml
pipeline:
  name: Build C
  identifier: Build_C
  projectIdentifier: default
  orgIdentifier: default
  properties:
    ci:
      codebase:
        connectorRef: YOUR_CODE_REPO_CONNECTOR_ID
        repoName: YOUR_REPO_NAME
        build: <+input>
  stages:
    - stage:
        name: Build
        identifier: Build
        description: ""
        type: CI
        spec:
          caching:
            enabled: true
          cloneCodebase: true
          platform:
            os: Linux
            arch: Amd64
          runtime:
            type: Cloud
            spec: {}
          execution:
            steps:
              - step:
                  type: Run
                  name: Run_1
                  identifier: Run_1
                  spec:
                    shell: Bash
                    command: |-
                      chmod 777 ./scripts/docker/build.sh
                      ./scripts/docker/build.sh --bionic --remote PROJECT test_PROJECT
              - step:
                  type: BuildAndPushDockerRegistry
                  name: BuildAndPushDockerRegistry_1
                  identifier: BuildAndPushDockerRegistry_1
                  spec:
                    connectorRef: YOUR_DOCKER_CONNECTOR_ID
                    repo: YOUR_DOCKER_HUB_USERNAME/DOCKER_REPO_NAME
                    tags:
                      - <+pipeline.sequenceId>
```

</details>

### Next steps <a href="#next-steps" id="next-steps"></a>

Now that you have created a pipeline that builds and tests a C or C++ app, you could:

* Create [triggers](/harness-ai/use-harness-platform/triggers.md) to automatically run your pipeline.
* Add steps to [build and upload artifacts](/continuous-integration/use-harness-ci/use-harness-ci/build-and-upload-artifacts.md).
* Add a step to [build and push an image to a Docker registry](/continuous-integration/use-harness-ci/use-harness-ci/build-and-upload-artifacts/build-and-push/build-and-push-to-docker-registry.md).
