본문 바로가기

Hello, World!

첫 Rust 소스 파일을 작성해 rustc로 컴파일·실행하고 main 함수와 println 매크로의 기본 구조를 이해합니다.

설치를 마쳤으니 첫 러스트 프로그램을 만들 차례입니다. 새 언어를 배울 때 흔히 그렇듯, 화면에 Hello, world!를 출력하는 프로그램을 작성해 컴파일러 rustc로 직접 컴파일하고 실행합니다. 아래 그림처럼 소스 파일을 저장하는 것, 컴파일해 실행 파일을 만드는 것, 그 실행 파일을 실행하는 것은 각각 따로 성공해야 하는 단계입니다.

단일 Rust 파일의 컴파일과 실행 경계

main.rs 저장→rustc→대상별 바이너리→별도 실행/출력의 실제 산출물 상태이다.

main.rs를 저장한 뒤 target용 표준 라이브러리와 linker를 사용해 rustc main.rs로 실행 파일을 만들고, 대상 운영체제와 ABI 및 동적 runtime dependency가 맞는 환경에서 실행해 Hello world 출력을 확인하며 파일 위치, 빌드 실패, 실행 실패를 구분하는 과정

Rust · single file · compile process

작성·컴파일·실행은 서로 다른 완료 조건이다

rustc main.rs가 성공해야 현재 대상용 실행 파일이 생기고, 그 파일을 별도로 실행해야 출력이 나타납니다. 막힌 단계를 나누면 파일 위치, 컴파일 진단, 실행 명령을 뒤섞지 않고 확인할 수 있습니다.

저장한 단일 Rust 파일에서 출력까지의 네 단계원4노드3간선의소스저장→rustc컴파일→타깃별실행파일→별도실행을보존한다.std/linker빌드입력과OS/ABI/native-runtime실행입력은별도조건이며저장만으로기존바이너리가업데이트된다는뜻이아니다.
소스 저장main.rs · 현재 디렉터리
연결 관계소스 저장 · main.rs · 현재 디렉터리 → 컴파일러 호출 · rustc main.rs · std · linker 필요
컴파일러 호출rustc main.rsstd · linker 필요
연결 관계컴파일러 호출 · rustc main.rs · std · linker 필요 → 실행 파일 · Unix · main · Windows · main.exe
실행 파일Unix · mainWindows · main.exe
연결 관계실행 파일 · Unix · main · Windows · main.exe → 별도로 실행 · ./main / .\main.exe · Hello, world!
별도로 실행./main / .\main.exeHello, world!

빌드: std · linker · native 입력실행: 대상 OS · ABI · dependency

단일 Rust 파일 컴파일과 실행 과정 main.rs 소스를 저장하고 target용 표준 라이브러리와 linker를 사용해 rustc main.rs로 컴파일하면 Unix 계열에서는 main, Windows에서는 main.exe 실행 파일이 생성됩니다. 대상 운영체제와 ABI 및 동적 runtime dependency가 맞는 환경에서 실행하면 Hello world 출력이 나타납니다. 1 · 작성소스 저장main.rs2 · 컴파일컴파일러 호출rustc main.rs3 · 산출물실행 파일Unix · mainWindows · main.exe4 · 실행프로그램 출력./main.\main.exeHello, world!
  1. main.rs 저장

    터미널의 현재 디렉터리와 파일이 저장된 디렉터리가 같은지 먼저 확인합니다.

  2. rustc main.rs

    구문·타입 검사와 코드 생성·링크가 성공해야 실행 파일이 생깁니다. 이때 선택 target용 std 산출물과 linker·native link 입력은 빌드 전제입니다.

  3. 대상별 실행 파일 확인

    기본 호스트 빌드에서는 Unix 계열의 main, Windows의 main.exe처럼 이름과 형식이 플랫폼에 따라 달라집니다.

  4. 실행하고 출력 확인

    ./main 또는 .\main.exe를 호출합니다. 대상 OS·architecture·ABI와 동적 native library·system runtime이 맞아야 출력이 나타납니다.

