영어프랑스어스페인어

Ad


온웍스 파비콘

makepp_cookbook - 클라우드 온라인

Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터를 통해 OnWorks 무료 호스팅 제공업체에서 makepp_cookbook 실행

이것은 Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터와 같은 여러 무료 온라인 워크스테이션 중 하나를 사용하여 OnWorks 무료 호스팅 공급자에서 실행할 수 있는 makepp_cookbook 명령입니다.

프로그램:

이름


makepp_cookbook -- 다양한 상황에 맞게 makefile을 설정하는 가장 좋은 방법

기술


나는 실제로 아무도 make 도구에 대한 설명서를 읽지 않는다는 것을 발견했습니다.
아무도 실제로 make 과정 자체에 관심이 없습니다. 우리는 결과에만 관심이 있습니다.
그래서 이 요리책은 사람들이 필요한 것을 얻을 수 있기를 바라는 마음에서 만들어졌습니다.
매뉴얼을 건너뛰지 않고 예제에서 빠르게 입력하는 방법을 보여줍니다.
설치 지침과 걸림돌은 다음에서 찾을 수 있습니다.
자주 묻는 질문.

건물 도서관
Do 당신 정말 필요한 것 a 도서관?

저는 많은 수의 모듈로 구성된 많은 대형 프로그램을 보았습니다.
자체 디렉토리에 있습니다. 일반적으로 각 디렉토리는 자체 라이브러리에 저장됩니다.
그런 다음 최종 프로그램이 모든 라이브러리와 연결됩니다.

많은 경우 라이브러리를 사용하는 것보다 더 나은 접근 방식이 있다고 생각합니다. 도서관
각 모듈을 다른 모듈에서 재사용할 수 없거나 재사용하지 않을 경우 올바른 솔루션이 아닙니다.
프로그램을 사용하면 라이브러리의 모든 단점을 얻을 수 있고
이점. 라이브러리는 다음과 같은 경우에 유용합니다.

1. 여러 개의 서로 다른 서브루틴과 연결해야 하는 서브루틴이 많은 경우
프로그램이며 실제로 서브루틴을 100% 사용하는 프로그램은 없습니다.
다른 하위 집합. 이 경우 정적 라이브러리(a
.a 파일 또는 아카이브 파일).

2. 여러 다른 프로그램에 연결해야 하는 모듈이 있고
각 프로그램이 별도의 복사본을 가질 필요가 없도록 동적으로 로드하려고 합니다.
도서관. 동적 라이브러리는 실행 파일 공간을 절약하고 때로는 향상시킬 수 있습니다.
모든 시스템에 대해 로드된 라이브러리 사본이 하나만 있기 때문에 시스템 성능
그것을 사용하는 다른 프로그램.

3. 링크 시간이 엄청나게 긴 경우 공유 라이브러리를 사용하여
프로그램은 링크 속도를 크게 높일 수 있습니다.

정적 라이브러리를 사용하면 한 가지 주요 단점이 있습니다. 일부 시스템(예: Linux)에서는 순서가
라이브러리를 링크하는 것이 매우 중요합니다. 링커는 라이브러리를 처리합니다.
명령줄에 지정된 순서대로. 필요하다고 생각하는 모든 것을 가져옵니다.
다음 라이브러리로 이동합니다. 일부 후속 라이브러리가
이전 라이브러리에서 아직 통합되지 않은 심볼, 링커는
돌아가서 이전 라이브러리에서 가져오는 것을 알고 있습니다. 결과적으로 필요할 수 있습니다.
링커 명령줄에서 라이브러리를 여러 번 나열합니다. (나는 프로젝트에서 일했다
전체 라이브러리 목록을 세 번 반복해야 했습니다. 이 프로젝트는 만든
저는 아래에 제안된 증분 링크의 대체 접근 방식을 선호합니다.)

동적 라이브러리를 사용하면 몇 가지 단점이 있습니다. 첫째, 귀하의 프로그램은 약간
라이브러리가 이미 다른 프로그램에서 사용되고 있지 않은 경우 시작 속도가 느립니다.
찾아서 로드해야 합니다. 둘째, 모든 동적
올바른 위치에 설치된 라이브러리 프로그램 실행 파일을 복사할 수 없습니다.
또한 모든 라이브러리를 복사했는지 확인해야 합니다. 셋째, 일부 시스템에서는
디버거가 지원하지 않기 때문에 공유 라이브러리 내부의 코드를 디버깅하기 어렵습니다.
그들을 잘.

모듈이 다른 프로그램에서 절대 사용되지 않는다면 사용할 이유가 거의 없습니다.
라이브러리: 라이브러리 사용의 모든 단점은 있지만 장점은 전혀 없습니다.
내가 선호하는 기술은 사용 가능한 증분 연결을 사용하는 것입니다.

Linux에서 이 작업을 수행하는 방법은 다음과 같습니다.

my_module.o : $(filter_out my_module.o, $(와일드카드 *.o))
ld -r -o $(출력) $(입력)

이것이 할 일은 다른 것을 만드는 것입니다. .o 라는 파일 my_module.o로 구성됩니다.
의 모든 .o 이 하위 디렉토리의 파일. 링커는 다음 중 많은 수를 해결합니다.
가능한 한 참조하고 나머지 참조는
연결의 다음 단계. 최상위 수준에서 최종적으로 프로그램을 빌드할 때
와 연결하는 대신 libmy_module.a or libmy_module.so, 당신은 단순히
my_module.o. 링크할 때 .o 파일에서 순서 종속성에 문제가 없습니다.
링커 명령줄.

시키는 메이크업 그림 아웃 어느 도서관 모듈 are 필요

주어진 프로그램이 라이브러리에서 몇 개의 파일만 필요로 하는 진정한 라이브러리가 있더라도
(모든 단일 모듈이 아닌) makepp는 어떤 모듈이
라이브러리에서 필요하고 빌드에 있는 항목만 포함합니다. 이것은 컴파일을 저장할 수 있습니다
프로그램과 함께 라이브러리를 개발하는 경우
작업 중인 특정 프로그램에 필요하지 않은 라이브러리 모듈을 컴파일합니다.

