Cmake, Makefile 실습

최현진·2023년 1월 3일
0

ㅇMpeon

목록 보기
3/9
post-thumbnail

Build

빌드는 다음의 세가지 상태로 과정을 구분하여 나뉜다

  • 소스파일
  • 목적파일
  • 실행파일

소스파일은 우리가 평소에 에디터에서 편집하고 수정할수있는 형태의 파일들로 *.c형태의 파일들을 의미하고, 목적파일은 *.o형태의 파일들이다, 실행파일은 최종적으로 빌드가 완료된 후 실행할수 있는 파일로 unix에선 .out, windows에선 .exe등으로 표기된다

Makefile 생성 전 준비

먼저 디렉토리를 하나 생성후, main.c에 의존성을 지닌 hum.c와 anm.c를 생성해준다.

실습용으로 사용할 각 소스파일의 내용들은 다음과 같다

main.c

#include "main.h"

int main(){
	printf("Hello, I'm main!\n");
    
    proc_hum();
    proc_anm();
}

main.h

#include <stdio.h>

void proc_anm();
void proc_hum();

anm.c

#include "main.h"

void proc_anm(){
	printf("Hello, I'm ANIMAL()\n");
}

hum.c

#include "main.h"

void proc_hum(){
	printf("Hello, I'm HUMAN()\n");
}

이후 만들어진 파일들을 gcc컴파일러로 컴파일 하는 과정이 필요하다, 그리고 이 과정에서 소스파일인 *.c 파일이 논리파일인 *.o파일로 바뀌게 되는것이다.
gcc -c (논리파일을 만들 소스파일) 명령어를 통해 main.c hum.c anm.c파일들의 논리파일을 생성해 주었다.
만들어진 논리파일들은 또다시 gcc 컴파일러로 실행 가능한 파일이 되게끔 빌드를 해주어야 한다.
위와 같이 새로운 실행파일인 app.out 이 생성된것을 확인할 수 있다.

기본적으로 실행파일의 이름을 지정하지 않을 경우에는 a.out 의 형태로 나타나게 되지만, gcc -o 다음 이름을 지정해서 써준다면 지정한 이름의 실행파일을 생성할수있다

위와같이 실행시켜보면 잘 출력되는것을 확인할수 있다.

Makefile의 이용

하지만 이렇게 목적파일과 실행파일을 일일히 빌드하고 생성해주게 된다면 위와같이 작은파일이 아니고서야 일일히 파일지정,빌드,실행파일생성,실행 의동작이 시간이 오래 걸릴수 밖에 없을것이다. 그리하여 Makefile을 이용하여 이러한 동작들을 단순화할수 있다는 장점이 Makefile을 사용하는 이유이다.

Makefile 사용

먼저 같은 디렉토리 내에 Makefile이라는 파일을 생성해준다.

※ 주의사항
Makefile을 생성할때에는 첫 글자인 M을 무조건 대문자로 생성해주어야 컴퓨터가읽고서 실행할수있다.

생성후에 다음과 같이 작성해준다

all : hello.out

main.o :
	gcc -c main.c
hum.o :
	gcc -c hum.c
anm.o : 
	gcc -c anm.c
hello.out : main.o hum.o anm.o
	gcc -o hello.out main.o hum.o anm.o

기본적으로 Makefile의 구조는
Target : Dependency
Command
의 구조를 가지고 있다고 할수있다
main.o의 부분을 예로 들어보자면.
타겟은 main.o 이고 의존성을 가지고 있지않으니 pass.
커맨드로 gcc 컴파일러를 이용해 main.c 파일을 컴파일 할것이라는 것을 명시해주는 것이다.

Target(Main.o) : Dependency(없음)
Command(gcc컴파일러로 main.c를 컴파일 하라)

정리하면 위와 같은 말을 명령어로 지정해줄수 있다고 하는것이다.
그렇다면 의존성이 있는 출력파일의 경우에는?
dependency 부분에 관계있는 파일들을 나열해주면 된다.
위와같이 지정해줄수 있다.

그렇다면 맨 위의 all명령어는 무엇일까?
기본적으로 Makefile은 절차지향형으로써 우리가 위에서 만들었던 Makefile을 순차적으로 읽은 다음 실행한다
이 과정에서 all로 일명 더미타겟을 지정해놓지 않는다면, Makefile은 제일 첫 target만 실행시키고 종료시킬수가 있다 그리하여 all타겟을 지정해줌으로써 순서 상관없이 원하는 결과물을 도출해낼수가 있게된다.

