rokdocs
v0.1

3.6. env:: - 환경 변수 / args / 디렉토리

rok::std::env 모듈은 프로세스의 environment 에 접근하기 위한 일관된 진입점을 제공합니다. 명령행 인자, 환경 변수, 표준 디렉토리 경로를 OS 차이를 가리고 한 자리에서 다룰 수 있도록 묶어 두었습니다.

3.6.1. API

먼저 모듈이 노출하는 함수와 타입을 한눈에 살펴봅니다.

// 명령행 인자
fn args() -> List<str>;                        // [0] = 프로그램 이름 - 런타임이 시작 시 argc/argv 를 잡아 둠
fn args_os() -> List<RawStr>;                  // non-UTF-8 보장 (rare)

// 프로세스 종료
fn exit(code: i32) -> !;                       // 즉시 종료 - 런타임 rok_exit 호출, 진입점 규칙은 refs-lang 4.16

// 환경 변수
fn var(name: str) throws (VarError) -> str;
fn var_os(name: str) -> RawStr | none;
fn vars() -> Vars;                             // Iterator<Item = (str, str)> 구현
fn vars_os() -> VarsOs;                        // Iterator<Item = (RawStr, RawStr)> 구현

fn set_var(name: str, value: str);            // 주의 - multi-thread 시 race
fn remove_var(name: str);

// 디렉토리
fn current_dir() throws (IoError) -> Path;
fn set_current_dir(path: Path) throws (IoError);
fn home_dir() -> Path | none;
fn temp_dir() -> Path;
fn config_dir() -> Path | none;               // macOS ~/Library/Application Support, 그 밖 $XDG_CONFIG_HOME / ~/.config
fn cache_dir() -> Path | none;                // macOS ~/Library/Caches, 그 밖 $XDG_CACHE_HOME / ~/.cache
fn data_dir() -> Path | none;                 // macOS ~/Library/Application Support, 그 밖 $XDG_DATA_HOME / ~/.local/share

// PATH 환경 변수 split (OS 별 구분자)
fn split_paths(paths: str) -> List<Path>;     // ":" on unix, ";" on windows
fn join_paths<I: Iterator<Item = Path>>(paths: I) throws (JoinPathsError) -> str;

// 실행 파일 자체
fn current_exe() throws (IoError) -> Path;

// 프로세스 ID
fn pid() -> u32;
fn parent_pid() -> u32 | none;

enum VarError {
    NotPresent,                                 // 변수가 없음
    NotUnicode,                                 // 값이 UTF-8 이 아님 (var_os 로 읽음)
}

RawStr 은 OS 가 준 바이트열 그대로의 문자열입니다 (UTF-8 이 아닐 수 있음). JoinPathsError 는 경로 하나가 구분자 (: / ;) 를 담고 있을 때입니다.

struct RawStr { /* OS 바이트 */ }

impl RawStr {
    fn len(self) -> usize;                       // 바이트 길이
    fn is_empty(self) -> bool;
    fn to_str(self) throws (Utf8Error) -> str;   // UTF-8 이 아니면 throw
    fn as_bytes(self) -> List<u8>;
}
impl PartialEq for RawStr { ... }
impl Debug for RawStr { ... }

struct JoinPathsError { path: str; }             // 구분자를 담은 경로

Windows 에서 바이트는 OS 의 UTF-16 을 WTF-8 로 담은 것이며, 거기서는 다음도 있습니다.

impl RawStr {
    fn from_wide(wide: List<u16>) -> RawStr;
    fn as_wide(self) -> List<u16>;
}

3.6.2. 사용 예

이제 실제 프로그램에서 이 API 들이 어떻게 어울려 동작하는지 살펴봅니다. 다음 예제는 명령행 인자, 환경 변수, 그리고 PATH 탐색까지 전형적인 흐름을 한 번에 보여 줍니다.

use rok::std::env;

// CLI 도구
fn main() {
    let args = env::args();
    if args.len() < 2 {
        eprintln("usage: tool <input>");
        env::exit(1);
    }
    let input = args[1];
    process(input);
}

// 환경 변수
let log_level = (try? env::var("LOG_LEVEL")) ?? "info";
let home = env::home_dir() ?? panic("HOME not set");
let config = home / ".config" / "myapp.toml";

// PATH 검색
let path_str = try env::var("PATH");
for dir in env::split_paths(path_str) {
    let candidate = dir / "myprog";
    if fs::exists(candidate) {
        log("found at {candidate:?}");
    }
}

3.6.3. set_var 의 multi-thread 위험

편의상 제공되는 set_var 에는 한 가지 주의해야 할 함정이 있습니다. 다른 스레드가 같은 시점에 환경 변수를 읽거나 쓰면 race 가 발생할 수 있다는 점입니다.

// 위험 - 다른 thread 가 동시에 var 호출 시 race
thread::spawn(|| { env::set_var("X", "1"); });
thread::spawn(|| { env::var("X"); });

POSIX 의 setenv / getenv 는 스레드 안전을 보장하지 않습니다. rok 표준 라이브러리가 global mutex 로 보호를 시도하기는 하지만, FFI 호출이나 signal handler 안에서는 여전히 race 가 발생할 여지가 있습니다.

따라서 권장 사용 패턴은 단순합니다. set_var 는 프로그램 시작 시점, 즉 main 의 첫 작업으로만 호출하세요. 그래야 이후 multi-thread 환경에서 silent corruption 을 피할 수 있습니다.

3.6.4. impl / target

플랫폼마다 동일한 의미를 어떻게 구현하는지는 다음 표에 정리됩니다.

항목linux/macos/windowswasi
argsargc/argv / GetCommandLinewasi:cli
var / varsgetenv / GetEnvironmentVariablewasi:cli
home_dir$HOME / SHGetKnownFolderPathwasi (no concept)
temp_dir$TMPDIR / GetTempPathwasi
config_dirXDG / AppData(no)
current_exe/proc/self/exe / _NSGetExecutablePath / GetModuleFileNameUnsupported (wasm32)

이때 표준 경로는 macOS 에서는 ~/Library/..., 그 밖의 Unix 에서는 XDG Base Directory spec ($XDG_*_HOME 이 절대 경로일 때만 쓰고, 아니면 ~/.config 등), Windows 에서는 Known Folders 를 사용합니다. 홈 디렉토리를 알 수 없으면 none 입니다.

GitHub에서 이 페이지 고치기