간단한 C ++ Makefile을 만드는 방법


303

우리는 프로젝트를 위해 모든 것을 하나로 모으기 위해 Makefile을 사용해야하지만 교수는 방법을 보여주지 않았습니다.

파일 이 하나만 있습니다 a3driver.cpp. 드라이버는 위치에서 클래스를 가져옵니다 "/user/cse232/Examples/example32.sequence.cpp".

그게 다야. 그 밖의 모든 것은에 포함되어 있습니다 .cpp.

라는 실행 파일을 만드는 간단한 Makefile을 만드는 방법은 a3a.exe무엇입니까?


9
.EXE는 확실히 Windows입니다. 다시 생각하면 ... 경로는 유닉스 스타일입니다. 아마도 Mingw-32를 사용했을 것입니다.
Nathan Osman

2
한숨. 나는 당신이 거래를 사용하지 않더라도 모든 거래의 기본을 배워야한다고 생각합니다. 물건이 어떻게 작동하는지 이해해야합니다. 그러나 Eclipse와 같은 IDE에서 항상 개발할 가능성이 높습니다. 간단한 한 줄의 사례에 대한 답변을 얻을 수 있으며 웹 자습서가 많이 있지만 dpth 지식을 원한다면 O'reilly 책을 이길 수 없습니다 (대부분의 s / w 주제와 동일). amazon.com/Managing-Projects-Make-Nutshell-Handbooks/dp/… amazon, half.com, betterworldbooks eBay에서 초침 사본 선택
Mawg는 Monica Monica

2
@Dennis가 게시 한 링크는 이제 죽었지 만이 자료는이 archive.org 페이지 에서 찾을 수 있습니다 .
길 레르 메 살로메

나는이 사람의 아이디어를 선호합니다. ( hiltmon.com/blog/2013/07/03/… ) 프로젝트 구조는 적합하도록 쉽게 수정할 수 있습니다. 또한 개발자 시간은 automake / autoconf 이외의 다른 것에 소비해야한다는 데 동의합니다. 이러한 도구는 그 자리에 있지만 내부 프로젝트에는 적합하지 않습니다. 그런 프로젝트 구조를 생성하는 스크립트를 작성 중입니다.
다이스케 아라 마키

@ GuilhermeSalomé 감사합니다. 이것이 가장 간단하고 완벽한 자습서라고 생각합니다.
Hareen Laks

답변:


560

이것은 유닉스 용이므로 실행 파일에는 확장자가 없습니다.

주의해야 할 것은 root-config올바른 컴파일 및 연결 플래그를 제공하는 유틸리티입니다. 그리고 루트에 대한 애플리케이션을 빌드하기위한 올바른 라이브러리. 이 문서의 독자층과 관련된 내용 일뿐입니다.

날 아기로 만들어

또는 당신은 당신이 처음 만든 것을 잊지

make에 대한 소개 토론과 간단한 makefile 작성 방법

Make 란 무엇입니까? 왜 내가 신경 써야합니까?

Make 라는 도구 는 빌드 종속성 관리자입니다. 즉, 소스 파일, 객체 파일, 라이브러리, 헤더 등의 모음에서 소프트웨어 프로젝트를 어떤 순서로 실행해야하는지 명령을 알아야합니다. 최근에-그리고 올바른 최신 버전의 프로그램으로 바 꾸었습니다.

사실, 당신은 다른 것들에도 Make를 사용할 수 있지만, 나는 그것에 대해 이야기하지 않을 것입니다.

사소한 메이크 파일

: 당신이 들어있는 디렉토리가 있다고 가정 tool tool.cc tool.o support.cc support.hh하고 support.o있는에 의존 root하고라는 프로그램으로 컴파일되어있다 tool, 당신은 (기존 의미하는 소스 파일에 해킹 된 적이 있다고 가정 tool오래된 지금) 및 원하는 프로그램을 컴파일하십시오.

이 작업을 직접 수행하려면

  1. support.cc또는 support.hh보다 최신 인지 확인 support.o하고 그렇다면 다음과 같은 명령을 실행하십시오.

    g++ -g -c -pthread -I/sw/include/root support.cc
  2. support.hh또는 tool.cc보다 최신 인지 확인 tool.o하고 그렇다면 다음과 같은 명령을 실행하십시오.

    g++ -g  -c -pthread -I/sw/include/root tool.cc
  3. tool.o보다 최신 인지 확인 tool하고 그렇다면 다음과 같은 명령을 실행하십시오.

    g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
    -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
    -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl

