나는 일련의 디렉토리를 가지고 있는데 그 중 일부는 makefile을 포함하고 일부는 clean
대상을 가지고 있습니다. 상위 디렉토리에는 간단한 스크립트가 있습니다.
#!/bin/bash
for f in *; do
if [[ -d $f && -f $f/makefile ]]; then
echo "Making clean in $f..."
make -f $f/makefile clean
fi
done
이것은 (정의된) "깨끗한" 대상이 없는 makefile을 사용하여 디렉토리에 액세스할 때 이상한 일을 합니다. 예를 들어, 두 개의 디렉토리 one
와 가 주어지면 two
다음을 포함합니다.
/메이크파일
clean:
-rm *.x
2개/메이크파일
clean:
두 번째 경우에는 "clean"이 지시어 없이 실행되므로 "make clean"을 실행하면 다음과 같은 결과가 two
나타납니다.
make: Nothing to be done for `clean'.
"클린"이 없는 경우와 비교:
make: *** No rule to make target `clean'. Stop.
그러나 내가 설명하는 문제의 경우 대상이 존재하지만 정의되지 않았거나 존재하지 않는 경우 결과는 동일합니다. clean.sh
상위 디렉토리에서 실행;
Making clean in one...
rm *.x
rm: cannot remove `*.x': No such file or directory
make: [clean] Error 1 (ignored)
그래서 one
청소할 필요가 없습니다. 별거 아닙니다. 예상되는 일입니다. 하지만:
Making clean in two...
cat clean.sh >clean
chmod a+x clean
왜 cat clean.sh>clean
기다려? 위에 표시된 대로 최소한의 예제를 만들었습니다. 주변에 다른 파일이나 디렉터리는 없습니다(clean.sh, 디렉터리 1과 2, 아주 작은 makefile만 있음). 하지만 clean.sh를 실행한 후에 make
는 복사되어 clean.sh > clean
실행 가능해졌습니다. clean.sh를 다시 실행하면:
Making clean in one...
make: `clean' is up to date.
Making clean in two...
make: `clean' is up to date.
Press any key to continue...
더 이상한 점은 이제 지정된 makefile을 전혀 사용하지 않기 때문입니다. "최신" 미스터리 대상을 사용합니다.
나는 관련이 있을 수 있는 것을 발견했습니다: 다음과 같이 clean.sh에서 테스트 절을 제거하는 경우:
# if [[ -d $f && -f $f/makefile ]]; then
if [[ -d $f ]]; then
makefile 없이 디렉토리를 생성하면 three
출력의 일부에 다음이 포함됩니다.
Making clean in three...
make: three/makefile: No such file or directory
make: *** No rule to make target `three/makefile'. Stop.
내가 아는 한 그런 파일이나 디렉터리는 없는데 왜 make
계속해서 그 이름을 가진 대상을 찾는 걸까요? 매뉴얼 페이지는 매우 간단해 보입니다.
-f 파일, --file=파일, --makefile=파일
Use file as a makefile.
답변1
이 동작은 버그가 아닙니다. 이것은 특징입니다. 정확한 기능 및 가능한 사용자 오류입니다.
문제의 기능은 Make의 암묵적인 규칙 중 하나입니다. 귀하의 경우 파일 "빌딩"에 대한 암시적 규칙입니다 *.sh
. 사용자 오류, 실수는 하위 디렉토리에서 makefile을 호출하기 전에 작업 디렉토리를 변경하지 않은 것입니다.
요약: 이 문제를 해결하려면 다음 중 하나 이상을 수행할 수 있습니다.
작업 디렉터리를 변경하는 쉘 스크립트를 수정합니다.
#!/bin/bash for f in *; do if [[ -d $f && -f $f/makefile ]]; then echo "Making clean in $f..." (cd $f; make clean) fi done
명시적으로 비어 있는 규칙:
clean: ;
clean
목표를 거짓으로 만드세요 :.PHONY: clean
상해:
Make에는 많은 암묵적인 규칙이 있습니다. 이를 통해 사람들은 makefile을 작성하지 않고도 간단한 프로젝트에서 make를 호출할 수 있습니다.
이 데모를 시도해 보세요:
- 빈 디렉터리를 만들고 변경합니다.
- 이라는 파일을 만듭니다
clean.sh
. - 달리기
make clean
산출:
$ make clean
cat clean.sh >clean
chmod a+x clean
쾅! 이것이 암묵적인 제조 규칙의 힘입니다. 보다암시적 규칙에 대한 매뉴얼 개발더 많은 정보를 알고 싶습니다.
나머지 미해결 질문에 답해 보겠습니다.
첫 번째 makefile에 대해 암시적 규칙을 호출하지 않는 이유는 무엇입니까?명시적인 규칙으로 암시적인 규칙을 무시하기 때문입니다 clean
.
clean
두 번째 makefile의 규칙이 암시적 규칙보다 우선하지 않는 이유는 무엇입니까 ?레시피가 없기 때문이죠. 레시피가 없는 규칙은 암시적 규칙을 재정의하지 않고 단순히 전제 조건을 추가합니다. 보다여러 규칙에 대한 매뉴얼 만들기더 많은 정보를 알고 싶습니다. 또한보십시오명시적인 빈 레시피를 사용하여 규칙에 대한 매뉴얼을 만듭니다..
하위 디렉터리에서 makefile을 호출하기 전에 작업 디렉터리를 변경하지 않으면 오류가 발생하는 이유는 무엇입니까?make는 작업 디렉토리를 변경하지 않기 때문입니다. Make는 상속된 작업 디렉토리에서 작동합니다. 기술적으로 이는 반드시 버그는 아니지만 대부분의 경우 발생합니다. 하위 디렉터리의 makefile이 하위 디렉터리에서 작동하도록 하시겠습니까? 아니면 상위 디렉터리에서 작업하도록 하시겠습니까?
clean
make가 두 번째 호출에서 첫 번째 makefile의 명시적 규칙을 무시하는 이유는 무엇입니까 clean.sh
?이제 대상 파일이 clean
존재하기 때문입니다. 이 규칙에는 clean
전제 조건이 없으므로 대상을 다시 빌드할 필요가 없습니다. 보다잘못된 대상에 대한 매뉴얼 만들기이는 문제를 정확하게 설명합니다.
three/makefile
세 번째 호출에서 대상을 검색하는 이유는 무엇입니까?make는 다른 작업을 수행하기 전에 항상 makefile을 다시 생성하려고 시도하기 때문입니다. 메이크파일이 명시적으로 요청되었지만 -f
존재하지 않는 경우 특히 그렇습니다. 보다makefile 재작성 매뉴얼 작성더 많은 정보를 알고 싶습니다.