make와 cmake를 다루기 전에 gcc 빌드 과정을 간단히 알아보자

gcc 빌드 과정

빌드(build)란?

소스코드 => 실행 가능한 프로그램으로 변환하는 과정

아래의 과정을 거친다

https://medium.com/@laura.derohan/compiling-c-files-with-gcc-step-by-step-8e78318052

전처리 (Preprocessing)

  • 전처리기 지시어 (#include, #define 등)를 처리
  • 헤더 파일을 포함하고 매크로를 확장하며 조건부 컴파일 수행
  • 결과물은 전처리가 끝난 C언어 형태

컴파일 (Compilation)

  • 전처리된 소스코드(.i 파일)을 기계어로 변환 가능한 중간 단계의 어셈블리 코드로 변환
  • 이 과정에서 문법 오류나 타입 관련 오류 등이 발견
  • 결과물은 어셈블리 코드 파일(.s)

어셈블링 (Assembling)

  • 어셈블리 코드 (.s)를 목적파일(Objective File) (.o)로 변환
  • 목적파일은 기계가 읽을 수 있는 이진코드 형태이지만 완전히 실행가능한 상태는 아님 

링킹(Linking)

  • 목적파일(.o)와 필요한 여러 라이브러리 파일을 연결하여 실행 파일 (.out 또는 .exe)을 생성
  • 링커는 프로그램에서 사용하는 모든 함수와 변수가 정의된 위치를 찾아 연결
  • 특정 함수나 변수가 정의되지 않았다면 링킹 오류 발생

 

크게 묶으면

하나의 소스코드를 Preprocessing, Compilation, Assembling을 거쳐서 Objective File을 만들고,

만들어진 Object files + 라이브러리들을 모아 Linking 하는 것이 빌드의 과정이다.

 

예시 진행

간단하게 예시로 진행하자.

폴더를 만들고 해당 폴더  안에 main.c, hyndrome.c, hyndrome.h 를 생성해보자

// main.c
#include <stdio.h>
#include "hyndrome.h"

int main()
{
    printf("I'm main!\n");
    Hyndrome();

    return 0;
}
// hyndrome.h
void Hyndrome();
// hyndrome.c
#include <stdio.h>

void Hyndrome()
{
    printf("I'm HYndrome!\n");
}

 

.c파일을 각각 컴파일, 어셈블링하자

gcc -c main.c
gcc -c hyndrome.c
ls

만들어진 .o 파일들과 라이브러리 함수들을 하나로 Linking하자

gcc main.o hyndrome.o -o go
ls
./go

GCC 는 똑똑해서 굳이 나눠서 작업하지 않아도 동작한다.

만들었던 .o 파일과 실행 파일을 지우고 다시 빌드해보자

rm -r *.o
rm -r ./go
ls
gcc ./*.c
ls
./a.out

 

빌드 자동화 시작

bash shell script (.sh)를 활용해서 위 과정을 다시 진행해보자

build.sh 파일을 생성하고 아래 코드를 작성한다.

#! /bin/bash
gcc -c ./main.c
gcc -c ./hyndrome.c
gcc ./main.o ./hyndrome.o -o ./go
rm -r ./*.o

 

source 로 .sh 파일을 실행할 수 있다.

source build.sh
./go

 

이렇게 shell script로 빌드를 자동화할 수는 있지만

중간에 파일 하나라도 변경점이 생긴다면 모든 파일을 다시 빌드해야하는 문제점이 있다!

make

소프트웨어 빌드를 자동화하는 데 사용되는 도구로, 주로 소스 코드를 컴파일하여 실행 가능한 프로그램으로 만드는 작업을 간소화하기 위해 사용된다

Makefile이라는 특별한 형식의 파일과 문법을 사용한다

 

make 설치

sudo apt install make -y

 

make 사용방법

  1. Makefile 스크립트 파일을 만든다
  2. make 명령어로 실행한다

예제 실습

파일 이름을 Makefile로 아래 코드를 작성한다.

go : main.o hyndrome.o
    gcc main.o hyndrome.o -o go
main.o : main.c
    gcc -c main.c
hyndrome.o : hyndrome.c
    gcc -c hyndrome.c
clean :
    rm -r ./*.o ./go

정상 작동 확인

다시 make를 사용하여 빌드를 하면 변경사항이 없어서 build가 되지 않는 것을 확인할 수 있다.

그러면 hyndrome.c 파일을 조금 수정해서 다시 빌드해보자.

// hyndrome.c
#include <stdio.h>

void Hyndrome()
{
    printf("I'm updated HYndrome!\n");
}

처음 make를 사용해서 빌드했을 때 와 다르게 gcc -c main.c 는 컴파일 안된 것을 확인할 수 있다.

변동사항이 생긴 hyndrome.c, hyndrome.c 변동사항으로 인해 변화가 생긴 hyndrome.o에 연동된 빌드들만 다시 진행된 것을 확인할 수 있다!

make는 특정 키워드로 동작시킬 수 있다

make clean

make 장점

  • build 자동화
    • 기술된 순서대로 build 작업을 수행하는 자동화 스크립트 지원
  • build 속도 최적화
    • 파일간의 의존성을 추적하여 파일이 변경된 경우에만 컴파일한다!

CMake

Makefile을 자동으로 생성해주는 build system

크로스 플랫폼 빌드 자동화 도구

 

CMake 설치

sudo apt install g++ cmake -y

 

CMakeList.txt 파일을 작성한다

cmake_minimum_required(VERSION 3.5)
project(HYndromeProject)

# 빌드할 실행 파일(go)과 소스 파일들을 정의합니다.
add_executable(go main.c hyndrome.c)

# 헤더 파일이 있는 디렉토리를 포함시킵니다.
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# 실행 파일(go)이 사용하는 헤더 파일(hyndrome.h)을 명시합니다.
target_include_directories(go PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

 

cmake한다

cmake .

 

약 200 줄 정도의  Makefile이 생성된 것을 확인할 수 있다!

 

생성된 Makefile로 빌드해보자!

정상적으로 빌드된 것을 확인할 수 있다.

+ Recent posts