5 분 소요

이 글은 conan 과 cmake 를 이용하여 C++ 빌드 시스템을 구성하는 방법을 설명합니다.

cmake 3.24.0 크로스 플랫폼 빌드 시스템 https://cmake.org/
conan 2.3.0 C++ 패키지 관리 시스템 https://conan.io/

cmake

사실, cmake 이 크로스 플랫폼 빌드 시스템이기 때문에 cmake 만으로도 프로젝트 빌드 환경을 구성할 수 있습니다.

아쉬운 점이 있다면 종속성 관리입니다.

오픈소스 라이브러리, 바이너리 라이브러리 등 배포 방법이 다른 라이브러리들을 일일이 관리해야 합니다.

패키지 관리 시스템

여러 언어들은 이런 종속성 관리를 위해 패키지 관리 시스템을 제공합니다.

언어 패키지 관리 시스템
java maven, gradle
c# nuget
javascript npm, yarn
python pip
rust cargo

C++ 도 패키지 관리 시스템이 있습니다. 바로 conan 과 vcpkg 입니다.

IDE

Visual Studio 와 같은 통합 개발 환경(Integration Development Environment) 에서는 자체적인 프로젝트 환경 구성 및 패키지 관리 시스템을 제공하기도 합니다.

Visual Studio Code(이하 vscode) 는 확장을 통해 IDE 를 구성할 수 있습니다. 여러 조합이 있을 수 있는데 이 글에서는 cmake + conan 을 사용합니다.

CMake Tools 확장을 설치합니다.

Image

CMakeLists.txt 파일을 생성하기 전에는 왼쪽 사이드바에 아직 보이지 않습니다.

시작

Visual studio 실행

vscode 에서 빈 프로젝트 디렉토리를 엽니다.

mkdir app
cd app
code .

conan new

conan 은 cmake 로 프로젝트를 구성할 수 있는 명령어를 제공해 줍니다.

$ conan new cmake_exe -d name=app -d version=1.0
File saved: CMakeLists.txt
File saved: conanfile.py
File saved: src/app.cpp
File saved: src/app.h
File saved: src/main.cpp
File saved: test_package/conanfile.py

CMakeLists.txt, conanfile.py 외에 초기 파일들이 생성됩니다.

conan install

$ conan install . --build=missing

======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=Debug        
compiler=msvc
compiler.cppstd=17      
compiler.runtime=dynamic
compiler.runtime_type=Debug
compiler.version=193
os=Windows

Profile build:
[settings]
arch=x86_64
build_type=Debug
compiler=msvc
compiler.cppstd=17
compiler.runtime=dynamic
compiler.runtime_type=Debug
compiler.version=193
os=Windows


======== Computing dependency graph ========
Graph root
    conanfile.py (app/1.0): C:\workspace\app\conanfile.py

======== Computing necessary packages ========

======== Installing packages ========

======== Finalizing install (deploy, generators) ========
conanfile.py (app/1.0): Calling generate()
conanfile.py (app/1.0): Generators folder: C:\workspace\app\build\generators
conanfile.py (app/1.0): CMakeToolchain generated: conan_toolchain.cmake
conanfile.py (app/1.0): CMakeToolchain: Preset 'conan-default' added to CMakePresets.json.
    (cmake>=3.23) cmake --preset conan-default
    (cmake<3.23) cmake <path> -G "Visual Studio 17 2022" -DCMAKE_TOOLCHAIN_FILE=generators\conan_toolchain.cmake  -DCMAKE_POLICY_DEFAULT_CMP0091=NEW
conanfile.py (app/1.0): CMakeToolchain generated: C:\workspace\app\build\generators\CMakePresets.json
conanfile.py (app/1.0): CMakeToolchain generated: C:\workspace\app\CMakeUserPresets.json
conanfile.py (app/1.0): Generating aggregated env files
conanfile.py (app/1.0): Generated aggregated env files: ['conanbuild.bat', 'conanrun.bat']
Install finished successfully

출력된 내용을 살펴보면 (cmake>=3.23) cmake –preset conan-default 을 발견할 수 있습니다.

cmake –preset

$ cmake --preset conan-default
Preset CMake variables:

  CMAKE_POLICY_DEFAULT_CMP0091="NEW"
  CMAKE_TOOLCHAIN_FILE:FILEPATH="generators\conan_toolchain.cmake"

