컴파일 타임 플래그
컴파일 타임 플래그 (Compile-time flags)
컴파일 타임 플래그(compile-time flag)는 컴파일러가 매크로 메서드를 통해 제공하는 불리언 값이에요. 이 값 덕분에 컴파일 타임 조건에 따라 코드를 조건적으로 포함하거나 제외할 수 있습니다. 어떤 운영체제용으로 컴파일되는지를 확인해 분기하고 싶을 때 딱 맞는 도구죠.
컴파일러에는 컴파일러 옵션과 대상 플랫폼에 대한 정보를 담은 기본 플래그가 여럿 있어요. 사용자 플래그는 컴파일러에 전달되며, 기능 플래그(feature flag)처럼 쓸 수 있습니다.
본문
플래그 조회하기 (Querying flags)
플래그는 설정돼 있거나(set) 돼 있지 않은 명명된 식별자예요. 그 상태는 매크로 메서드 flag?로 코드에서 조회할 수 있습니다. flag?는 플래그 이름을 문자열이나 심볼 리터럴로 받아, 그 플래그의 상태를 나타내는 불리언 리터럴을 돌려줘요. 플래그는 옵션으로 값을 가질 수 있는데, 이 경우 flag?는 불리언 대신 문자열 리터럴을 돌려줍니다.
다음 프로그램은 대상 OS 계열을 출력하며 컴파일 타임 플래그의 사용법을 보여줘요.
{% if flag?(:unix) %}
puts "This program is compiled for a UNIX-like operating system"
{% elsif flag?(:windows) %}
puts "This program is compiled for Windows"
{% else %}
# Currently, all supported targets are either UNIX or Windows platforms, so
# this branch is practically unreachable.
puts "Compiling for some other operating system"
{% end %}
또 host_flag?라는 매크로 메서드도 있어요. 이 메서드는 호스트(host) 플랫폼에 플래그가 설정돼 있는지 돌려줍니다. 크로스 컴파일을 할 때 호스트 플랫폼은 대상(target) 플랫폼(flag?가 조회하는 것)과 다를 수 있어요.
컴파일러 제공 플래그 (Compiler-provided flags)
컴파일러는 몇 가지 암묵적인 플래그를 정의해요. 이들은 대상 플랫폼이나 컴파일러 옵션을 나타냅니다.
대상 플랫폼 플래그 (Target platform flags)
플랫폼별 플래그는 대상 트리플(target triple)에서 유래합니다. 지원되는 대상 플랫폼 목록은 Platform Support를 참고하세요.
crystal --version은 컴파일러의 기본 대상 트리플을 보여줘요. 이것은 --target 옵션으로 바꿀 수 있습니다.
아래 표들의 플래그들은 서로 배타적이에요. 단 _(derived) 로 표시된 것만 예외입니다.
아키텍처 (Architecture)
대상 아키텍처는 대상 트리플의 첫 번째 구성 요소예요.
| 플래그 이름 | 설명 |
|---|---|
aarch64 |
AArch64 아키텍처 |
avr |
AVR 아키텍처 |
arm |
ARM 아키텍처 |
i386 |
x86 아키텍처 (32-bit) |
wasm32 |
WebAssembly |
x86_64 |
x86-64 아키텍처 |
bits32 (derived) |
32-bit 아키텍처 |
bits64 (derived) |
64-bit 아키텍처 |
벤더 (Vendor)
벤더는 대상 트리플의 두 번째 구성 요소예요. 보통은 사용되지 않기 때문에 가장 흔한 벤더는 unknown입니다.
| 플래그 이름 | 설명 |
|---|---|
macosx |
Apple |
portbld |
FreeBSD 변형 |
unknown |
알 수 없는 벤더 |
운영체제 (Operating System)
운영체제는 대상 트리플의 세 번째 구성 요소에서 유래합니다.
| 플래그 이름 | 설명 |
|---|---|
bsd (derived) |
BSD 계열 (DragonFlyBSD, FreeBSD, NetBSD, OpenBSD) |
darwin |
Darwin (MacOS) |
dragonfly |
DragonFlyBSD |
freebsd |
FreeBSD |
linux |
Linux |
netbsd |
NetBSD |
openbsd |
OpenBSD |
solaris |
Solaris/illumos |
unix (derived) |
UNIX 계열 (BSD, Darwin, Linux, Solaris) |
windows |
Windows |
운영체제 버전 (Operating System versions)
운영체제 버전은 가능하다면 대상 트리플의 세 번째 구성 요소에서 유래합니다.
| 플래그 이름 | 설명 |
|---|---|
freebsd12 |
FreeBSD 버전 12 |
freebsd13 |
FreeBSD 버전 13 |
ABI
ABI는 대상 트리플의 마지막 구성 요소에서 유래합니다.
| 플래그 이름 | 설명 |
|---|---|
android |
Android (Bionic C 런타임) |
armhf (derived) |
하드 플로트를 쓰는 ARM EABI |
gnu |
GNU |
gnueabihf |
하드 플로트를 쓰는 GNU EABI |
msvc |
Microsoft Visual C++ |
musl |
musl |
wasi |
Web Assembly System Interface |
win32 (derived) |
Windows API |
컴파일러 옵션 (Compiler options)
컴파일러는 컴파일러 설정에 따라 이 플래그들을 설정해요.
| 플래그 이름 | 설명 |
|---|---|
release |
컴파일러가 릴리스 모드에서 동작 (--release 또는 -O3 --single-module CLI 옵션) |
debug |
컴파일러가 디버그 심볼을 생성 (--no-debug CLI 옵션 없이) |
static |
컴파일러가 정적 링크 실행 파일을 생성 (--static CLI 옵션) |
docs |
API 문서를 생성하기 위해 코드를 처리 (crystal docs 명령) |
interpreted |
인터프리터에서 실행 (crystal i) |
사용자 제공 플래그 (User-provided flags)
사용자 제공 플래그는 자동으로 정의되지 않아요. --define 또는 -D 커맨드 라인 옵션으로 컴파일러에 전달할 수 있습니다. 플래그는 foo=bar 형태로 정의하면 명시적인 문자열 값을 가질 수 있어요.
이 플래그들은 보통 특정 기능을 켜서, 획기적인 새 기능이나 레거시 기능을 활성화하거나, 새 기능의 미리보기를 보여주거나, 완전히 대안적인 동작(예: 디버깅 목적)을 켭니다.
$ crystal eval -Dfoo 'p {{ flag?(:foo) }}'
true
$ crystal eval -Dfoo=bar 'p {{ flag?(:foo) }}'
"bar"
표준 라이브러리 기능 (Stdlib features)
이 플래그들은 Crystal 프로그램을 빌드할 때 표준 라이브러리의 기능을 켜거나 끕니다.
| 플래그 이름 | 설명 |
|---|---|
gc_none |
가비지 컬렉션 비활성화 (#5314) |
debug_raise |
raise 로직 디버깅 플래그. 발생시키기 전에 backtrace를 출력. |
evloop=epoll, evloop=kqueue, evloop=libevent |
이벤트 루프 드라이버 선택 (RFC 0009). 1.15에서 도입 |
evloop=io_uring |
실험적 io_uring 이벤트 루프 드라이버 선택. 1.20에서 도입 #16264 |
io_uring_sq_thread_idle=<milliseconds> |
SQPOLL 모드 활성화 및 io_uring 이벤트 루프의 유휴 시간 설정. 1.20에서 도입 #16264 |
execvpe_impl |
시스템 함수 대신 커스텀 execvpe 구현을 선택하는 실험 플래그. 1.19에서 도입 |
skip_crystal_compiler_rt |
Crystal의 네이티브 compiler-rt 구현 제외 |
tracing |
런타임 트레이싱 지원으로 빌드 |
use_libiconv |
iconv 시스템 라이브러리 대신 libiconv 사용 |
use_pcre |
정규식 엔진으로 (PCRE2 대신) PCRE 사용. 1.8.0에서 도입 |
win7 |
Windows 7용 Win32 WinNT API 사용 |
without_iconv |
iconv/libiconv 링크 안 함 |
without_main |
main 함수 생성 안 함. 1.21에서 도입 (#17074) |
without_openssl |
OpenSSL 지원 없이 빌드 |
without_zlib |
Zlib 지원 없이 빌드 |
이 플래그들은 동시성·병렬 런타임을 선택합니다.
| 플래그 이름 | 설명 |
|---|---|
execution_context |
실행 컨텍스트 활성화 (RFC 0002). 1.16에서 도입 (#15350). 1.21부터 구식 (#17100) |
preview_mt |
레거시 멀티스레딩 런타임으로 되돌림. 0.28에서 도입 (#7546). 1.21부터 deprecated #17100 |
without_mt |
레거시 싱글스레딩 런타임으로 되돌림. 1.21에서 도입 #17100 |
언어 기능 (Language features)
이 플래그들은 Crystal 프로그램을 빌드할 때 언어 기능을 켜거나 끕니다.
| 플래그 이름 | 설명 |
|---|---|
no_number_autocast |
숫자 표현식을 자동 캐스팅하지 않고 리터럴만 캐스팅 |
no_restrictions_augmenter |
향상된 제약 증강기(restrictions augmenter) 비활성화. 1.5에서 도입 (#12103) |
preview_overload_order |
def 오버로드 사이의 더 견고한 순서 활성화. 1.6에서 도입 (#10711) |
strict_multi_assign |
일대다 대입에 대한 엄격한 의미 활성화. 1.3.0에서 도입 (#11145, #11545) |
코드 생성 기능 (Codegen features)
이 플래그들은 Crystal 프로그램을 빌드할 때 코드 생성 기능을 켜거나 끕니다.
| 플래그 이름 | 설명 |
|---|---|
cf-protection=branch, cf-protection=return, cf-protection=full |
x86·x86_64용 간접 분기 추적. OpenBSD에서 암묵적으로 설정. 1.15.0에서 도입 (#15122) |
branch-protection=bti |
aarch64용 간접 분기 추적. OpenBSD에서 암묵적으로 설정. 1.15.0에서 도입 (#15122) |
컴파일러 빌드 기능 (Compiler build features)
이 플래그들은 Crystal 컴파일러를 빌드할 때 기능을 켜거나 끕니다.
| 플래그 이름 | 설명 |
|---|---|
without_ffi |
libffi 없이 컴파일러 빌드 |
without_interpreter |
인터프리터 지원 없이 컴파일러 빌드 |
without_libxml2 |
문서 생성기의 삭제(sanitization) 없이 컴파일러 빌드. 1.19에서 도입. 참고: 기본 Makefile은 docs_sanitizer=1이 아닌 한 이 플래그를 전달 |
without_playground |
플레이그라운드(crystal play) 없이 컴파일러 빌드 |
i_know_what_im_doing |
컴파일러를 실수로 빌드하지 않도록 하는 안전 가드 |
사용자 코드 기능 (User code features)
사용자 지정 플래그는 컴파일러 제공 플래그나 다른 사용자 정의 플래그와 충돌하지 않는 한, 사용자 코드에서 자유롭게 쓸 수 있어요. 샤드에 특화된 플래그를 쓸 때는 샤드 이름을 접두사로 쓰는 것이 권장됩니다.
더 알아보기 (Learn more)
- Crystal 공식 문서 - Compile-time flags
- Platform Support — 지원되는 대상 플랫폼
- Macros — 매크로에서 컴파일 타임 플래그 사용하기