모바일 오유 바로가기
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
    조회수 : 1539
    IP : 222.233.***.246
    댓글 : 1개
    등록시간 : 2018/12/29 06:24:34
    http://todayhumor.com/?programmer_22762 모바일
    나의 기본 Makefile
    <strong><a target="_blank" href="https://youtu.be/qxmJ_Ep-Fz0" target="_blank">두근두근 울렁울렁 가슴 뛰지만 무섭고도 두려워서 겁이 나지만</a></strong> 오늘은 제가 사용하는 Makefile 의 기본 형식에 대해 써볼까해요 :) 한가지 주의할 점은, 모두 알고 있겠지만 Makefile 의 들여쓰기는 탭을 사용한다는 것이에요. 아래 코드에서 들여쓰기 한 것은 모두 탭으로 바꿔야해요. 일단, 기본 형식입니다.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-</code><br><code>MAKEFLAGS += --no-builtin-rules</code><br><code>MAKEFLAGS += --no-builtin-variables</code><br><br><code>OBJECTS := libexample.o example0.o</code><br><code>TARGETS := example0</code><br><br><code>CC := gcc</code><br><code>CFLAGS := -flto -Wall</code><br><code>LDFLAGS := -flto</code><br><br><code>.PHONY: all debug release clean distclean</code><br><code>all: debug</code><br><code>debug: $(TARGETS)</code><br><code>debug: CFLAGS += -g -O0</code><br><code>release: $(TARGETS)</code><br><code>release: CFLAGS += -O2</code><br><code>release: CPPFLAGS += -DNDEBUG</code><br><code>release: TARGET_ARCH += -march=native -mtune=native -mfpmath=both</code><br><code>clean:</code><br><code>    rm -f $(OBJECTS) $(OBJECTS:.o=.d)</code><br><code>distclean: clean</code><br><code>    rm -f $(TARGETS)</code><br><br><code>%: %.o</code><br><code>    $(CC) -o $@ $^ $(LDFLAGS) $(TARGET_ARCH) $(LOADLIBES) $(LDLIBS)</code><br><code>%.o: %.c</code><br><code>    $(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)</code><br><code>%.d: %.c</code><br><code>    @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@</code><br><code>    @[ -s $@ ] || rm -f $@</code><br><code>ifneq ($(MAKECMDGOALS), clean)</code><br><code>ifneq ($(MAKECMDGOALS), distclean)</code><br><code>include $(OBJECTS:.o=.d)</code><br><code>endif</code><br><code>endif</code><br><br><code>$(TARGETS:=.d): %.d: %.c</code><br><code>    @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@</code><br><code>    @(for i in $$(sed 's/ /\n/g' $@ | sed -n '/\.h$$/p'); do \</code><br><code>        f=$$(basename $$i .h); \</code><br><code>        t=$(<:.c=); \</code><br><code>        [ $$f == $$t ] || [ ! -e $$f.c ] || echo $$t: $$f.o; \</code><br><code>    done) | uniq >> $@</code><br><code>    @[ -s $@ ] || rm -f $@</code><br><br>이 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 파일을 링크해야하는데 그것을 정의하는 부분이 보이지 않는 것 같습니다 :)<br><br>사실은... 의존성 규칙을 자동으로 만들도록 트릭을 쓴 것 입니다. 만일 example0.c 파일이 libexample.h 파일을 include 한다면, example0 바이너리를 만들면서 example0.o 파일 뿐 아니라 libexample.o 파일도 같이 링크하는 규칙을 생성하도록 한 것이에요. 이러한 트릭을 쓰지 않았다면...<br><br><code>example0: libexample.o</code><br><br>라는 규칙을 명시적으로 적시해야겠죠. 복잡해보이는 쉘 명령이 하는 일이 이것입니다. 의존성이 있는 해더 파일, 즉 인클루드한 해더파일과 같은 이름의 C 소스 파일이 있다면 그것의 오브젝트 파일을 타겟의 의존성에 추가합니다. 이러한 Makefile 이 있으면 example0.c 와 조금 다른 example1.c, example2.c 같은 파일들도 바이너리로 만들기 쉽습니다. Makefile 에서 수정할 부분이 이것밖에 없거든요.<br><br><code>OBJECTS := libexample.o example0.o example1.o example2.o</code><br><code>TARGETS := example0 example1 example2</code><br><br>만일 바이너리가 전부 example 이란 이름으로 시작한다면 이렇게 써도 됩니다.<br><code>TARGETS := $(patsubst %.o, %, $(filter example%.o, $(OBJECTS)))</code><br>이렇게 써두고 OBJECTS 부분에 example3.o, example4.o, ... 등 계속 추가해도 되죠 :) 실제로는... 최종 바이너리 이름이 다른 경우가 많으니 저는 TARGETS 에 하나 하나 적어두는 편입니다. 자... 이제 응용편 입니다.<br><br>프로젝트 루트 디렉터리에 include, lib, makefiles, src 라는 서브 디렉터리들이 있다고 가정합시다. makefiles 디렉터리에는 위 기본 Makefile 을 조금 수정한 다음 세 개의 조각 파일들이 있습니다. 첫번째 파일은 common.mk 라는 이름입니다.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-</code><br><code>CC := gcc</code><br><code>CFLAGS := -flto -Wall</code><br><code>CPPFLAGS := -I$(ROOTDIR)/include</code><br><code>LDFLAGS := -flto</code><br><br><code>.PHONY: all debug release clean distclean</code><br><code>all: debug</code><br><code>debug: CFLAGS += -g -O0</code><br><code>release: CFLAGS += -O2</code><br><code>release: CPPFLAGS += -DNDEBUG</code><br><code>release: TARGET_ARCH += -march=native -mtune=native -mfpmath=both</code><br><br><code>clean:</code><br><code>    rm -f $(OBJECTS) $(OBJECTS:.o=.d)</code><br><br><code>%.d: %.c</code><br><code>    @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@</code><br><code>    @[ -s $@ ] || rm -f $@</code><br><code>ifneq ($(MAKECMDGOALS), clean)</code><br><code>ifneq ($(MAKECMDGOALS), distclean)</code><br><code>include $(OBJECTS:.o=.d)</code><br><code>endif</code><br><code>endif</code><br><code>%.o: %.c</code><br><code>    $(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)</code><br><code>%: %.o</code><br><code>    $(CC) -o $@ $^ $(LDFLAGS) $(TARGET_ARCH) $(LOADLIBES) $(LDLIBS)</code><br><br>다음 파일은 target.mk 라는 이름입니다. common.mk 와 합치면 위 기본 Makefile 과 거의 비슷하게 됩니다. 차이점은 조금 뒤에 설명하겠습니다.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-</code><br><code>debug: $(TARGETS)</code><br><code>release: $(TARGETS)</code><br><br><code>distclean: clean</code><br><code>    rm -f $(TARGETS)</code><br><br><code>$(TARGETS:=.d): %.d: %.c</code><br><code>    @$(CC) -MM $(CPPFLAGS) $< | sed 's/\($*\)\.o[ :]*/\1.o $@: /g' > $@</code><br><code>    @(for i in $$(sed 's/ /\n/g' $@ | sed -n '/\.h$$/p'); do \</code><br><code>        f=$$(basename $$i .h); \</code><br><code>        d=$$(dirname $$i); \</code><br><code>        [ $$(basename $$d) == include ] && d=$$(dirname $$d)/lib; \</code><br><code>        [ $$d == . ] || f=$$d/$$f; \</code><br><code>        t=$(<:.c=); \</code><br><code>        [ $$f == $$t ] || [ ! -e $$f.c ] || echo $$t: $$f.o; \</code><br><code>    done) | uniq >> $@</code><br><code>    @[ -s $@ ] || rm -f $@</code><br><br>우선 눈에 띄는 것이 타겟의 의존성을 자동 설정하는 부분이 조금 길어졌습니다. 기본 Makefile 에서는 현재 디렉터리에 있는 해더 파일을 인클루드하면 해더 파일에 해당하는 오브젝트 파일을 링크하도록 했었습니다. 이 규칙을, 해더 파일이 include 디렉터리에 있을 경우 lib 디렉터리에 있는 오브젝트 파일을 링크하도록 확장한 것 입니다.<br><br>이런 방식으로 쉘 명령을 수정해서 다양한 작업을 할 수 있습니다. 예에서는 오브젝트 파일을 링크하도록 했지만, 라이브러리 파일을 링크하도록 수정할 수도 있습니다. 같은 이름의 오브젝트 파일을 링크하도록 만들었지만, 어떤 특정한 해더 파일이 사용될 경우 여러 개의 다른 오브젝트 파일들을 의존성에 추가할 수도 있습니다. 간단한 프로젝트에서는 그럴 필요까지는 없을지도 모르겠습니다. 이러한 위부 쉘 명령을 쓰지 않고, 각각의 타겟별로 의존성을 따로 추가하는 방법이 원래의 기본 방식이거든요. 조금 귀찮을 뿐이죠.<br><br>세번째 조각 파일은 그런 간단한 프로젝트를 위한 lib.mk 파일 입니다. 라이브러리를 만들지 않고 컴파일만 합니다.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-</code><br><code>debug: $(OBJECTS)</code><br><code>release: $(OBJECTS)</code><br><br><code>distclean: clean</code><br><br>이 lib.mk 조각 파일은 lib 디렉터리의 Makefile 에서 사용됩니다. 이런 방식이 되겠죠.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-<code><br><code>OBJECTS := libexample.o</code><br><br><code>CURRDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))</code><br><code>ROOTDIR := $(abspath $(CURRDIR)/..)</code><br><code>include $(ROOTDIR)/makefiles/common.mk</code><br><code>include $(ROOTDIR)/makefiles/lib.mk</code></code></code><br><br>src 디렉터리의 Makefile 은 이렇게 됩니다.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-</code><br><code>OBJECTS := local_libexample.o example0.o example1.o</code><br><code>TARGETS := example0 example1</code><br><br><code>CURRDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))</code><br><code>ROOTDIR := $(abspath $(CURRDIR)/..)</code><br><code>include $(ROOTDIR)/makefiles/common.mk</code><br><code>include $(ROOTDIR)/makefiles/target.mk</code><br><br>프로젝트의 루트 디렉터리의 Makefile 은 이런 방식이 될 것 입니다.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-</code><br><code>MAKEFLAGS += --no-builtin-rules</code><br><code>MAKEFLAGS += --no-builtin-variables</code><br><br><code>SUBDIRS := lib src</code><br><code>ROOTDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))</code><br><br><code>.PHONY: all debug release clean distclean</code><br><code>all: debug</code><br><code>debug release clean distclean:</code><br><code>    @for i in $(SUBDIRS); do \</code><br><code>        $(MAKE) -C $(ROOTDIR)/$$i $@; \</code><br><code>        [ $$? == 0 ] || exit 1; \</code><br><code>    done</code><br><br>src1, src2, src3, ... 이런 식으로 다른 디렉터리가 생긴다면 SUBDIRS 에 추가하면 됩니다. 만일, 서브디렉터리에 또 다른 서브디렉터리가 있는 경우라면 어떨까요? 예를 들어 test 란 디렉터리 밑에 test1 과 test2 란 디렉터리가 있다면 test 디렉터리의 Makefile 은 이런 식이 됩니다. 프로젝트의 루트 디렉터리에 있는 Makefile 과 거의 같습니다.<br><br><code># -*- mode: makefile-gmake; coding: utf-8; -*-</code><br><code>SUBDIRS := test1 test2</code><br><code>CURRDIR := $(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))</code><br><br><code>.PHONY: all debug release clean distclean</code><br><code>all: debug</code><br><code>debug release clean distclean:</code><br><code>    @for i in $(SUBDIRS); do \</code><br><code>        $(MAKE) -C $(CURRDIR)/$$i $@; \</code><br><code>        [ $$? == 0 ] || exit 1; \</code><br><code>    done</code><br><br>test1 디렉터리나 test2 디렉터리의 Makefile 은 src 디렉터리의 Makefile 과 거의 같습니다. 프로젝트 루트 디렉터리의 경로는 바뀌겠죠.<br><br><code>ROOTDIR := $(abspath $(CURRDIR)/../..)</code><br><br><hr><br>덧붙임1: ROOTDIR 을 환경으로 하지 않고 CURRDIR 로부터 상대적 위치로 구하는 것은 각각의 디렉터리에서 make 명령을 내릴 경우를 위해서 입니다. 예를 들어 src 디렉터리의 파일을 계속 수정해가면서 프로그래밍하고 있는데 make 명령은 프로젝트의 루트 디렉터리에서 내려야 되는 것이 불편했습니다. 그 경우 src 디렉터리의 Makefile 이 독립적으로 동작하도록 하기 위해 CURRDIR 로부터 상대적 위치로 include 디렉터리나 lib 디렉터리를 구하도록 했습니다.<br><br>덧붙임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 초과시 해당없음)

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

    번호 제 목 이름 날짜 조회 추천
    22790
    웹 프로그래밍 인터넷 옵션 체크 가능성 [1] 은바가지 19/01/21 10:09 1090 1
    22788
    윈도우 원격 데스크톱과 Xrdp 서버 사이에 클립보드 공유 실패 ★☆ 19/01/19 03:39 1759 0
    22787
    배치 파일 만드는거 문의 드려요 엄지바라기 19/01/18 21:17 776 0
    22786
    [emacs] 글꼴 설정 [2] ★☆ 19/01/18 08:52 2014 1
    22785
    MongoDB 관련 쿼리 질문 드립니다. [5] 본인삭제금지 목욕통 19/01/15 09:13 1155 0
    22784
    엑셀 한문제만 풀어주세요. [4] 본인삭제금지 맥심코리아 19/01/14 02:41 1290 0
    22783
    프로그래머분들만 알아들을수 있는 자막? 푸른촴치 19/01/13 21:20 1972 4
    22782
    4년차 웹개발자 안드로이드 도전기 아자뵤옹 19/01/12 11:42 1301 4
    22780
    비쥬얼 협업툴(Sameboard) 정식오픈및 무료배포 홍보 합니다 빅준 19/01/11 15:51 1159 2
    22779
    도움!! PHP mongoDB 환경 설정 도움 요청합니다. [6] 본인삭제금지 목욕통 19/01/11 08:36 1025 0
    22778
    R프로그램, 하둡 어떤것을 공부하는게 더 좋을까요? [4] 본인삭제금지 길냥이 19/01/09 03:49 1039 0
    22777
    C 언어 array 로 queue 만드는 법좀 알려주세요 [4] 고무매지션 19/01/09 00:17 1159 0
    22776
    안드로이드로 나가려는데 [1] 본인삭제금지 수원오징어 19/01/08 18:06 974 0
    22774
    라즈베리파이3 wifi를 c언어로 만든 프로그램으로 설정 하고 싶어요.. [4] 베스트금지베오베금지본인삭제금지외부펌금지 개념나무 19/01/08 16:22 1111 0
    22773
    [emacs] EXWM 간단히 맛보기(?), 냄새 맡기(?), 암튼 소개 ★☆ 19/01/08 05:59 1601 1
    22772
    음성채팅 node.js 말고 다른 방법이 있나요? [10] 앗흥~오빠 19/01/07 17:53 2158 0
    22771
    회사에서 갑자기 개발업무를 맡게 되었습니다... [6] 본인삭제금지외부펌금지 가르시미드 19/01/07 07:57 1509 0
    22770
    0과 1로 이루어진 기차는? ^ㅅ^)/ 19/01/06 22:27 1272 3
    22769
    게임 프로그래밍 학원 질문합니다ㅠㅠ [3] 피치피치어피치 19/01/05 06:38 1222 0
    22767
    파이썬 공부 [2] 피크닉복숭아 19/01/04 16:09 1104 0
    22766
    c# 코드를 안드로이드로 바꾸고있는데 [3] 본인삭제금지 뭐꼬 19/01/04 01:14 1041 0
    22765
    [안드로이드] 액티비티를 추가 했더니 이런 에러가 발생합니다. [1] 본인삭제금지 달려라하니~ 19/01/03 18:20 793 0
    22764
    전 이런 유머가 왜 이리 좋죠 ㅋㅋㅋ [6] 궭뷁뛣뉅 19/01/02 21:18 1399 3
    22763
    의사소통 안되는 31살 된 저 프로그래머 접어야 할 까요? [18] 외부펌금지 Sku공대생 19/01/01 19:38 2087 0
    나의 기본 Makefile [1] ★☆ 18/12/29 06:24 1540 4
    22760
    리눅스 문의입니다.. 고수분이 계시려나.. [7] 본인삭제금지 울산아재 18/12/28 20:37 1195 0
    22759
    안녕하세요 선배님들! 도움을 받고 싶습니다! [1] MC요한 18/12/28 17:00 618 0
    22758
    Java for문 테스트 [6] 창작글본인삭제금지 봄아 18/12/28 13:13 1436 0
    22757
    아두이노 카 에다가 디자인을 적용하려면 어떤게 좋을까요? [4] 길냥이 18/12/27 22:16 741 0
    22756
    MySQL 테이블 Join 관련 문의드립니다. [3] 본인삭제금지 상사꽃 18/12/27 15:23 1009 0
    [◀이전10개] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [다음10개▶]
    단축키 운영진에게 바란다(삭제요청/제안) 운영게 게시판신청 자료창고 보류 개인정보취급방침 청소년보호정책 모바일홈