우분투에서 C++ 개발하기 (2) - Make

우분투에서 C++ 개발하기 (1) : https://ladofa.blogspot.com/2018/07/c-1.html


 1탄을 만들어 놓고 몇 년이 흘렀는가 모르겠다. 2탄을 만들게 될 줄도 몰랐다.

하여튼 이어서 makefile에 대해서 알아본다.

C나 C++을 사용하다 보면 수도 없이 컴파일 하고 빌드하고 이런 일이 반복되는데 매번 라이브러리 경로와 관련된 라이브러리 파일과 기타 등등등을 입력하는 것도 번거롭고 새로 수정한 파일이 무엇인지 따라다니면서 컴파일하는 것도 힘들다. 그래서 리눅스에서는 Makefile이란 툴을 쓴다. 윈도우에서 Visual Studio로 개발하면 이런 거 필요없는데.

Makefile은 빌드에 필요한 스크립트를 텍스트 형식으로 저장한 파일이다. 이 파일은 반드시 이름이 Makefile 이어야 한다. 확장자 없이 이름만 Makefile 이면 된다. 무슨 파일 이름이 Makefile이냐. ...

Makefile 속에 있는 스크립트를 해석해서 실행하는 프로그램은 make이다. 프로그램 이름이 make 다. make를 실행하면 실행한 현재 경로에서 Makefile을 찾아내고 요걸 해석해서 빌드를 수행한다.


우선 다음과 같은 예제를 생각해보자.

<my.h>

int my_func(int x);


<my.cpp>

#include "my.h"

int my_func(int x)

{

    return x * x;

}


<main.cpp>

#include <iostream>

#include "my.h"

int main(void)

{

    printf("%d^2 == %d\n", 3, my_func(3));

}


뭐 이렇게 간단히 구성되어 있다고 하자. 요걸 컴파일 하려면 1탄에서 배운 대로 다음과 같이 입력해야 할 것이다.

$ g++ -c my.cpp

$ g++ -c main.cpp

$ g++ -o test main.o my.o


매번 이렇게 하기 귀찮으니까 이제 Makefile을 이용할 차례이다. Makefile 은 타깃의 집합이다. 타깃은 다음과 같이 서술해야 한다.

[타깃이름]: [타깃에 필요한 파일들]

      [타깃 실행 코드]

여기서 타깃 이름은 그냥 아무 이름이 될 수도 있고, 파일명이 될 수도 있다. 실행 코드를 통해 결과 파일 하나가 확실히 나오는 경우에는 타깃 이름을 파일명으로 한다. 예를 들어

<Makefile>

my.o: my.h my.cpp

    g++ -c my.cpp

이와 같이 Makefile을 작성할 수 있다. 달랑 두 줄이다. 여기서 중요한 것은 두 번째 줄 앞에 있는 공간이 탭 하나이다. 지금 블로그를 작성할 때는 어쩔 수 없이 스페이스를 때려 넣었지만 실제로는 반드시 1탭이어야 한다.

이제 아래와 같이 실행한다.

$ make my.o

그 결과로 my.o 파일이 생성된다. 만약 이미 생성되었다면 up to date. 메시지가 뜰 것이다.


하나의 타깃은 다음 타깃의 재료가 될 수 있다. my.o 그리고 main.o 는 링커에서 실행 파일을 만드는 재료가 된다. 혹은 재료가 필요 없는 명령도 있다. 다음 예를 보자.

<Makefile>

my.o: my.h my.cpp

    g++ -c my.cpp


main.o: my.h main.cpp

    g++ -c main.cpp


test: my.o main.o

    g++ -o test main.o my.o


all: test


clear:

    rm -f my.o main.o test


여기서 my.o 와 main.o 는 test의 재료가 된다. 만약 make test를 했는데 my.o가 존재하지 않는다면 해당 타깃부터 만들고 난 뒤에 test를 만들게 된다. 한 번 더 make test를 실행하면 기존에 모든 것이 이미 있으므로 더 이상 작업을 진행하지 않는다. 파일을 수정하고 나면 수정된 파일을 재료로 하는 타깃만 새로 빌드될 것이다.

all 타깃은 재미있게도 실행 명령이 없고 타깃만 명시되어 있다. make all 을 실행하게 되면 그 재료가 되는 test를 만들 것이다. 만들고 나서 특별히 할 일은 없다.

clear는 반대로 타깃 파일이 없다. 보통은 타깃 파일이 존재해야 그 다음으로 명령문을 수행하게 될테지만 요구사항이 되는 타깃이 없으므로 그냥 무조건 명령을 수행하게 된다.

all, clear, install 이 세 가지 타깃은 모든 Makefile에서 관용적으로 쓰이는 것들이다. 모르는 설치파일이라도 우선 make install 부터 실행해보면 된다.


여기까지 이해했으면 이제 위키피디아에서 제공하는 샘플 Makefile을 살펴보자.

맨 윗줄에 있는 것들은 환경변수이다. 환경 변수의 이름 역시 암묵적으로 정해져 있다. 왤케 암묵적인게 많냐... $(OBJ)을 보면 타깃 여러 개를 한 번에 지정하고 있다. 그리고 이상한 기호들이 보이는데 $@는 타깃 이름, $^는 재료 이름, $<는 재료 중 맨 첫번째 항목을 의미한다. 

대충 이 정도면 원리는 이해한 셈이고, 그 밖에 엄청난 규칙들이 많다. 심지어는 요즘도 버전업이 되고 있다. 나머지는  http://doc.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-4.html 이런 곳에서 자세히 살펴보길 바란다.


요즘은 CMake나 다른 툴을 이용하고 Makefile은 거의 안 쓰기는 하지만 그래도 기본 원리 정도는 어렵지 않으므로 알고 있는 것이 좋다. 임베디드나 기타 작은 소프트웨어에서는 여전히 직접 작성해서 쓰기도 한다.


다음으로는 CMake를 사용한 컴파일 과정을 간단히 살펴볼 것이다.


우분투에서 C++ 개발하기 (3) - CMake

댓글 5개:

  1. 감사합니다 도움 많이 되었습니다! 2년의 공백기 끝에 계속 연재해주셔서 감사합니다ㅋㅋㅋㅋㅋㅋ

    답글삭제
    답글
    1. 저야말로 방문해주셔서 감사합니다 여기 저기 감사가 넘치는군요 ㅋㅋㅋ

      삭제
  2. waited two whole years for this, keep up the good work bro

    답글삭제

Powered by Blogger.