file location

파일을 찾지 못함

main.rs가 저장된 위치와 터미널의 현재 디렉터리를 맞춥니다. 이 문제는 Rust 코드 진단과 별개입니다.

compile

컴파일 진단이 발생함

코드 진단뿐 아니라 선택 target용 std, linker와 native link 입력을 확인한 뒤 rustc를 다시 실행합니다. 성공 전에는 새 실행 파일을 기대하지 않습니다.

run

실행 명령이 실패함

파일 이름·권한과 대상 OS·architecture·ABI를 확인합니다. 동적으로 링크한 native library나 system runtime이 빠져도 컴파일 뒤 실행 단계에서 실패합니다.

빌드 전제: 선택 target용 std 산출물, linker, native link 입력. 실행 전제: 대상 OS·architecture·ABI, 동적 native library와 system runtime. rustc는 기본적으로 host target을 빌드하며, 두 경계의 실패를 따로 진단해야 합니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명원 4노드 3간선의 소스 저장→rustc 컴파일→타깃별 실행 파일→별도 실행을 보존한다. std/linker 빌드 입력과 OS/ABI/native-runtime 실행 입력은 별도 조건이며 저장만으로 기존 바이너리가 업데이트된다는 뜻이 아니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
소스 저장

main.rs를 컴파일 입력으로 둔다.

  • 입력: main.rs
  • 실행 파일: 아직 생성 전
  • 소스 작성과 컴파일은 다른 작업이다.
rustc 빌드

대상 플랫폼의 바이너리를 만든다.

  • 명령: rustc main.rs
  • 산출물: 대상별 실행 파일
  • rustc 성공 뒤 별도로 실행해야 출력이 발생한다.
바이너리 실행

생성 파일을 실행해 출력한다.

  • 상태: 프로그램 실행
  • 출력: 본문의 인사 문자열
  • 컴파일 진단은 프로그램 stdout과 다른 근거다.

단일 Rust 파일의 컴파일과 실행 경계

main.rs 저장→rustc→대상별 바이너리→별도 실행/출력의 실제 산출물 상태이다.

main.rs를 저장한 뒤 target용 표준 라이브러리와 linker를 사용해 rustc main.rs로 실행 파일을 만들고, 대상 운영체제와 ABI 및 동적 runtime dependency가 맞는 환경에서 실행해 Hello world 출력을 확인하며 파일 위치, 빌드 실패, 실행 실패를 구분하는 과정

Rust · single file · compile process

작성·컴파일·실행은 서로 다른 완료 조건이다

rustc main.rs가 성공해야 현재 대상용 실행 파일이 생기고, 그 파일을 별도로 실행해야 출력이 나타납니다. 막힌 단계를 나누면 파일 위치, 컴파일 진단, 실행 명령을 뒤섞지 않고 확인할 수 있습니다.

저장한 단일 Rust 파일에서 출력까지의 네 단계원4노드3간선의소스저장→rustc컴파일→타깃별실행파일→별도실행을보존한다.std/linker빌드입력과OS/ABI/native-runtime실행입력은별도조건이며저장만으로기존바이너리가업데이트된다는뜻이아니다.
소스 저장main.rs · 현재 디렉터리
연결 관계소스 저장 · main.rs · 현재 디렉터리 → 컴파일러 호출 · rustc main.rs · std · linker 필요
컴파일러 호출rustc main.rsstd · linker 필요
연결 관계컴파일러 호출 · rustc main.rs · std · linker 필요 → 실행 파일 · Unix · main · Windows · main.exe
실행 파일Unix · mainWindows · main.exe
연결 관계실행 파일 · Unix · main · Windows · main.exe → 별도로 실행 · ./main / .\main.exe · Hello, world!
별도로 실행./main / .\main.exeHello, world!

빌드: std · linker · native 입력실행: 대상 OS · ABI · dependency

