코딩/C와 C++

2편, c++ 프로그래밍 CMake 예제

드리프트 2020. 12. 2. 22:02
728x170

 

 

안녕하세요?

 

1편에 이어 2편에서는 본격적인 개발에 들어가 보도록 하겠습니다.

 

들어가기 전에 먼저 TDD에 대해 들어보셨는지요?

 

TDD란 Test Driven Development인데 간단히 소개하면 다음과 같습니다. 

 

기존 개발방식은 개발을 먼저 하고 나중에 테스트하는 방식인데

 

 

 

 

TDD 방식은 테스트 코드를 작성하고 검토해서 최종적으로 개발코드를 작성하는 방식입니다.

 

 

 

우리는 TDD 방식을 따라 개발할 예정입니다.

 

TDD 방식에서 테스트 코드를 작성한다는 얘기는 내가 개발할 라이브러리를 작성한다는 얘기와 같습니다.

 

1편에서 우리가 원했던 기능은 youtube-dl로 다운로드한 파일의 이름을 변경하는 기능이 있는 나만의 라이브러리를 만드는 것입니다.

 

그럼 먼저, 디렉터리 구조를 짜야 합니다.

 

C++ 개발에서 가장 일반적인 구조로 짤 예정입니다.

 

저는 3개의 디렉터리를 만듭니다.

 

src, test, external입니다.

 

src야 가장 기본적인 소스파일이 저장하는 디렉터리고

 

test는 TDD를 위한 유닛 테스트 코드를 작성하기 위한 디렉터리입니다.

 

external은 제3자의 소스코드를 저장하는 디렉터리입니다.

 

오픈소스에는 좋은 라이브러리가 많습니다.

 

이걸 이용해야 작업 능률이 오릅니다.

 

이제 우리가 원했던 기능을 구현할 라이브러리를 만들어야죠.

 

일단 src 디렉터리 밑에 lib 디렉터리를 만들고 그 안에 myStringLib.hpp 란 파일을 만듭시다.

 

 

 

 

이제 본격적인 라이브러리를 만들어 봅시다.

 

먼저, helper 라이브러리로 spdlog 를 다운받아서 external에 저장합시다.

 

spdlog 라이브러리는 로그 기능을 하는 printf 보다 강력하고 쉬운 라이브러리로 개발자라면 많이 씁니다.

 

링크는 다음과 같습니다.

 

https://github.com/gabime/spdlog

 

gabime/spdlog

Fast C++ logging library. Contribute to gabime/spdlog development by creating an account on GitHub.

github.com

 

코드를 압축파일로 다운로드하시고 우리가 필요한 Helper 라이브러리만 우리 프로젝트에 복사하면 됩니다.

 

압축받은 파일에서 include 밑에 있는 spdlog 디렉터리 전체를 우리 프로젝트 external에 복사하면 됩니다.

 

 

이제 spdlog 헬퍼 라이브러리도 설치했으니까 우리가 원했던 myStringLib.hpp 파일을 본격적으로 만들어 봅시다.

 

myStringLib.hpp는 최근 유행하는 header-only library로 만들 예정입니다.

 

#include "spdlog/spdlog.h"

namespace myStringLib
{

    // lib test function
    int myStringLib(void)
    {
        spdlog::info("myStringLib Init...");
        return 0;
    }
} // namespace myStringLib

 

namespace를 이용했고 일단 클래스의 Constructor 같은 기본 함수를 만들었습니다.

 

첫 번째 문구를 보면 위에서 helper 라이브러리를 include 했습니다.

 

그런데, VS Code에서 includePath가 없다고 하면 다음과 같이 .vscode 디렉터리 밑에 c_cpp_properties.json 파일을 만들어서 다음과 같이 작성하면 됩니다.

 

{
    "configurations": [
        {
            "name": "Mac",
            "includePath": [
                "${workspaceFolder}/**",
                "${workspaceFolder}/external/**"
            ],
            "defines": [],
            "macFrameworkPath": [
                "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
            ],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64",
            "configurationProvider": "vector-of-bool.cmake-tools"
        }
    ],
    "version": 4
}

 

위 파일은 VS Code 가 include 파일은 찾는 경로를 지정하기 위함인데, 우리는 external 폴더에 저장했기 때문에

 

"${workspaceFolder}/external/**"

 

이 문구를 추가했습니다.

 

 

 

 

 

 

자 그럼 위에서 myStringLib.hpp를 만들었으니 컴파일해 볼까요?

 

TDD 방식으로는 진행하기로 했으니까 Unit Test (유닛 테스트)를 진행합시다.

 

유닛 테스트에 필요한 Helper 라이브러리는 Google Test, Catch2 등 여러 가지가 있는데 header-only library 인 Catch2를 사용하기로 합시다.

 

https://github.com/catchorg/Catch2

 

catchorg/Catch2

A modern, C++-native, header-only, test framework for unit-tests, TDD and BDD - using C++11, C++14, C++17 and later (or C++03 on the Catch1.x branch) - catchorg/Catch2

github.com

 

Catch2 라이브러리를 다운로드해서 압축을 풉시다.

 

여기서 우리가 필요한 파일은 딱 한 개인데

 

single_include/catch2/catch.hpp 파일입니다.

 

이 파일을 우리 프로젝트 test 디렉터리 밑에 복사합시다.

 

Catch 2.13.3 버전이네요.

 

자 그럼 본격적인 테스트 코드를 작성해 볼까요?

 

먼저 test 폴더에 myTest.cpp 파일을 만듭시다.

 

Catch2 유닛 테스트 작성 방법도 간단히 설명해 드리겠습니다.

 

일단 소스코드를 보시죠

 

#define CATCH_CONFIG_MAIN
#include <string>

#include "../src/lib/myStringLib.hpp"
#include "catch.hpp"
#include "spdlog/spdlog.h"

TEST_CASE("myStringLib") {
  SECTION("Constructor") {
    spdlog::info("myStringLib Consturctor");
    REQUIRE(myStringLib::myStringLib() == 0);
  }
}

 

일단 std::string을 include 하고

 

우리가 작성한 라이브러리인 myStringLib.hpp 도 include 합니다.

 

또, catch랑 spdlog도 include 합시다.

 

Catch 유닛 테스트는 다음과 같이 사용하는 게 일반적입니다.

 

TEST_CASE("xxxx") {

   SECTION("Constructor") {

        REQUIRE(myStringLib::myStringLib());

   }

}

 

간단하게 실행만 시키는 코드입니다.

 

자 그럼 컴파일을 해봐야겠죠!!!

 

3편에서 좀 더 알아봅시다.

 

그리드형