휴! 번거 로움! 기억해야 할 것이 많고 실수 할 수있는 몇 가지 기회가 있습니다. (BTW-- 여기에 표시된 명령 줄의 세부 사항은 소프트웨어 환경에 따라 다릅니다.이 명령 줄은 내 컴퓨터에서 작동합니다.)

물론 매번 세 명령을 모두 실행할 수 있습니다. 그것은 효과가 있지만, MacBook의 기초부터 컴파일하는 데 15 분 이상 걸리는 DOGS와 같은 실질적인 소프트웨어에는 적합하지 않습니다.

대신 다음 makefile과 같은 파일을 작성할 수 있습니다 .

tool: tool.o support.o
    g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
        -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
        -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl

tool.o: tool.cc support.hh
    g++ -g  -c -pthread -I/sw/include/root tool.cc

support.o: support.hh support.cc
    g++ -g -c -pthread -I/sw/include/root support.cc

make명령 행에 입력 하십시오. 위의 세 단계가 자동으로 수행됩니다.

여기에 들여 쓰기되지 않은 행은 "target : dependencies" 형식 이며, 종속 항목이 대상보다 최신 인 경우 연관된 명령 (들여진 행)을 실행해야합니다. 즉, 종속성 라인은 다양한 파일의 변경 사항을 수용하기 위해 재구성해야하는 논리를 설명합니다. support.cc변경 사항이 있으면 support.o다시 작성해야하지만 tool.o단독으로 남겨 둘 수 있습니다. 때 support.o변화는 tool다시 작성해야합니다.

각 의존성 라인과 관련된 명령은 탭으로 시작되며 (아래 참조) 대상을 수정해야합니다 (또는 수정 시간을 업데이트하려면 적어도 터치해야합니다).

변수, 내장 규칙 및 기타 케이크

이 시점에서 makefile은 단순히 수행해야하는 작업을 기억하고 있지만 여전히 필요한 모든 명령을 모두 파악하고 입력해야했습니다. 그렇게 할 필요는 없습니다. Make는 변수, 텍스트 조작 기능 및 내장 규칙이 포함 된 강력한 언어로,이를 훨씬 쉽게 해줍니다.

변수 만들기

make 변수에 액세스하는 구문은 $(VAR)입니다.

Make 변수에 할당하는 구문은 다음과 같습니다 VAR = A text value of some kind (또는 VAR := A different text value but ignore this for the moment).

이 개선 된 메이크 파일 버전과 같은 규칙에 변수를 사용할 수 있습니다.

CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
       -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
       -Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
       -lm -ldl

tool: tool.o support.o
    g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)

tool.o: tool.cc support.hh
    g++ $(CPPFLAGS) -c tool.cc

support.o: support.hh support.cc
    g++ $(CPPFLAGS) -c support.cc

좀 더 읽기 쉽지만 여전히 많은 타이핑이 필요합니다

함수 만들기

GNU make는 파일 시스템이나 시스템의 다른 명령에서 정보에 액세스하기위한 다양한 기능을 지원합니다. 이 경우 우리는에 관심이있는 $(shell ...)인수 (들)의 출력으로 확장하는, 그리고 $(subst opat,npat,text)의 모든 인스턴스를 대체하는 opatnpat텍스트입니다.

이를 활용하면 다음과 같은 이점이 있습니다.

CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)

SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))

tool: $(OBJS)
    g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)

tool.o: tool.cc support.hh
    g++ $(CPPFLAGS) -c tool.cc

support.o: support.hh support.cc
    g++ $(CPPFLAGS) -c support.cc

입력하기 쉽고 훨씬 더 읽기 쉽습니다.

그것을주의해라

  1. 우리는 여전히 각 객체 파일과 최종 실행 파일에 대한 의존성을 명시 적으로 언급하고 있습니다.
  2. 두 소스 파일 모두에 대해 컴파일 규칙을 명시 적으로 입력해야했습니다

암시 적 및 패턴 규칙

일반적으로 모든 C ++ 소스 파일은 동일한 방식으로 처리되어야하며 Make는이를 설명하는 세 가지 방법을 제공합니다.

  1. 접미사 규칙 (GNU make에서 사용되지 않는 것으로 간주되지만 이전 버전과의 호환성을 위해 유지됨)
  2. 암시 적 규칙
  3. 패턴 규칙

