makefile 기호 $ @와 $ <는 무엇을 의미합니까?


416
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
    $(CC) $(CFLAGS) $< -o $@

무엇을 $@하고 $<정확합니까?


5
위의 링크가 끊어졌으며 여기에 다른 링크가 있습니다. gnu.org/software/make/manual/html_node/Automatic-Variables.html
asciz

1
안녕하세요.이 ".cpp.o :"가 대상이란 무엇입니까? (마지막 줄?)
pseudonym_127

3
".cpp.o :"는 ".cpp"(소스 파일)에서 ".o"(오브젝트 파일)를 빌드하는 것을 의미합니다.
jaguzu

1
Mohit이 자신의 게시물에서 makefile을 얻었을 것이라고 생각하는 다음 링크에 make 튜토리얼이 있다는 것을 알아야합니다. mrbook.org/blog/tutorials/make
DeepDeadpool

Microsoft는 이를 자동 변수 (MAKE 용) 보다 명확한 파일 이름 매크로 (NMAKE 용)라고합니다. 교육 목적으로 양쪽을 보는 것이 유용합니다.
Ivanzinho

답변:


502

$@생성되는 파일의 이름이며 $<첫 번째 전제 조건 (일반적으로 소스 파일)입니다. GNU Make 매뉴얼 에서 이러한 모든 특수 변수 목록을 찾을 수 있습니다 .

예를 들어 다음 선언을 고려하십시오.

all: library.cpp main.cpp

이 경우 :

  • $@ ~에 평가하다 all
  • $< ~에 평가하다 library.cpp
  • $^ ~에 평가하다 library.cpp main.cpp

16
그 지적이의 가치가 $@반드시 파일 끝나게 할 필요가 없습니다, 그것은 또한의 이름이 될 수 .PHONY대상입니다.
Ephemera

$@sname.os와 같은 어셈블리 출력을 생성 하기 위해 명령 줄 옵션에 이것을 추가 할 수 있습니까 ?
huseyin tugrul buyukisik

4
첫 번째 종속성이 목록을 나타내는 변수 인 경우 $ <는 확장 된 후에 평가됩니다. 따라서 LIST = lib1.cpp이고 lib2.cpp이고 모두 $ {LIST} main.cpp 인 경우 $ <는 lib1.cpp로 평가됩니다. 몇 년 전, 나는이 행동으로 인한 결과가 어떻게되는지 알아내는 데 시간을 보냈습니다.
Chan Kim

일반적으로 $ @는 다음의 왼쪽에있는 대상 이름을 나타냅니다.
Deepak Kiran

78

$@$<호출되는 자동 변수를 . 변수 $@는 작성된 파일 이름 (예 : 대상)을 $<나타내고 출력 파일을 작성하는 데 필요한 첫 번째 전제 조건을 나타냅니다.
예를 들면 다음과 같습니다.

hello.o: hello.c hello.h
         gcc -c $< -o $@

여기서, hello.o출력 파일입니다. 이것이 $@확장되는 것입니다. 첫 번째 종속성은 hello.c입니다. 그것이 $<확장되는 것입니다.

-c플래그는 생성 .o파일을; man gcc자세한 설명 은 참조하십시오 . 는 -o만들 수있는 출력 파일을 지정합니다.

자세한 내용은 Linux Makefiles에 대한이 기사를 읽으십시오 .

또한 GNU make매뉴얼을 확인할 수 있습니다 . Makefile을보다 쉽게 ​​만들고 디버깅 할 수 있습니다.

이 명령을 실행하면 makefile 데이터베이스가 출력됩니다.

make -p 

1
귀하의 답변 $<hello.c hello.h(둘 다)로 확장됩니다 . 명확히하십시오.
Dr Beco

예, 그것은에서는 hello.c와 hello.h 모두 포함됩니다
손재주

19
$<첫 번째 항목입니다. 모두 포함하려면을 사용하십시오 $^.
Dr Beco

1
베코 박사가 옳습니다. 저자는 그의 답변을 수정해야합니다.
PT Huynh

67

에서 GNU의 메이크업, 제 3 판, P와 프로젝트 관리. 16 ( GNU Free Documentation License 하에 있음 ) :

자동 변수make규칙이 일치 한 후에 설정됩니다 . 대상 및 전제 조건 목록에서 요소에 대한 액세스를 제공하므로 파일 이름을 명시 적으로 지정할 필요가 없습니다. 코드 중복을 피하는 데 매우 유용하지만보다 일반적인 패턴 규칙을 정의 할 때 중요합니다.

