Coding Memo

Protobuf 프로젝트에 추가하기 (Windows, CMake) 본문

Language/C++

Protobuf 프로젝트에 추가하기 (Windows, CMake)

minttea25 2023. 10. 10. 22:43

C#에서 Protobuf를 사용할 때는 간단하게 nuget 패키지에 있는 Google.Protobuf만 설치하면 되지만, C++은 직접 헤더 및 라이브러리들을 추가해주어야 한다.

(C#이 굉장히 편했던 것이었다!!!!!!!!!!!!!!!!!!!)

 

먼저 짚고 넘어가야 할 것은 프로토버퍼 특정 버전 이후에 릴리즈 된 프로젝트는 단순히 cmake로 솔루션을 생성하고 빌드하려고 하면 에러가 날 것이다. 이 경우 다음글을 참고하자. ( https://minttea25.tistory.com/128 )

(그 이전 버전은 cmake 폴더에 있는 CMakeLists.txt파일을 포함하고 있어서 하는 방법이 다소 간단하다.)

(일단 확인해 본 것은 3.19까지는 가능한 것 같다.)

 

추가적으로 proto파일에 대한 output 파일을 생성하는 protoc.exe가 어떤 버전인지 알 필요성이 있다.

protoc --version

위 명령을 cmd에서 실행시키면 확인 할 수 있을 것이다.

 

이미 생성되어 있는 파일이라면, C++로 생성된 헤더파일 앞부분 코드를 보면

#if PROTOBUF_VERSION < 3021000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif

위와 같다.

두번째 if문에 있는 3021012가 버전을 나타낸다. 3.21.12 버전에서 생성된 파일이라는 뜻이다.

 

준비물

 

- CMake : 최신 버전을 받아주자. (Protobuf 프로젝트마다 CMake 최소 버전이 명시가 되어 있긴하다.)

(https://cmake.org/download/)


특정 버전 이하 (cmake 폴더에 CMakeLists.txt가 있을 때)

 

1. 아래 github 주소에서 리포지토리를 git을 이용하여 복사하거나 직접 zip을 다운하여 자신의 컴퓨터에 저장하고 압축을 해제해서 프로젝트를 준비한다.

 

https://github.com/protocolbuffers/protobuf

 

GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format

Protocol Buffers - Google's data interchange format - GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format

github.com

Releases에서 버전를 선택하여 다운로드하면 된다.

Releases에서 지금까지 릴리즈된 여러가지 버전의 프로토타입을 확인할 수 가 있는데, 기본적인 소스 코드(protobuf-x.x.zip)과 그 버전으로 빌드된 실행파일(protoc-x.x-win64.zip)을 모두 다운로드 할 수 있다. (Windows 기준)

여기서 같이 다운하면 버전 차이때문에 고생하는 일은 없을 것이다...

 

(실행파일은 protoc.exe를 말하는 것이다.)

2. CMake를 실행하여 소스 코드의 위치와 빌드 위치를 지정한다.

CMake는 GUI를 사용하는 것이 편할 것이다. (CLI를 사용한다면, README.md에 나와있으니 참고하자.)

 

cmake 폴더는 압축 해제한 소스 파일 폴더(protobuf-x.x)에서 찾을 수 있을 것이다.

(이 폴더에 CMakeLists.txt가 있어야한다.)

빌드 출력파일 경로는 새로 폴더를 만들어서 지정하자.

 

3. Generate 버튼을 누르고  Visual Studio 버전을 선택한 후,  바이너리를 빌드한다.

 

Visual Studio 버전은 자신이 해당 프로젝트를 빌드할 버전을 선택해주면 될 것이다.

*만약 오류가 떳더라도 일부 프로젝트에서 뜬 것이니 일단 다음 과정으로 넘어가자.

 

4. 빌드 출력 위치에 프로젝트 파일(protobuf.sln)이 생성되었는지 확인하자

프로젝트 파일 외에도 여러가지 파일들이 생겼을 것이다.

 

여기서 주의할 점은 단순히 ALL_BUILD와 ZERO_CHECK에 대한 파일들만 보인다면 잘못된 것이다. (꼭 체크하자.)

이 경우에는 vcpkg를 활용하여 라이브러리를 생성하는 편이 훨씬 편하므로 다음 포스팅을 확인하자.

 

5. CMake GUI를 보면 몇몇 항목에 check가 되어있을 건데, 모두 해제하고 generate를 다시 누르자.

(물론 이전에 출력 위치에 있는 파일들을 모두 삭제하고 다시 generate를 해도 깔끔하다.)

 

Note: 만약 실행 바이너리 파일(protoc.exe)가 없다거나 처음에 다운로드 하지 않았다면 protobuf_BUILD_PROTOC_BINARIES를 체크하고 다시 generate를 누르면 된다. (이 항목이 protoc-x.x.x-win64.zip에 있는 실행파일(protoc.exe)을 생성해줄 프로젝트이다.)

 

 

6. 출력폴더에 생성된 sln 확장자의 프로젝트 파일(protobuf.sln)을 실행한다. (Visual Studio 실행)

그러면 다음 대략 6-7개의 프로젝트가 포함된 솔루션이 나타날 것이다.

 

7. Visual Studio에서 빌드를 실행한다. (Debug, Release 둘다 빌드하자.)

Release빌드는 상단에 있는 Debug를 Release로 바꾸고 빌드를 하면 된다. 시간이 다소 걸릴 수 있다.

(필요하면 환경(x64)도 확인해서 빌드하자, 아마 기본으로 x64가 되어있을 것이다.)

 

7. 출력 디렉터리에서 생성된 라이브러리 확인

기본으로 출력 디렉터리는 Debug, Release로 되어 있을 것이다. 솔루션 폴더에 가보면 Debug 디렉터리와 Release 디렉터리가 생성되어 있고 각각 생성된 정적 라이브러리 파일들과 그 외 여러가지 파일들이 있는 것을 확인할 수 있다.

(protobuf_BUILD_PROTOC_BINARIES를 체크 했다면 protoc.exe 파일도 있을 것이다. proto파일을 이 실행파일로 각 언어에 맞게 결과물을 만들 수 있다.)

위에서 사용할 파일은

Debug에서

libprotobufd.lib

libprotobufd.pdb (Debug 용)

 

Release에서

libprotobuf.lib

 

 

8. 위에서 언급된 파일들을 Debug용과 Release용으로 따로 나누어 protobuf를 사용할 프로젝트 내부에 복사한다.

 

 

9. 소스 코드 (protobuf-x.x)의 src 디렉터리에 있는 google 이름의 디렉터리를 복사하여 마찬가지로 protobuf를 사용할 프로젝트 내부에 복사한다. (Include 용)

 

 

10. 8, 9에서 가져온 파일들을 프로젝트에서 참조하도록 한다.

 

아래 내용을 프로젝트 속성의 `VC++ 디렉터리`에서 진행한다.

 

  • 헤더파일 참조: 포함 디렉터리(Include Directories) 항목에서 google 디렉터리를 복사한 경로를 추가한다.

ex) 만약 솔루션 디렉터리의 `Include` 디렉터리 내에 google 디렉터리가 있다면, 

$(SolutionDir)Include\

를 추가하면 된다. 주의 해야 할점은 생성된 pb.h, pb.cc 파일을 보면 헤더파일 참조가 google부터 시작한다는 점으로, google 디렉터리는 포함되면 안된다.

 

  • 정적 라이브러리(.lib) 참조: Debug와 Release가 따로 있으므로 일단 이 두 디렉터리를 포함하는 공통 경로를 추가한다.

ex) 만약 솔루션 디렉터리의 'Libraries' 디렉터리 내에 (아까 빌드한 라이브러리가 있는) Debug와 Release 디렉터리가 있다면,

$(SolutionDir)Libraries\

까지만 추가한다.

이후 Debug 및 Release는 코드에서 컨트롤 하도록 한다.

lib는 아까 지정한 라이브러리 경로이고 이후 오는 string 값은 직접 지정 상대경로이다.

#ifdef _DEBUG
#pragma comment(lib, "Debug\\libprotobufd.lib")
#else
#pragma comment(lib, "Release\\libprotobuf.lib")
#endif

Note: 모든 파일에 추가 할 수는 없으니 미리 컴파일 된 헤더 등에 추가하면 편할 것이다.


버전 불일치 오류

 

빌드시 오류가 나타날 수도 있다. 해당 오류 라인을 확인해보면...

 

#if PROTOBUF_VERSION < 3021000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3021012 < PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif

바로 proto파일로 생성한 헤더 파일에 포함되어 있는 저 구문에서 오류가 나는 것이다. 

위 뜻은 이 헤더파일은 3021012 버전으로 생성되었는데, PROTOBUF_VERSION(현재 프로젝트가 참조하고 있는 protobuf 라이브러리의 버전)과 일치하지 않거나 PROTOBUF_MIN_PROTOC_VERSION, 즉 최소 요구 프로토버프 라이브러리 버전이 아니라는 것이다. 

 

proto파일을 생성할 때 사용한 protoc.exe 의 버전과 프로젝트가 참조하고 있는 프로토버프 라이브러리의 버전에 차이가 있어서 나는 문제다.

 

뭐... 해결방법은 맨 처음에도 언급했듯이, 버전을 하나로 통일하자. (아예 사용할 때부터 하나의 버전에서 가져와 사용하자.)

 

proto파일에 대한 출력파일들 다시 생성하기 귀찮고 양이 많다면, 필자가 만든 프로그램을 사용해도 좋을지도...

(https://github.com/minttea25/SimpleProtoc)


만약 CMake를 사용할 수 없다면... 아래 글을 확인해보자.

(필자도 여러가지 해보았는데 정확하게 해결하지 못했다... 따라서 이미 바이너리가 생성되어 있는 프로젝트를 패키지로 다운받아(vcpkg 이용) 그것을 가져와 사용하는 방법을 찾았다.)

https://minttea25.tistory.com/128


수정: 동적라이브러리(dll)제외 빌드 및 protoc.exe 빌드 추가, 3.18.0 버전으로 테스트 진행