-- Using Conan toolchain: C:/workspace/app/build/generators/conan_toolchain.cmake
-- Conan toolchain: CMAKE_GENERATOR_TOOLSET=v143
-- Conan toolchain: C++ Standard 17 with extensions OFF
-- Selecting Windows SDK version 10.0.22000.0 to target Windows 10.0.19045.
-- The CXX compiler identification is MSVC 19.34.31937.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.34.31933/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/workspace/app/build

여기까지 진행하면 cmake 를 configuration 할 수 있는 상태가 됩니다.

cmake configuration

configuration 을 cmake cli 로 시작할 수 있지만, CMake Tools 확장을 사용하면 편합니다.

그런데 왼쪽 사이드바에 아직 CMake Tools 아이콘이 안보이는데, CMakeLists.txt 을 인식하지 못했기 때문입니다.

vscode 를 재시작하거나,

Image

CMakeLists.txt 파일을 우클릭하면 나오는 메뉴에서 [Configure All Projects] 를 선택하면 CMake Tools 아이콘이 생깁니다.

또한 방금 생성된 preset 으로 configuration 을 시작할 수 있습니다.

Image

[‘conan-default’ config] 를 선택하면 configuration 이 시작됩니다.

왼쪽 사이드바에서 CMake Tools 아이콘이 보이고 해당 탭에서는 프로젝트 빌드 환경을 볼 수 있습니다.

Image

CMake Tools 탭에서 [Configure] - [‘conan-default’ config] 오른쪽의 연필 모양의 아이콘을 누르면 configuration 할 preset 을 선택할 수 있습니다.

Image

[Configure] 오른쪽의 화살표 아이콘을 누르면 configuration 이 시작됩니다.

Image

build

CMake Tools 탭에서 [Build] - [conan-debug] 오른쪽의 연필 모양의 아이콘을 누르면 빌드할 preset 을 선택할 수 있습니다.

Image

[Build] 오른쪽의 화살표 모양의 아이콘을 누르면 빌드가 시작됩니다.

Image

실행

[Launch] 오른쪽의 세모 모양의 아이콘을 누르면 빌드한 앱이 실행됩니다.

Image

$ "C:/workspace/app/build/Debug/app.exe"
app/1.0: Hello World Debug!
  app/1.0: _M_X64 defined
  app/1.0: MSVC runtime: MultiThreadedDebugDLL
  app/1.0: _MSC_VER1934
  app/1.0: _MSVC_LANG201703
  app/1.0: __cplusplus199711
app/1.0 test_package

디버깅

src/main.cpp 파일을 열고, breakpoint 를 설정한 후,

Image

[Debug] 오른쪽의 벌레 세모 모양의 아이콘을 누르면 디버깅이 시작됩니다.

Image

Image

의존성 설치

conanfile.py

https://conan.io/center

conan center 에서 설치할 라이브러리를 검색합니다.

검색된 라이브러리를 선택하면 conanfile.py 문서를 찾을 수 있습니다.

from conan import ConanFile
from conan.tools.cmake import cmake_layout


