모바일 오유 바로가기
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도쿄올림픽
  • 게시판찾기
  • 게시물ID : programmer_22762
    작성자 : ★☆
    추천 : 4
    조회수 : 1505
    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 초과시 해당없음)

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

    번호 제 목 이름 날짜 조회 추천
    23195
    [질문] riscv32-unknown-elf-gcc memory map 본인삭제금지 어린이바이엘 20/11/09 11:24 624 0
    23194
    sql 디벨로퍼 질문이있습니다..ㅠㅜㅠ [1] 따까디스코 20/11/08 17:32 873 0
    23193
    c# wpf 의 그리드에 관한질문입니다 [2] 본인삭제금지 뭐꼬 20/11/08 11:03 916 0
    23192
    유니티 어디서 배울까요 [2] Dev_땅콩 20/11/07 22:58 700 0
    23191
    Visual Studio에서 NuGet 패키지관리 오류.. [3] 달려라하니~ 20/11/04 11:43 2270 0
    23189
    안녕하세요 제가 국비지원 6개월학원다니고 취업준비중인데 조언좀요.. ㅜㅜ [11] 딱다구리마요 20/10/29 13:25 1724 1
    23185
    안녕하세요 초보 개발자 입니다. C# 메모리 Exception질문드립니다 [3] 부산영 20/10/20 16:29 768 0
    23184
    안녕하세요 프로그래머지망생입니다. 상담받고 싶어서 이렇게 글씁니다. [10] 초co 20/10/19 21:18 1073 0
    23183
    파이썬 질문입니다. se1251 20/10/16 20:28 786 0
    23180
    자료구조 책 추천 부탁드립니다. 본인삭제금지 Minion 20/09/17 23:26 955 0
    23176
    redis 오류 관련 문의드립니다. [3] 본인삭제금지 순정있는남자 20/09/07 16:21 868 0
    23175
    크롬 버그(파란색 커서) [3] 마지막연금술 20/09/05 18:09 1150 0
    23173
    sendmail 설정 관련 질문 있습니다! [5] 본인삭제금지 소독제 20/09/03 10:23 757 0
    23172
    1 나를읽어줘 20/09/03 00:40 822 1
    23171
    1인개발한 소프트웨어, 어떻게 홍보하면 좋을까요ㅠㅠ & adobe CEP [8] 빠라빠라 20/09/02 17:21 1313 2
    23170
    음성관련 프로그램 공부를 해보려고 하는데 막막하네요;; [2] 임당이 20/09/02 00:57 693 0
    23169
    비쥬얼 스튜디오 2015 Professional 설치 파일 있으신분.. [2] 야광눈 20/08/27 16:21 917 0
    23168
    C언어 쌉초보자입니다. 이 코드 왜 안되는지 모르겠습니다. [4] llallin 20/08/27 13:15 1436 1
    23167
    닷넷 c# winform 에 콘솔창을 붙일수있는방법 없을까요? [2] 본인삭제금지 엿먹이기 20/08/19 22:41 1107 0
    23165
    윈도우 hosts 파일에 대한 질문 [1] 본인삭제금지 dbf62 20/08/12 15:15 858 0
    23163
    C# 하드코딩으로 사운드 만드는법??? [2] 한시운 20/08/08 17:46 1191 0
    23162
    앱을 만들려고 하는데, 어떤 프로그램이 좋을까요? [4] 본인삭제금지 endwhy 20/08/07 19:45 1088 0
    23160
    jsp 네이버 로그인 연동하고 있는데 토큰 관련 질문 있습니다 ㅠㅠㅠ [1] 토왕 20/08/06 13:44 729 0
    23159
    전역 후 공무원 준비냐 학부 공부 준비냐 고민중입니다. [5] 본인삭제금지 삶은토마토 20/07/31 17:25 858 0
    23158
    어떤프로세스에서 알림광고를 띄우는지 알아내는방법있으면 [1] 본인삭제금지 뭐꼬 20/07/29 06:26 789 0
    23157
    초보의 클레스에 대한 딜레마 존.(feat.Winform With C#) [2] 창작글펌글베스트금지베오베금지 꽃게뢍 20/07/27 15:37 993 0
    23154
    네이버 아이디 로그인 연동 질문 ... ㅠㅠ 본인삭제금지 토왕 20/07/15 12:26 727 0
    23153
    c# 에서의 날짜 디비저장 과 웹에서 날짜 표시... [3] 베스트금지베오베금지본인삭제금지 뭐꼬 20/07/12 00:32 1241 0
    23152
    mysql 한글 300글자는 컬럼을 varchar,text 중 뭘로.. [2] 레드워터 20/07/11 15:58 986 0
    23151
    프로그래밍 노트북... 3개중 하나 정해주십쇼...ㅠㅠ [30] 본인삭제금지 삶은토마토 20/07/08 18:33 1832 2
    [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [다음10개▶]
    단축키 운영진에게 바란다(삭제요청/제안) 운영게 게시판신청 자료창고 보류 개인정보취급방침 청소년보호정책 모바일홈