단일 Rust 파일 컴파일과 실행 과정 main.rs 소스를 저장하고 target용 표준 라이브러리와 linker를 사용해 rustc main.rs로 컴파일하면 Unix 계열에서는 main, Windows에서는 main.exe 실행 파일이 생성됩니다. 대상 운영체제와 ABI 및 동적 runtime dependency가 맞는 환경에서 실행하면 Hello world 출력이 나타납니다. 1 · 작성소스 저장main.rs2 · 컴파일컴파일러 호출rustc main.rs3 · 산출물실행 파일Unix · mainWindows · main.exe4 · 실행프로그램 출력./main.\main.exeHello, world!
  1. main.rs 저장

    터미널의 현재 디렉터리와 파일이 저장된 디렉터리가 같은지 먼저 확인합니다.

  2. rustc main.rs

    구문·타입 검사와 코드 생성·링크가 성공해야 실행 파일이 생깁니다. 이때 선택 target용 std 산출물과 linker·native link 입력은 빌드 전제입니다.

  3. 대상별 실행 파일 확인

    기본 호스트 빌드에서는 Unix 계열의 main, Windows의 main.exe처럼 이름과 형식이 플랫폼에 따라 달라집니다.

  4. 실행하고 출력 확인

    ./main 또는 .\main.exe를 호출합니다. 대상 OS·architecture·ABI와 동적 native library·system runtime이 맞아야 출력이 나타납니다.

file location

파일을 찾지 못함

main.rs가 저장된 위치와 터미널의 현재 디렉터리를 맞춥니다. 이 문제는 Rust 코드 진단과 별개입니다.

compile

컴파일 진단이 발생함

코드 진단뿐 아니라 선택 target용 std, linker와 native link 입력을 확인한 뒤 rustc를 다시 실행합니다. 성공 전에는 새 실행 파일을 기대하지 않습니다.

run

실행 명령이 실패함

파일 이름·권한과 대상 OS·architecture·ABI를 확인합니다. 동적으로 링크한 native library나 system runtime이 빠져도 컴파일 뒤 실행 단계에서 실패합니다.

빌드 전제: 선택 target용 std 산출물, linker, native link 입력. 실행 전제: 대상 OS·architecture·ABI, 동적 native library와 system runtime. rustc는 기본적으로 host target을 빌드하며, 두 경계의 실패를 따로 진단해야 합니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.

관계도의 보충 설명

원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명원 4노드 3간선의 소스 저장→rustc 컴파일→타깃별 실행 파일→별도 실행을 보존한다. std/linker 빌드 입력과 OS/ABI/native-runtime 실행 입력은 별도 조건이며 저장만으로 기존 바이너리가 업데이트된다는 뜻이 아니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
소스 저장

main.rs를 컴파일 입력으로 둔다.

  • 입력: main.rs
  • 실행 파일: 아직 생성 전
  • 소스 작성과 컴파일은 다른 작업이다.
rustc 빌드

대상 플랫폼의 바이너리를 만든다.

  • 명령: rustc main.rs
  • 산출물: 대상별 실행 파일
  • rustc 성공 뒤 별도로 실행해야 출력이 발생한다.
바이너리 실행

생성 파일을 실행해 출력한다.

  • 상태: 프로그램 실행
  • 출력: 본문의 인사 문자열
  • 컴파일 진단은 프로그램 stdout과 다른 근거다.

이 교재는 터미널 명령을 중심으로 설명하지만, 러스트는 특정 편집기를 요구하지 않으므로 익숙한 IDE를 써도 됩니다. 대부분의 편집기는 러스트 팀이 만드는 rust-analyzer로 자동 완성과 오류 표시를 제공하며, 자세한 내용은 부록 D 유용한 개발 도구에 있습니다.

프로젝트 폴더 만들기

러스트 코드는 어디에 두어도 되지만, 이 교재의 예제는 홈 폴더 아래 projects 폴더에 모아 두기로 합니다. 터미널에서 다음 명령으로 projects 폴더와 그 안의 hello_world 폴더를 만들고 이동합니다. 이 명령은 Linux, macOS, Windows PowerShell에서 모두 쓸 수 있습니다.

