[C] C언어 디버깅, MakeFile

wrld_worthy·2023년 11월 3일

C

목록 보기
5/6

C언어 디버깅, MakeFile

프로그그래밍에서 디버깅과 빌드 자동화는 개발자가 효율적으로 코드를 작성하고 유지 보수하는데 필수적인 과정이다. C언어는 저수준 언어의 특성을 가지고 있어서 디버깅과 빌드 자동화의 중요성이 더욱 강조된다.

C언어 디버깅

왜 디버깅을 해야할까?

  • 버그 식별: 프로그램의 오류(버그)를 찾아내고 원인을 분석하기 위해.
  • 효율적 수정: 코드의 문제점을 정확하게 식별하고, 최소한의 수정으로 정확하게 해결하기 위해.
  • 시간 절약: 시스템 적으로 문제를 진단하여 문제 해결에 걸리는 시간을 줄이기 위해.

특징

  • 브레이크 포인트 설정: 프로그램의 실행을 특정 지점에서 멈추게 하여 해당 지점의 변수 값 등을 조사할 수 있다.
  • 단계별 실행: 프로그램을 한 줄씩 실행하면서 문제가 발생하는 지점을 찾을 수 있다.
  • 변수 감시: 프로그램 실행 중 특정 변수의 값 변화를 지켜보며 문제를 분석할 수 있다.

장단점

  • 장점: 버그의 정확한 위치와 원인을 신속하게 파악할 수 있음.
  • 단점: 초보자에게 다소 복잡하고 어려울 수 있다.

GCC를 활용한 사용법

GCC를 사용하여 디버깅 정보를 포함시키려면 -g옵션을 사용한다.

gcc -g -o program source_file.c

그 후에 gdb(GNU Debugger)같은 디버거를 사용하여 프로그램을 디버깅한다.

gdb ./program

MakeFile

MakeFile은 소프트웨어 빌드 자동화 도구인 make의 설정 파일이다. 대규모 소프트웨어 프로젝트에서 소스 코드 파일을 컴파일하고 관련 파일을 링크하여 실행 가능한 프로그램을 만드는 복잡한 과정을 간소화하고 자동화하기 위한 프로그램이다.

make 유틸리티를 사용할 때, 이 유틸리티는 MakeFile이라는 특별한 파일을 찾아 지시에 따라 작업을 수행한다. MakeFIle을 명령어를 미리 정의해두고, 필요할 때 해당 명령어들을 순서대로 실행하여 빌드 과정을 자동화 한다.

배경

원래 소프트웨어 프로젝트에서 소스 파일을 수동으로 컴파일하고 링크하는 것은 시간이 많이 걸리고, 에러가 발생하기 쉬운 과정이었다. 이러한 문제를 해결하기 위해 빌드 자동화 도구가 필요했고, 그 결과 MakeFIle과 make 유틸리티가 개발되었다.

특징

  1. 종속성 추가: 파일 간의 의존성을 파악하고 ,변화가 있는 파일만 재 컴파일하여 시간을 절약한다.
  2. 재사용 가능: MakeFile은 프로젝트마다 재작성하는 것이 아니라, 일정한 패턴을 가지므로 다른 프로젝트에도 쉽게 재사용할 수 있다.
  3. 변수와 패턴 규칙 사용: 코드의 중복을 줄이고, 유지 보수를 용이하게 한다.
  4. 조건부 실행: 특정 조건에 따라 다른 명령어를 실행할 수 있다.

기본 구조

target: dependencies
    command
  • target: 빌드 과정의 최족 목표 또는 중간 결과물을 나타낸다.
  • dependancies:해당 타겟을 빌드하기 위해 필요한 파일이나 다른 타겟들이다.
  • command: 타겟을 빌드할 때 실행할 실제 명령어이다.

MakeFile 작성

  • 변수 정의
    컴파일러, 컴파일 옵션, 소스파일, 오브젝트 파일 등을 변수로 정의해서 재사용성을 높이고 관리를 편하게 한다.
CC = gcc
CFLAGS = -Wall -g
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
TARGET = program

SRCS=$(wildcard *.c)
SRCS: 이것은 Source Files의 약자로, 소스 파일 목록을 저장하는 변수명입니다.
=: 변수를 정의할 때 사용하는 대입 연산자입니다.
$(wildcard *.c): wildcard 함수를 호출하며, *.c 패턴에 일치하는 모든 파일을 확장합니다.
즉, 현재 디렉토리에 있는 모든 C 소스 파일(.c로 끝나는 파일)의 목록을 생성합니다.

OBJS = $(SRCS:.c=.o)
자동 변수 치환을 사용 한 것이다. 이 구문은 SRCS 변수에 저장된 값들 중에서 .c로 끝나는 부분을 모두 .o로 치환하는 것이다.

  • 전체 프로그램 빌드 타겟
    가장 먼저 나오는 타겟이 기본 타겟으로 make 명령어를 입력했을 때 실행된다.
all: $(TARGET)

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

$@
현재 타겟의 이름을 타나낸다. 예를 들어 all:program 규칙에서 $@는 all이 된다.

$^
현재 타겟의 모든 의존성들의 리스트를 나타낸다. 의존성들은 공백으로 구분되며, 중복은 제거된다.
ex)

program: main.o utils.o
    gcc -o $@ $^
# $@는 program을 나타냅니다. 따라서 gcc -o program ...가 된다.
# $^는 main.o utils.o을 나타냅니다. 따라서 gcc ... main.o utils.o가 된다.
  • 오브젝트 파일 빌드 규칙
    각 .c파일로부터 .o오브젝트 파일을 만드는 규칙이다. 이는 자동 변수 $<를 사용하여 현재의 의존성 소스 파일을 가리킨다.
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
  • 정리 규칙
    오브젝트 파일과 실행 파일을 삭제하는 clean 타겟을 정의한다. 이 타겟은 .PHONY로 표시해야 한다. 이는 clean이라는 파일과 중돌나지 않도록 하기 위함이다.
.PHONY: clean
clean:
    rm -f $(OBJS) $(TARGET)
  • 추가 규칙
    필요에 따라 테스트 실행, 설치, 배포 등을 위한 추가 규칙을 정의 할 수 있다.
.PHONY: install
install:
    cp $(TARGET) /usr/local/bin/
  • 패턴 규칙과 와일드카드 사용
    MakeFile에서는 패턴과 와일드카드를 사용하여 복잡한 규칙을 단순화 할 수 있다.
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
  • 주석
# This is a comment explaining the following command
$(CC) $(CFLAGS) -o $@ $^

주로 사용되는 곳

  1. 대규모 프로젝트: 여러 개의 소스 파일과 복잡한 의존성이 있는 프로젝트에서 사용한다.
  2. 반복적인 빌드: 소스 코드가 자주 변경되고 ,그 때마다 빌드를 반복해야 할 때 사용한다.
  3. 다양한 플랫폼 지원: 여러 플랫폼이나 환경에 대해 다른 빌드 옵션이 필요할 때 유용하다.
  4. 자동화: 빌드를 자동화하여, 개발자가 더 복잡하고 창의적인 작업에 집중할 수 있도록 한다.

0개의 댓글