모바일 오유 바로가기
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
    조회수 : 1527
    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 초과시 해당없음)

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

    번호 제 목 이름 날짜 조회 추천
    23105
    일반인 입니다 무작위의 숫자와영어로 적혀 있는 파일입니다. [2] 창작글 너를위한마음 20/04/21 15:13 1106 0
    23104
    c++ 코딩 간단한 질문 하나만 올립니다. [2] 중국인의피 20/04/21 14:54 1014 0
    23103
    C#으로 오토캐드용 보조프로그램 만들고 싶어요 [5] 본인삭제금지 별빛러브 20/04/20 22:08 1515 0
    23102
    네트워크 통신에 관해서.. [5] 본인삭제금지 DJ.A 20/04/17 01:17 923 0
    23100
    파이썬 pywinauto로 자동화 구현해보신 분 계신가요? [8] 본인삭제금지 훗날닭집사장 20/04/15 23:39 2717 0
    23098
    API 질문있습니다! 생공장 20/04/14 21:55 619 0
    23097
    파이썬 Qt Designer로 UI를 구현중인데 질문이 있습니다! [4] 본인삭제금지 훗날닭집사장 20/04/12 16:14 948 0
    23095
    [본삭금] linux svn commit 에러 문제입니다. 베스트금지베오베금지본인삭제금지외부펌금지 오늘이라도 20/04/08 20:37 678 0
    23093
    mfc typedef carray 만들면 자기 클래스에 선언 못하나요?? [2] 소막 20/04/04 12:51 744 0
    23092
    [1인개발][안드로이드][cocos2dx] 틀린그림찾기 게임을 만들었습니 [2] 창작글 하오링찡 20/04/04 11:24 793 2
    23091
    파이썬) pymysql 사용 처음부터 문제가 생겼습니다! ㅠㅠ [8] 본인삭제금지 훗날닭집사장 20/04/01 17:13 7679 0
    23089
    c++ 조언 부탁드려요. [1] 본인삭제금지 우홋 20/03/30 15:49 695 0
    23088
    Java IDE 선호도가 궁금하네요. [9] 목욕통 20/03/30 12:44 1069 0
    23087
    죄송하지만. 혹여 잠시 시간 내어 주실 분들에게 질문 구해요. [3] 본인삭제금지 초급인 20/03/29 15:22 811 0
    23086
    비베 고수님들 질문있습니다2 인천개장수 20/03/28 01:07 535 0
    23085
    장글 질문입니다. C++ 프로그램에 대해서 질문 있습니다. [3] 본인삭제금지 초급인 20/03/26 06:25 673 0
    23083
    파이썬으로 크롤링 + 로그인 관련해서 질문이 있습니다.. [14] 본인삭제금지 훗날닭집사장 20/03/24 15:58 1336 0
    23082
    참 궁금한 것이 있는데요 [8] 큰녀가좋아 20/03/24 14:41 758 2
    23081
    자바 이클립스 간단한 질문하나 올립니다 [15] 외부펌금지 중국인의피 20/03/22 19:53 823 1
    23080
    캡스톤 디자인 과제로 모바일 pos를 만들어볼까 합니다. [3] 본인삭제금지 창기름 20/03/18 17:38 724 0
    23079
    c# 불용어처리기 제작중 질문이 생겼습니다. [14] 창작글본인삭제금지 창기름 20/03/17 23:19 823 0
    23078
    mfc 정보는 최신글 찾기가 왜이렇게 어려운가요 ㅠㅠ [2] 소막 20/03/17 21:17 733 0
    23077
    혹시 여기서 책 추천도 해주시려나요?.. [2] user6000 20/03/14 18:11 659 0
    23075
    안드로이드에서 다른패케이지의 파일접근권한에대한 질문입니다 본인삭제금지 엿먹이기 20/03/11 13:41 549 0
    23074
    공적 마스크 실시간 알림에 관하여 [1] 튜머 20/03/10 15:39 824 1
    23071
    (업무관련)g매크로와 비슷한 기능을 가진 프로그램이 있나요? [7] 문식이당 20/03/06 14:22 1767 0
    23070
    게임 관련 공모전에 관심 있는 분 있으신 분!!! 송초코 20/03/05 19:00 684 0
    23069
    안드로이드 에서 nfc 를이용해서 출결체크하는 앱을 만들고싶습니다 [3] 본인삭제금지 뭐꼬 20/03/03 14:19 780 0
    23068
    c# 사운드 녹음에대해 질문. [1] 외부펌금지 눙무이 20/03/03 11:47 1005 0
    23067
    c# 에서 sqlite 작업시 System.Data.SQLite.dll [1] 본인삭제금지 엿먹이기 20/02/29 13:22 857 0
    [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [다음10개▶]
    단축키 운영진에게 바란다(삭제요청/제안) 운영게 게시판신청 자료창고 보류 개인정보취급방침 청소년보호정책 모바일홈