7 가지“핵심”자동 변수가 있습니다 :

  • $@: 대상을 나타내는 파일 이름입니다.

  • $%: 아카이브 멤버 스펙의 파일 이름 요소입니다.

  • $<: 첫 번째 전제 조건의 파일 이름입니다.

  • $?: 대상보다 최신 인 모든 전제 조건의 이름을 공백으로 구분합니다.

  • $^: 모든 전제 조건의 파일 이름을 공백으로 구분합니다. 이 목록에는 편집, 복사 등과 같은 대부분의 용도에서 중복을 원하지 않기 때문에 중복 된 파일 이름이 제거되었습니다.

  • $+:와 유사하게 $^, 이것은 $+중복 을 포함하는 것을 제외하고 공백으로 구분 된 모든 전제 조건의 이름입니다 . 이 변수는 중복 값이 ​​의미가있는 링커에 대한 인수와 같은 특정 상황을 위해 만들어졌습니다.

  • $*: 대상 파일 이름의 스템입니다. 줄기는 일반적으로 접미사가없는 파일 이름입니다. 패턴 규칙 외부에서의 사용은 권장하지 않습니다.

또한 위의 각 변수에는 다른 제조사와의 호환성을 위해 두 가지 변형이 있습니다. 하나의 변형은 값의 디렉토리 부분 만 반환합니다. 이것은 심볼에 "D"를 추가하여 표시되는 $(@D), $(<D)등의 다른 변형 반환 값의 파일 부. 이것은, 기호에 "F"를 추가로 표시됩니다 $(@F), $(<F)이러한 변형의 이름은 괄호로 묶어야합니다 둘 이상의 문자 길이 너무 있다는 등 참고. GNU make는 dir 및 notdir 함수에 대한보다 읽기 쉬운 대안을 제공합니다.


37

$@와는 $<특별한 매크로입니다.

어디:

$@ 대상의 파일 이름입니다.

$< 첫 번째 종속성의 이름입니다.


19

메이크는 빌드 hello중 하나가 있다면 실행을 main.cpp, hello.cpp, factorial.cpp변경. 해당 사양을 달성 할 수있는 가장 작은 Makefile은 다음과 같습니다.

hello: main.cpp hello.cpp factorial.cpp
    g++ -o hello main.cpp hello.cpp factorial.cpp
  • 프로 : 매우 읽기 쉽다
  • 단점 : 유지 관리의 악몽, C ++ 종속성의 중복
  • 단점 : 효율성 문제, 하나만 변경된 경우에도 모든 C ++를 다시 컴파일

위의 내용을 개선하기 위해 편집 된 C ++ 파일 만 컴파일합니다. 그런 다음 결과 객체 파일을 서로 연결하면됩니다.

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

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

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

factorial.o: factorial.cpp
    g++ -c factorial.cpp
  • 프로 : 효율성 문제 해결
  • 죄수 : 새로운 유지 관리 악몽, 객체 파일 규칙의 오타 가능성

이를 개선하기 위해 모든 객체 파일 규칙을 단일 .cpp.o규칙으로 바꿀 수 있습니다 .

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

.cpp.o:
    g++ -c $< -o $@
  • 찬성 : 짧은 makefile로 돌아가서 약간 읽기 쉽다.

여기에 .cpp.o규칙을 구축하는 방법을 정의 anyfile.o에서 anyfile.cpp.

  • $< 이 경우 첫 번째 종속성과 일치합니다. anyfile.cpp
  • $@이 경우 타겟과 일치합니다 anyfile.o.

Makefile에 존재하는 다른 변경 사항은 다음과 같습니다.

  • 컴파일러를 g ++에서 C ++ 컴파일러로 쉽게 변경할 수 있습니다.
  • 컴파일러 옵션을보다 쉽게 ​​변경할 수 있습니다.
  • 링커 옵션을보다 쉽게 ​​변경할 수 있습니다.
  • C ++ 소스 파일 및 출력을보다 쉽게 ​​변경할 수 있습니다.
  • 응용 프로그램 빌드를 시도하기 전에 모든 소스 파일이 있는지 확인하는 빠른 검사 역할을하는 기본 규칙 'all'이 추가되었습니다.

1

소스를 컴파일하고 싶지만 다른 디렉토리에 객체가있는 경우 예를 들어 :

당신은해야합니다 :

gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...

그러나 대부분의 매크로에서 결과는 다음과 같이 모든 객체와 모든 소스가 뒤 따릅니다.

gcc -c -o <all OBJ path> <all SRC path>

그래서 이것은 아무것도 컴파일하지 않을 것입니다 ^^ 객체 파일을 다른 디렉토리에 넣을 수 없습니다 :(

해결책은 이러한 특수 매크로를 사용하는 것입니다

$@ $<

이것은 SRC (src / file.c)의 각 .c 파일에 대해 .o 파일 (obj / file.o)을 생성합니다.

$(OBJ):$(SRC)
   gcc -c -o $@ $< $(HEADERS) $(FLAGS)

그 뜻은 :

    $@ = $(OBJ)
    $< = $(SRC)

그러나 OBJ의 모든 라인의 INSTEAD 라인과 SRC의 모든 라인


"you"대신 "u"를 입력하면 절약 한 시간을 어떻게 처리 할 수 ​​있을까요?
Ivanzinho
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.