암시 적 규칙이 기본 제공되며 몇 가지가 아래에서 설명됩니다. 패턴 규칙은 다음과 같은 형식으로 지정됩니다

%.o: %.c
    $(CC) $(CFLAGS) $(CPPFLAGS) -c $<

이는 "자동"변수 $<가 첫 번째 종속성의 이름으로 확장 되는 표시된 명령을 실행하여 C 소스 파일에서 오브젝트 파일이 생성됨을 의미합니다 .

내장 규칙

Make에는 내장 된 규칙이 많이 있는데, 이는 매우 간단한 makefile로 프로젝트를 컴파일 할 수 있다는 의미입니다.

C 소스 파일에 대한 GNU 기본 제공 규칙은 위에 표시된 것입니다. 마찬가지로 C ++ 소스 파일에서 객체 규칙을와 같은 규칙으로 $(CXX) -c $(CPPFLAGS) $(CFLAGS)만듭니다.

단일 객체 파일은을 사용하여 연결 $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)되지만 여러 객체 파일을 연결하려는 경우에는 작동하지 않습니다.

내장 규칙에 사용되는 변수

기본 제공 규칙은 모든 규칙을 다시 쓰지 않고도 로컬 환경 정보 (ROOT 포함 파일을 찾는 위치 등)를 지정할 수있는 표준 변수 세트를 사용합니다. 우리에게 가장 흥미로운 것은 다음과 같습니다.

  • CC -사용할 C 컴파일러
  • CXX -사용할 C ++ 컴파일러
  • LD -사용할 링커
  • CFLAGS -C 소스 파일의 컴파일 플래그
  • CXXFLAGS C ++ 소스 파일의 컴파일 플래그
  • CPPFLAGS C 및 C ++에서 사용하는 c- 전 처리기 플래그 (일반적으로 명령 줄에 정의 된 파일 경로 및 기호 포함)
  • LDFLAGS -링커 플래그
  • LDLIBS -링크 할 라이브러리

기본 메이크 파일

내장 규칙을 활용하여 makefile을 단순화하여 다음을 수행 할 수 있습니다.

CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)

SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))

all: tool

tool: $(OBJS)
    $(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)

tool.o: tool.cc support.hh

support.o: support.hh support.cc

clean:
    $(RM) $(OBJS)

distclean: clean
    $(RM) tool

또한 소스 디렉토리 정리와 같은 특수 조치를 수행하는 몇 가지 표준 대상을 추가했습니다.

make가 인수없이 호출 될 때 파일에서 발견 된 첫 번째 대상 (이 경우 모두)을 사용하지만 make clean이 경우 대상 파일을 제거 할 대상의 이름을 지정할 수도 있습니다 .

우리는 여전히 모든 의존성을 하드 코딩했습니다.

몇 가지 신비한 개선

CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)

SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))

all: tool

tool: $(OBJS)
    $(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)

depend: .depend

.depend: $(SRCS)
    $(RM) ./.depend
    $(CXX) $(CPPFLAGS) -MM $^>>./.depend;

clean:
    $(RM) $(OBJS)

distclean: clean
    $(RM) *~ .depend

include .depend

그것을주의해라

  1. 더 이상 소스 파일에 대한 의존성 라인이 없습니다!?!
  2. 의존하고 의존하는 이상한 마법이 있습니다.
  3. 당신이 할 경우 make다음 ls -A당신은라는 이름의 파일을 참조 .depend메이크업의 종속 행처럼 보이는 것들을 포함

다른 독서

버그 및 기록 메모를 알고

Make의 입력 언어는 공백에 민감합니다. 특히 종속성 다음에 나오는 조치 행은 탭으로 시작해야합니다 . 그러나 일련의 공백은 동일하게 보일 수 있으며 (실제로 탭을 공백으로 또는 그 반대로 자동으로 변환하는 편집기가 있음) 결과 파일이 올바르게 보이고 여전히 작동하지 않습니다. 이것은 (초기에 버그로 확인 되었으나 이야기가 간다 이미 10 명의 사용자가 있었기 때문에,)가 고정되지 않았습니다.

(이것은 물리학 대학원생을 위해 쓴 위키 포스트에서 복사 한 것입니다.)


9
종속성을 생성하는이 방법은 더 이상 사용되지 않으며 실제로 유해합니다. 고급 자동 종속성 생성을 참조하십시오 .
Maxim Egorushkin