라이브러리에서 선언된 모든 함수 또는 클래스의 규칙을 엄격하게 준수하는 경우
파일 xyz.h 로 컴파일되는 소스 파일에서 완전히 구현됩니다. xyz.o (즉, 당신
구현을 분할하지 마십시오. xyz1.oxyz2.o), 다음을 사용할 수 있습니다
"$(infer_objects)" 함수는 makepp에게 관련 모듈만 가져오도록 지시합니다.
도서관. 이것은 수십 개의 포함 파일이 있는 라이브러리에서도 놀라울 정도로 잘 작동할 수 있습니다.
기본적으로 "$(infer_objects)"는 .h 포함된 파일 및 모양
대응을 위해 .o 파일. 라이브러리 및 프로그램을 빠르게 개발하는 경우
의 모듈을 컴파일할 필요가 없기 때문에 컴파일 시간을 절약할 수 있습니다.
프로그램이 사용하지 않는 라이브러리.

다음은 내가 사용하는 방법의 예입니다.

my_program: $(infer_objects *.o, $(LIB1)/*.o $(LIB2)/*.o)
$(CXX) $(입력) -o $(출력) $(SYSTEM_LIBRARIES)

"$(infer_objects )" 함수는 첫 번째 인수를 반환합니다(와일드카드를 사용한 후).
확장), 또한 두 번째 인수에서 파일 목록을 살펴봅니다.
이름이 모든 파일의 이름과 동일한 파일 .h 첫 번째 파일에 포함된 파일
논쟁. 이러한 파일이 있으면 목록에 추가됩니다.

건물 a 정적 인 도서관

실제로 라이브러리가 필요하고 증분 링크를 사용할 수 없는 경우 또는
당신이하고 싶은 것이 아닙니다. 몇 가지 방법이 있습니다. 먼저, 여기에 예가 있습니다.
여기서 모든 파일은 명시적으로 나열됩니다.

LIBRARY_FILES = abcde

libmine.a: $(LIBRARY_FILES).o
&rm -f $(출력)
$(AR) cr $(출력) $(입력)
ranlib $(output) # OS에 따라 필요하지 않을 수도 있습니다.

&rm은 makepp의 내장 "rm" 명령입니다. makefile 작성에 익숙하다면
이 명령에 약간 놀랐습니다. 다음과 같은 것에 익숙할 수 있습니다.

libmine.a: $(LIBRARY_FILES).o
$(AR) ru $@ $? # 비추천!!!!!!
ranlib $(출력)

어디서 $? ("$(changed_inputs)"라고도 함)는 모든 파일을 의미하는 자동 변수입니다.
라이브러리가 마지막으로 빌드된 이후 변경되었으며 $@는 거의 동일합니다.
"$(출력)"으로.

이 접근 방식은 여러 가지 이유로 권장되지 않습니다.

· 현재 디렉터리에서 소스 파일을 제거한다고 가정합니다. 아직
라이브러리를 처음부터 다시 빌드하지 않았기 때문입니다. 결과적으로 무엇이든
이 라이브러리와의 링크는 오래된 .o 파일을 망칠 수 있습니다.
빌드합니다. (한때 죽은 코드를 제거하려고 할 때 이것 때문에 완전히 혼란스러웠습니다.
프로젝트에서: 파일을 계속 삭제했는데 여전히 연결되어 있어서 코드가
죽은. 그러나 다른 사람이 프로젝트를 처음부터 다시 빌드했을 때 아무 것도 연결하지 않았습니다.
더! 문제는 오래된 .o 파일은 여전히 ​​아카이브에 있었습니다.)

또한 "ar"에 대한 옵션과 "ar" 구현에 따라(예:
"r" 대신 "q" 옵션 사용), 여러 버전의
같은 .o 내부 .a 파일. 다른 버전이 다른 전역을 정의하는 경우
링커는 둘 다 가져오려고 할 수 있습니다. 이것은 아마도 나쁜 것입니다.

이것이 우리가 먼저 라이브러리 파일을 제거하고 처음부터 새로 만드는 이유입니다. 이것은
라이브러리에서 모듈을 업데이트하는 것보다 약간 더 오래 걸리지만 그리 길지는 않습니다. ~에
최신 컴퓨터, ar 프로그램에 비해 미미하다
C 컴파일러가 일반적인 빌드에서 차지하는 것이므로 걱정할 필요가 없습니다.
약.

· 올바른 빌드를 보장하기 위해 makepp가 시도하는 방법 중 하나는
지정된 대상을 빌드하는 명령줄이 변경된 경우 자동으로 다시 빌드합니다. 하지만
$?를 사용하여 라이브러리가 업데이트될 때마다 변수가 문제를 일으킬 수 있습니다.
빌드 명령이 다릅니다. (이를 사용하여 억제할 수 있습니다.
":build_check ignore_action"; 자세한 내용은 makepp_build_check를 참조하십시오.)

· 아카이브를 재구축하지 않고 업데이트하면 makepp에서
파일을 빌드 캐시에 적절하게 넣습니다(자세한 내용은 makepp_build_cache 참조).

때로는 모든 파일을 나열하는 것이 고통스러운 경우, 특히
프로젝트는 빠르게 발전하고 있으며 파일 목록은 지속적으로 변경됩니다. 그것
다음과 같이 와일드카드를 사용하여 라이브러리를 빌드하는 것이 더 쉬울 수 있습니다.

libmine.a: $(only_targets *.o)
&rm $(출력)
$(AR) cr $(출력) $(입력)

이것은 모든 .o 현재 디렉터리에 있는 파일을 라이브러리로 복사합니다. 와일드카드
일치 .o 존재하거나 빌드할 수 있는 파일이므로 파일이 없어도 작동합니다.
아직 존재합니다.

"only_targets" 기능은 제외하는 데 사용됩니다. .o 해당 파일이 없는 파일
더 이상 소스 파일. 라는 파일이 있다고 가정합니다. xyz.c 당신이 당신의
도서관. 이는 다음이 있음을 의미합니다. xyz.o 주변에 누워있는 파일. 이제 삭제 xyz.c
더 이상 사용되지 않기 때문에 삭제하는 것을 잊었습니다. xyz.o. "only_targets" 없이
기능, xyz.o 여전히 목록에 포함됩니다 .o 라이브러리에 포함된 파일.

건물 a 동적 도서관

동적 라이브러리를 구축하는 프로세스는 전적으로 시스템에 따라 다릅니다. 나는 매우
libtool을 사용하여 동적 라이브러리를 구축하는 것이 좋습니다(참조
<http://www.gnu.org/software/libtool/>), 그래서 당신은 그것을 수행하는 방법을 알아낼 필요가 없습니다
플랫폼으로 전환하더라도 makefile이 계속 작동하도록 합니다.
다른 OS. 자세한 내용은 libtool 설명서를 참조하십시오. 다음은 샘플 Makefile입니다.

LIBTOOL := libtool

libflick.la : $(only_targets *.lo)
$(LIBTOOL) --mode=링크 $(CC) $(입력) -o $(출력)

%.lo : %.c
$(LIBTOOL) --모드=컴파일 $(CC) $(CFLAGS) $(INCLUDES) -c $(입력) -o $(출력)

건물 on 몇몇의 다른 기계 or 네트워크
makefile의 가장 성가신 문제 중 하나는 makefile이 거의 작동하지 않는다는 것입니다.
다른 시스템이나 다른 네트워크로 전환하십시오. makefile이 작동해야 하는 경우
지구상의 가능한 모든 기계라면 일종의 구성이 필요할 것입니다.
스크립트. 그러나 몇 가지 다른 시스템에서만 작업해야 하는 경우 여러 가지 방법이 있습니다.
이 문제에 접근할 수 있습니다.

a 다른 포함 파일 in 모든 전에, 환경

각 makefile의 시작 부분에 다음과 같은 줄을 포함할 수 있습니다.

system_defs.mk 포함

파일 system_defs.mk 일반적으로 각각 다른 위치에 위치합니다.
환경. 모든 시스템에서 빌드 디렉토리를 동일하게 하려면 다음을 입력하십시오.
system_defs.mk 빌드 디렉토리 위의 디렉토리에서 또는 포함 경로를 제공하십시오.
"-I" 명령줄 옵션을 사용하여 makepp에.

이것은 일반적으로 수행하기 다소 고통스럽지만 많은 수의 데이터가 있는 경우 잘 작동합니다.
차이점.

if

이것은 가장 추악한 방법이지만 일반적으로 작동합니다.

ifsys i386
CC := gcc
그렇지 않으면 ifsys sun4u
CC := CC
그렇지 않으면 ifsys hpux11
CC = c89
ENDIF

몇 가지 프로그램이나 라이브러리를 찾거나 다른 폴더에 파일을 포함하기만 하면 됩니다.
더 나은 방법이 있을 수 있습니다(아래 참조).

찾기 프로그램, 첫 번째_사용 가능, 파일 찾기

이 기능은 시스템의 다양한 디렉토리를 검색하여
적절한 파일. 물론 이것은 구성 스크립트만큼 강력하지는 않지만
유용한. 예를 들어 다음을 수행합니다.

CXX ;= $(find_program g++ c++ pg++ cxx CC aCC)
# PATH에서 사용할 수 있는 첫 번째 C++ 컴파일러를 선택합니다.
# (참고로 CXX를 전혀 정의하지 않으면 이
#은 정의된 방식입니다.)
TCL_INCLUDE ;= -I$(dir_noslash $(findfile tcl.h, \
/usr/local/stow/tcl-8.4.5-nothread/include \
/usr/include/tcl8.4 /usr/include/tcl \
/net/na1/tcl8.4a3/include /net/na1/tcl8.4a3/include))
# $(findfile )은 표시된 각 파일에서 tcl.h를 찾습니다.
# 디렉토리를 반환하고 전체 경로를 반환합니다. 이것은 그때
# 다음을 제거하여 컴파일 옵션으로 변환
# 파일 이름(디렉토리에서 나옴) 및 접두어 -I.
%.o : %.cpp
$(CXX) $(CXXFLAGS) $(TCL_INCLUDE) $(입력) -o $(출력)

TCL_LIB ;= $((첫 번째_사용 가능
/usr/local/stow/tcl-8.4.5-nothread/lib/libtcl8.4.so
/usr/lib/libtcl8.4.so /usr/lib/libtcl.so
/net/na1/tcl8.4a3/lib/libtcl8.4.a
/net/na1/tcl8.4a3/lib/libtcl8.4.sl))
# Tcl 라이브러리가 있는 곳을 찾습니다. 이것은 명시적으로
# 링크 명령에 나열됨:
my_program : *.o
$(CXX) $(CXXFLAGS) $(입력) -o $(출력) $(TCL_LIB)

받아 이점 of 설정 정보

다음에 대한 추가 정보가 필요한 경우 위의 기술로는 충분하지 않을 수 있습니다.
long double이 존재하는지 또는 바이트 순서가 무엇인지와 같은 시스템. 하지만,
perl은 이미 이러한 것들을 계산했으므로 그 답을 사용할 수 있습니다.

Perl의 자동 구성 스크립트를 통해 모든 구성 정보를 사용할 수 있습니다.
%Config 해시. makepp에서 Perl 해시에 직접 액세스할 수 있는 구문은 없지만
Perl에 드롭하고 makepp에서 직접 액세스할 수 있는 스칼라 변수를 설정합니다.

perl_begin
# 구성 해시에서 값을 가져옵니다.
구성을 사용하십시오.
$CC = $Config{'cc'}; # Perl이 사용한 C 컴파일러;
$byteorder_flags = "-DBYTEORDER=$Config{'byteorder'}";
$longdouble_defined = $Config{'d_longdbl'} eq '정의';
$CFLAGS_for_shared_libs = $Config{'cccdlflags'};
$LDFLAGS_for_shared_libs = $Config{'ccdlflags'};
펄_엔드

또한 'use Config'를 완료하면 다음과 같이 "$(perl )" 문을 사용할 수 있습니다.
이:

SHARED_LIB_EXTENSION := $(perl $Config{'dlext'})

%Config 해시를 통해 사용 가능한 정보를 보려면 "perldoc Config"를 입력하십시오.

Perl의 구성은 정수 유형, 바이트에 대한 정보와 같은 정보를 얻을 수 있는 좋은 장소입니다.
주문 및 일반적으로 찾기 위해 별도의 구성 스크립트가 필요한 기타 사항. 일부
파일 시스템에 존재하는 것과 관련된 정보는 그렇지 않을 수 있습니다.
유효한. 예를 들어 $Config{'cc'}는 perl이 빌드된 C 컴파일러를 나타냅니다.
사용하려는 C 컴파일러와 다를 수 있습니다. 사실 존재하지 않을 수도 있다.
아마도 바이너리 패키지를 통해 Perl을 설치했기 때문입니다.

방문 꿀팁 for 사용 와일드 카드
매칭 모든 파일 a 어떤 서브 세트

Makepp의 와일드카드는 현재 모든 파일을 일치시키는 방법이 없습니다. 특정의
설정하지만 기능의 조합으로 할 수 있습니다.

예를 들어 라이브러리의 각 모듈에 대한 테스트 프로그램이 있지만
라이브러리에 테스트 프로그램을 포함하고 싶습니다. 모든 테스트 프로그램이
test, 다음과 같이 제외할 수 있습니다.

libproduction.a: $(filter_out 테스트*, $(와일드카드 *.o))

"$(filter )" 및 "$(filter_out )" 함수는 매우 강력한 필터 집합입니다.
모든 종류의 집합 교집합 및 차이 연산. 예를 들어,

SUBDIRS ;= $(filter_out *test* *$(ARCH)*, $(shell find . -type d -print))
# 없는 모든 하위 디렉토리를 반환합니다.
# "test" 또는 $(ARCH).

$(필터 $(patsubst test_dir/test_%.o, %.o, $(와일드카드 test_dir/*.o)), \
$(와일드카드 *.o))
# 현재 .o 파일 목록을 반환합니다.
# 해당하는 디렉토리가 있는 디렉토리
# test_dir 하위 디렉토리에 있는 test_*.o 파일.
$(filter_out $(patsubst man/man3/%.3, %.o, $(와일드카드 man/man3/*.3)), \
$(와일드카드 *.o))
# 현재 .o 파일 목록을 반환합니다.
# 매뉴얼 페이지가 없는 디렉토리
# man/man3 하위 디렉토리에 동일한 파일 이름이 있습니다.

사용 전에, "$(only_targets )" 기능 제거 탁한 .o 파일

다음과 같은 빌드 명령을 사용하여 프로그램이나 라이브러리를 빌드한다고 가정합니다.

프로그램: *.o
$(CC) $(입력) -o $(출력)

이제 소스 파일을 삭제한다고 가정합니다. 해당 삭제를 잊은 경우 .o 파일
더 이상 빌드할 방법이 없더라도 여전히 연결됩니다. 에서
미래에 makepp은 아마도 이 상황을 자동으로 인식하고 제외할 것입니다.
와일드카드 목록이지만 현재로서는 수동으로 제외하도록 지시해야 합니다.

프로그램: $(only_targets *.o)
$(CC) $(입력) -o $(출력)

Makepp은 부실을 구축하는 방법을 모릅니다 .o 소스 파일이
없어졌으므로 "$(only_targets )" 함수는 종속성 목록에서 제외합니다.

방문 꿀팁 for 여러 디렉토리
makepp를 작성하는 주된 이유 중 하나는 여러
디렉토리. Makepp은 여러 makefile의 빌드 명령을 결합할 수 있으므로
에 의해 빌드된 파일에 의존하는 하나의 메이크파일에서 규칙을 적절하게 처리합니다.
다른 makefile.

do in 장소 of 재귀 확인

Makepp은 이전 버전과의 호환성을 위해 재귀적 make를 지원하지만 적극 권장됩니다.
그 당신 지원 그걸 써. 그것이 무엇인지 모른다면 좋습니다.

원하지 않는 이유에 대한 자세한 내용은 makepp의 "Better system for hierarchical builds"를 참조하십시오.
재귀 make를 사용하거나 웹에서 "유해한 것으로 간주되는 재귀 make"를 검색하십시오.

모든 makefile에서 "all" 대상을 만들기 위해 재귀 make를 수행하는 대신,
일반적으로 makepp가 실제로 구축해야 할 대상을 파악하도록 하는 것이 더 쉽습니다.
또한 모든 것을 넣으면 .o 와 같은 디렉토리에 있는 라이브러리 파일
그러면 makepp는 어떤 makefile이 필요한지 자동으로 파악합니다.
필요한 유일한 것은 최상위 수준에서 필요한 파일 목록을 작성하는 것입니다.
마지막 연결 단계를 위해. 아래 예를 참조하십시오.

메이크 파일 for 마다 예배 규칙서: 절대적인 로드

여러 디렉토리를 처리하는 가장 일반적인 방법은 makefile을 각 디렉토리에 넣는 것입니다.
해당 디렉토리에서 모든 것을 빌드하는 방법을 설명합니다. 넣으면 .o 파일
소스 파일과 동일한 디렉토리, 그런 다음 암시적 로드("암시적 로드" 참조)
makepp_build_algorithm)은 자동으로 모든 makefile을 찾습니다. 당신이 당신의 .o
다른 디렉토리(예: 아키텍처 종속 하위 디렉토리)에 있는 파일을
아마도 "load_makefile" 문을 사용하여 관련된 모든 makefile을 로드해야 할 것입니다.

다음은 암시적 로드를 사용하는 디렉터리 계층 구조에 대한 샘플 최상위 메이크파일입니다.
많은 공유 라이브러리로 구성된 프로그램을 빌드하려면(그러나 "정말로
라이브러리?" makepp_cookbook의 공유 라이브러리에서 프로그램을 만들기 때문입니다.
반드시 좋은 생각은 아닙니다):

# 최상위 메이크파일:
program : main.o **/*.la # 모든 하위 디렉토리에서 공유 라이브러리를 연결합니다.
$(LIBTOOL) --모드=링크 $(CC) $(CFLAGS) $(입력) -o $(출력) $(LIBS)

이것이 최상위 makefile에 필요한 거의 모든 것입니다. 각 하위 디렉토리에서
아마도 다음과 같이 할 것입니다.

# 각 하위 디렉토리의 Makefile:
include standard_defs.mk # 검색 ., .., ../ ..등이 될 때까지
# 표시된 포함 파일을 찾습니다.
# 여기에서 일부 변수 정의를 재정의합니다.
SPECIAL_FLAGS := -do_something_다른

각 메이크파일은 대상을 빌드하는 명령이 거의 동일할 수 있습니다.
상당히 유사합니다.

마지막으로 다음을 표준_defs.mk 파일(아마도
최상위 디렉토리에 위치):

# 모든 디렉토리에 대한 공통 변수 설정 및 빌드 규칙.
CFLAGS := -g -O2
INCLUDE_DIR := $(find_upwards 포함)
# 검색 ., .., ../ ..등 파일 또는
# include라는 디렉토리가 있으므로 다음을 입력하면
# 거기에 있는 모든 포함 파일, 이것은
# 찾아보세요.
포함 := -I$(INCLUDE_DIR)

%.lo : %.c
$(LIBTOOL) --모드=컴파일 $(CC) $(CFLAGS) $(INCLUDES) -c $(입력) -o $(출력)

lib$(relative_to ., ..).la: $(only_targets *.lo)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(출력) $(입력)
# $(relative_to ., ..)는 현재
# 상위 레벨에 상대적인 서브디렉토리
# 하위 디렉토리. 따라서 이 makefile이 xyz/Makefile이면
# 이 규칙은 xyz/libxyz.la를 빌드합니다.

# 공개 포함 파일을 최상위 포함 디렉터리에 게시합니다.
$(INCLUDE_DIR)/public_%.h : public_%.h
:build_check 기호
&ln -fr $(입력) $(출력)

메이크 파일 for 마다 예배 규칙서: 명백한 로드

당신의 모든 것을 담고 싶다면 .o 파일을 아키텍처 종속 하위 디렉토리에 넣은 다음
위의 예는 다음과 같이 수정되어야 합니다.

# 최상위 메이크파일:
MAKEFILES := $(와일드카드 **/Makeppfile) # 만들 모든 하위 디렉토리 목록
# makefile을 가져옵니다.

load_makefile $(MAKEFILES) # 모두 로드합니다.

include standard_defs.mk # main.o에 대한 컴파일 명령을 가져옵니다.

프로그램 : $(ARCH)/main.o */**/$(ARCH)/*.la
$(LIBTOOL) --모드=링크 $(CC) $(CFLAGS) $(입력) -o $(출력) $(LIBS)
# */**/$(ARCH) 하위 디렉토리 제외
# $(ARCH), 빌드하고 싶지 않은 곳
# 공유 ​​라이브러리.

각 makefile은 이전과 정확히 동일합니다.

# 각 하위 디렉토리의 Makefile:
standard_defs.mk 포함
# ... 여기에서 변수 재정의

그리고 마지막으로, 표준_defs.mk 다음과 같은 내용이 포함됩니다.

# 모든 디렉토리에 대한 공통 변수 설정 및 빌드 규칙.
ARCH ;= $(쉘 uname -s)-$(쉘 uname -m)-$(쉘 uname -r)
# 때때로 사람들은 $(shell uname -m)만 사용하지만
# 이것은 FreeBSD와 Linux에서 동일합니다.
# x86. -r은 Linux에서 실제로 유용하지 않습니다.
# 그러나 다른 OS에서는 중요합니다.
# SunOS 5.8은 일반적으로 SunOS 5.7에서 실행되지 않습니다.
&mkdir -p $(ARCH) # 출력 디렉토리가 있는지 확인하십시오.
CFLAGS := -g -O2
INCLUDE_DIR := $(find_upwards 포함)
# 검색 ., .., ../ ..등 파일 또는
# include라는 디렉토리가 있으므로 다음을 입력하면
# 거기에 있는 모든 포함 파일, 이것은
# 찾아보세요.
포함 := -I$(INCLUDE_DIR)

$(ARCH)/%.lo : %.c
$(LIBTOOL) --모드=컴파일 $(CC) $(CFLAGS) $(INCLUDES) -c $(입력) -o $(출력)

$(아치)/ lib$(relative_to ., ..).la: $(only_targets *.lo)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(출력) $(입력)
# $(relative_to ., ..)는 현재
# 상위 레벨에 상대적인 서브디렉토리
# 하위 디렉토리. 따라서 이 makefile이 xyz/Makefile이면
# 이 규칙은 xyz/$(ARCH)/libxyz.la를 빌드합니다.

# 공개 포함 파일을 최상위 포함 디렉터리에 복사합니다.
$(INCLUDE_DIR)/public_%.h : public_%.h
&cp $(입력) $(출력)

자동적으로 만들기 전에, 메이크파일

makefile이 모두 매우 유사한 경우(위의 예에서처럼) Makepp에 알릴 수 있습니다.
존재하지 않는 경우 자동으로 빌드합니다. 최상위 레벨에 다음을 추가하십시오.
메이크 파일:

SUBDIRS := $(filter_out 원치 않는_dir1 원하지 않는_dir2, $(와일드카드 */**))
$(foreach)/Makeppfile: : foreach $(SUBDIRS)
&echo "include standard_defs.mk" -o $(출력)
&echo "_include additional_defs.mk" -o >>$(출력)
# additional_defs.mk 파일이 존재하면
# 포함되겠지만 없으면
# _include 문은 무시됩니다.

이제 makefile 자체가 자동으로 빌드됩니다.

메이크 파일 at 전에, 상단 수평

모든 메이크파일이 동일하다면 다음과 같이 질문할 수 있습니다. 각 메이크파일이 왜 있어야 합니까?
수준? 그 모든 것을 최상위 makefile에 넣지 않겠습니까?

예, 가능합니다. 가장 큰 단점은 지정하기가 더 어렵다는 것입니다.
각 하위 디렉토리에 대한 다른 빌드 옵션. 두 번째 단점은
makefile은 아마도 읽기가 조금 더 어려워질 것입니다.

다음은 이를 수행하는 예입니다.

# 디렉토리 계층을 위한 최상위 makefile. 프로그램 구축
# 예시로 공유 라이브러리 세트 중. (위 주의사항 참조
# 증분 링크 또는 다른 것을 사용하려는 이유
# 공유 ​​라이브러리보다는 접근합니다.)
makepp_percent_subdirs := 1 # %가 여러 디렉토리와 일치하도록 허용합니다.
SUBDIRS := $(filter_out *CVS* other-unwanted_dirs $(와일드카드 **))
CFLAGS := -g -O2
포함 := -포함

%.lo: %.c
$(LIBTOOL) --모드=컴파일 $(CC) $(INCLUDES) $(CFLAGS) -c $(입력) -o $(출력)

$(foreach)/ lib$(notdir $(foreach)).la: $(foreach)/*.lo : foreach $(SUBDIRS)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(출력) $(입력)
# 모든 라이브러리를 만드는 규칙.

프로그램 : main.o **/*.la
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(출력) $(입력)

포함/$(notdir $(foreach)) : $(foreach) : foreach **/public_*.h
&cp $(입력) $(출력)
# 공개적으로 복사하기 위한 샘플 규칙
# 액세스 가능한 .h 파일을 올바른 위치에.

A 황어 무리 목표

기존 메이크파일에는 클린 대상이 포함되어 있어 이전에 있었던 모든 항목을 제거할 수 있습니다.
세워짐. makepp에서 이 작업을 수행하면 안 되는 세 가지 이유가 있습니다.

1. Makepp은 올바른 빌드를 보장하기 위해 최선을 다합니다. 그래서 간절한 "싫어.
무엇이 잘못되었는지 알고 있습니다.", 처음부터 다시 시작하고 싶게 만드는 것은 과거의 일입니다.

2. 사람들은 때때로 두 가지 상반된 일을 한 번에 함으로써 시간을 절약하려고 할 것입니다.
"모두 청소". 이는 makepp의 스마트 와일드카드 시스템을 혼란스럽게 할 수 있습니다.
어떤 일을 하기 전에 먼저 사실을 파악하십시오. 그런 다음 클린 액션이 나옵니다.
무엇을 하는지 makepp에 말하지 않습니다(실제로 할 수 없습니다.
빌드 도구의 용도와는 반대로). 그런 다음 "모두" 나오지만 최신 파일,
그곳에서 신비롭게 사라졌습니다.

3. "makeppclean" 명령이 있습니다. 이 명령은 동일한 작업을 보다 효율적으로 수행합니다.

그럼에도 불구하고 우리는 이 역사적 부분을 유지합니다.
makepp 작동 방식: "clean"이라는 가짜 대상은 명령 집합의 이름일 뿐입니다.
make 프로세스에서 생성된 모든 파일을 제거합니다. 일반적으로 깨끗한 대상이 보입니다.
이 같은:

$(포니 클린):
&rm -fm $(와일드카드 *.o .makepp_log)
# -m 및 .makepp_log는 makepp의 모든 쓰레기를 제거합니다.

삭제하려는 파일을 명시적으로 나열하는 대신 makepp에 다음과 같이 지시할 수도 있습니다.
다음과 같이 구축 방법을 알고 있는 모든 것을 제거합니다.

$(포니 클린):
&rm -fm .makepp_log $(only_targets *)

이것은 소스 파일 중 하나가 다른 파일에서 빌드될 수 있는 경우 이점이 있습니다.
그것들도 삭제됩니다. 반면에 낡은 .o 파일(예전에는
빌드 가능하지만 그 이후에 소스 파일이 제거된 파일)은 삭제되지 않습니다.

여러 다른 디렉토리에 makefile이 포함된 빌드가 있는 경우 최상위
레벨 메이크파일은 "깨끗한" 대상(또는 다른 가짜 대상)을 참조할 수 있습니다.
메이크 파일:

# 최상위 메이크파일
SUBDIRS := 서브1 서브2

# 여기에 규칙을 세웁니다.

# 빌드 후 정리:
$(포니 클린): $(SUBDIRS)/클린
&rm -fm .makepp_log $(only_targets *)

또는 최상위 메이크파일에만 "깨끗한" 대상을 넣을 수 있습니다.
다음과 같이 모든 디렉토리를 처리합니다.

$(포니 클린):
&rm -fm $(only_targets **/*)

사용 Qt의 모의 전 처리기
이 예는 Nokia의 Qt GUI 라이브러리를 사용하는 유틸리티의 makefile을 보여줍니다(참조:
<http://qt.nokia.com>). 이것에 대해 약간 특이한 점은 당신이
위젯 정의를 포함하는 대부분의 ".h" 파일에서 "moc"라는 전처리기를 실행해야 합니다.
그러나 "Q_OBJECT" 매크로를 사용하지 않는 ".h" 파일에서 "moc"를 실행하고 싶지는 않습니다.

자동적으로 결정 어느 파일 필요한 것 모의 파일

물론 "moc"를 실행해야 하는 모든 ".h" 파일을 나열할 수도 있습니다.
그러나 새 위젯을 빠르게 개발하는 경우에는
makefile의 목록을 계속 업데이트하십시오. moc를 나열해야 할 필요성을 피할 수 있습니다.
모듈은 다음과 같이 명시적으로 사용합니다.

MOC := $(QTDIR)/bin/moc
MODULES := 프로그램에 있는 모든 모듈
MOC_MODULES := $(patsubst %.h, moc_%, $(&grep -l /Q_OBJECT/ *.h))
# Q_OBJECT 매크로에 대한 모든 .h 파일을 스캔합니다.

my_program: $(MODULES).o $(MODULES).o
$(CXX) $(입력) -o $(출력)

moc_%.cxx: %.h # .h 파일에서 moc 파일을 만듭니다.
$(MOC) $(입력) -o $(출력)

%.o: %.cxx
$(CXX) $(CXXFLAGS) -c $(입력) -o $(출력)

이 접근 방식은 각 .h makepp가 실행될 때마다 파일을 찾고
"Q_OBJECT" 매크로. 이것은 비싸게 들리지만 아마 오래 걸리지 않을 것입니다. (그만큼 .h
파일은 어쨌든 컴파일 프로세스에 의해 모두 디스크에서 로드되어야 하므로
캐시됩니다.)

#포함 전에, .moc 파일

또 다른 접근 방식은 위젯의 "moc" 전처리기에서 출력을 "#include"하는 것입니다.
구현 파일. 즉, "#include"를 작성하는 것을 기억해야 하지만
컴파일할 모듈이 적기 때문에 컴파일 속도가 빨라진다는 장점이 있습니다.
(대부분의 C++ 컴파일에서 대부분의 시간은 헤더 파일을 읽는 데 소비되며
전처리기의 출력에는 거의 위젯만큼 많은 파일이 포함되어야 합니다.
어쨌든.) 예를 들면 다음과 같습니다.

// my_widget.h
클래스 MyWidget : 공개 QWidget {
Q_OBJECT
// ...
}

// my_widget.cpp

#include "my_widget.h"
#include "my_widget.moc" // my_widget.moc는
// moc 전처리기.
// 여기에 다른 구현 사항이 있습니다.
MyWidget::MyWidget(QWidget * 부모, const char * 이름) :
QWidget(부모, 이름)
{
// ...
}

이제 다음과 같이 모든 ".moc" 파일을 만들기 위해 makefile에 규칙이 있어야 합니다.

MOC := $(QTDIR)/bin/moc
# .moc 파일을 만드는 규칙:
%.moc: %.h
$(MOC) $(입력) -o $(출력)

Makepp은 "my_widget.moc"를 만들지 않으면 만들어야 한다는 것을 깨달을 만큼 똑똑합니다.
이미 존재하거나 오래된 경우.

이 두 번째 방법은 컴파일 속도를 높이기 때문에 일반적으로 사용하는 방법입니다.

교체 for 사용되지 않는 확인 숙어
MAKECMDGOALS

때때로 사람들은 메이크파일에 그들이 만들고 있는 대상에 따라 달라지는 규칙을 가지고 있습니다.
특수 변수 "MAKECMDGOALS"를 사용합니다. 예를 들어, 때때로 다음과 같은 것을 볼 수 있습니다.
이:

ifneq ($(필터 생성, $(MAKECMDGOALS)),)
CFLAGS := -O2
그렇지 않으면
CFLAGS := -g
ENDIF

이것은 makepp에서 잘 작동합니다. 그러나 "MAKECMDGOALS"를 사용하지 않는 것이 좋습니다.
경우(그리고 GNU도 매뉴얼을 만듭니다). 당신은 당신의 최적화된
디버그 컴파일 .o 파일을 별도의 디렉토리에 두거나 다른 접두사를 지정하거나
접미사를 사용하거나 리포지토리를 사용하여 분리합니다.

실제로 "MAKECMDGOALS"를 참조할 수 있는 유일한 경우는 다음과 같은 경우입니다.
makefile을 로드하는 데 오랜 시간이 걸리며 "깨끗한" 대상에는 필요하지 않습니다.
(그러나 깨끗한 대상은 필요하지 않습니다). 예를 들어,

ifneq ($(MAKECMDGOALS), 청소)
load_makefile $(와일드카드 **/Makeppfile)
그렇지 않으면
no_implicit_load . # 다른 makefile의 자동 로딩을 방지합니다.
ENDIF

$(포니 클린):
&rm -f $(와일드카드 **/*.o)

재귀 확인 빌드 in 다른 디렉토리

makepp_cookbook의 "여러 디렉토리에 대한 팁"을 참조하십시오.

재귀 확인 이전 단계로 돌아가기 가치 of a 변수

일부 makefile은 변수의 다른 값(예: 디버그
다음 메이크파일 조각의 대상

.PHONY: 모든 디버그

최적화:
$(MAKE) 프로그램 CFLAGS=-O2

디버그:
$(MAKE) 프로그램 CFLAGS=-g

프로그램: 아오 보
$(CC) $(CFLAGS) $^ -o $@

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

사용자가 "make debug"를 입력하면 디버그가 활성화된 기본 모드에서 프로그램을 빌드합니다.
최적화 대신.

이를 수행하는 더 좋은 방법은 두 개의 다른 세트로 두 개의 다른 프로그램을 빌드하는 것입니다.
다음과 같은 목적 파일:

CFLAGS := -O2
DEBUG_FLAGS := -g
모듈 := ab

프로그램: $(MODULES).o
$(CC) $(CFLAGS) $(입력) -o $(출력)

디버그/프로그램: debug/$(MODULES).o
$(CC) $(DEBUG_FLAGS) $(입력) -o $(출력)

%.o : %.c
$(CC) $(CFLAGS) -c $(입력) -o $(출력)

디버그/%.o : %.c
$(CC) $(DEBUG_FLAGS) -c $(입력) -o $(출력)

$(포니 디버그): 디버그/프로그램

이 방법의 이점은 (a)
디버그에서 최적화로 전환했다가 다시 전환합니다. (비)

위의 내용은 리포지토리를 사용하여 좀 더 간결하게 작성할 수 있습니다. 다음과 같은
makefile은 정확히 동일합니다.

저장소 디버그=. # 디버그 서브디렉토리를 다음의 복사본처럼 보이게 합니다.
# 현재 서브디렉토리.
load_makefile 디버그 CFLAGS=-g
# 디버그 하위 디렉토리에서 호출될 때 CFLAGS를 재정의합니다.
CFLAGS := -O2 # 이 하위 디렉토리에서 호출될 때 CFLAGS의 값

프로그램: 아오 보
$(CC) $(CFLAGS) $^ -o $@

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

$(포니 디버그): 디버그/프로그램
# 사용자가 "makepp debug"를 입력하면 빌드
# 프로그램 대신 디버그/프로그램.

그 외 도움말
방법 do I 빌드 부품 다르게 다만 한번?

Makepp은 결과가 규칙과 일치하지 않기 때문에 이를 어렵게 만듭니다.
그러나 이것이 필요할 수 있는 상황이 있습니다. 예를 들어 다음과 같이 하나의 모듈만 컴파일하는 경우입니다.
무거운 디버깅 정보. 먼저 다음을 빌드하여 두 단계로 이를 달성할 수 있습니다.
종속성을 별도로 분리한 다음 연결 단계에서 제외합니다.

makepp DEBUG=3 buggy.o # 다른 옵션으로 빌드합니다.
makepp --dont-build=buggy.o buggy # "잘못된" 빌드 옵션에도 불구하고 사용하십시오.

방법 do I 확인 확인 my 출력 디렉토리 있다?

출력 디렉터리를 빌드하는 규칙을 지정한 다음 각 파일이
출력 디렉토리에 들어가는 것은 그것에 달려 있습니다. 그러나 일반적으로 다음과 같은 작업을 수행하는 것이 더 쉽습니다.
이:

# 고전적인 방법
더미 := $(쉘 테스트 -d $(OUTPUT_DIRECTORY) || mkdir -p $(OUTPUT_DIRECTORY))
# 이것은 일반적으로 모든 파일을 의존하게 만드는 것보다 쉽습니다.
# $(OUTPUT_DIRECTORY) 그리고 그것을 만드는 규칙이 있습니다.
# 강제로 하려면 = 대신 :=를 사용해야 합니다.
# 즉시 실행합니다.
# 다른 방법: Perl 코드 사용, OUTPUT_DIRECTORY local var
perl_begin
-d $OUTPUT_DIRECTORY 또는 mkdir $OUTPUT_DIRECTORY;
펄_엔드
# 현대적인 방법은 기존 디렉토리에 대해 아무 것도 하지 않습니다.
&mkdir -p $(OUTPUT_DIRECTORY)

이 명령문 중 하나는 makefile의 맨 위에 있어야 하므로 실행됩니다.
디렉토리가 필요할 수 있는 것보다 먼저.

방법 do I 정력에도 유리합니다. a 명령 실행 on 매주 짓다?

가장 쉬운 방법은 규칙 메커니즘을 전혀 사용하지 않고 단순히 실행하는 것입니다.
이:

dummy := $(셸 날짜 > last_build_timestamp)

또는 다음과 같이 perl 블록에 넣습니다.

perl_begin
system("실행 명령");
펄_엔드

이 접근 방식은 관련 없는 대상이 있더라도 실행된다는 단점이 있습니다.
실행 중입니다.

두 번째 접근 방식은 파일이 실제 파일인 경우에도 파일을 가짜 대상으로 선언하는 것입니다.
이렇게 하면 makepp가 매번 빌드 명령을 다시 실행하게 됩니다.
일부 규칙의 종속성 목록에 나타납니다.

방법 do I 단축 전에, 표시된 빌드 명령?

종종 컴파일 명령에 너무 많은 옵션이 있어서
화면을 읽을 수 없습니다. 의 표시를 억제하여 표시되는 내용을 변경할 수 있습니다.
명령의 흥미로운 부분을 명시적으로 출력합니다. 그것은
다음과 같이 "$(filter_out )"를 사용하여 명령의 관련 부분만 쉽게 인쇄할 수 있습니다.
이:

ALL_CFLAGS = $(CFLAGS) $(포함) $(ADDL_CXX_FLAGS) $(DEBUG_FLAGS)

%.o : %.c
@&echo $(notdir $(CC)) ... \
$(filter_out -I* $(ADDL_CXX_FLAGS), $(ALL_CFLAGS)) \
-c $(입력)
@$(CC) $(ALL_CFLAGS) -c $(입력) -o $(출력)

(명령어 앞의 "@"는 명령 출력을 억제합니다.)

이렇게 하면 대부분의 흥미로운 옵션을 볼 수 있지만 모든 옵션이 표시되지는 않습니다.
디렉토리를 포함합니다(종종 매우 많습니다!). 관심있는 부분이라면
in이 명령에서 연속적이면 "인쇄" 기능을 사용할 수도 있습니다(
줄 바꿈, 그래서 당신은 그들 중 몇 개를 원하지 않습니다):

표적:
@... $(흥미로운 부분 출력) ...

방법 do I 변하게 하다 a 파일 으로 종속성?

일부 모호한 파일 형식의 경우 스캐너를 구현할 가치가 없습니다. 한 프로젝트에서
xml 파일이 있습니다. foobar.xml 다음에 대한 종속성을 포함하는 푸바.아웃:







우리는 이 간단한 레이아웃을 고수하기로 결정했기 때문에 xml을 구문 분석할 필요가 없습니다. 와 더불어
builtin &sed, 다음은 세 종류의
윤곽:

%.d: %.xml
&sed 의! !$(줄기).out: \\! || 에스! (.+) !$$1 \\! || 에스! !# 비어 있는!' \
$(입력) -o $(출력)

foobar.d 포함

이것을 포함하려고 시도하면 먼저 "foobar.d"가 생성됩니다.

푸바.아웃: \
NS \
비 \
씨 \
# 비어 있는

비어 있는(단지 주석이거나 실제로 비어 있는) 줄은 후행에 대해 걱정할 필요가 없습니다.
백슬래시. 여러 줄 목록을 생성하는 대안은 다음과 같습니다.

%.d: %.xml
&sed 의! !$(stem).out: \$$((! || s! !))! || s!<.+?>!!g' \
$(입력) -o $(출력)

foobar.d 포함

이는 다음과 같은 결과를 생성합니다.

푸바.아웃: $((
a
b
c
))

더 복잡한 재작성이 필요한 경우 makefile 또는
당신이 포함하는 모듈. 예를 들어 $_를 정의하지 않으면 입력 줄을 건너뜁니다.

하위 myfilter {
/이면 undef $_를 반환합니다.
내 $stem = f_stem;
에스! !$stem.out: \$((! || s! !))! || s!<.+?>!!g;
}

%.d: %.xml
&sed 의! !$(stem).out: \$$((! || s! !))! || s!<.+?>!!g' \
$(입력) -o $(출력)

foobar.d 포함

onworks.net 서비스를 사용하여 온라인에서 makepp_cookbook 사용


무료 서버 및 워크스테이션

Windows 및 Linux 앱 다운로드

Linux 명령

Ad