# Colcon 빌드 옵션

#### Colcon 기본 개념

ROS2 Humble 환경에서 여러 패키지를 동시에 빌드하고 관리하기 위해서는 Colcon 빌드 툴을 주로 사용한다. Colcon은 ROS1 시절의 catkin\_tools나 catkin\_make\_isolated와 유사하지만, ROS2 전용으로 설계되었으며 더 범용적으로 확장 가능하다. 여러 패키지를 한 번에 빌드하며, 각 패키지의 빌드 시스템(예: CMake, ament\_cmake, Python setup.py 등)에 맞춰 자동으로 빌드 과정을 진행한다.

Colcon은 기본적으로 아래 명령으로 사용한다.

```
colcon build
```

다만 이 명령만으로는 사용자의 다양한 요구사항(병렬 빌드 수준 조정, 결과물 설치 경로, 빌드 출력 형식, 의존성 처리 등)을 모두 해결하기 어렵다. 따라서 추가적으로 다양한 옵션을 제공하며, 개발자는 이 옵션들을 활용하여 빌드 과정을 세밀하게 제어할 수 있다.

#### 병렬 빌드 옵션

**- 병렬 빌드의 필요성**

다수의 패키지를 빌드할 때, 단일 코어로 빌드하는 것은 시간 소요가 크게 늘어나게 된다. 동시에 여러 코어를 활용하면 빌드 시간을 단축할 수 있다. Colcon은 병렬 빌드를 지원하여, 가능한 코어를 활용해 빌드 속도를 높인다.

**`--parallel-workers`**

Colcon에서는 기본적으로 시스템 내 코어 수를 자동으로 감지하여 병렬 빌드를 수행한다. 하지만 특정 코어 수로 제한하고 싶거나, 빌드 중 발생하는 CPU 사용률을 조정하고 싶다면 `--parallel-workers` 옵션을 사용한다.

```
colcon build --parallel-workers <N>
```

위 명령에서 `<N>`은 동시에 빌드를 실행할 쓰레드(또는 코어)의 개수를 의미한다. 예를 들어 4개의 코어만 사용하려면 다음과 같이 실행한다.

```
colcon build --parallel-workers 4
```

만약 시스템에서 8코어를 제공하지만, 다른 작업과 병행해야 해서 빌드에 4코어만 할당하고 싶다면 적절한 값으로 조정할 수 있다. 이 옵션은 ROS2 패키지가 많을 때 빌드 시간을 극적으로 단축시키는 중요한 설정이다.

**`--executor`**

Colcon은 빌드 과정에서 여러 패키지를 병렬로 빌드할 때 ‘executor(실행자)’ 방식을 설정할 수도 있다. 예를 들어, `--executor sequential` 옵션은 패키지를 순차적으로 빌드하여 디버그가 용이하게 만들 수 있다.

```
colcon build --executor sequential
```

이 경우 병렬로 빌드하지 않고 1개 패키지씩 순차적으로 빌드한다. 디버깅이 필요한 상황이나, 빌드 순서를 엄격하게 통제해야 하는 상황에서 사용할 수 있다.

**실제 동작 원리**

Colcon은 패키지 간 의존 관계를 분석하여 서로 간 의존이 없는 패키지는 동시에 빌드한다. 가령, 패키지 A가 B에 의존하지만, C와는 독립적이라면, A와 C는 병렬 빌드가 가능하지만, B는 A가 빌드된 이후에 빌드 과정을 시작한다. 이와 같은 병렬 처리는 내부적으로 Directed Acyclic Graph(DAG)를 구성한 뒤 topological sort를 수행하여 빌드 순서를 결정한다.

의존성을 그래프로 표현하면 다음과 같이 그릴 수 있다.