5
-pthread플래그는 gcc필요한 매크로를 정의 -D_REENTRANT하게하므로 불필요합니다.
Maxim Egorushkin

8
@jcoe 의존성을 생성하기 위해 불필요한 추가 전 처리기 통과를 수행합니다. 불필요한 일을하면 얼음 기둥을 녹이는 열이 사라지고 더 큰 규모로 우리 우주의 열사병이 다가오고 있습니다.
Maxim Egorushkin

2
아마도 "유해한"것은 너무 많지만, GCC 3에서 명시 적 의존성 생성 단계 또는 목표가 오래되었다는 점을 감안할 때, 우리 모두가 그 과거를 지나야한다고 생각합니다. bruno.defraine.net/techtips/makefile-auto-dependencies-with-gcc/…
hmijail 애도 사임 자

2
실제로 허용되는 답변은 특정 소프트웨어에 의존해서는 안됩니다 ( root-config). 동일한 기능을 가진보다 일반적인 대안을 제안해야합니다. 가장 많이 사용되는 make 매크로의 목록과 설명으로 인해 공감하지 않았습니다.
green diod

56

필자는 항상 자세한 예제를 통해 배우기가 더 쉽다고 생각했기 때문에 makefile에 대한 생각은 다음과 같습니다. 각 섹션마다 들여 쓰기되지 않은 한 줄이 있으며 섹션 이름과 종속성이 표시됩니다. 종속성은 다른 섹션 (현재 섹션 전에 실행 됨) 또는 파일 (업데이트 된 경우 다음에 실행할 때 현재 섹션이 다시 실행되도록 함 make) 일 수 있습니다.

다음은 간단한 예입니다 (탭을 사용해야하는 4 개의 공백을 사용하고 있음을 명심하십시오. 스택 오버플로에서는 탭을 사용할 수 없습니다).

a3driver: a3driver.o
    g++ -o a3driver a3driver.o

a3driver.o: a3driver.cpp
    g++ -c a3driver.cpp

를 입력 make하면 첫 번째 섹션 (a3driver)이 선택됩니다. a3driver는 a3driver.o에 의존하므로 해당 섹션으로 이동합니다. a3driver.o는 a3driver.cpp에 의존하므로 a3driver.cpp가 마지막으로 실행 된 후 변경된 경우에만 실행됩니다. 실행 중이거나 실행되지 않았다고 가정하면 a3driver.cpp를 .o 파일로 컴파일 한 다음 a3driver로 돌아가서 최종 실행 파일을 컴파일합니다.

파일이 하나뿐이므로 다음과 같이 줄일 수도 있습니다.

a3driver: a3driver.cpp
    g++ -o a3driver a3driver.cpp

첫 번째 예를 보여준 이유는 메이크 파일의 힘을 보여주기 때문입니다. 다른 파일을 컴파일해야하는 경우 다른 섹션을 추가하면됩니다. 다음은 secondFile.cpp (secondFile.h라는 헤더에로드)가있는 예입니다.

a3driver: a3driver.o secondFile.o
    g++ -o a3driver a3driver.o secondFile.o

a3driver.o: a3driver.cpp
    g++ -c a3driver.cpp

secondFile.o: secondFile.cpp secondFile.h
    g++ -c secondFile.cpp

이런 식으로 secondFile.cpp 또는 secondFile.h에서 무언가를 변경하고 다시 컴파일하면 secondFile.cpp 만 다시 컴파일합니다 (a3driver.cpp 아님). 또는 a3driver.cpp에서 무언가를 변경하면 secondFile.cpp를 다시 컴파일하지 않습니다.

궁금한 점이 있으면 알려주세요.

"all"이라는 섹션과 "clean"이라는 섹션을 포함하는 것도 일반적입니다. "all"은 일반적으로 모든 실행 파일을 빌드하고 "clean"은 .o 파일 및 실행 파일과 같은 "build artifacts"를 제거합니다.

all: a3driver ;

clean:
    # -f so this will succeed even if the files don't exist
    rm -f a3driver a3driver.o

편집 : 나는 당신이 Windows에 있다는 것을 알지 못했습니다. 유일한 차이점은을 변경하는 -o a3driver-o a3driver.exe입니다.


내가 사용하려는 절대 코드는 다음과 같습니다. p4a.exe : p4driver.cpp g ++ -o p4a p4driver.cpp 그러나 "미리 분리 기호"를 알려줍니다. TAB을 사용하고 있지만 여전히 알려줍니다. 어떤 생각?
일어날

