117 – make 규칙 1: 암시적 규칙

make 파일을 작성할 때는 컴파일에 필요한 각 처리 단계와 의존성을 분명히 지정해주었다. 이와 같이 make가 해야 할 일을 분명히 지정하는 것을 명시적 규칙(explicit rules)이라고 한다. 이와 반대로, make 내에 미리 정의된 규칙을 이용해 make 파일을 단순화시키는 규칙을 암시적 규칙(inference rules)이라고 한다.

이를 보여주기 위해서 전에 작성하던 make 파일을 상당히 줄여서 예시로 보여주겠다.

20180116_234757.png

소스 파일에서 오브젝트 파일로 컴파일하도록 하는 단계를 빼고 그냥 바로 test를 오브젝트로 만들어서 빌드하도록 하였다. 전에 글들의 코드를 보고 비교하면 상당히 단축시킨 것을 볼 수 있다. 이 코드는 실행하면 그대로 컴파일 된다. 그 결과가 아래의 화면이다.

20180116_234811.png

대상이 되는 test를 생성하기 위해 make는 의존하는 파일들을 살필 것이다. 그러나 대상이 의존하는 test1.o test2.o test3.o 이 세 파일이 존재하지 않기 때문에 make는 다시 저 파일들의 대상으로 있는 곳을 찾으려 한다. 이때, 찾지 못할 경우에는 오류를 내고 중단할 것 같지만, 실제로는 암시적 규칙에 따라 오브젝트 파일을 gcc가 생성할 수 있는 것을 알기 때문에, test1.o test2.o test3.o 파일을 생상하기 위해 의존하는 파일을 스스로 찾고 컴파일러 호출까지 알아서 수행한다. 이때, 실행 결과에 찍힌 규칙을 보면 알겠지만 gcc를 호출하는 것이 아니라 cc 컴파일러를 호출하였다.

이 과정을 보고 싶다면 make -p 라고 해서 -p 옵션을 통해서 볼 수 있다. 실행하면 아래와 같이 쭉 나온다. 아래 화면에 스크롤 바를 주목해라. 내용 장난 아니게 많다. 암시적 규칙으로 어떤 것들이 불러지는지 알고 싶다면 계속 스크롤을 내려서 살펴보는 것도 좋을 것이다. 근데 당장은 이해 못한다.

20180116_234940

20180116_234956.png

20180116_235008

Advertisements

116 – make 매크로 수정

이미 정의된 매크로 부분을 다음과 같이 바꿔봤다.

20180108_175146

OB 매크로에 test3를 추가하는 형태로 OBJF를 바꾼 것이다. 그러면 일전에 모든 것을 다 선언했던 매크로와 동일한 효과가 있다.

그렇다면 이제 프로그래밍 좀 해본 분들은 한 번 정도는 생각해 볼 만한 것이 바로 변수에 변수 뒤엎어 쓰듯이 매크로도 그런 식으로 쓸 수 있지 않을까 하는 생각을 할 것이다. 예를 들어 이렇게 말이다.

20180108_175537.png

확대해서 보일 수 있도록 캡쳐를 하였다. 위의 화면과 같이 하면 되겠지? 라는 생각들 할 수도 있다. 결론부터 말하면 안된다. 아래처럼 된다.

20180108_175639

매크로가 정의되는 방식에는 두 가지 방식이 존재한다. 재귀 확장형 매크로와 단순 확장형 매크로가 존재하는데, 우리가 지금 이용하는 make의 경우에는 재귀 확장형 매크로이다. 따라서 이미 선언한 OBJF에 대해서 불러오는 부분에서 이용한 $(OBJF) 부분에서 재귀 콜이 불러져서 다시 참조하는 형태, 즉 다른 매크로를 포함하면 같이 확장을 하는 형태로 만들어졌기 때문에 오류를 낸 것이다. 똑똑한 매크로 실행기가 먼저 알아서 멈춰진 것이다.

그럼 이걸 단순 확장으로 만들 수 없는 걸까? 당연히 있다. 단순 확장 매크로는 말 그대로 단순히 확장만 되는 형태로 만들어지고, 매크로의 정의 차이에 따라서 이걸 판단하게 된다. 우선 단순확장에 대해서만 살펴보려고 하는데, 단순 확장의 경우에는 :=를 통해 확장하면 된다. 아래처럼 해주면 된다.

20180108_180207

간단하다. 설명만 힘들 뿐이다. (ㅠㅠ) 이를 실행해보면 오류 없이 진행될 수 있는 것을 볼 수 있다.

20180108_180225.png

그렇다면 기존에 있는 내용에 대해서 치환할 수 있는 매크로도 존재한다. 기본식이 다음과 같다.

$(M_NAME:old=new)

old가 기존에 있던 부분이고, new가 치환하려는 부분이다. 이건 예시 코드를 만들어서 보여주겠다. OBJF에 있는 .o 확장자를 .c 확장자로 변경해 보겠다.

20180108_181120

위의 화면과 같이 SRCS라고 하는 소스코드 파일들을 매크로 선언으로 하였다. 그 다음에 이걸 확인하기 위해서 명령어를 하나 추가해서 보여주려고 한다. 아마 오류가 날 코드이다.

20180108_181144.png

실제 실행한 화면이다. 예상대로 오류가 났다. (이거에 대해서는 나중에 글을 추가하겠다.) 그러나, 실행하려는 구문에 보면 뒤에 확장자가 .c로 바뀐 것을 볼 수 있다.

115 – make의 내부 매크로

앞에서 살펴본 매크로의 경우에는 사용자가 원하는 대로 맞출 수 있는 매크로이기 때문에 사용자 정의 매크로라고 한다. (이 표현은 프로그래밍 언어 관련된 내용을 많이 보다보면 중복되게 나오는 표현이라 익숙할 것이다.) 그러나, make 파일을 만들 때 이용할 수 있도록 미리 정의된 매크로들이 존재하는데, 이를 내부 매크로라고 한다. 내부 매크로의 종류와 의미는 아래와 같다.

  • $@ |현재 목표 파일의 이름
  • $* | 확장자를 제외한 현재 목표 파일의 이름
  • $< | 현재 필수 조건 파일 중 첫 번째 파일 이름
  • $? | 현재 대상보다 최슨에 변경된 함수 조건 파일 이름
  • $^ | 현재 모든 필수 조건 파일들

이 내부 매크로를 이용하여 앞에서 살펴본 예제를 더 간단하게 만들어보자.

20180108_174737

이 표현이 익숙하다면 상관 없겠는데 필자의 경우에는 은근 싫어하는 스타일이라서 사용하진 않는다.