C/C++의 만년, 패키지 매니저

by Vincent Lee,

프로그래밍 언어의 인기 순위를 나타내는 TIOBE 프로그래밍 커뮤니티 지수1 2015년 3월 순위에서 C++는 4위, C는 1위에 랭크하고 있다. 인기와는 달리, C/C++에서 시리얼 포트로 데이터를 전송하는 방법은 파이썬에서 하는 것만큼 간단하지 않은 일이 된다.

$ pip install pyserial
import serial
ser = serial.Serial(0)
ser.write("Hello World")
ser.close()

파이썬에서는 이렇게 쉬운 일이 저수준 프로그래밍에 더 적절하다고 알려진 C/C++에서 쉽지 않은 이유는 인기 있는 다른 언어들과는 대조적으로 C와 C++ 언어를 구성하는 생태계에는 크게 두 가지 걸림돌이 있기 때문이다.

1. 크로스 플랫폼 빌드 시스템

CMake Logo

C 언어가 등장한 이래로 많은 시간이 지났지만 1977년, Make가 등장한 이후로 크로스 플랫폼, 크로스 아키텍처 환경에서 빌드할 수 있는 프로젝트를 구성하기 위해 Automake가 등장하기까지 20년에 가까운 시간이 걸렸다. Automake는 일련의 설정 파일을 읽어드려 빌드 대상이 되는 플랫폼과 아키텍처에 알맞은 Makefile을 생성하는 툴이다. 이 Makefile을 읽어드려 Make가 프로젝트를 빌드하게 되는데, 여전히 GNU 툴체인이 준비되지 않은 환경에서는 쓸 수 없는 방법이다(몇 가지 툴들의 모음으로 이루어진 GNU 빌드 시스템은 Autotools로 불린다).

2000년대로 들어서면서 이런 빌드 툴의 수준을 한 차원 더 높이는 CMake, SCons, Premake같은 툴이 등장하기 시작한다. 이 툴들은 Makefile은 물론이며, Xcode, Visual Studio같은 IDE의 프로젝트 파일을 직접 생성해내어, 모든 플랫폼에서 빌드할 수 있는 프로젝트를 쉽게 구성할 수 있게 되었다.

하지만 이런 툴이 아직 표준인 것으로 여겨지지 않고, 각 프로젝트가 선호하는 빌드 시스템을 채택하거나, 이런 것에 만족하지 못할 때는 에픽 게임즈가 만드는 언리얼 엔진처럼 독자적인 빌드 시스템을 개발해 사용하기도 해 언어 생태계 차원의 표준화되고 통일된 방법으로 아직 체감되지 않는다.

2. 패키지 매니저

다른 언어보다 시스템에 가까이 의존 하는 C/C++ 언어에서 빌드 시스템은 표준화하기 어려운 부분도 있었지만 툴의 고급화로 인해 조금씩 발전하고 있다. C/C++ 언어에서 제일 부재했던 두 번째 부분은 패키지의 의존(dependency) 관리자다.

루비, 파이썬, 펄 같은 고수준 언어들은 각각 gem, pip, CPAN이라는 패키지 매니저를 가지고 있어 필요한 패키지를 쉽게 검색하고 설치, 삭제할 수 있다. 의존하는 다른 패키지도 자동으로 설치되고, 삭제된다. 유닉스, 리눅스 환경에서는 각 OS가 가진 패키지 매니저, pkg(FreeBSD), apt-get(Debian), pacman(Arch Linux) 등을 통해 필요한 C/C++ 라이브러리를 패키지로 설치하기도 했지만, 플랫폼에 의존하는 시스템이었다.

크로스 플랫폼 빌드 시스템이 발달하면서 이런 필요성을 해소하기 위해 C/C++ 생태계에도 패키지 매니저가 등장하기 시작했다.

3. Biicode

Biicode2는 프로젝트 설정, 생성에서 의존 관리와 빌드까지 수행하는 빌드 시스템이다. Java에 비유하면 Gradle3과 비슷한 위치라 할 수 있다. 빌드 백엔드로 CMake를 사용하기 때문에 CMake의 크로스 플랫폼 빌드 시스템을 그대로 사용하고 biicode.conf 파일을 통해 프로젝트 설정을 기술하는 형태이다.

$ bii init example -L
$ cd example
# create a main.cpp
$ bii find
$ bii configure -G Xcode # optional
$ bii build

init 커맨드로 프로젝트를 생성하고, find 명령어로 필요한 패키지를 다운로드하여 사용할 수 있도록 준비한다. build 커맨드로 CMakeLists.txt 파일이 (없다면) 생성되고 프로젝트를 빌드한다. configure 명령어로 생성기(generator)를 변경할 수 있어 Xcode나 Visual Studio 프로젝트 파일을 생성하도록 할 수 있다.

[requirements]
   google/gtest: 10

[includes]
    gtest/*.h: google/gtest/include

위와 같이 biicode.conf 파일에 필요한 패키지를 추가하면, 다음과 같이 C++ 코드에서 해당 패키지를 사용할 수 있게 된다.

#include "gtest/gtest.h"

간단한 사용법은 시작하기4 문서에서 잘 설명하고 있다.

4. CPM (C++ Package Manager)

CPM5은 Biicode와는 달리 별도의 툴체인을 필요로 하지 않아 심플한 형태로 사용할 수 있는 패키지 매니저이다. 역시 CMake를 기반으로 하고 있어 자신의 CMakeLists.txt 파일에 특정한 코드를 추가하는 것으로 준비가 끝나고, 필요한 패키지를 CMakeLists.txt에 직접 기술하게 되면 프로젝트 빌드 절차에서 자동으로 패키지가 사용할 수 있도록 준비된다.6

 CPM_AddModule("aabb"
    GIT_REPOSITORY "https://github.com/iauns/cpm-glm-aabb"
    GIT_TAG "1.0.2")
}

위와 같이 필요한 패키지(모듈)를 추가하면, 다음과 같이 C++ 코드에서 해당 패키지를 사용할 수 있게 된다.

#include <glm-aabb/AABB.hpp>

5. 끝으로

기존의 OS에 의존하는 패키지 매니저를 통한 설치를 넘어서, (심지어 Windows에서는 이런 것조차 없다) 프로젝트가 필요로 하는 정확한 버전의 패키지를 관리되는(version controlled) 파일로써 설치하고, 모든 개발자들이 같은 환경을 동기화할 수 있는 시스템은 다른 언어에서는 일찍부터 발전해왔다. 대표적으로 자바에는 Maven이 있고, 루비에는 Bundler가 있다. iOS와 OS X 개발자들은 CocoaPods를 사용해 왔다.

C/C++ 언어 생태계에도 이런 시스템이 정착되기 시작했으므로, 이제 개발자들도 더 중요한 일에 시간을 쓸 수 있어질 것이다.

The Sunset of C and C++

CPU 사이클뿐 아니라 개발자의 시간도 중요하기 때문에

6. 참고 자료

1 TIOBE Index

2 Biicode

3 Gradle

4 Getting Started (Biicode)

5 CPM (C++ Package Manager)

6 CPM (GitHub)