mkdir ~/projects
cd ~/projects
mkdir hello_world
cd hello_world

Windows의 cmd에서는 홈 폴더를 %USERPROFILE%로 적습니다. cmd는 ~를 홈 폴더로 해석하지 않기 때문입니다. cd /d의 /d는 다른 드라이브의 폴더로도 이동하게 하는 옵션이고, 경로를 큰따옴표로 감싼 것은 사용자 이름에 공백이 있어도 하나의 경로로 읽게 하려는 것입니다.

mkdir "%USERPROFILE%\projects"
cd /d "%USERPROFILE%\projects"
mkdir hello_world
cd hello_world

프로그램 작성하고 실행하기

hello_world 폴더에 main.rs 파일을 만들고 다음 코드를 입력합니다. 러스트 소스 파일은 확장자가 .rs이며, 파일 이름이 두 단어 이상이면 helloworld.rs처럼 붙이지 않고 hello_world.rs처럼 밑줄로 잇는 것이 관례입니다.

main.rs
fn main() {
    println!("Hello, world!");
}

파일을 저장하고 터미널에서 hello_world 폴더에 있는지 확인한 뒤, Linux와 macOS에서는 다음 명령으로 컴파일하고 실행합니다. 첫 줄의 rustc main.rs가 소스 파일을 컴파일해 같은 폴더에 실행 파일 main을 만들고, 둘째 줄이 그 파일을 실행합니다. 컴파일과 실행이 서로 다른 명령이라는 점은 뒤의 절에서 다시 봅니다.

rustc main.rs
./main

Windows의 PowerShell에서는 실행 파일 이름이 main.exe이므로 다음과 같이 실행합니다. PowerShell은 지금 폴더의 프로그램을 이름만으로는 실행하지 않으므로, 앞에 .\를 붙여 지금 폴더에 있는 파일이라고 밝힙니다.

rustc main.rs
.\main.exe
Hello, world!

운영체제와 관계없이 Hello, world!가 출력되면 첫 러스트 프로그램을 작성한 것입니다. 출력되지 않으면 그림의 단계대로 나누어, 파일이 지금 폴더에 있는지, rustc가 오류 없이 끝났는지, 실행 명령이 맞는지를 차례로 확인하고, 설치 문제라면 러스트 설치를 다시 봅니다.

프로그램 뜯어보기

방금 만든 프로그램을 한 줄씩 살펴봅니다. 세 줄짜리 프로그램이지만 함수 정의, 매크로 호출, 문자열, 세미콜론처럼 앞으로 계속 쓸 문법이 들어 있습니다. 먼저 본문을 비운 함수의 뼈대부터 보고, 그 안에 들어가는 출력 줄은 따로 봅니다.

fn main() {

}

이 줄은 main이라는 이름의 함수를 정의합니다. main은 실행 파일이 시작될 때 가장 먼저 실행되는 특별한 함수로, 모든 실행 프로그램의 시작점입니다. 이 main은 매개변수를 받지 않고 아무것도 돌려주지 않으며, 매개변수가 있다면 괄호 () 안에 적습니다. 함수의 본문은 중괄호 {}로 감싸며, 러스트에서는 여는 중괄호를 함수 선언과 같은 줄에 두고 그 사이에 공백 하나를 넣는 것이 표준 스타일입니다.

코드 모양을 표준 스타일로 맞추고 싶다면 rustfmt라는 자동 서식 도구를 씁니다. rustfmt는 rustc처럼 러스트를 설치할 때 함께 설치되므로 따로 설치할 필요가 없으며, 자세한 사용법은 부록 D에서 다룹니다.

main 함수 안에는 다음 한 줄이 있습니다.

    println!("Hello, world!");

