컴파일 타임 플래그

컴파일 타임 플래그 (Compile-time flags)

컴파일 타임 플래그(compile-time flag)는 컴파일러가 매크로 메서드를 통해 제공하는 불리언 값이에요. 이 값 덕분에 컴파일 타임 조건에 따라 코드를 조건적으로 포함하거나 제외할 수 있습니다. 어떤 운영체제용으로 컴파일되는지를 확인해 분기하고 싶을 때 딱 맞는 도구죠.

컴파일러에는 컴파일러 옵션과 대상 플랫폼에 대한 정보를 담은 기본 플래그가 여럿 있어요. 사용자 플래그는 컴파일러에 전달되며, 기능 플래그(feature flag)처럼 쓸 수 있습니다.

출처: Crystal 공식 문서 - Compile-time flags

본문

플래그 조회하기 (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에서 도입.
참고: 기본 Makefiledocs_sanitizer=1이 아닌 한 이 플래그를 전달
without_playground 플레이그라운드(crystal play) 없이 컴파일러 빌드
i_know_what_im_doing 컴파일러를 실수로 빌드하지 않도록 하는 안전 가드

사용자 코드 기능 (User code features)

사용자 지정 플래그는 컴파일러 제공 플래그나 다른 사용자 정의 플래그와 충돌하지 않는 한, 사용자 코드에서 자유롭게 쓸 수 있어요. 샤드에 특화된 플래그를 쓸 때는 샤드 이름을 접두사로 쓰는 것이 권장됩니다.

더 알아보기 (Learn more)