{% @mermaid/diagram content="graph LR
B --> A
C --> A
A --> D" %}

* B, C → A → D 위 그래프에서 B와 C는 독립적이므로 서로 병렬 빌드가 가능하다. A는 B와 C가 모두 빌드 완료된 후에 빌드된다. 그 후 D가 빌드된다.

이 과정을 Colcon은 자체 알고리즘으로 자동으로 수행하며, 병렬 빌드 옵션을 통해 작업자(워커) 수 등을 조정하여 빌드 시간을 줄일 수 있다.

#### 설치 경로 옵션

**기본 설치 위치**

Colcon은 기본적으로 빌드 결과물을 `install` 디렉터리에 설치한다. 이 경로는 ROS2 워크스페이스 내에서 표준으로 사용되며, `colcon build` 명령으로 빌드하고 `source install/setup.bash` 명령으로 환경 변수를 적용하는 형태가 가장 일반적이다.

패키지를 빌드하면, 해당 패키지에서 생성된 바이너리, 라이브러리, 헤더, 메시지/서비스 등 다양한 결과물이 `install/<패키지이름>` 하위에 위치하게 된다. 또한 패키지마다 고유한 구조를 가지지만, 대부분 ament\_cmake 방식의 패키지는 `install/lib` 또는 `install/include` 등과 같은 디렉터리에 결과물이 배치된다.

**`--merge-install`**

Colcon에서는 ROS1의 catkin 구조와 유사하게, 패키지별로 구분 없이 전체 바이너리, 라이브러리, 헤더 등을 하나의 디렉터리에 모을 수도 있다. 이를 위해 `--merge-install` 옵션을 사용한다.

```
colcon build --merge-install
```

이 옵션을 주면, 각 패키지의 출력물은 패키지별 하위 폴더가 아니라, 전역 디렉터리(예: `install/lib`, `install/include` 등)에 직접 배치된다. 이때 패키지 이름을 접두사로 붙여 파일을 구분하기도 하며, 패키지별 분리가 엄격하게 필요하지 않다면 작업 효율 측면에서 유리할 수 있다.

**`--install-base`**

설치 디렉터리를 변경하고 싶다면 `--install-base` 옵션으로 경로를 지정할 수 있다.

```
colcon build --install-base /custom/install/path
```

이렇게 하면 빌드 결과물(설치 파일들)이 `/custom/install/path` 디렉터리에 배치된다. 별도의 디렉터리를 사용하여 워크스페이스를 분할하거나, 여러 버전의 ROS2를 동시에 설치해야 할 때 유용하게 쓰일 수 있다.

#### 빌드 출력 형식 옵션

Colcon은 빌드 중 출력되는 로그를 보기 좋게 정리하는 기능을 제공한다. 특히 병렬 빌드 시에 여러 패키지가 동시에 로그를 남기면, 터미널에서 확인하기가 번잡해질 수 있다. 이러한 상황을 위해 여러 형태의 이벤트 핸들러를 제공하며, 이를 통해 빌드 로그를 한 번에 확인하거나 개별 패키지별로 구분해서 확인할 수 있다.

**`--event-handlers`**

Colcon에서 빌드 이벤트(빌드 시작, 빌드 성공/실패, 경고, 오류 등)가 발생할 때 처리 방식을 지정하기 위해 `--event-handlers` 옵션을 사용한다. 예를 들어, 빌드 결과를 요약해서 보여주는 `console_cohesion+` 핸들러나, 빌드 중 발생한 모든 로그를 한꺼번에 모아서 보여주는 `log` 핸들러 등을 조합해서 쓸 수 있다.

```
colcon build --event-handlers console_cohesion+ --merge-install
```

위와 같은 명령으로 빌드하면, 패키지 빌드 과정에서 터미널에 불필요하게 출력이 뒤섞이지 않고, 빌드 완료 시점에 한꺼번에 빌드 로그를 확인할 수 있다.

* **console\_direct+**: 빌드 과정 메시지를 즉시 출력한다. (병렬 빌드시 로그가 섞일 수 있음)
* **console\_cohesion+**: 병렬 빌드 중에도 한 패키지의 빌드가 끝날 때까지 로그 출력을 모아서 보여준다.
* **log**: 패키지 빌드 단계마다 로그를 별도의 파일로 남긴다.

사용자는 상황에 맞게 적절한 이벤트 핸들러를 조합할 수 있다. 복수의 핸들러를 지정할 때는 콤마(,)나 공백 대신 `+`를 이용해 연달아 표기한다.

#### `--build-base`

Colcon은 빌드 결과물을 중간 단계와 최종 설치 단계로 구분해서 저장한다. 중간 빌드 산출물(예: 오브젝트 파일, 임시 파일 등)은 보통 `build` 디렉터리에 생성된다. 이 경로를 바꾸고 싶다면 `--build-base` 옵션을 사용한다.

```
colcon build --build-base /tmp/my_build_dir
```

이처럼 중간 빌드 디렉터리를 변경해두면, 최종 설치 경로와 분리하여 빌드 산출물을 관리하기가 수월하다. 다만 일반적으로는 `build` 디렉터리를 그대로 두는 경우가 많다.

#### `--packages-up-to`

Colcon은 특정 패키지에 필요한 의존 패키지만 골라서 빌드할 수 있는 `--packages-up-to` 옵션을 제공한다. 예를 들어, 패키지 `my_robot_driver`와 그 의존 패키지들만 빌드하고 싶다면 다음처럼 사용한다.

```
colcon build --packages-up-to my_robot_driver
```

이 명령은 `my_robot_driver` 패키지를 빌드하기 위해 필요한 모든 상위 의존 패키지를 함께 빌드하지만, 그 외 패키지(예: 전혀 상관없는 시뮬레이션 패키지 등)는 빌드하지 않는다. 이 방식은 작업 중인 패키지와 직간접적 의존 패키지만 빌드하기 때문에, 불필요한 빌드 시간을 줄일 수 있다.

#### `--packages-select / --packages-ignore`

특정 패키지만 선택해서 빌드하거나, 특정 패키지를 빌드 대상에서 제외하려면 각각 `--packages-select`, `--packages-ignore` 옵션을 사용한다.

* **--packages-select**: 지정한 패키지만 빌드 (의존성 고려 없이 선택된 패키지만 빌드)
* **--packages-ignore**: 지정한 패키지를 빌드 대상에서 제외

예를 들어, `nav2_bringup` 패키지와 `nav2_costmap_2d` 패키지만 빌드하려면,

```
colcon build --packages-select nav2_bringup nav2_costmap_2d
```

또는 LIDAR 관련 패키지들만 빌드하고 싶고, 특정 패키지(예: rviz2)를 빌드에서 제외하려면,

```
colcon build --packages-select my_lidar_pkg other_lidar_pkg --packages-ignore rviz2
```

이렇게 선택적으로 빌드할 수 있다.

#### `--cmake-args`

CMake 기반 빌드 시스템(예: ament\_cmake)의 패키지에 대해, CMake 인자를 직접 전달하려면 `--cmake-args` 옵션을 사용한다. 예를 들어, CMake 단계에서 특정 변수를 켜거나 끄고 싶을 때 유용하다.

```
colcon build --cmake-args -DWITH_MY_FEATURE=ON -DCMAKE_BUILD_TYPE=Debug
```

Colcon은 내부적으로 각 패키지 빌드 시점에 `--cmake-args`에 전달된 인자를 CMake에 넘겨준다. 위 예시처럼 디버그 빌드 설정(`-DCMAKE_BUILD_TYPE=Debug`)과 특정 기능을 활성화/비활성화하는 옵션(`-DWITH_MY_FEATURE=ON`)을 한 번에 지정할 수 있다.

#### `--continue-on-error`

여러 패키지를 빌드하는 도중 오류가 발생했을 때, Colcon은 기본적으로 빌드를 중단한다. 하지만 `--continue-on-error` 옵션을 사용하면, 해당 패키지는 실패 처리가 되지만 그 외에 독립적인 다른 패키지에 대해서는 빌드를 계속 진행한다.

```
colcon build --continue-on-error
```

이 기능은 대규모 프로젝트에서 특정 패키지 하나가 실패해도, 다른 패키지 빌드를 진행하고 싶을 때 유용하다. 실패한 패키지는 최종 빌드 결과에서 제외되며, Colcon은 마지막에 어떤 패키지가 실패했는지 표시한다.

#### `--symlink-install`

Colcon은 설치 과정에서 파일을 실제로 복사(혹은 생성)하는 대신 심볼릭 링크를 생성하여 개발 편의성을 높일 수 있는 `--symlink-install` 옵션을 지원한다. 심볼릭 링크를 쓰면, 빌드 후 코드 수정 시 재빌드가 훨씬 빨라질 수 있다. 특히 메시지, 라이브러리 등이 서로 참조되는 대규모 프로젝트에서 유용하다.

```
colcon build --symlink-install
```

* **장점**:
  * 빌드 후 결과물을 바로 편집하거나, 패키지 디렉터리를 변경하면 심볼릭 링크를 통해 즉시 반영된다.
  * 개발 중 잦은 수정·빌드 과정을 반복할 때 효율적이다.
* **단점**:
  * 배포 환경에서 심볼릭 링크를 사용하면, 링크 깨짐 문제(심볼릭 링크가 가리키는 실제 파일이 바뀌거나 삭제됨) 등이 발생할 수 있다.
  * 러닝 시스템(예: 임베디드)에서 심볼릭 링크가 비표준이거나 제한되는 경우도 있으므로 주의가 필요하다.

#### 환경 변수 활용

Colcon 빌드 옵션과 함께, make나 CMake 등의 빌드 도구를 제어하는 다양한 환경 변수를 사용할 수도 있다. 예를 들어 `$MAKEFLAGS`, `$MAKE_OPTIONS` 같은 변수를 설정하면, Colcon 내부적으로 CMake가 Make를 호출할 때 해당 옵션이 전달된다.

* **$MAKEFLAGS**
  * GNU Make에서 병렬 빌드를 위한 `-jN` 옵션이나, 에러 발생 시 중단하는 `-k` 옵션 등을 지정할 수 있다.
  * Colcon에서 `--parallel-workers` 옵션을 대신 사용할 수도 있지만, 더 세부적인 make 동작을 제어하기 위해 사용하기도 한다.
* **$CMAKE\_PREFIX\_PATH**
  * ROS2 워크스페이스 외에 추가 라이브러리가 위치한 경로를 지정할 수 있다.
  * 예: $CMAKE\_PREFIX\_PATH에 `/usr/local/my_lib` 경로를 추가하면 CMake에서 해당 경로를 우선적으로 검색한다.
* **$LD\_LIBRARY\_PATH**
  * 런타임에 라이브러리를 찾는 경로를 지정한다.
  * 빌드 후, ROS2 노드 실행 시 동적으로 로드되는 라이브러리가 위치하는 디렉터리를 등록할 수 있다.

이러한 환경 변수들은 Colcon에서 직접적으로 제어하는 옵션이 아니라, 빌드 툴 체인(Make, Ninja, CMake, ament\_cmake 등)에 영향을 주는 역할을 한다. Colcon을 통해 세분화된 빌드 설정을 하려면, 필요한 환경 변수를 적절히 설정한 뒤 `colcon build`를 실행하면 된다.

#### `--cmake-target / --make-target`

Colcon 빌드를 수행할 때, 특정 빌드 타깃(target)만 실행하고 싶으면 `--cmake-target`(CMake 기반) 또는 `--make-target`(Makefile 기반) 옵션을 사용한다. 이 옵션은 패키지 전체를 빌드하지 않고도 특정 테스크(예: install, clean, tests 등)만 수행할 수 있는 방법을 제공한다.

**CMake 기반 예시**:

```
colcon build --cmake-target install
```

해당 명령은 각 패키지의 CMake 프로젝트에서 ‘install’ 타깃만 수행한다. 즉, 이미 빌드된 결과물이 있을 때, 굳이 다시 빌드하지 않고 설치 과정만 실행한다.

**Makefile 기반 예시**:

```
colcon build --make-target clean
```

해당 명령은 Makefile에 정의된 ‘clean’ 타깃을 실행하여 이전 빌드 산출물을 정리한다.

단, 이 옵션들은 모든 패키지 유형에서 동일하게 동작하지는 않는다. ament\_cmake 기반 패키지는 대부분 CMake 작업을 수행하므로 `--cmake-target`을, Python setup.py 기반 패키지는 해당 옵션이 무용할 수 있다.

#### `--test-result-base`

Colcon에서는 빌드와 동시에 테스트를 수행할 수 있으며(`colcon test`), 그 결과물(예: 테스트 로그, 결과 파일)을 저장할 위치를 지정하기 위해 `--test-result-base` 옵션을 사용하기도 한다.

```
colcon build --test-result-base /custom/test_results
```

물론 일반적으로 테스트는 `colcon build` 후에 `colcon test`를 통해 별도로 실행하는 방식으로 쓰이지만, CI/CD 파이프라인 구성 등에서 빌드와 테스트 결과 경로를 일관성 있게 유지하기 위해 유용할 수 있다.

#### Colcon mixin 활용

Colcon에서는 자주 쓰는 빌드 옵션의 집합을 “mixin”으로 만들어 재사용할 수 있다. 예를 들어, 디버그 빌드에 사용되는 모든 옵션을 한꺼번에 정리해두고 싶다면 아래와 같은 mixin 파일(예: `debug.mixin.yaml`)을 구성할 수 있다.

```yaml
debug:
  build:
    cmake-args:
      - "-DCMAKE_BUILD_TYPE=Debug"
    event-handlers:
      - console_cohesion+
```

이렇게 만든 mixin을 등록해두고 나면, 아래 명령으로 손쉽게 디버그 빌드를 실행할 수 있다.

```
colcon build --mixin debug
```

mixin 기능을 통해 자주 사용하는 빌드 옵션들을 프로젝트나 팀 차원에서 공유하면, 빌드 환경을 빠르고 일관되게 구성할 수 있다는 장점이 있다.

#### 캐시 활용 (ccache)

ROS2 프로젝트 빌드 시, 변경되지 않은 코드를 매번 새로 컴파일하는 것은 시간 낭비다. 이를 줄이기 위해 **ccache**(C/C++ 컴파일 결과를 캐시하는 툴)를 사용할 수 있다. Colcon에서 직접 ccache를 제어하는 옵션은 없지만, CMake 인자를 활용하면 손쉽게 적용 가능하다.

**ccache 설치**:

* Ubuntu 계열:

```
sudo apt-get update
sudo apt-get install ccache
```

* 설치 후, 다음처럼 확인 가능:

```
ccache --version
```

* `$HOME/.cache/ccache` 등지에 캐시가 쌓이며, 컴파일 결과가 재사용된다.

**ccache 적용**:

* 일반적으로 CMake에서 `CCACHE`를 적용하려면 `CMAKE_CXX_COMPILER_LAUNCHER`와 `CMAKE_C_COMPILER_LAUNCHER`를 설정한다.
* Colcon에서는 `--cmake-args`를 통해 아래와 같은 인자를 넘길 수 있다.

```
colcon build \
  --cmake-args \
    -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
    -DCMAKE_C_COMPILER_LAUNCHER=ccache
```

* 이렇게 설정하면, C++ 컴파일 시 `g++` 대신 `ccache g++`, C 컴파일 시 `gcc` 대신 `ccache gcc`를 사용하여 캐시가 자동으로 생성된다.

**효과 확인**:

* 첫 빌드 후, 두 번째 빌드에서 변경 사항이 없으면 ‘cache hit’이 증가하는 것을 확인할 수 있다.
* 캐시 경로나 최대 용량 등은 `ccache --show-stats`, `ccache --max-size` 명령어로 관리 가능하다.

#### 크로스 컴파일 (Cross-compiling)

ROS2 패키지를 임베디드 환경이나 ARM 보드(예: Raspberry Pi)에서 구동하려면, 데스크톱 머신(x86\_64)에서 **크로스 컴파일**을 수행해야 할 수 있다. Colcon은 내부적으로 CMake나 ament\_cmake 등을 호출하므로, “toolchain 파일” 등을 통해 손쉽게 크로스 컴파일을 진행할 수 있다.

**툴체인 파일 작성**:

* 일반적으로 `$project_root/toolchain.cmake` 등으로 이름을 지정하고, 다음과 같은 내용을 포함한다.

```cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
# 필요한 설정 추가...
```

* 실제로 사용하는 ARM GCC 컴파일러의 경로나 타겟 아키텍처에 맞춰 수정한다.

**Colcon 빌드 명령**:

* 만들어둔 툴체인 파일을 CMake 인자로 넘긴다.

```
colcon build \
  --merge-install \
  --cmake-args \
    -DCMAKE_TOOLCHAIN_FILE=path/to/toolchain.cmake \
    -DCMAKE_BUILD_TYPE=Release
```

* 이렇게 하면 CMake가 지정된 컴파일러로 빌드 과정을 수행하므로, 빌드 산출물은 ARM 아키텍처용 바이너리가 된다.

**주의 사항**:

* ROS2 의존 라이브러리(예: rmw, rclcpp 등) 역시 해당 아키텍처용이 필요하므로, 호환되는 크로스 컴파일 환경(예: sysroot, cross-compiled library 등)을 준비해야 한다.
* Colcon만으로 모든 준비가 자동화되는 것은 아니며, 사용자 환경에 맞춰 CMake 설정 및 종속 라이브러리 경로를 꼼꼼히 지정해야 한다.

#### Colcon list / graph

Colcon은 빌드 외에도 **패키지 구조**를 시각적으로 파악할 수 있는 명령을 제공한다.

**colcon list**:

```
colcon list
```

워크스페이스에 포함된 모든 패키지와 빌드 타입(ament\_cmake, python, etc.)을 나열한다. 패키지 이름, 경로, 빌드 유형 등을 빠르게 확인할 수 있다.

**colcon graph**:

```
colcon graph
```

패키지 간 의존 관계를 텍스트 형태로 시각화해준다. 예를 들어, 특정 패키지가 어떤 패키지에 의존하는지, 어떤 계층 구조를 갖는지 등을 한눈에 확인할 수 있다.

* `--dot` 옵션을 붙여 그래프 정보를 DOT 포맷으로 출력하면, `dot` 커맨드(그래프비즈)로 PDF나 이미지로 변환 가능하다.
* 예:

  ```
  colcon graph --dot | dot -Tpdf > ros2_dep_graph.pdf
  ```

#### Colcon test / test-result

여러 패키지를 빌드한 뒤, 테스트를 실행하고 결과를 확인하기 위해선 다음 명령을 사용할 수 있다.

**테스트 실행**:

```
colcon test
```

* 빌드 시점에 테스트를 수행하지 않고, 별도로 실행하는 명령이다.
* 모든 패키지에 대해 자동화된 단위 테스트, 통합 테스트 등을 수행한다.

**테스트 결과 확인**:

```
colcon test-result
```

* 각 패키지별 테스트 결과(성공/실패/스킵 등)를 요약해서 보여준다.
* `--all` 옵션을 붙이면 세부 로그를 더 자세히 볼 수 있다.

예:

```
colcon test-result --all
```

**자동화**:

* CI/CD 파이프라인에서 `colcon build -> colcon test -> colcon test-result` 과정을 순차적으로 실행해 테스트 성공 여부를 검사할 수 있다.
* `--test-result-base` 옵션 등을 통해 테스트 로그가 저장될 경로를 지정할 수 있다(앞서 설명).

#### 더 알아보기

* **colcon run**: 빌드된 실행 파일(ROS2 노드)을 직접 실행할 수도 있다. (주로 `ros2 run` 명령을 쓰지만, colcon도 실험적으로 `colcon run`을 지원)
* **colcon extensions**: 서드파티 플러그인으로 기능을 확장할 수 있다. 예: colcon-bundle, colcon-docker 등.