이 한 줄이 화면에 글자를 출력하는 이 프로그램의 전부이지만, 여기에도 눈여겨볼 점이 네 가지 있습니다. 첫째, 러스트는 들여쓰기에 탭 대신 공백 네 칸을 씁니다. 둘째, println!은 함수가 아니라 러스트의 매크로(macro)를 호출합니다. 함수였다면 ! 없이 println이라고 썼을 것이며, 이름 끝의 !는 매크로 호출이라는 표시입니다. 매크로는 코드를 만들어 내는 코드로 함수와 항상 같은 규칙을 따르지는 않으며, 매크로에서 자세히 다룹니다.

셋째, println!에 넘긴 문자열 "Hello, world!"가 그대로 화면에 출력됩니다. 넷째, 이 줄은 세미콜론 ;으로 끝나며, 세미콜론은 이 식이 끝났고 다음 식이 시작될 수 있다는 표시입니다. 다만 함수에서 보겠지만 블록의 마지막에 값을 돌려주는 식에는 세미콜론을 붙이지 않으므로, 모든 줄 끝에 기계적으로 붙인다고 기억하지는 마세요.

컴파일과 실행은 별개의 단계

앞에서 프로그램을 실행하기 전에 rustc에 소스 파일 이름을 넘겨 컴파일했습니다. C나 C++를 써 보았다면 gcc나 clang과 비슷하다는 것을 알아챘을 것입니다. 컴파일에 성공하면 rustc는 실행 파일을 만듭니다. Linux와 macOS에서는 ls 명령으로 폴더의 파일을 볼 수 있습니다.

ls
main  main.rs

Windows의 PowerShell에서는 Get-ChildItem -Name으로 이름만 출력합니다. -Name 없이 실행하면 크기와 수정 시각이 함께 나오는 표가 출력되므로, 여기서는 이름만 남겨 앞의 ls 출력과 비교하기 쉽게 합니다.

Get-ChildItem -Name
main.exe
main.pdb
main.rs

소스 파일 main.rs와 실행 파일(Windows에서는 main.exe, 다른 플랫폼에서는 main)이 보이며, Windows에서는 디버깅 정보를 담은 main.pdb도 함께 만들어집니다. 산출물의 종류는 대상 플랫폼과 빌드 설정에 따라 달라질 수 있으므로, 파일 개수보다 실행 파일이 만들어졌는지와 그 실행 결과로 성공을 판단합니다.

Ruby, Python, JavaScript처럼 한 명령으로 프로그램을 바로 실행하는 언어에 익숙하다면 컴파일과 실행이 나뉜 것이 낯설 수 있습니다. 그런 언어로 쓴 .rb, .py, .js 파일을 다른 컴퓨터에서 실행하려면 그 컴퓨터에도 해당 언어의 실행 환경이 설치되어 있어야 합니다. 러스트는 실행 전에 미리 기계어로 컴파일하는 AOT(ahead-of-time) 컴파일 언어이므로, 만들어진 실행 파일은 러스트가 설치되지 않은 컴퓨터에서도 실행할 수 있습니다.

다만 이 말에는 조건이 있습니다. 컴파일할 때는 대상 플랫폼용 표준 라이브러리와 그 플랫폼의 링커가 있어야 하고, 실행할 때는 그 실행 파일이 대상 운영체제와 CPU 아키텍처에 맞아야 하며, 동적으로 연결한 시스템 라이브러리도 실행할 컴퓨터에 있어야 합니다. 동적 연결(dynamic linking)은 실행 파일에 라이브러리의 코드 대신 필요한 라이브러리의 이름만 적어 두고, 실행할 때 운영체제가 그 라이브러리 파일을 찾아 불러오는 방식입니다. 정적 연결과 동적 연결의 차이는 C++ 교재의 컴파일과 실행 과정에서 다룹니다. 러스트 툴체인 자체는 실행할 컴퓨터에 필요하지 않습니다.

