모바일 오유 바로가기
http://m.todayhumor.co.kr
분류 게시판
베스트
  • 베스트오브베스트
  • 베스트
  • 오늘의베스트
  • 유머
  • 유머자료
  • 유머글
  • 이야기
  • 자유
  • 고민
  • 연애
  • 결혼생활
  • 좋은글
  • 자랑
  • 공포
  • 멘붕
  • 사이다
  • 군대
  • 밀리터리
  • 미스터리
  • 술한잔
  • 오늘있잖아요
  • 투표인증
  • 새해
  • 이슈
  • 시사
  • 시사아카이브
  • 사회면
  • 사건사고
  • 생활
  • 패션
  • 패션착샷
  • 아동패션착샷
  • 뷰티
  • 인테리어
  • DIY
  • 요리
  • 커피&차
  • 육아
  • 법률
  • 동물
  • 지식
  • 취업정보
  • 식물
  • 다이어트
  • 의료
  • 영어
  • 맛집
  • 추천사이트
  • 해외직구
  • 취미
  • 사진
  • 사진강좌
  • 카메라
  • 만화
  • 애니메이션
  • 포니
  • 자전거
  • 자동차
  • 여행
  • 바이크
  • 민물낚시
  • 바다낚시
  • 장난감
  • 그림판
  • 학술
  • 경제
  • 역사
  • 예술
  • 과학
  • 철학
  • 심리학
  • 방송연예
  • 연예
  • 음악
  • 음악찾기
  • 악기
  • 음향기기
  • 영화
  • 다큐멘터리
  • 국내드라마
  • 해외드라마
  • 예능
  • 팟케스트
  • 방송프로그램
  • 무한도전
  • 더지니어스
  • 개그콘서트
  • 런닝맨
  • 나가수
  • 디지털
  • 컴퓨터
  • 프로그래머
  • IT
  • 안티바이러스
  • 애플
  • 안드로이드
  • 스마트폰
  • 윈도우폰
  • 심비안
  • 스포츠
  • 스포츠
  • 축구
  • 야구
  • 농구
  • 바둑
  • 야구팀
  • 삼성
  • 두산
  • NC
  • 넥센
  • 한화
  • SK
  • 기아
  • 롯데
  • LG
  • KT
  • 메이저리그
  • 일본프로야구리그
  • 게임1
  • 플래시게임
  • 게임토론방
  • 엑스박스
  • 플레이스테이션
  • 닌텐도
  • 모바일게임
  • 게임2
  • 던전앤파이터
  • 마비노기
  • 마비노기영웅전
  • 하스스톤
  • 히어로즈오브더스톰
  • gta5
  • 디아블로
  • 디아블로2
  • 피파온라인2
  • 피파온라인3
  • 워크래프트
  • 월드오브워크래프트
  • 밀리언아서
  • 월드오브탱크
  • 블레이드앤소울
  • 검은사막
  • 스타크래프트
  • 스타크래프트2
  • 베틀필드3
  • 마인크래프트
  • 데이즈
  • 문명
  • 서든어택
  • 테라
  • 아이온
  • 심시티5
  • 프리스타일풋볼
  • 스페셜포스
  • 사이퍼즈
  • 도타2
  • 메이플스토리1
  • 메이플스토리2
  • 오버워치
  • 오버워치그룹모집
  • 포켓몬고
  • 파이널판타지14
  • 배틀그라운드
  • 기타
  • 종교
  • 단어장
  • 자료창고
  • 운영
  • 공지사항
  • 오유운영
  • 게시판신청
  • 보류
  • 임시게시판
  • 메르스
  • 세월호
  • 원전사고
  • 2016리오올림픽
  • 2018평창올림픽
  • 코로나19
  • 2020도쿄올림픽
  • 게시판찾기
  • 오유인페이지
    개인차단 상태
    ★☆님의
    개인페이지입니다
    가입 : 17-07-17
    방문 : 493회
    닉네임변경 이력
    회원차단
    회원차단해제
    게시물ID : programmer_22762
    작성자 : ★☆
    추천 : 4
    조회수 : 1523
    IP : 222.233.***.246
    댓글 : 1개
    등록시간 : 2018/12/29 06:24:34
    http://todayhumor.com/?programmer_22762 모바일
    나의 기본 Makefile
    두근두근 울렁울렁 가슴 뛰지만 무섭고도 두려워서 겁이 나지만 오늘은 제가 사용하는 Makefile 의 기본 형식에 대해 써볼까해요 :) 한가지 주의할 점은, 모두 알고 있겠지만 Makefile 의 들여쓰기는 탭을 사용한다는 것이에요. 아래 코드에서 들여쓰기 한 것은 모두 탭으로 바꿔야해요. 일단, 기본 형식입니다.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    MAKEFLAGS += --no-builtin-rules
    MAKEFLAGS += --no-builtin-variables

    OBJECTS := libexample.o example0.o
    TARGETS := example0

    CC := gcc
    CFLAGS := -flto -Wall
    LDFLAGS := -flto

    .PHONY: all debug release clean distclean
    all: debug
    debug: $(TARGETS)
    debug: CFLAGS += -g -O0
    release: $(TARGETS)
    release: CFLAGS += -O2
    release: CPPFLAGS += -DNDEBUG
    release: TARGET_ARCH += -march=native -mtune=native -mfpmath=both
    clean:
        rm -f $(OBJECTS) $(OBJECTS:.o=.d)
    distclean: clean
        rm -f $(TARGETS)

    %: %.o
        $(CC) -o $@ $^ $(LDFLAGS) $(TARGET_ARCH) $(LOADLIBES) $(LDLIBS)
    %.o: %.c
        $(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)
    %.d: %.c
        @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@
        @[ -s $@ ] || rm -f $@
    ifneq ($(MAKECMDGOALS), clean)
    ifneq ($(MAKECMDGOALS), distclean)
    include $(OBJECTS:.o=.d)
    endif
    endif

    $(TARGETS:=.d): %.d: %.c
        @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@
        @(for i in $$(sed 's/ /\n/g' $@ | sed -n '/\.h$$/p'); do \
            f=$$(basename $$i .h); \
            t=$(<:.c=); \
            [ $$f == $$t ] || [ ! -e $$f.c ] || echo $$t: $$f.o; \
        done) | uniq >> $@
        @[ -s $@ ] || rm -f $@

    이 Makefile 은 C 코드를 컴파일하기 위한 것 입니다. 만일 C++ 코드를 컴파일하려 했다면, CC 대신 CXX 를 정의했을 것 입니다. 그리고 %o: %c 규칙 대신 %o: %cc 규칙을 정의하고, %: %o 규칙에서 CC 대신 CXX 를 사용했겠죠. 위 예에서는 libexample.c 파일과 example0.c 파일을 컴파일해서 libexample.o 파일과 example0.o 파일을 만들도록 합니다. 최종적으로 만들어지는 것은 example0 이라는 바이너리입니다. 여기에 특이한 점이 있는데요... example0 이란 바이너리를 만들려면 example0.o 파일과 libexample.o 파일을 링크해야하는데 그것을 정의하는 부분이 보이지 않는 것 같습니다 :)

    사실은... 의존성 규칙을 자동으로 만들도록 트릭을 쓴 것 입니다. 만일 example0.c 파일이 libexample.h 파일을 include 한다면, example0 바이너리를 만들면서 example0.o 파일 뿐 아니라 libexample.o 파일도 같이 링크하는 규칙을 생성하도록 한 것이에요. 이러한 트릭을 쓰지 않았다면...

    example0: libexample.o

    라는 규칙을 명시적으로 적시해야겠죠. 복잡해보이는 쉘 명령이 하는 일이 이것입니다. 의존성이 있는 해더 파일, 즉 인클루드한 해더파일과 같은 이름의 C 소스 파일이 있다면 그것의 오브젝트 파일을 타겟의 의존성에 추가합니다. 이러한 Makefile 이 있으면 example0.c 와 조금 다른 example1.c, example2.c 같은 파일들도 바이너리로 만들기 쉽습니다. Makefile 에서 수정할 부분이 이것밖에 없거든요.

    OBJECTS := libexample.o example0.o example1.o example2.o
    TARGETS := example0 example1 example2

    만일 바이너리가 전부 example 이란 이름으로 시작한다면 이렇게 써도 됩니다.
    TARGETS := $(patsubst %.o, %, $(filter example%.o, $(OBJECTS)))
    이렇게 써두고 OBJECTS 부분에 example3.o, example4.o, ... 등 계속 추가해도 되죠 :) 실제로는... 최종 바이너리 이름이 다른 경우가 많으니 저는 TARGETS 에 하나 하나 적어두는 편입니다. 자... 이제 응용편 입니다.

    프로젝트 루트 디렉터리에 include, lib, makefiles, src 라는 서브 디렉터리들이 있다고 가정합시다. makefiles 디렉터리에는 위 기본 Makefile 을 조금 수정한 다음 세 개의 조각 파일들이 있습니다. 첫번째 파일은 common.mk 라는 이름입니다.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    CC := gcc
    CFLAGS := -flto -Wall
    CPPFLAGS := -I$(ROOTDIR)/include
    LDFLAGS := -flto

    .PHONY: all debug release clean distclean
    all: debug
    debug: CFLAGS += -g -O0
    release: CFLAGS += -O2
    release: CPPFLAGS += -DNDEBUG
    release: TARGET_ARCH += -march=native -mtune=native -mfpmath=both

    clean:
        rm -f $(OBJECTS) $(OBJECTS:.o=.d)

    %.d: %.c
        @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@
        @[ -s $@ ] || rm -f $@
    ifneq ($(MAKECMDGOALS), clean)
    ifneq ($(MAKECMDGOALS), distclean)
    include $(OBJECTS:.o=.d)
    endif
    endif
    %.o: %.c
        $(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)
    %: %.o
        $(CC) -o $@ $^ $(LDFLAGS) $(TARGET_ARCH) $(LOADLIBES) $(LDLIBS)

    다음 파일은 target.mk 라는 이름입니다. common.mk 와 합치면 위 기본 Makefile 과 거의 비슷하게 됩니다. 차이점은 조금 뒤에 설명하겠습니다.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    debug: $(TARGETS)
    release: $(TARGETS)

    distclean: clean
        rm -f $(TARGETS)

    $(TARGETS:=.d): %.d: %.c
        @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@
        @(for i in $$(sed 's/ /\n/g' $@ | sed -n '/\.h$$/p'); do \
            f=$$(basename $$i .h); \
            d=$$(dirname $$i); \
            [ $$(basename $$d) == include ] && d=$$(dirname $$d)/lib; \
            [ $$d == . ] || f=$$d/$$f; \
            t=$(<:.c=); \
            [ $$f == $$t ] || [ ! -e $$f.c ] || echo $$t: $$f.o; \
        done) | uniq >> $@
        @[ -s $@ ] || rm -f $@

    우선 눈에 띄는 것이 타겟의 의존성을 자동 설정하는 부분이 조금 길어졌습니다. 기본 Makefile 에서는 현재 디렉터리에 있는 해더 파일을 인클루드하면 해더 파일에 해당하는 오브젝트 파일을 링크하도록 했었습니다. 이 규칙을, 해더 파일이 include 디렉터리에 있을 경우 lib 디렉터리에 있는 오브젝트 파일을 링크하도록 확장한 것 입니다.

    이런 방식으로 쉘 명령을 수정해서 다양한 작업을 할 수 있습니다. 예에서는 오브젝트 파일을 링크하도록 했지만, 라이브러리 파일을 링크하도록 수정할 수도 있습니다. 같은 이름의 오브젝트 파일을 링크하도록 만들었지만, 어떤 특정한 해더 파일이 사용될 경우 여러 개의 다른 오브젝트 파일들을 의존성에 추가할 수도 있습니다. 간단한 프로젝트에서는 그럴 필요까지는 없을지도 모르겠습니다. 이러한 위부 쉘 명령을 쓰지 않고, 각각의 타겟별로 의존성을 따로 추가하는 방법이 원래의 기본 방식이거든요. 조금 귀찮을 뿐이죠.

    세번째 조각 파일은 그런 간단한 프로젝트를 위한 lib.mk 파일 입니다. 라이브러리를 만들지 않고 컴파일만 합니다.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    debug: $(OBJECTS)
    release: $(OBJECTS)

    distclean: clean

    이 lib.mk 조각 파일은 lib 디렉터리의 Makefile 에서 사용됩니다. 이런 방식이 되겠죠.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    OBJECTS := libexample.o

    CURRDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
    ROOTDIR := $(abspath $(CURRDIR)/..)
    include $(ROOTDIR)/makefiles/common.mk
    include $(ROOTDIR)/makefiles/lib.mk


    src 디렉터리의 Makefile 은 이렇게 됩니다.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    OBJECTS := local_libexample.o example0.o example1.o
    TARGETS := example0 example1

    CURRDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
    ROOTDIR := $(abspath $(CURRDIR)/..)
    include $(ROOTDIR)/makefiles/common.mk
    include $(ROOTDIR)/makefiles/target.mk

    프로젝트의 루트 디렉터리의 Makefile 은 이런 방식이 될 것 입니다.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    MAKEFLAGS += --no-builtin-rules
    MAKEFLAGS += --no-builtin-variables

    SUBDIRS := lib src
    ROOTDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))

    .PHONY: all debug release clean distclean
    all: debug
    debug release clean distclean:
        @for i in $(SUBDIRS); do \
            $(MAKE) -C $(ROOTDIR)/$$i $@; \
            [ $$? == 0 ] || exit 1; \
        done

    src1, src2, src3, ... 이런 식으로 다른 디렉터리가 생긴다면 SUBDIRS 에 추가하면 됩니다. 만일, 서브디렉터리에 또 다른 서브디렉터리가 있는 경우라면 어떨까요? 예를 들어 test 란 디렉터리 밑에 test1 과 test2 란 디렉터리가 있다면 test 디렉터리의 Makefile 은 이런 식이 됩니다. 프로젝트의 루트 디렉터리에 있는 Makefile 과 거의 같습니다.

    # -*- mode: makefile-gmake; coding: utf-8; -*-
    SUBDIRS := test1 test2
    CURRDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))

    .PHONY: all debug release clean distclean
    all: debug
    debug release clean distclean:
        @for i in $(SUBDIRS); do \
            $(MAKE) -C $(CURRDIR)/$$i $@; \
            [ $$? == 0 ] || exit 1; \
        done

    test1 디렉터리나 test2 디렉터리의 Makefile 은 src 디렉터리의 Makefile 과 거의 같습니다. 프로젝트 루트 디렉터리의 경로는 바뀌겠죠.

    ROOTDIR := $(abspath $(CURRDIR)/../..)



    덧붙임1: ROOTDIR 을 환경으로 하지 않고 CURRDIR 로부터 상대적 위치로 구하는 것은 각각의 디렉터리에서 make 명령을 내릴 경우를 위해서 입니다. 예를 들어 src 디렉터리의 파일을 계속 수정해가면서 프로그래밍하고 있는데 make 명령은 프로젝트의 루트 디렉터리에서 내려야 되는 것이 불편했습니다. 그 경우 src 디렉터리의 Makefile 이 독립적으로 동작하도록 하기 위해 CURRDIR 로부터 상대적 위치로 include 디렉터리나 lib 디렉터리를 구하도록 했습니다.

    덧붙임2: 이 Makefile 에 사용된 가장 중요한 트릭은 동적으로 의존성을 추가하도록 한 것입니다. 또한, 소스 코드가 바뀔 때 마다 의존성을 다시 점검합니다. 의존성이 계속 변하는 단계에서 편리한 기능입니다. 더 이상 의존성이 변할 가능성이 없을 때 이 트릭을 제거하고 전통적인 방법으로 돌아가는 것도 고려해 볼 수 있습니다. 동적으로 변하는 기능은 다른 사람이 프로젝트를 분석해야 할 경우 단점이 될 가능성이 있습니다. 그런데, 배포까지 고려해야하는 프로젝트라면 이 예에서 상정한 간단한 프로젝트는 아닙니다.

    이 게시물을 추천한 분들의 목록입니다.
    [1] 2018/12/30 17:40:35  220.88.***.54  nsys  483176
    [2] 2018/12/31 17:20:18  147.46.***.42  CandyJelly  566431
    [3] 2018/12/31 21:14:59  211.219.***.220  을파소  440752
    [4] 2019/01/10 16:19:24  97.122.***.105  nc스테고  414704
    푸르딩딩:추천수 3이상 댓글은 배경색이 바뀝니다.
    (단,비공감수가 추천수의 1/3 초과시 해당없음)

    죄송합니다. 댓글 작성은 회원만 가능합니다.

    번호 제 목 이름 날짜 조회 추천
    897
    윈도우 원격 데스크톱과 Xrdp 서버 사이에 클립보드 공유 실패 ★☆ 19/01/19 03:39 116 0
    896
    [emacs] 글꼴 설정 [2] ★☆ 19/01/18 08:52 83 1
    895
    [emacs] EXWM 간단히 맛보기(?), 냄새 맡기(?), 암튼 소개 ★☆ 19/01/08 05:59 116 1
    나의 기본 Makefile [2] ★☆ 18/12/29 06:24 120 4
    893
    [gcc] 적용되는 옵션 플래그 확인하기 ★☆ 18/12/26 22:51 73 0
    892
    [gcc] 어셈블리 코드 보기 [11] ★☆ 18/12/26 18:08 104 0
    891
    const 한정자는 좋은 코딩 습관의 기초 [1] ★☆ 18/12/22 00:30 78 2
    890
    [gcc] 의미없어 보이지만 의미심장한 (X)+0 그리고 함수 오버로딩 [6] ★☆ 18/12/21 07:40 108 2
    889
    재미있는 상황?? [1] ★☆ 18/10/12 18:23 63 0
    888
    아빠가 너무 나대요... [5] 펌글 ★☆ 18/10/12 15:29 2104 12
    887
    저금통 샀다고 와잎한테 쳐맞은 남편... [4] 펌글 ★☆ 18/10/11 18:44 2099 19
    886
    관악산에 노루가 뛰논다를 영어로?(feat. 서울대 법대 합격하는 법) [5] 펌글 ★☆ 18/10/10 23:58 1662 12
    885
    ㅈ간지 연출 [6] 펌글 ★☆ 18/10/10 23:53 2018 10
    884
    뒤틀린 학구열 [2] 펌글 ★☆ 18/10/10 23:50 1667 14
    883
    웃대가 오유 먹었다 야호 [4] 펌글 ★☆ 18/10/10 23:38 1127 17
    882
    귀여운 약사를 만난 루리웹 유저 [6] 펌글 ★☆ 18/10/10 23:26 1497 18
    881
    미대생의 농락 ㅋㅋㅋㅋㅋㅋㅋㅋㅋ [2] 펌글 ★☆ 18/10/10 23:11 1622 15
    880
    군필자가 세금으로 배워온 기술 [6] 펌글 ★☆ 18/10/10 23:01 1618 16
    879
    마법사 세계에서 포켓몬이 금지인 이유 [1] 펌글 ★☆ 18/10/10 22:51 1197 5
    878
    조별과제 침대 빌런 [7] 펌글 ★☆ 18/10/10 22:39 1420 15
    877
    이거 방울토마토 맞음? 펌글 ★☆ 18/10/10 22:30 883 5
    876
    입뺀 당한 김희철 [2] 펌글 ★☆ 18/10/10 22:23 1133 10
    875
    32살이나 먹고 똥을 지린 남자 [12] 펌글 ★☆ 18/10/10 22:15 1554 11
    874
    무술의 천재 [2] 펌글 ★☆ 18/10/10 22:11 1190 11
    873
    환장의 호흡 feat.웃대 [10] 펌글 ★☆ 18/10/10 22:04 872 10
    872
    북한 야동사이트 접속기록 통계 [10] 펌글 ★☆ 18/10/10 21:53 1741 10
    871
    북서유럽과 동남유럽의 차이 [2] 펌글 ★☆ 18/10/10 21:42 1287 7
    870
    경계가 너무 심한 중고나라 [3] 펌글 ★☆ 18/10/10 21:38 1446 19
    869
    소개팅 직업 레전드 [2] 펌글 ★☆ 18/10/10 21:34 1411 10
    868
    흔한 뇌가 히토미류 甲 [14] 펌글 ★☆ 18/10/10 21:23 1415 14
    [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [다음10개▶]
    단축키 운영진에게 바란다(삭제요청/제안) 운영게 게시판신청 자료창고 보류 개인정보취급방침 청소년보호정책 모바일홈