[Linux] make - 1

 

  • 프로그램 빌드 자동화 소프트웨어
  • 여러 파일들 간의 의존성과 각 파일을 위한 명령어를 정의 한 Makefile을 해석하여 실행파일 또는 라이브러리를 빌드 함
  • 따로 옵션을 주지 않을 경우 default로 Makefile 또는 makefile 파일을 찾고, 다른 이름의 파일을 넘겨 줄 경우에는 -f 옵션으로 파일 이름을 지정 함.


  • 기본구조
Target: Dependencies
[TAB키] Commands

TAB키 부분에 SPACE키를 사용하면 안됨.

  • Target - Command 실행 결과로 만들어 지게 되는 목적(object) 파일
  • Dependencis - Target을 만들 때 의존성(연관관계)를 규정. 이 부분에 나열된 파일이 수정되면 command를 수행해서 target을 다시 만듦. 즉 target 파일의 최종 수정 시간과 dependencies에 있는 파일들의 최종 수정 시간을 비교해서 command 수행여부를 결정
  • Command - Target을 만들기 위해 실행해야 하는 명령. command는 여러줄이 될 수도 있음.
  • Comment - '#' 뒤에 오는 글자는 주석 처리 함.


Command 앞에 '@'을 붙여주면 그 명령은 화면에 출력 되지 않음.


# 커맨드 앞에 @를 붙이지 않은 경우

# Makefile

all:
	echo hello
#----------------------------------------
$ make
echo hello
hello


# 커맨드 앞에 @를 붙인 경우

# Makefile

all:
	@echo hello
#----------------------------------------
$ make
hello


예를 들어 다음과 같은 2개의 소스 파일과 1개의 헤더 파일이 있다고 할 때,

/* add.h */
int add(int x, int y);

// --------------------------------------------------------------------------------------------

/* add.c */
#include "add.h"

int add(int x, int y)
{
	return x + y;
}

// --------------------------------------------------------------------------------------------

/* main.c */
#include <stdio.h>
#include "add.h"

int main(void)
{
        int value = 0;
        value = add(3, 5);
        printf("%d\n", value);

        return 0;
}


Makefile은 다음과 같이 작성 할 수 있다.

# Makefile

result: main.o add.o
	gcc main.o add.o -o result

main.o: main.c
	gcc -c main.c
    
add.o: add.c
	gcc -c add.c

쉘에서 make 명령어를 입력하면, 오브젝트 파일과 실행 파일이 생성 된다.


그럼 이제 Makefile 을 조금씩 고쳐 나가 보자.

일단 변수를 사용하여 반복되는 커맨드를 대체 해 보자. 커맨드에서 반복되는 gcc를 다음과 같이 변수를 사용하여 대체 할 수 있다.

# Makefile

CC = gcc

result: main.o add.o
    $(CC) main.o add.o -o result

main.o: main.c
    $(CC) -c main.c

add.o: add.c
    $(CC) -c add.c

gcc 부분은 개발환경에 따라 크로스컴파일러로도 변경 될 수 있으니, 나중에 CC 변수의 값만 변경 하면 된다.


그 다음단계는 변수를 좀 더 사용하여 컴파일러 옵션과 실행파일 및 의존파일을 대체 해 보자

# Makefile

CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o

$(TARGET): $(OBJS)
    $(CC) $(OBJS) -o $(TARGET)

main.o: main.c
    $(CC) $(CFLAGS) main.c

add.o: add.c
    $(CC) $(CFLAGS) add.c


다음엔 내장 매크로를 사용하여 보자.

  • $< : 의존관계 파일 중에 첫 번째 파일로 대치 됨
  • $^ : 의존관계 파일 전체로 대치 됨
  • $@ : target으로 대치 됨
  • $* : 확장자가 없는 target 으로 대치 됨
  • $? : 의존관계 파일 중에 target 보다 새로운 파일들 목록으로 대치 됨


의존관계에 있는 C 파일들을 커맨드라인에서 $< 를 사용하여 대치 해 보자.

# Makefile

CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o

$(TARGET): $(OBJS)
    $(CC) $(OBJS) -o $(TARGET)

main.o: main.c
    $(CC) $(CFLAGS) $<

add.o: add.c
    $(CC) $(CFLAGS) $<

하지만 C 파일이 점점 늘어 날 수록 Makefile의 라인 수는 점점 늘어날 것이므로 문제가 된다.


중복이 발생 하는 부분은 C 소스파일을 컴파일하여 오브젝트 파일을 만든다는 부분이다.

다음과 같은 방법으로 획기적으로 중복이 발생 하는 부분을 줄일 수 있게 된다.

# Makefile

CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o

$(TARGET): $(OBJS)
    $(CC) $(OBJS) -o $(TARGET)

%.o: %.c
    $(CC) $(CFLAGS) $<


최종적으로 오브젝트 파일과 실행파일을 정리할 수 있는 clean 더미 타겟을 추가하고, 내장 매크로를 사용하면 다음과 같이 Makefile을 작성 할 수 있다.

# Makefile

CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o

$(TARGET): $(OBJS)
    $(CC) $^ -o $@

%.o: %.c
    $(CC) $(CFLAGS) $<

clean:
    rm -rf $(OBJS) $(TARGET)



이 블로그의 인기 게시물

Crusader Kings 3 - Converting DNA code using Portrait Editor