파일 하나짜리 프로그램이라면 rustc로 충분하지만, 프로젝트가 커지면 여러 파일과 외부 라이브러리, 컴파일 옵션을 관리해야 합니다. 다음 글에서 볼 Cargo는 rustc를 대신하는 컴파일러가 아니라, 프로젝트 설정 파일과 의존성을 읽어 필요한 rustc 호출과 빌드 설정, 반복 작업을 대신 맡아 주는 도구입니다. 아래 표는 rustc를 직접 부르는 방식과 Cargo 프로젝트가 무엇을 다르게 다루는지 비교합니다.

단일 파일을 rustc에 직접 넘기는 방식과 Cargo.toml이 있는 프로젝트를 Cargo로 관리하는 방식의 입력 단위, 명령, 의존성, 반복 작업과 실제 컴파일 책임을 비교한 표와 모바일 카드

Rust · rustc vs Cargo · responsibility matrix

Cargo는 컴파일러를 바꾸지 않고 프로젝트 작업을 조율한다

직접 rustc를 부르면 한 크레이트 루트와 옵션을 개발자가 조립합니다. Cargo는 manifest와 의존성 그래프를 읽어 필요한 rustc 호출, 프로필, 캐시와 실행 순서를 반복 가능하게 묶습니다.

직접 단일 파일 컴파일과 Cargo 프로젝트의 책임 경계
비교 기준직접 rustcCargo 프로젝트
입력 단위main.rs처럼 명령에 지정한 단일 크레이트 루트와 compiler 옵션Cargo.toml이 선언한 package·target 소스, feature와 의존성 그래프
기본 명령rustc main.rs 뒤 생성된 바이너리를 별도로 실행cargo build로 빌드하거나 cargo run으로 빌드 뒤 실행
의존성 책임필요한 crate artifact, --extern, 검색 경로와 관련 옵션을 호출자가 준비manifest와 lockfile을 바탕으로 버전을 해석·다운로드하고 올바른 순서로 의존성을 빌드
반복 작업대상, 최적화, 출력 경로와 실행 명령을 개발자나 별도 스크립트가 재현target·profile·feature·build script·테스트와 target/ 캐시를 프로젝트 규칙으로 재현
실제 Rust 컴파일rustc가 소스를 분석하고 코드 생성·링크Cargo가 적절한 rustc 호출을 조율하며, Rust 코드를 컴파일하는 주체는 여전히 rustc

직접 rustc · 단일 크레이트 루트

  • 입력: main.rs와 직접 지정한 compiler 옵션
  • 명령: rustc main.rs 뒤 바이너리를 별도로 실행
  • 의존성: artifact와 --extern·검색 경로를 호출자가 준비
  • 반복: 대상·최적화·출력·실행 명령을 직접 재현
  • 컴파일: rustc가 분석·코드 생성·링크

Cargo · manifest가 있는 프로젝트

  • 입력: package·target·feature·의존성을 선언한 Cargo.toml
  • 명령: cargo build 또는 cargo run
  • 의존성: manifest와 lockfile로 해석·다운로드·빌드 순서를 관리
  • 반복: profile·target·build script·테스트와 캐시를 규칙화
  • 컴파일: Cargo가 호출을 조율하고 실제 Rust 컴파일은 rustc가 수행

직접 호출이 잘 맞는 때

한 파일의 컴파일·실행 경계를 배우거나 외부 의존성 없는 작은 실험을 빠르게 확인할 때입니다.

Cargo로 넘어갈 기준

여러 target, 외부 crate, feature, 테스트, build script나 팀이 반복할 명령이 생기면 package 단위 조율이 필요합니다.

Cargo는 rustc를 대체하는 또 다른 compiler가 아닙니다. 개발자가 직접 구성하던 여러 compiler 호출과 주변 작업을 manifest 중심으로 조직하는 build system이자 package manager입니다.

더 깊이: 실행 파일 안에 들어가는 것과 빠지는 것

