Make (소프트웨어)
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
Make는 스튜어트 펠드먼이 개발한 소프트웨어 빌드 자동화 도구로, 1976년에 처음 출시되었다. Make는 파일 간의 의존 관계를 정의하고, 변경 사항을 감지하여 필요한 명령을 실행함으로써 소프트웨어 빌드 과정을 효율적으로 관리한다. Make는 다양한 파생 버전과 GNU Make, BSD Make, Microsoft nmake 등 여러 구현이 있으며, Makefile을 사용하여 빌드 규칙과 명령을 정의한다. Make는 텍스트 기반의 Makefile을 통해 대상 파일과 종속성을 지정하고, 매크로, 와일드카드, 규칙 등을 활용하여 빌드 과정을 유연하게 설정할 수 있다. Make는 프로그램 빌드 외에도 다양한 작업을 자동화하는 데 사용되며, 재귀적 사용 및 기타 기능들을 지원한다.
더 읽어볼만한 페이지
- 빌드 자동화 - GNU 빌드 시스템
GNU 빌드 시스템은 Autoconf, Automake, Libtool 등의 오토툴과 GNU make 등으로 구성되어 다양한 UNIX 시스템에서 소프트웨어 빌드 및 설치를 지원하지만, 복잡성과 이식성에 대한 비판도 존재한다. - 빌드 자동화 - MSBuild
MSBuild는 마이크로소프트에서 개발한 빌드 자동화 도구로서, 프로젝트 파일에 기술된 대상을 실행하여 빌드 과정을 자동화하며, Team Foundation 빌드와 연동하여 팀 빌드 환경을 구성하는 데 사용된다. - 스크립트 언어 - Tcl
Tcl은 존 오스터하우트가 개발한 명령어 기반의 프로그래밍 언어로, Tk 툴킷과 결합하여 GUI 스크립팅 환경으로 발전했으며, 다양한 운영체제에서 사용 가능하고 C, C++, Java 등 다른 언어와의 인터페이스를 지원한다. - 스크립트 언어 - PHP
PHP는 라스무스 러도프가 개발한 범용 스크립팅 언어로, 웹 개발에 널리 사용되며 LAMP 아키텍처의 핵심 요소이다. - GNU 프로젝트 소프트웨어 - GNU 코어 유틸리티
GNU 코어 유틸리티는 유닉스 계열 운영체제에서 파일, 셸, 텍스트 조작을 위한 기본적인 명령어 모음으로, GNU 파일 유틸리티에서 시작하여 3개의 패키지가 통합되어 발전했으며 셸 스크립트 및 시스템 관리에 필수적인 도구를 제공한다. - GNU 프로젝트 소프트웨어 - GNU 허드
GNU 허드는 유닉스 운영 체제를 대체하는 것을 목표로 개발된 GNU 프로젝트의 커널로, 마이크로커널 기반의 서버-클라이언트 아키텍처를 사용하며, 파일 시스템 기능을 확장하는 트랜슬레이터 개념을 제공한다.
| Make (소프트웨어) - [IT 관련 정보]에 관한 문서 | |
|---|---|
| 일반 정보 | |
| 종류 | 빌드 자동화 도구 |
| 패러다임 | 매크로, 선언형 |
| 설계자 | 스투어트 펠트먼 |
| 개발자 | 벨 연구소 |
| 발표일 | 1976년 4월 |
| 프로그래밍 언어 | C |
| 운영 체제 | 유닉스 계열, 인페르노 |
| 파일 확장자 | Makefile makefile |
| 구현체 | BSD make GNU make Microsoft nmake |
| 영향을 받은 것 | Ant |
| 영향을 준 것 | Ant Rake MSBuild 기타 빌드 자동화 소프트웨어 |
2. 역사
스튜어트 펠드먼은 벨 연구소에서 근무하며 Make를 만들었다. 초기 버전은 1976년 4월에 완성되었다.[1][2][4] 펠드먼은 Make를 개발한 공로로 2003년 ACM 소프트웨어 시스템상을 수상했다.[3]
Make는 여러 번 구현되었으며, 일반적으로 동일한 makefile 형식을 사용하고 동일한 기능을 제공하지만, 일부는 원본에서 개선된 기능을 제공한다.
펠드먼은 Make를 개발하게 된 영감을 당시 동료의 도구 사용에 대한 불만에서 얻었다고 설명한다. 스티븐 C. 존슨이 올바른 프로그램을 디버깅하는 데 시간을 낭비하게 한 경험을 언급하며, 의존성 분석기를 만드는 복잡한 아이디어에서 시작하여 Make로 발전했다고 밝혔다. Make 파일은 텍스트 파일 형태로, 유닉스 철학의 일부처럼 출력, 디버깅, 이해가 가능하도록 만들어졌다.
Make가 나오기 전에는 유닉스에서 빌드는 주로 각 프로그램의 코드베이스에 맞춰 작성된 셸 스크립트로 구성되었다. Make의 의존성 정렬과 구식 확인 기능은 빌드 프로세스를 더 강력하고 효율적으로 만들었으며, makefile을 사용하면 빌드 로직을 더 잘 구성하고 빌드 파일을 줄일 수 있게 되었다.
Make는 초기에 PWB/UNIX 1.0부터 유닉스에 포함되면서 널리 사용되었으며, 다양한 소프트웨어 개발 도구를 갖추고 있었다.[4]
3. 파생
POSIX는 Make 유틸리티의 기본 기능 및 작동에 대한 표준화를 포함하며, Unix 기반 버전의 Make와의 호환성을 다양한 수준으로 구현한다. GNU Make, Makepp 및 일부 버전의 BSD Make는 각각 "GNUmakefile",[35] "Makeppfile"[36] 및 "BSDmakefile"[37]이라는 파일을 먼저 찾도록 기본 설정되어 있다.
리눅스 표준 기반(Linux Standard Base)에서도 지정된 명령이다.[54] 최근에는 CMake를 사용하는 경우가 있다.
make에는 호환되지 않는 아종이 존재한다. 유사한 도구로는 rake(Ruby용), setup(Python용)이 있다.
4. Makefile
make을 실행하기 전에 프로젝트의 목록 및 컴파일 및 링크 규칙을 만들어야 한다. 이것은 보통 Makefile을 사용한다. 이 파일에 규칙을 입력하여 파일로 만든다.
Makefile 언어는 부분적으로 선언형 프로그래밍이며, 종료 조건이 설명되지만 수행할 작업의 순서는 지정되지 않는다.[40][41][42][43] 이러한 유형의 프로그래밍은 명령형 프로그래밍에 익숙한 프로그래머에게 혼란스러울 수 있다.
Makefile은 다음 구성을 포함할 수 있다:[44]
- '''명시적 규칙''': 대상 업데이트 시점 및 방법을 정의하며, ''사전 요구 사항'' (종속 대상)과 ''레시피''라고 하는 업데이트 작업을 정의하는 명령을 나열한다.
- '''암시적 규칙''': 대상과 유사한 이름의 파일에 대상이 어떻게 종속되는지와 업데이트 레시피를 포함하여 파일의 이름을 기반으로 파일 클래스를 다시 만드는 시점과 방법을 정의한다.
- '''변수 정의''': 나중에 텍스트로 대체될 수 있는 이름에 텍스트 값을 연결한다.
- '''지시어''': 다른 makefile을 포함하는 것과 같은 특별한 작업을 수행하는 지침
- '''주석''': #로 시작하는 줄
== 규칙 (Rules) ==
규칙은 일반적으로 대상(TARGET)과 의존성(PREREQUISITES), 그리고 대상 생성을 위한 명령(RECIPE)으로 구성된다.
각 규칙은 규칙의 대상 이름, 콜론(:)과 선택적으로 규칙의 대상이 의존하는 대상 목록인 필수 구성 요소로 구성된 ''종속성 줄''로 시작한다.[45]
일반적으로 규칙은 여러 대상이 아닌 단일 대상을 갖는다.
종속성 줄 뒤에는 레시피, 즉 구성 요소(예: 소스 파일)에서 대상을 생성하는 방법을 정의하는 일련의 TAB 들여쓰기된 명령 줄이 올 수 있다. 필수 구성 요소 중 대상 파일보다 최신 타임스탬프를 갖거나 대상이 파일로 존재하지 않는 경우 레시피가 수행된다.
첫 번째 명령은 필수 구성 요소 뒤에 세미콜론으로 구분되어 동일한 줄에 나타날 수 있다.
각 명령 줄은 탭 문자로 시작해야 한다. 공백도 공백이지만, Make는 탭을 요구한다. 이는 종종 혼란과 실수를 유발하므로 makefile 구문의 이러한 측면은 비판의 대상이 된다. 에릭 S. 레이먼드는 이를 "유닉스 역사상 최악의 설계 실수 중 하나"라고 묘사했고,[46] ''유닉스 혐오자 핸드북''은 "구문의 일부로 탭을 사용하는 것은 ''그린 베레''에 나오는 펀지 스틱 함정 중 하나와 같다"고 말했다. 펠드만은 이 선택이 초창기 구현의 어려움에 대한 대처 방법과 최초 사용자들과의 하위 호환성을 유지하려는 열망 때문에 발생했다고 설명한다.[46]
GNU Make. 버전 3.82부터는 .RECIPEPREFIX 특수 변수를 사용하여 레시피 접두사로 모든 기호(한 문자)를 선택할 수 있다.
각 명령은 별도의 셸에서 실행된다. 운영 체제는 서로 다른 셸을 사용하므로 이로 인해 이식 불가능한 makefile이 발생할 수 있다. 예를 들어, GNU Make(모든 POSIX Make)는 기본적으로 /bin/sh로 명령을 실행하며, 여기에서는 cp와 같은 유닉스 명령이 일반적으로 사용된다. 이와 대조적으로, Microsoft의 ''nmake''는 copy와 같은 배치 명령이 사용 가능하지만 cp가 아닐 수 있는 cmd.exe로 명령을 실행한다.
레시피는 선택 사항이므로 종속성 줄은 다른 대상을 참조하는 구성 요소만으로 구성될 수 있다.
명령은 다음 접두사 중 하나 이상을 가질 수 있다(탭 뒤에).
- 마이너스 (-)는 명령에서 오류를 무시하도록 지정한다.
- 앳 (@)는 명령 실행 전에 명령을 출력하지 ''않도록'' 지정한다.
- 플러스 (+)는 Make가 "실행하지 않음" 모드로 호출된 경우에도 명령을 실행하도록 지정한다.
오류 무시 및 에코 음소거는 특수 대상 .IGNORE 및 .SILENT를 통해 얻을 수도 있다.[47]
== 매크로 (Macros) ==
makefile은 매크로를 정의하고 사용할 수 있다. 매크로는 `CC=clang`와 같이 단순한 문자열 정의를 포함할 때 일반적으로 ''변수''라고 불린다.[48] makefile의 매크로는 Make 유틸리티에 전달된 명령줄 인자에서 재정의될 수 있으며, 환경 변수도 매크로로 사용할 수 있다.[48]
예를 들어, 매크로 `CC`는 makefile에서 C 컴파일러의 위치를 참조하는 데 자주 사용된다. makefile 전체에서 일관되게 사용되면 컴파일러를 호출하는 각 규칙 명령을 변경하는 대신 매크로의 값을 변경하여 사용되는 컴파일러를 변경할 수 있다. 매크로는 일반적으로 대문자로 이름이 지정된다.
매크로 값은 다른 매크로 값으로 구성될 수 있다. 매크로 값은 사용할 때마다 확장된다 (지연적으로).
매크로는 `$`'NAME'` 또는 `$(''NAME'')`을 통해 확장하여 사용한다. 후자는 괄호를 생략하면 Make가 `$` 뒤의 다음 문자를 전체 변수 이름으로 해석하기 때문에 더 안전하다. 이에 상응하는 형식은 괄호 대신 중괄호를 사용한다. 즉 `${}`이며, 이는 BSD에서 사용되는 스타일이다.
매크로는 명령 대체 연산자 `!=`를 사용하여 셸 명령으로 구성할 수 있다.[48]
매크로를 재정의하기 위한 명령줄 구문은 다음과 같다.
Makefiles는 `?` 및 `@`가 일반적인 미리 정의된 ''내부 매크로''에 액세스할 수 있다.
매크로를 정의할 때 일반적인 구문은 등호 (=) 대신 `+=`, `?=`, `!=`를 사용하는 것으로, BSD 및 GNU Make에서 작동한다.[49]
== 와일드카드 (Wildcards) ==
와일드카드는 명령에서 사용될 수 있으며, 이는 셸에 의해서 확장된다.[50]
와일드카드는 규칙의 종속물에서도 유용하다.
와일드 카드는 규칙 안에서 자동으로 확장된다. 그러나 변수가 설정되었을 때, 또는 함수의 매개변수 안에서는 일반적으로 발생하지 않는다. 그런 경우에서 와일드카드 확장을 하려고 한다면 `wildcard` 함수를 사용해야 한다.[50]
== Makefile 예제 ==
다음은 makefile의 예시이다.
```make
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
rm edit $(objects)
```
위의 예에서 최종 실행 출력 파일은 `edit`이다. `edit` 실행 파일을 만들기 위해 여러 개의 소스 코드 파일을 이용한다. 어떤 프로그램 소스 파일이 있는가는 objects 변수에 의해 설정되었다.[58]
`.PHONY : make clean`을 실행하면 `rm` 명령만을 실행하게 한다. 위의 경우 단순히 명령줄로 사용할 때 사용한다. `clean` 뒤에 의존성 파일이 없으므로 타겟을 변경할 필요가 없어진다. 따라서 `rm`을 실행하지 않는다. 업데이트 필요성이 없어진다. 생성 파일이 아니 단순 타켓으로만 인식하게 할 수 있다.[58]
clean을 실행해서 삭제하고 다시 컴파일하려면
```bash
$ make clean
```
명령을 실행한다.
```make
rm edit $(objects)
```
이 실행되어 모든 오브젝트 파일이 삭제된다. 동시에 실행 파일 edit도 삭제된다.[58]
위의 예에서 구조를 다음과 같이 간단히 줄일 수 있다.
```make
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h
```
다음 명령어들은 뒤따르는 makefile의 컨텍스트에 있다.
```makefile
CFLAGS ?= -g
all: helloworld
helloworld: helloworld.o
$(CC) $(LDFLAGS) -o $@ $^
helloworld.o: helloworld.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
$(RM) helloworld helloworld.o
```
와 는 소위 내부 매크로(자동 변수라고도 함) 중 두 가지이며 각각 대상 이름과 "암시적" 소스를 나타낸다. 위 예에서 는 선행 조건의 공백으로 구분된 목록으로 확장된다. 다른 여러 내부 매크로가 있다.[53]
많은 시스템에는 파일 접미사를 기반으로 컴파일과 같은 일반적인 작업을 지정하기 위한 미리 정의된 Make 규칙과 매크로가 함께 제공된다. 이렇게 하면 사용자가 소스에서 대상을 생성하는 방법에 대한 실제(종종 이식성이 없는) 지침을 생략할 수 있다. 이러한 시스템에서 위의 makefile은 다음과 같이 수정할 수 있다.
```makefile
all: helloworld
helloworld: helloworld.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
clean:
$(RM) helloworld helloworld.o
# 접미사 규칙
.c.o:
$(CC) $(CFLAGS) -c $<
.SUFFIXES: .c
```
이제 "helloworld.o"가 "helloworld.c"에 종속된다는 사실은 Make에서 자동으로 처리된다. 여기에 설명된 것과 같은 간단한 예에서는 이것이 거의 중요하지 않지만, 접미사 규칙의 실제 성능은 소프트웨어 프로젝트의 소스 파일 수가 증가하기 시작할 때 분명해진다. 사용자는 링크 단계에 대한 규칙을 작성하고 개체 파일을 선행 조건으로 선언하기만 하면 된다. 그러면 Make는 모든 개체 파일을 만드는 방법을 암시적으로 결정하고 모든 소스 파일의 변경 사항을 찾는다.
소스 파일이 서로 및 헤더 파일과 같은 다른 파일에 종속되지 않는 한 간단한 접미사 규칙이 잘 작동한다. 빌드 프로세스를 단순화하는 또 다른 방법은 컴파일러 지원 종속성 생성을 결합할 수 있는 소위 패턴 일치 규칙을 사용하는 것이다. GCC 컴파일러와 GNU Make가 필요한 마지막 예로, 폴더의 모든 C 파일을 해당 개체 파일로 컴파일한 다음 최종 실행 파일에 연결하는 일반 makefile이 있다. 컴파일이 수행되기 전에 종속성은 makefile 친화적인 형식으로 숨겨진 파일 ".depend"로 수집된 다음 makefile에 포함된다. 이식 가능한 프로그램은 아래에 사용된 구성을 피해야 한다.
```makefile
# 일반 GNUMakefile
# GNU가 아닌 경우 실패하는 코드 조각
ifneq (,)
This makefile requires GNU Make.
endif
PROGRAM = foo
C_FILES := $(wildcard *.c)
OBJS := $(patsubst %.c, %.o, $(C_FILES))
CC = cc
CFLAGS = -Wall -pedantic
LDFLAGS =
LDLIBS = -lm
all: $(PROGRAM)
$(PROGRAM): .depend $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(PROGRAM) $(LDLIBS)
depend: .depend
.depend: cmd = gcc -MM -MF depend $(var); cat depend >> .depend;
.depend:
@echo "Generating dependencies..."
@$(foreach var, $(C_FILES), $(cmd))
@rm -f depend
- include .depend
# 다음은 패턴 일치 규칙이다. 여기에 사용된 자동
# 변수 외에도 %가 나타내는 모든 것을 일치시키는 변수 $*는
# 특수한 경우에 유용할 수 있다.
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%: %.o
$(CC) $(CFLAGS) -o $@ $<
clean:
rm -f .depend $(OBJS)
.PHONY: clean depend
```
4. 1. 규칙 (Rules)
Make는 복잡하게 관련된 파일의 의존 관계를 해결하는 데 장점을 가지고 있다.[47] 예를 들어 A 파일을 처리하여 B 파일을 생성할 때, Make는 각 파일의 갱신 시각(타임스탬프)을 참조하여 A가 B보다 새로운 경우에는 작업을 수행하지만, B가 A보다 새롭다면 작업이 필요 없다고 간주하여 아무것도 하지 않는다.[47] 파일 수가 증가하고 의존 관계가 복잡해져도 Make는 makefile의 記述에 따라 필요한 최소한의 작업만 자동으로 수행한다.[47] 오토툴즈(Autotools)라는 다른 도구를 사용하여 makefile을 자동 생성할 수 있다.[47]유닉스계 소프트웨어는 소스 코드 형태로 배포되는 경우가 있는데, Make는 이러한 소프트웨어의 빌드 작업에 거의 필수적인 도구라고 할 수 있다(극히 드물게 Make를 사용하지 않는 소프트웨어도 존재한다).[47]
Make는 프로그램 코드의 빌드 외에도 다양한 용도로 사용 가능하다.[47] 예를 들어, LaTeX 소스 파일에서 DVI 형식의 파일을 생성하는 작업 등에 사용할 수 있다.[47] 배치 처리를 간소화하는 데에도 사용할 수 있다.[47]
규칙은 일반적으로 대상(TARGET)과 의존성(PREREQUISITES), 그리고 대상 생성을 위한 명령(RECIPE)으로 구성된다.
```text
TARGET ...: PREREQUISITES ...
RECIPE
...
```
또 다른 형식은 다음과 같다.
```text
TARGETS: PREREQUISITES ; RECIPE
RECIPE
...
```
- TARGET: 실행 파일, object 파일, 라이브러리 등 목적 규칙을 정의한다. RECIPE에서 실행된 결과로 만들어진다. RECIPE 여러개의 명령줄을 사용할 수가 있어 복잡한 기능도 수행이 가능하다. 생성파일이나 install 같은 기능적 블럭도 가능하다.
- PREREQUISITES: TARGET을 만들 때, 의존성(연관관계)를 규정한다. 이 부분에 나열된 파일 중 수정된 파일이 있으면 TARGET을 다시 만든다.
- RECIPE: TARGET을 만들기 위한 실행 파일이다. 이 실행 규칙에 따라 TARGET이 생성 된다. 주로 cc나 리눅스 명령어를 사용한다. 이 명령 줄은 여러 줄이 가능하다. 주의 할 것은 RECIPE 부분의 앞 공간은 키보드 을 사용해야 한다. 키로 공간을 넣으면 안 된다.
각 규칙은 규칙의 대상 이름, 콜론(:)과 선택적으로 규칙의 대상이 의존하는 대상 목록인 필수 구성 요소로 구성된 ''종속성 줄''로 시작한다.[45]
```text
대상 [대상 ...]: [구성 요소 ...]
[명령 1]
.
.
.
[명령 n]
```
일반적으로 규칙은 여러 대상이 아닌 단일 대상을 갖는다.
종속성 줄 뒤에는 레시피, 즉 구성 요소(예: 소스 파일)에서 대상을 생성하는 방법을 정의하는 일련의 TAB 들여쓰기된 명령 줄이 올 수 있다. 필수 구성 요소 중 대상 파일보다 최신 타임스탬프를 갖거나 대상이 파일로 존재하지 않는 경우 레시피가 수행된다.
첫 번째 명령은 필수 구성 요소 뒤에 세미콜론으로 구분되어 동일한 줄에 나타날 수 있다.
```text
대상: 필수 구성 요소; 명령
```
예를 들어:
```text
hello:; @echo "hello"
```
각 명령 줄은 탭 문자로 시작해야 한다. 공백도 공백이지만, Make는 탭을 요구한다. 이는 종종 혼란과 실수를 유발하므로 makefile 구문의 이러한 측면은 비판의 대상이 된다. 에릭 S. 레이먼드는 이를 "유닉스 역사상 최악의 설계 실수 중 하나"라고 묘사했고,[46] ''유닉스 혐오자 핸드북''은 "구문의 일부로 탭을 사용하는 것은 ''그린 베레''에 나오는 펀지 스틱 함정 중 하나와 같다"고 말했다. 펠드만은 이 선택이 초창기 구현의 어려움에 대한 대처 방법과 최초 사용자들과의 하위 호환성을 유지하려는 열망 때문에 발생했다고 설명한다.[46]
GNU Make. 버전 3.82부터는 .RECIPEPREFIX 특수 변수를 사용하여 레시피 접두사로 모든 기호(한 문자)를 선택할 수 있다. 예를 들면:
```text
.RECIPEPREFIX := :
all:
:@echo "recipe prefix symbol is set to '$(.RECIPEPREFIX)'"
```
각 명령은 별도의 셸에서 실행된다. 운영 체제는 서로 다른 셸을 사용하므로 이로 인해 이식 불가능한 makefile이 발생할 수 있다. 예를 들어, GNU Make(모든 POSIX Make)는 기본적으로 /bin/sh로 명령을 실행하며, 여기에서는 cp와 같은 유닉스 명령이 일반적으로 사용된다. 이와 대조적으로, Microsoft의 ''nmake''는 copy와 같은 배치 명령이 사용 가능하지만 cp가 아닐 수 있는 cmd.exe로 명령을 실행한다.
레시피는 선택 사항이므로 종속성 줄은 다른 대상을 참조하는 구성 요소만으로 구성될 수 있다. 예를 들면:
```text
realclean: clean distclean
```
다음 예제 규칙은 Make가 target file.txt를 업데이트할 때 평가된다. 즉, 를 통해. file.html이 file.txt보다 최신이거나 file.txt가 존재하지 않으면 명령이 실행되어 file.html에서 file.txt를 생성한다.
```text
file.txt: file.html
lynx -dump file.html > file.txt
```
명령은 다음 접두사 중 하나 이상을 가질 수 있다(탭 뒤에).
- 마이너스 (-)는 명령에서 오류를 무시하도록 지정한다.
- 앳 (@)는 명령 실행 전에 명령을 출력하지 ''않도록'' 지정한다.
- 플러스 (+)는 Make가 "실행하지 않음" 모드로 호출된 경우에도 명령을 실행하도록 지정한다.
오류 무시 및 에코 음소거는 특수 대상 및 를 통해 얻을 수도 있다.[47]
Microsoft의 NMAKE는 이러한 makefile에서 생략할 수 있는 미리 정의된 규칙을 가지고 있다. 예를 들어, .
4. 2. 매크로 (Macros)
makefile은 매크로를 정의하고 사용할 수 있다. 매크로는 `CC=clang`와 같이 단순한 문자열 정의를 포함할 때 일반적으로 ''변수''라고 불린다.[48] makefile의 매크로는 Make 유틸리티에 전달된 명령줄 인자에서 재정의될 수 있으며, 환경 변수도 매크로로 사용할 수 있다.[48]예를 들어, 매크로 `CC`는 makefile에서 C 컴파일러의 위치를 참조하는 데 자주 사용된다. makefile 전체에서 일관되게 사용되면 컴파일러를 호출하는 각 규칙 명령을 변경하는 대신 매크로의 값을 변경하여 사용되는 컴파일러를 변경할 수 있다. 매크로는 일반적으로 대문자로 이름이 지정된다.
```make
MACRO = definition
```
매크로 값은 다른 매크로 값으로 구성될 수 있다. 매크로 값은 사용할 때마다 확장된다 (지연적으로).
매크로는 `$`'NAME'` 또는 `$(''NAME'')`을 통해 확장하여 사용한다. 후자는 괄호를 생략하면 Make가 `$` 뒤의 다음 문자를 전체 변수 이름으로 해석하기 때문에 더 안전하다. 이에 상응하는 형식은 괄호 대신 중괄호를 사용한다. 즉 `${}`이며, 이는 BSD에서 사용되는 스타일이다.
```make
NEW_MACRO = $(MACRO)-$(MACRO2)
```
매크로는 명령 대체 연산자 `!=`를 사용하여 셸 명령으로 구성할 수 있다.[48]
```make
YYYYMMDD != date
```
매크로를 재정의하기 위한 명령줄 구문은 다음과 같다.
```bash
make MACRO="value" [MACRO="value" ...] TARGET [TARGET ...]
```
Makefiles는 `?` 및 `@`가 일반적인 미리 정의된 ''내부 매크로''에 액세스할 수 있다.
```make
target: component1 component2
# echo components YOUNGER than TARGET
echo $?
# echo TARGET name
echo $@
```
매크로를 정의할 때 일반적인 구문은 등호 (=) 대신 `+=`, `?=`, `!=`를 사용하는 것으로, BSD 및 GNU Make에서 작동한다.[49]
make(소프트웨어)는 복잡하게 관련된 파일의 의존 관계를 해결하는 데 장점을 가지고 있다. 예를 들어 A라는 파일을 처리하여 B라는 파일을 생성할 때, make는 각 파일의 갱신 시각(타임스탬프)을 참조하여 A가 B보다 새로운 경우에는 작업을 수행하지만, B가 A보다 새롭다면 작업이 필요 없다고 간주하여 아무것도 하지 않는다.[49] 파일 수가 증가하고 의존 관계가 복잡해져도 make는 makefile의 記述에 따라 필요한 최소한의 작업만 자동으로 수행한다. 오토툴즈(Autotools)라는 다른 도구를 사용하여 makefile을 자동 생성할 수 있다.
유닉스계 소프트웨어는 소스 코드 형태로 배포되는 경우가 있다. make는 이러한 소프트웨어의 빌드 작업에 거의 필수적인 도구라고 할 수 있다(극히 드물게 make를 사용하지 않는 소프트웨어도 존재한다).
make는 프로그램 코드의 빌드 외에도 다양한 용도로 사용 가능하다. 예를 들어, LaTeX 소스 파일에서 DVI 형식의 파일을 생성하는 작업 등에 사용할 수 있다. 배치 처리를 간소화하는 데에도 사용할 수 있다.
4. 3. 와일드카드 (Wildcards)
와일드카드는 명령에서 사용될 수 있으며, 이는 셸에 의해서 확장된다.[50]```make
clean:
rm -f *.o
```
위 규칙은 모든 오브젝트 파일들을 삭제한다. 와일드카드는 규칙의 종속물에서도 유용하다. 다음 규칙에서 '`make print`'는 대상의 인쇄한 마지막 시간 이후로 변경된 모든 '.c' 파일들을 인쇄한다:[50]
```make
print: *.c
lpr -p $?
touch print
```
와일드 카드는 규칙 안에서 자동으로 확장된다. 그러나 변수가 설정되었을 때, 또는 함수의 매개변수 안에서는 일반적으로 발생하지 않는다. 그런 경우에서 와일드카드 확장을 하려고 한다면 `wildcard` 함수를 사용해야 한다.[50]
```make
$(wildcard pattern...)
$(wildcard *.c) # 한 디렉토리에 있는 모든 C 소스 파일들의 리스트를 획득하는 것이다.
$(patsubst %.c,%.o,$(wildcard *.c)) # '.c' 접미사를 '.o'로 변경해서 오브젝트 파일들의 리스트로 변경할 수 있다.
```
한 디렉토리에 있는 모든 C 파일들을 컴파일하고 이들을 모두 모아서 링크하려고 하는 makefile은 다음과 같이 작성될 수 있다:[50]
```make
objects := $(patsubst %.c,%.o,$(wildcard *.c))
foo : $(objects)
cc -o foo $(objects)
```
make(소프트웨어)는 복잡하게 관련된 파일의 의존 관계를 해결하는 데 장점을 가지고 있다. 예를 들어 A라는 파일을 처리하여 B라는 파일을 생성할 때, make는 각 파일의 갱신 시각(타임스탬프)을 참조하여 A가 B보다 새로운 경우에는 작업을 수행하지만, B가 A보다 새롭다면 작업이 필요 없다고 간주하여 아무것도 하지 않는다. 파일 수가 증가하고 의존 관계가 복잡해져도 make는 makefile의 記述에 따라 필요한 최소한의 작업만 자동으로 수행한다. 오토툴즈(Autotools)라는 다른 도구를 사용하여 makefile을 자동 생성할 수 있다.[50]
유닉스계 소프트웨어는 소스 코드 형태로 배포되는 경우가 있다. make는 이러한 소프트웨어의 빌드 작업에 거의 필수적인 도구라고 할 수 있다(극히 드물게 make를 사용하지 않는 소프트웨어도 존재한다).[50]
make는 프로그램 코드의 빌드 외에도 다양한 용도로 사용 가능하다. 예를 들어, LaTeX 소스 파일에서 DVI 형식의 파일을 생성하는 작업 등에 사용할 수 있다. 배치 처리를 간소화하는 데에도 사용할 수 있다.[50]
4. 4. Makefile 예제
Make는 복잡하게 관련된 파일의 의존 관계를 해결하는 데 장점을 가지고 있다. 예를 들어 A 파일을 처리하여 B 파일을 생성할 때, make는 각 파일의 갱신 시간(타임스탬프)을 참조하여 A가 B보다 새로운 경우에는 작업을 수행하지만, B가 A보다 새롭다면 작업이 필요 없다고 간주하여 아무것도 하지 않는다.[58] 파일 수가 증가하고 의존 관계가 복잡해져도 make는 makefile의 記述에 따라 필요한 최소한의 작업만 자동으로 수행한다. 오토툴즈(Autotools)라는 다른 도구를 사용하여 makefile을 자동 생성할 수 있다.유닉스계 소프트웨어는 소스 코드 형태로 배포되는 경우가 있으며, make는 이러한 소프트웨어의 빌드 작업에 거의 필수적인 도구라고 할 수 있다(극히 드물게 make를 사용하지 않는 소프트웨어도 존재한다).
make는 프로그램 코드의 빌드 외에도 다양한 용도로 사용 가능하다. 예를 들어, LaTeX 소스 파일에서 DVI 형식의 파일을 생성하는 작업 등에 사용할 수 있다. 배치 처리를 간소화하는 데에도 사용할 수 있다.
다음은 makefile의 예시이다.
```make
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
rm edit $(objects)
```
위의 예에서 최종 실행 출력 파일은 `edit`이다. `edit` 실행 파일을 만들기 위해 여러 개의 소스 코드 파일을 이용한다. 어떤 프로그램 소스 파일이 있는가는 objects 변수에 의해 설정되었다.[58]
`.PHONY : make clean`을 실행하면 `rm` 명령만을 실행하게 한다. 위의 경우 단순히 명령줄로 사용할 때 사용한다. `clean` 뒤에 의존성 파일이 없으므로 타겟을 변경할 필요가 없어진다. 따라서 `rm`을 실행하지 않는다. 업데이트 필요성이 없어진다. 생성 파일이 아니 단순 타켓으로만 인식하게 할 수 있다.[58]
clean을 실행해서 삭제하고 다시 컴파일하려면
```bash
$ make clean
```
명령을 실행한다.
```make
rm edit $(objects)
```
이 실행되어 모든 오브젝트 파일이 삭제된다. 동시에 실행 파일 edit도 삭제된다.[58]
위의 예에서 구조를 다음과 같이 간단히 줄일 수 있다.
```make
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h
```
다음 명령어들은 뒤따르는 makefile의 컨텍스트에 있다.
```bash
make # 첫 번째 대상인 'all'을 업데이트한다.
make help # 대상 'help'를 업데이트하여 대상을 나열한다.
make dist # 배포를 위해 대상 'dist'를 업데이트한다.
```
```makefile
PACKAGE = package
VERSION = ` date "+%Y.%m%d%" `
RELEASE_DIR = ..
RELEASE_FILE = $(PACKAGE)-$(VERSION)
# 기본 대상
# 참고: 변수 LOGNAME은 환경에서 가져온다.
all:
echo "Hello $(LOGNAME), nothing to do by default"
echo "Try 'make help'"
# 이 파일을 검색하여 대상 표시
help:
egrep "^# target:" [Mm]akefile
# 릴리스 만들기
dist:
tar -cf $(RELEASE_DIR)/$(RELEASE_FILE) && \
gzip -9 $(RELEASE_DIR)/$(RELEASE_FILE).tar
```
다음은 기본적으로(규칙 "all"이 먼저 나열됨) 시스템의 C 컴파일러를 사용하여 "helloworld.c"라는 소스 파일을 컴파일하고 사용자가 다시 시작하려는 경우 생성된 파일을 제거하는 "clean" 대상을 제공하는 간단한 makefile이다.
```makefile
CFLAGS ?= -g
all: helloworld
helloworld: helloworld.o
$(CC) $(LDFLAGS) -o $@ $^
helloworld.o: helloworld.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
$(RM) helloworld helloworld.o
```
와 는 소위 내부 매크로(자동 변수라고도 함) 중 두 가지이며 각각 대상 이름과 "암시적" 소스를 나타낸다. 위 예에서 는 선행 조건의 공백으로 구분된 목록으로 확장된다. 다른 여러 내부 매크로가 있다.[53]
많은 시스템에는 파일 접미사를 기반으로 컴파일과 같은 일반적인 작업을 지정하기 위한 미리 정의된 Make 규칙과 매크로가 함께 제공된다. 이렇게 하면 사용자가 소스에서 대상을 생성하는 방법에 대한 실제(종종 이식성이 없는) 지침을 생략할 수 있다. 이러한 시스템에서 위의 makefile은 다음과 같이 수정할 수 있다.
```makefile
all: helloworld
helloworld: helloworld.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
clean:
$(RM) helloworld helloworld.o
# 접미사 규칙
.c.o:
$(CC) $(CFLAGS) -c $<
.SUFFIXES: .c
```
이제 "helloworld.o"가 "helloworld.c"에 종속된다는 사실은 Make에서 자동으로 처리된다. 여기에 설명된 것과 같은 간단한 예에서는 이것이 거의 중요하지 않지만, 접미사 규칙의 실제 성능은 소프트웨어 프로젝트의 소스 파일 수가 증가하기 시작할 때 분명해진다. 사용자는 링크 단계에 대한 규칙을 작성하고 개체 파일을 선행 조건으로 선언하기만 하면 된다. 그러면 Make는 모든 개체 파일을 만드는 방법을 암시적으로 결정하고 모든 소스 파일의 변경 사항을 찾는다.
소스 파일이 서로 및 헤더 파일과 같은 다른 파일에 종속되지 않는 한 간단한 접미사 규칙이 잘 작동한다. 빌드 프로세스를 단순화하는 또 다른 방법은 컴파일러 지원 종속성 생성을 결합할 수 있는 소위 패턴 일치 규칙을 사용하는 것이다. GCC 컴파일러와 GNU Make가 필요한 마지막 예로, 폴더의 모든 C 파일을 해당 개체 파일로 컴파일한 다음 최종 실행 파일에 연결하는 일반 makefile이 있다. 컴파일이 수행되기 전에 종속성은 makefile 친화적인 형식으로 숨겨진 파일 ".depend"로 수집된 다음 makefile에 포함된다. 이식 가능한 프로그램은 아래에 사용된 구성을 피해야 한다.
```makefile
# 일반 GNUMakefile
# GNU가 아닌 경우 실패하는 코드 조각
ifneq (,)
This makefile requires GNU Make.
endif
PROGRAM = foo
C_FILES := $(wildcard *.c)
OBJS := $(patsubst %.c, %.o, $(C_FILES))
CC = cc
CFLAGS = -Wall -pedantic
LDFLAGS =
LDLIBS = -lm
all: $(PROGRAM)
$(PROGRAM): .depend $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(PROGRAM) $(LDLIBS)
depend: .depend
.depend: cmd = gcc -MM -MF depend $(var); cat depend >> .depend;
.depend:
@echo "Generating dependencies..."
@$(foreach var, $(C_FILES), $(cmd))
@rm -f depend
- include .depend
# 다음은 패턴 일치 규칙이다. 여기에 사용된 자동
# 변수 외에도 %가 나타내는 모든 것을 일치시키는 변수 $*는
# 특수한 경우에 유용할 수 있다.
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%: %.o
$(CC) $(CFLAGS) -o $@ $<
clean:
rm -f .depend $(OBJS)
.PHONY: clean depend
5. 동작
make는 일반적으로 실행 가능한 프로그램과 라이브러리를 소스 코드로부터 빌드하는 데 사용된다. 그러나 소스 파일을 대상 결과물로 변환하는 데 필요한 어떠한 프로세스라도 (임의의 명령어들을 실행함으로써) make에 적용할 수 있다.[38]
명령 줄 변수로서 빌드할 대상 파일의 목록과 함께 `make`를 호출할 수 있다.
```bash
$ make 대상 [대상 ...]
```
변수 없이 `make`를 실행하면 makefile 안에 보이는 첫 번째 대상만을 빌드한다. 일반적으로 메이크파일을 기반으로, Make는 대상 파일이 존재하지 않거나 대상 파일의 타임스탬프가 소스 파일보다 오래된 경우 소스 파일로부터 대상 파일을 업데이트한다. 예를 들어, C 파일(*.c)을 오브젝트 파일로 컴파일한 다음, 오브젝트 파일을 실행 가능한 프로그램으로 링크하거나, TypeScript 파일(*.ts)을 JavaScript로 컴파일 할 수 있다.
메이크파일은 각 대상이 생성할 파일이거나 "가짜" 대상이라고 하는 사용자 정의 개념인 대상을 정의한다. Make는 인수로 전달된 대상을 업데이트한다.
```bash
make [-f makefile] [options] [targets]
```
대상이 지정되지 않은 경우, Make는 메이크파일의 첫 번째 대상을 업데이트하며, 이는 종종 가장 일반적으로 사용되는 작업을 수행하는 가짜 대상이다.
Make는 대상 파일의 타임스탬프가 소스 파일의 타임스탬프보다 이후인 경우 빌드 작업을 건너뛴다.[38] 이는 대상 파일이 최신 상태일 때 작업을 건너뛰어 빌드 프로세스를 최적화하지만, 소스 파일의 이전 버전을 복원하거나, 네트워크 파일 시스템이 파일의 소스이고 해당 시계 또는 시간대가 Make를 실행하는 머신과 동기화되지 않는 경우와 같은 파일 타임스탬프 문제로 인해 때때로 업데이트가 잘못 건너뛰어질수 있다.[38] 또한 소스 파일의 타임스탬프가 미래인 경우, make는 불필요한 작업을 반복적으로 트리거하여 빌드 시간을 더 길게 만든다.[38]
Make가 시작될 때, 명령줄에 지정된 메이크파일을 사용하거나, 지정되지 않은 경우 특정 검색 규칙을 통해 찾아낸 메이크파일을 사용한다. 일반적으로 Make는 작업 디렉토리에 있는 Makefile이라는 파일을 사용한다. GNU Make는 GNUmakefile, makefile, 또는 Makefile과 일치하는 첫 번째 파일을 검색한다.
Make는 로드된 메이크파일을 기반으로 명령줄의 옵션을 처리한다.
make는 복잡하게 관련된 파일의 의존 관계를 해결하는 데 장점을 가지고 있다. 예를 들어 A라는 파일을 처리하여 B라는 파일을 생성할 때, make는 각 파일의 갱신 시각(타임스탬프)을 참조하여 A가 B보다 새로운 경우에는 작업을 수행하지만, B가 A보다 새롭다면 작업이 필요 없다고 간주하여 아무것도 하지 않는다. 파일 수가 증가하고 의존 관계가 복잡해져도 makefile의 記述에 따라 필요한 최소한의 작업만 자동으로 수행한다. 오토툴즈(Autotools)라는 다른 도구를 사용하여 makefile을 자동 생성할 수 있다.
유닉스계 소프트웨어는 소스 코드 형태로 배포되는 경우가 있으며, make는 이러한 소프트웨어의 빌드 작업에 필수적인 도구라고 할 수 있다.
make는 프로그램 코드의 빌드 외에도 LaTeX 소스 파일에서 DVI 형식의 파일을 생성하는 작업 등에도 사용할 수 있으며, 배치 처리를 간소화하는 데에도 사용할 수 있다.
6. make의 재귀적 사용
재귀적 사용이란 make를 makefile에서 하나의 명령으로 사용한다는 것이다. 큰 시스템을 만드는 여러 서브시스템들을 위한 여러 분리된 makefile들을 make 실행할 때 유용하다. 예를 들어서 자신의 makefile을 가지고 있는 'subdir' 서브디렉토리를 가지고 있고 상위 디렉토리의 makefile을 사용해서 그 서브 디렉토리에 대해서 make를 실행하고자 한다고 가정할때, 다음과 같이 할 수 있다.
```make
subsystem:
cd subdir && $(MAKE)
```
또는:
```make
subsystem:
$(MAKE) -C subdir
```
재귀적인 make 명령들은, 다음에서 볼 수 있듯이 'make' 명령 이름을 명시적으로 쓰지 않고, 항상 MAKE 변수를 사용하는 것이 좋다. 특정 변수가 sub-make에 익스포트되기를 원한다면 `export` 지시어를 사용한다.
```make
export variable ...
unexport variable ...
```
어떤 변수를 정의하면서 동시에 그것을 익스포트할 수 있다 :
```make
export variable = value
```
이것은 다음과 같은 결과를 가진다:
```make
variable = value
export variable
```
다른 참조도 가능하다.
```make
export variable := value
```
```make
export variable += value
```
'-s'와 '-k' 같은 플래그들은 자동으로 변수 `MAKEFLAGS`를 통해서 서브-make에게 전달된다.
'-C', '-f', '-o', 그리고 '-W' 옵션들은 `MAKEFLAGS`에 들어가지 않는다. 이들 옵션들은 아래로 전달되지 않는다.
다른 플래그들은 아래로 전달하고자 하지 않는다면 반드시 다음과 같이 `MAKEFLAGS`의 값을 변경해야 한다:
```make
subsystem:
cd subdir && $(MAKE) MAKEFLAGS=
MAKEOVERRIDES =
7. 기타 기능
리눅스 표준 기반(Linux Standard Base)에서도 지정된 명령이다.[54] 최근에는 CMake를 사용하는 경우가 있다.
make에는 호환되지 않는 아종이 존재한다. 유사한 도구로는 rake(Ruby용), setup(Python용)이 있다.
8. 빈 명령 사용하기
어떠한 명령도 실행하지 않는 빈 명령을 정의하는 것이 유용할 때가 있다.
```make
target: ;
9. 결론
참조
[1]
웹사이트
V7/usr/src/cmd/make/ident.c
https://archive.toda[...]
2013-09-01
[2]
간행물
Make --- A Program for Maintaining Computer Programs
1979-04
[3]
서적
Practical Development Environments
O'Reilly Media
[4]
간행물
Designer's Workbench: Providing a Production Environment
1980-11
[5]
웹사이트
Google Groups
https://groups.googl[...]
2018-03-18
[6]
웹사이트
OpenSolaris at Two (Jim Grisanzio)
https://web.archive.[...]
2013-12-12
[7]
문서
The OpenSolaris Story
http://www.guug.de/v[...]
[8]
웹사이트
Apache OpenOffice Building Guide - Apache OpenOffice Wiki
https://wiki.openoff[...]
[9]
웹사이트
Development/Gbuild - The Document Foundation Wiki
https://wiki.documen[...]
2018-03-18
[10]
웹사이트
FreeBSD 2.0.5 Make Source Code
https://svnweb.freeb[...]
1993
[11]
웹사이트
Bmake(1)
https://www.freebsd.[...]
[12]
웹사이트
fmake(1) General Commands Manual
https://manpages.deb[...]
2020-11-30
[13]
웹사이트
make
https://web.archive.[...]
2020-07-09
[14]
웹사이트
make(1) - OpenBSD manual pages
https://man.openbsd.[...]
[15]
웹사이트
make
https://www.freebsd.[...]
2020-07-09
[16]
문서
Unix in a Nutshell, Fourth Edition
http://www.linuxdevc[...]
O'Reilly
2005
[17]
문서
8. Functions for Transforming Text
https://www.gnu.org/[...]
Free Software Foundation
2013
[18]
문서
8.5 The foreach Function
https://www.gnu.org/[...]
Free Software Foundation
2013
[19]
웹사이트
GCC 3.4 Release Series Changes, New Features, and Fixes
https://www.gnu.org/[...]
Free Software Foundation
2006
[20]
간행물
Kbuild: the Linux Kernel Build System
http://www.linuxjour[...]
2012-12-26
[21]
문서
Linux Kernel in a Nutshell
http://www.linuxtopi[...]
O'Reilly
2006
[22]
웹사이트
Build Instructions
https://web.archive.[...]
[23]
웹사이트
Remake – GNU Make with comprehensible tracing and a debugger
http://bashdb.source[...]
2018-01-20
[24]
웹사이트
nmake Overview
https://web.archive.[...]
Information and Software Systems Research, AT&T Labs Research
2012-01-04
[25]
웹사이트
NMAKE Reference Visual Studio 2015
http://msdn.microsof[...]
Microsoft
2015
[26]
웹사이트
Makefile Preprocessing Directives
http://msdn.microsof[...]
2014
[27]
웹사이트
Makefile Preprocessing Operators
http://msdn.microsof[...]
Microsoft
2014
[28]
웹사이트
Search Paths in Rules
http://msdn.microsof[...]
Microsoft
2014
[29]
웹사이트
MAKE
http://docs.embarcad[...]
CodeGear(TM)
2008
[30]
웹사이트
Jom - Qt Wiki
https://wiki.qt.io/J[...]
Qt Project
2021
[31]
기술 보고서
A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986
http://www.9grid.fr/[...]
[32]
백과사전
Maintaining files on Plan 9 with Mk
http://9p.io/sys/doc[...]
AT&T Bell Laboratories
[33]
웹사이트
google/kati: An experimental GNU make clone
https://github.com/g[...]
2020-11-30
[34]
간행물
Sustainable data analysis with Snakemake
2021-04-19
[35]
웹사이트
GNU 'make'
https://www.gnu.org/[...]
Free Software Foundation
2014-04-16
[36]
웹사이트
Makepp
http://makepp.source[...]
[37]
웹사이트
Free BSD make
https://www.freebsd.[...]
2018-05-07
[38]
웹사이트
How to sort Linux ls command file output
http://alvinalexande[...]
2016-09-13
[39]
웹사이트
makefile
https://developer.ap[...]
Apple Inc
2023-05-22
[40]
논문
An overview of the CAPITL software development environment
Springer Berlin Heidelberg
1993
[41]
웹사이트
an overview on dsls
http://phoenix.labri[...]
2007-10-23
[42]
웹사이트
Re: Choreography and REST
http://lists.w3.org/[...]
2016-09-12
[43]
웹사이트
Target Junior Makefiles
http://www.robots.ox[...]
2010-01-07
[44]
웹사이트
3.1 What Makefiles Contain
https://www.gnu.org/[...]
Free Software Foundation
2021-05-05
[45]
웹사이트
Prerequisite Types (GNU make)
https://www.gnu.org/[...]
GNU Project
2020-12-15
[46]
서적
Chapter 15. Tools: make: Automating Your Recipes
2003
[47]
문서
make
[48]
웹사이트
Archived copy
https://pubs.opengro[...]
2024-10-29
[49]
문서
make
[50]
웹사이트
GNU make manual: suffix rules
https://www.gnu.org/[...]
Free Software Foundation
2014-05-24
[51]
웹사이트
GNU make manual: pattern rules
https://www.gnu.org/[...]
Free Software Foundation
2014-05-24
[52]
웹사이트
See section Pattern Matching Rules in the SunPro man page
http://www.lehman.cu[...]
2014-05-29
[53]
웹사이트
Automatic Variables
https://www.gnu.org/[...]
GNU `make'
2016-04-25
[54]
간행물
LSB Specifications
https://refspecs.lin[...]
Linux Standard Base
[55]
웹사이트
PMake -- A Tutorial
https://docs.freebsd[...]
2020-12-11
[56]
인용
FreeBSD 2.0.5 Make Source Code
https://svnweb.freeb[...]
1993
[57]
웹인용
nmake Overview
https://web.archive.[...]
Information and Software Systems Research, AT&T Labs Research
2017-03-16
[58]
URL
http://www.gnu.org/s[...]
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com