2
내가 알 수있는 한, 오류 메시지는 공백이있는 경우에만 나타납니다. 공백으로 시작하는 줄이 없는지 확인하십시오 (공백 + 탭에서 오류가 발생 함). 그것이 내가 생각할 수있는 유일한 것입니다.
Brendan Long

향후 편집자 참고 사항 : 답변으로 탭을 편집해도 StackOverflow에서 탭을 렌더링 할 수 없으므로 이에 대한 내 메모를 "수정"하지 마십시오.
Brendan Long

35

모든 사람이 소스 파일을 나열하는 것을 좋아하는 이유는 무엇입니까? 간단한 찾기 명령으로 쉽게 처리 할 수 ​​있습니다.

다음은 간단한 C ++ Makefile의 예입니다. .C파일이 들어있는 디렉토리에 넣고 make...

appname := myapp

CXX := clang++
CXXFLAGS := -std=c++11

srcfiles := $(shell find . -name "*.C")
objects  := $(patsubst %.C, %.o, $(srcfiles))

all: $(appname)

$(appname): $(objects)
    $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)

depend: .depend

.depend: $(srcfiles)
    rm -f ./.depend
    $(CXX) $(CXXFLAGS) -MM $^>>./.depend;

clean:
    rm -f $(objects)

dist-clean: clean
    rm -f *~ .depend

include .depend

2
소스 파일을 자동으로 찾지 않는 이유는 다른 파일이 필요한 다른 빌드 대상을 가질 수 있기 때문입니다.
hmijail의 신음은 resignees

컴파일 / 링크하고 싶지 않은 수많은 소스 / 헤더를 포함하는 서브 모듈뿐만 아니라 @hmijail과 합의 된 것입니다.
엔지니어

대신 "와일드 카드"가 아닌 "쉘 찾기"를 사용하는 이유는 무엇입니까?
놀란

1
소스 디렉토리 트리에서 소스 파일을 찾기위한 @Nolan
AlejandroVD

13

두 가지 옵션이 있습니다.

옵션 1 : 가장 간단한 makefile = NO MAKEFILE.

"a3driver.cpp"의 이름을 "a3a.cpp"로 바꾼 다음 명령 행에 다음을 작성하십시오.

nmake a3a.exe

그리고 그게 다야. GNU Make를 사용하는 경우 "make"또는 "gmake"등을 사용하십시오.

옵션 2 : 2 줄 메이크 파일.

a3a.exe: a3driver.obj
    link /out:a3a.exe a3driver.obj

3
OP 환경의 세부 사항에 대해 너무 많은 것을 전제로하지 않으면 훌륭한 답변이 될 것입니다. 예, Windows에 있지만을 사용한다는 의미는 아닙니다 nmake. link명령 줄은 적어도 문서 하나에 특정 컴파일러에 대한 매우 구체적인보고,해야한다.
tripleee

6

Make 파일에는 하나의 명령으로 컴파일 및 링크하는지 또는 하나의 컴파일 명령 및 링크에 대해 하나 또는 두 개의 종속성 규칙이 있습니다.

종속성은 다음과 같은 규칙 트리입니다 (들여 쓰기 이어야 함).

main_target : source1 source2 etc
    command to build main_target from sources

source1 : dependents for source1
    command to build source1

있어야합니다 대상에 대한 명령 후 빈 줄, 그리고 거기에 있어야 하지 명령 앞에 빈 줄 수. makefile의 첫 번째 대상은 전체 목표이며 다른 대상은 첫 번째 대상이 종속 된 경우에만 빌드됩니다.

따라서 makefile은 다음과 같이 보일 것입니다.

a3a.exe : a3driver.obj 
    link /out:a3a.exe a3driver.obj

a3driver.obj : a3driver.cpp
    cc a3driver.cpp

6

나는 제안한다 (들여 쓰기는 탭이다) :

tool: tool.o file1.o file2.o
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

또는

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
tool: tool.o file1.o file2.o

후자의 제안은 GNU Make 암시 적 규칙을 재사용하기 때문에 약간 더 좋습니다. 그러나 작업을 위해, 소스 파일이 최종 실행 파일과 동일한 이름이 있어야합니다 (예 : tool.ctool ).

소스를 선언 할 필요는 없습니다. 중간 오브젝트 파일은 내재적 규칙을 사용하여 생성됩니다. 결과적으로 이것은 MakefileC 및 C ++ (및 Fortran 등에서도)에서 작동합니다.