rustc가 기본으로 만드는 크레이트 종류는 실행 파일(bin)이며, Reference의 링크 설명에 따르면 이 형식은 러스트 의존성과 네이티브 의존성을 모두 연결해 배포할 수 있는 바이너리 하나를 만듭니다. 이때 컴파일러는 의존하는 러스트 크레이트를 먼저 정적 라이브러리 형식인 rlib에서 찾고, -C prefer-dynamic을 주었거나 rlib가 없을 때만 동적 연결을 시도합니다. 표준 라이브러리도 러스트 크레이트이므로 이 규칙에 따라 실행 파일 안에 들어갑니다. 러스트 툴체인이 없는 컴퓨터에서도 실행 파일이 동작하는 것은 이 때문입니다.

반면 C 런타임(C runtime)은 대상마다 기본 연결 방식이 따로 정해져 있습니다. Reference는 대부분의 대상이 C 런타임을 동적으로 연결하며, x86_64-unknown-linux-musl 같은 musl 대상이 예외적으로 정적으로 연결한다고 적습니다. 그래서 Linux의 흔한 x86_64-unknown-linux-gnu 대상으로 만든 실행 파일은, 실행할 컴퓨터에 그 대상이 쓰는 C 라이브러리가 있어야 합니다. 이 방식은 crt-static 대상 기능(target feature)으로 바꿀 수 있어서 -C target-feature=+crt-static이면 정적으로, -crt-static이면 동적으로 연결하며, 연결 방식을 바꿀 수 없는 대상은 이 설정을 무시합니다.

정리

  • 러스트 소스 파일의 확장자는 .rs이고, 여러 단어로 된 이름은 밑줄로 잇습니다.
  • main 함수는 실행 프로그램이 시작되는 곳이며, 본문은 중괄호로 감쌉니다.
  • println!의 !는 함수가 아니라 매크로를 호출한다는 표시입니다.
  • rustc main.rs로 컴파일해 실행 파일을 만든 뒤, 그 파일을 따로 실행해야 출력이 나옵니다.
  • 컴파일한 실행 파일은 대상 플랫폼이 맞으면 러스트가 없는 컴퓨터에서도 실행됩니다.
  • 프로젝트가 커지면 rustc 호출과 의존성 관리를 Cargo에 맡깁니다.

연습 문제

1. 저장한 소스와 실행한 파일

Hello, world!를 한 번 컴파일하고 실행한 뒤, 문자열을 Ready로 바꾸어 main.rs를 저장했습니다. (가) 다시 컴파일하지 않고 실행 파일을 실행하면 무엇이 출력되나요? (나) rustc main.rs가 성공한 뒤 실행하면 어떻게 되나요? (다) 이번에는 큰따옴표 하나를 지워 컴파일이 실패했는데, 남아 있던 실행 파일을 실행하면 무엇이 출력되나요?

해설 보기

(가)는 아직 이전 소스로 만든 실행 파일이 그대로이므로 Hello, world!가 출력됩니다. (나)는 새로 컴파일한 실행 파일이므로 Ready가 출력됩니다. (다)는 컴파일이 실패해 실행 파일이 바뀌지 않았으므로, (나)에서 만든 실행 파일의 Ready가 출력됩니다. 소스를 저장한 것, 컴파일에 성공한 것, 그 실행 파일을 실행한 것은 각각 따로 확인해야 합니다.

2. 매크로와 함수

println!("Hello, world!");에서 !를 빼고 println("Hello, world!");라고 쓰면 어떻게 될까요?

해설 보기

컴파일되지 않습니다. 컴파일러는 함수를 기대한 자리에서 println이라는 매크로를 찾았다는 E0423 오류를 내고, 끝에 !를 붙인 println!(...)을 뜻한 것이 아닌지 묻습니다. 매크로를 함수처럼 부를 수는 없으며, 이름 끝의 !가 매크로 호출이라는 표시입니다.

다음 글 Cargo 기초에서는 Cargo로 프로젝트를 만들고, 빌드와 실행, 검사를 Cargo 명령으로 하는 방법을 익힙니다.