C++의 modules
와 static polymorphism
에 관심이 생겼다. 이 글에서는 그 중 modules
를 살펴본 후 import std;
를 사용하기 위한 과정을 살펴본다.
전처리 과정에서 파일의 내용을 그대로 복사하기 때문에 여러 가지 문제가 발생한다.
문제를 해결하기 위해 include guard나 PCH(Precompiled Header) 같이 별도의 처리가 필요
modules의 장점은:
1. 한 번만 로드: 중복 포함 방지
2. 매크로 충돌 방지: 동일한 매크로가 있는 두 헤더를 포함할 때, 순서에 따라 값이 달라지는 문제 해결
3. 순서 독립적: 모듈은 포함 순서에 영향 받지 않음
4. 불필요한 의존성 제거: 직접 참조하는 모듈만 알면 됨
그리고 헤더와 소스를 나눌 필요가 없다. 파일을 복사하는 방식은 컴파일 시간을 단축하기 위해서 분리가 필요했지만, 컴파일러는 export
로 명시한 모듈의 인터페이스와 구현을 구분한다. 따라서 코드를 분리하여 복잡하게 만들필요가 없다.
파일 분리가 필요 없어진 상황에서 어떻게 가독성을 높일지 고민 할만한 것 같다.
module
,import
, export
키워드를 통해서 모듈을 사용할 수 있다.
// Vector.cpp
export module Vector;
export class Vector {
public:
explicit Vector(int s);
double &operator[](int i) const;
private:
double *elem;
int elemSize;
};
// 구현 부분 ...
// main.cpp
import Vector;
int main() {
import std;
는 표준 라이브러리의 모듈 인터페이스를 가져온다. 하지만 clang c++23 환경에서는 제대로 지원을 하지 않았다.
#include <iostrema>
한 후 export를 하려고 했다.export std::cout
개별로 export 하는 것만 동작해서 실패clang에서는 불가능한 것인가 생각하던 찰나 cmake를 사용하는 방법을 찾았다.Clion how to enable std module support?
CmakeList.txt
를 다음 글을 보고 수정했다.
cmake_minimum_required(VERSION 3.30)
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
# This specific value changes as experimental support evolves. See
# `Help/dev/experimental.rst` in the CMake source corresponding to
# your CMake build for the exact value to use.
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
project(untitled LANGUAGES CXX)
set(CMAKE_CXX_MODULE_STD 1)
set(CMAKE_CXX_STANDARD 23)
add_executable(untitled src/main.cpp
)
target_sources(untitled
PUBLIC
FILE_SET modules TYPE CXX_MODULES FILES
src/Vector.cppm
src/Transport/Server.cppm
src/StdAll.cppm
)
이런 오류가 생겼다.
Experimental
import std
support not enabled when detecting toolchain; it must be set beforeCXX
is enabled (usually aproject()
call)
CLion 설정에 CMake option을 직접 넣어줬다.
-DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=0e5b6991-d74f-4b3d-a41c-cf096e0b2508
또 오류...
libc++.modules.json
resource does not exist
https://github.com/NixOS/nixpkgs/issues/370217
같은 고민을 하는 사람이 좀 있었다. CLion 내장 CMake 사용 중이라서 homebrew로 CMake 설치 및 연동하고 아래 파일 수정했다.
/opt/homebrew/share/cmake/Modules/Compiler/Clang-CXX-CXXImportStd.cmake
Go to the line 13 and change -print-file-name=libc++.modules.json
to -print-file-name=../../c++/libc++.modules.json
빌드가 됐다. 그런데 문제가 또 남았다.
CLion에서 std모듈을 resolve를 못했다.
'import std': CLion can't resolve module 'std' in case of clang
CMakeList.txt 수정하여 해결
add_library(unused_std_target STATIC)
target_sources(unused_std_target
PRIVATE
FILE_SET CXX_MODULES
BASE_DIRS <path-to-llvm>/share/libc++/v1
FILES <path-to-llvm>/share/libc++/v1/std.cppm <path-to-llvm>/share/libc++/v1/std.compat.cppm)
--
modules 사용 부터 import std;
까지 여러번 막히며 예상보다 많은 시간을 들였다. 중간에 #include
로 되돌아갈까 고민도 했다. 하지만 모던한 C++을 경험하고 싶고 개발 환경도 결국 문법과 같은 언어의 일부라는 생각으로 끝까지 시도해봤다. 결과적으로 import std;
는 사용할 수 있었지만 modules
에서 아직 cyclic dependency에 대한 처리를 지원하지 않았다. 내가 원하는 방식으로 개발을 하지 못할 것 같아 Go
언어를 살펴보기로 했다.
회사에서 처음 환경 세팅을 했을 때도 비슷한 어려움을 겪었다. 몇 번 반복하며 익숙해졌고 이후에는 귀찮음을 덜기 위해 Docker Compose로 손쉽게 구축했다. 돌아보면, 이 과정은 언어와 환경뿐 아니라 서비스에 까지 도움이 되는 중요한 준비 단계였다. 왜냐하면 php의 개발 환경은 실제 서비스의 실행환경과 유사하다. 요청이 처리되는 과정과도 연관되어있다. 코드가 실행 & 요청이 처리 되는 환경의 이해로 이슈 발생 시에 빠르고 정확하게 대처 할 수 있다.