또한 기본적으로 Makefile $(CC)은 링커로 사용 됩니다. $(CC)C ++ 오브젝트 파일을 링크하는 데 작동하지 않습니다. 우리 LINK.o는 그 때문에 수정 합니다. C 코드를 컴파일하려면 LINK.o값 을 강제로 지정할 필요가 없습니다 .

물론 변수로 컴파일 플래그를 CFLAGS추가하고에 라이브러리를 추가 할 수도 있습니다 LDLIBS. 예를 들면 다음과 같습니다.

CFLAGS = -Wall
LDLIBS = -lm

한 가지 참고 사항 : 외부 라이브러리를 사용해야 하는 경우 올바르게 설정 CFLAGS하고 pkg-config사용하는 것이 좋습니다 LDLIBS.

CFLAGS += $(shell pkg-config --cflags libssl)
LDLIBS += $(shell pkg-config --libs libssl)

주의 깊게 읽는 사람은 Makefile하나의 헤더가 변경되면 올바르게 다시 작성되지 않습니다. 문제를 해결하려면 다음 줄을 추가하십시오.

override CPPFLAGS += -MMD
include $(wildcard *.d)

-MMD헤더 종속성에 대한 Makefile 조각이 포함 된 .d 파일을 빌드 할 수 있습니다. 두 번째 줄은 그것들을 사용합니다.

확실히 잘 작성된 Makefile에는 다음 clean과 같은 distclean규칙이 포함되어야합니다 .

clean:
    $(RM) *.o *.d

distclean: clean
    $(RM) tool

유의 사항은와 $(RM)동일 rm -f하지만 rm직접 호출하지 않는 것이 좋습니다 .

all규칙은 이해된다. 작동하려면 파일의 첫 번째 규칙이어야합니다.

all: tool

install규칙을 추가 할 수도 있습니다 .

PREFIX = /usr/local
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

DESTDIR기본적으로 비어 있습니다. 사용자는 다른 시스템에 프로그램을 설치하도록 설정할 수 있습니다 (교차 컴파일 프로세스에 필수). 다중 배포 용 패키지 관리자는 패키지 PREFIX를 설치하기 위해 변경 될 수도 있습니다 ./usr .

마지막 한 단어 : 소스 파일을 하위 디렉토리에 두지 마십시오. 정말로 그렇게 Makefile하려면 루트 디렉토리에 보관 하고 전체 경로를 사용하여 파일을 식별하십시오 (예 :) subdir/file.o.

요약하면 전체 Makefile은 다음과 같아야합니다.

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
PREFIX = /usr/local
override CPPFLAGS += -MMD
include $(wildcard *.d)

all: tool
tool: tool.o file1.o file2.o
clean:
    $(RM) *.o *.d
distclean: clean
    $(RM) tool
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

끝 부분 : 규칙 사이에 빈 줄이 없어야합니까? John Knoeller의 답변에 따르면
Peter Mortensen

make내가 아는 구현 (GNU Make 및 BSD Make)은 규칙 사이에 빈 줄이 필요하지 않습니다. 그러나 make자체 버그 ^ W 특성을 가진 수많은 구현이 있습니다.
Jérôme Pouiller

5

나는 friedmud의 대답을 사용 했다 . 나는 이것을 잠시 살펴 보았고 시작하는 좋은 방법 인 것 같습니다. 이 솔루션에는 컴파일러 플래그를 추가하는 잘 정의 된 방법도 있습니다. 내 환경, Ubuntu 및 g ++에서 작동하도록 변경했기 때문에 다시 대답했습니다. 때로는 더 효과적인 사례가 최고의 교사입니다.

appname := myapp

CXX := g++
CXXFLAGS := -Wall -g

srcfiles := $(shell find . -maxdepth 1 -name "*.cpp")
objects  := $(patsubst %.cpp, %.o, $(srcfiles))

all: $(appname)

$(appname): $(objects)
    $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)

depend: .depend

.depend: $(srcfiles)
    rm -f ./.depend
    $(CXX) $(CXXFLAGS) -MM $^>>./.depend;

clean:
    rm -f $(objects)

dist-clean: clean
    rm -f *~ .depend

include .depend

Makefile은 매우 복잡한 것 같습니다. 하나를 사용했지만 g ++ 라이브러리에서 링크하지 않는 것과 관련된 오류가 발생했습니다. 이 구성은 그 문제를 해결했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.