완성된 코드

변수선언

위의 완성된 코드와 다음 코드를 비교해보자
무엇이 달라졌을까?
바로 gcc를 변수로 선언하여 프로그램을 만들었다는것이다.
Makefile에서는 여러가지 커맨드들을 변수로 선언한다음 사용자가 원하는 만큼 사용자화 해서 사용할수가 있다, 실제로 위에서 다른 이용자가 컴파일러를 g++로 변경하고 싶다면, 방금전 완성된 코드와는 다르게 위의 코드에서 CC 부분을 g++로만 변경해주면 된다.
이런식으로 선언을 수정하면 된다.
위의 코드에서 보듯, 변수선언은 간단히 변수 = 값 으로 지정할수가 있고 본문에서 사용할때에는 $(변수이름)식으로 쉽게 사용이 가능하다.

  • 변수선언
    변수 = 값
  • 변수사용
    $(변수 이름)

그렇다면 타겟도 지정하여 변수 선언을 할수있을까?
물론 가능하다.
기존 코드를 위와같은 형식으로 변환하여 사용가능하다.

*추가사항
Dependency도 환경변수로 추가가 가능하다, 이에따라 프로젝트를 구성하는 파일이 증감하더라도 변수를 적절히 수정하기만 하면 굳이 하나하나 찾아다닐 필요가 없다.
환경변수로 추가하여 코드를 수정한 모습

완벽하게 출력이 가능하다.

Cmake

위와같이 Makefile에 대해서 알아봤는데, Makefile은 의존성을 가진 파일들이 늘어날수록, 프로젝트가 커질수록 점점더 복잡해져서 Makefile하나만으로는 감당할 수 없기 때문에, 여러 Makefile을 중첩시키는 식으로 관리를 하게된다
이러한 과정속에서 이 많은 makefile들을 관리하기 어렵기 때문에 이를 관리하기 위해 나온것이 Cmake라고 지난번 개념잡기에서 정리해놓았다.
그렇다면 이번에는 Cmake에 대해서 알아보도록 하자

실습전 준비

Cmake는 vs code상에서 실습해보도록 하겠다.
expansion탭에서 cmake를 설치해주자.
간단한 프로그램을 통해 Cmake를 다루는 법을 배운다
위의 프로그램을 사용자의 아무 디렉토리에 저장한다.
그런다음, vs code 단축키 Ctrl + Shift + ` 나 상단의 <터미널> 탭에서 새 터미널을 선택하여 터미널을 실행시킨다
문제없이 실행 되었다.

같은 디렉토리 내에 CMakeLists.txt 라는 파일을 하나 생성해준다. cmake가 깔려있다면 자동으로 cmake파일이 만들어진다.cmake파일이 만들어졌다
코드를 보면서 하나씩 살펴보자
가장 먼저 cmake_minimum_required(원하는 버전 3.10추천)라는 명령어(command)를 통해 Cmake의 최소 실행 버전을 지정해준다 그후, 프로젝트 이름을 project(원하는 이름)으로 설정해줄수 있다

message 는 원하는 항목의 메세지를 cmake를 실행시킬때에 띄울수있게 해주는 커맨드이다, 다음과 같이 환경변수,ID,버전등을 나타나게 설정할수 있다.

add_executable은 add_executable((실행파일명) (소스파일) (소스파일...))의 식으로 구성되어있으며 최종 빌드를 위한 명령어이다. 간단한 구성만으로도 최종 빌드 명령어를 통해 결과물을 도출해낼수 있다.

결과물

먼저, 터미널에서 cmake . 명령어를 실행시켜준다.
현재 디렉토리에서 cmake 빌드를 수행하겠다는 의미이다
방금 설정했던것과 같이 컴파일러의 정보를 확인할수있는걸 볼수있다.
이렇게 하면 현재 디렉토리에 cmake 지시서를 기반으로 Makefile이 하나만들어 지는데, 여기서 makefile에게 make명령어로 빌드를 지시하면 된다.

다음과 같이 program 실행파일의 빌드가 완료된것을 확인할수 있다.실행 또한 정상적으로 실행이 가능하다

profile
Lorem ipsum dolor sit amet

0개의 댓글