class ExampleRecipe(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeDeps", "CMakeToolchain"

    def requirements(self):
        self.requires("fmt/10.2.1")

    def layout(self):
        cmake_layout(self)

이 문서에서

def requirements(self):
        self.requires("fmt/10.2.1")

부분만 복사하여 프로젝트의 conanfile.py 에 붙여넣고 저장합니다.

from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps


class appRecipe(ConanFile):
    name = "app"
    version = "1.0"
    package_type = "application"

    # Optional metadata
    license = "<Put the package license here>"
    author = "<Put your name here> <And your email here>"
    url = "<Package recipe repository url here, for issues about the package>"
    description = "<Description of app package here>"
    topics = ("<Put some tag here>", "<here>", "<and here>")

    # Binary configuration
    settings = "os", "compiler", "build_type", "arch"

    # Sources are located in the same place as this recipe, copy them to the recipe
    exports_sources = "CMakeLists.txt", "src/*"

    def layout(self):
        cmake_layout(self)

    def generate(self):
        deps = CMakeDeps(self)
        deps.generate()
        tc = CMakeToolchain(self)
        tc.generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

    def package(self):
        cmake = CMake(self)
        cmake.install()

    def requirements(self):
        self.requires("fmt/10.2.1")

CMakeLists.txt

conan install 을 실행하면 패키지가 설치됩니다.

$ conan install . --build=missing

======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=Debug
compiler=msvc
compiler.cppstd=17
compiler.runtime=dynamic
compiler.runtime_type=Debug
compiler.version=193
os=Windows

Profile build:
[settings]
arch=x86_64
build_type=Debug
compiler=msvc
compiler.cppstd=17
compiler.runtime=dynamic
compiler.runtime_type=Debug
compiler.version=193
os=Windows


======== Computing dependency graph ========
Graph root
    conanfile.py (app/1.0): C:\workspace\app\conanfile.py
Requirements
    fmt/10.2.1#9199a7a0611866dea5c8849a77467b25 - Cache

======== Computing necessary packages ========
Requirements
    fmt/10.2.1#9199a7a0611866dea5c8849a77467b25:f134d4c4e8c78a64bfdbe69deb29a8569e822900#328015a59043e2883eed8cd803f0c8b7 - Cache

======== Installing packages ========
fmt/10.2.1: Already installed! (1 of 1)
WARN: deprecated: Usage of deprecated Conan 1.X features that will be removed in Conan 2.X:
WARN: deprecated:     'cpp_info.names' used in: fmt/10.2.1

======== Finalizing install (deploy, generators) ========
conanfile.py (app/1.0): Calling generate()
conanfile.py (app/1.0): Generators folder: C:\workspace\app\build\generators
conanfile.py (app/1.0): CMakeDeps necessary find_package() and targets for your CMakeLists.txt
    find_package(fmt)
    target_link_libraries(... fmt::fmt)
conanfile.py (app/1.0): CMakeToolchain generated: conan_toolchain.cmake
conanfile.py (app/1.0): CMakeToolchain: Preset 'conan-default' added to CMakePresets.json.
    (cmake>=3.23) cmake --preset conan-default
    (cmake<3.23) cmake <path> -G "Visual Studio 17 2022" -DCMAKE_TOOLCHAIN_FILE=generators\conan_toolchain.cmake  -DCMAKE_POLICY_DEFAULT_CMP0091=NEW
conanfile.py (app/1.0): CMakeToolchain generated: C:\workspace\app\build\generators\CMakePresets.json
conanfile.py (app/1.0): CMakeToolchain generated: C:\workspace\app\CMakeUserPresets.json
conanfile.py (app/1.0): Generating aggregated env files
conanfile.py (app/1.0): Generated aggregated env files: ['conanbuild.bat', 'conanrun.bat']
Install finished successfully

출력되는 내용에서

find_package(fmt)
target_link_libraries(... fmt::fmt)

을 찾을 수 있습니다.

프로젝트의 CMakeLists.txt 파일에 add_executable() 밑에 추가합니다. target_link_libraries() 의 … 부분을 executable 인 app 으로 수정합니다.

cmake_minimum_required(VERSION 3.15)
project(app CXX)

add_executable(app src/app.cpp src/main.cpp)

find_package(fmt)
target_link_libraries(app fmt::fmt)

install(TARGETS app DESTINATION "."
        RUNTIME DESTINATION bin
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        )

main.cpp

include<> 추가하고, 함수를 호출을 추가합니다.

#include <fmt/core.h>
fmt::print("Hello world!\n");
#include "app.h"
#include <vector>
#include <string>

#include <fmt/core.h>

int main() {
    app();

    std::vector<std::string> vec;
    vec.push_back("test_package");

    app_print_vector(vec);

    fmt::print("Hello world!\n");
}

빌드하고 실행해보면 잘 호출되는 것을 볼 수 있습니다.

$ "C:/workspace/app/build/Debug/app.exe"
app/1.0: Hello World Debug!
  app/1.0: _M_X64 defined
  app/1.0: MSVC runtime: MultiThreadedDebugDLL
  app/1.0: _MSC_VER1934
  app/1.0: _MSVC_LANG201703
  app/1.0: __cplusplus199711
app/1.0 test_package
Hello world!

맺음말

vscode 에서 cmake, conan 을 사용하여 프로젝트 환경 구성을 해보았습니다. conan 이외에 vcpkg 를 사용할 수도 있습니다. 제공하는 패키지 저장소에 원하는 라이브러리가 있는지 살펴보고 선택하면 좋을 것 같습니다.

댓글남기기