"make -f"를 사용하여 이상한 동작 자동화

"make -f"를 사용하여 이상한 동작 자동화

나는 일련의 디렉토리를 가지고 있는데 그 중 일부는 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을 호출하기 전에 작업 디렉토리를 변경하지 않은 것입니다.


요약: 이 문제를 해결하려면 다음 중 하나 이상을 수행할 수 있습니다.

  1. 작업 디렉터리를 변경하는 쉘 스크립트를 수정합니다.

    #!/bin/bash
    
    for f in *; do
            if [[ -d $f && -f $f/makefile ]]; then
                    echo "Making clean in $f..."
                    (cd $f; make clean)
            fi
    done
    
  2. 명시적으로 비어 있는 규칙:

    clean: ;
    
  3. clean목표를 거짓으로 만드세요 :

    .PHONY: clean
    

상해:

Make에는 많은 암묵적인 규칙이 있습니다. 이를 통해 사람들은 makefile을 작성하지 않고도 간단한 프로젝트에서 make를 호출할 수 있습니다.

이 데모를 시도해 보세요:

  1. 빈 디렉터리를 만들고 변경합니다.
  2. 이라는 파일을 만듭니다 clean.sh.
  3. 달리기make clean

산출:

$ make clean
cat clean.sh >clean 
chmod a+x clean

쾅! 이것이 암묵적인 제조 규칙의 힘입니다. 보다암시적 규칙에 대한 매뉴얼 개발더 많은 정보를 알고 싶습니다.


나머지 미해결 질문에 답해 보겠습니다.

첫 번째 makefile에 대해 암시적 규칙을 호출하지 않는 이유는 무엇입니까?명시적인 규칙으로 암시적인 규칙을 무시하기 때문입니다 clean.

clean두 번째 makefile의 규칙이 암시적 규칙보다 우선하지 않는 이유는 무엇입니까 ?레시피가 없기 때문이죠. 레시피가 없는 규칙은 암시적 규칙을 재정의하지 않고 단순히 전제 조건을 추가합니다. 보다여러 규칙에 대한 매뉴얼 만들기더 많은 정보를 알고 싶습니다. 또한보십시오명시적인 빈 레시피를 사용하여 규칙에 대한 매뉴얼을 만듭니다..

하위 디렉터리에서 makefile을 호출하기 전에 작업 디렉터리를 변경하지 않으면 오류가 발생하는 이유는 무엇입니까?make는 작업 디렉토리를 변경하지 않기 때문입니다. Make는 상속된 작업 디렉토리에서 작동합니다. 기술적으로 이는 반드시 버그는 아니지만 대부분의 경우 발생합니다. 하위 디렉터리의 makefile이 하위 디렉터리에서 작동하도록 하시겠습니까? 아니면 상위 디렉터리에서 작업하도록 하시겠습니까?

cleanmake가 두 번째 호출에서 첫 번째 makefile의 명시적 규칙을 무시하는 이유는 무엇입니까 clean.sh?이제 대상 파일이 clean존재하기 때문입니다. 이 규칙에는 clean전제 조건이 없으므로 대상을 다시 빌드할 필요가 없습니다. 보다잘못된 대상에 대한 매뉴얼 만들기이는 문제를 정확하게 설명합니다.

three/makefile세 번째 호출에서 대상을 검색하는 이유는 무엇입니까?make는 다른 작업을 수행하기 전에 항상 makefile을 다시 생성하려고 시도하기 때문입니다. 메이크파일이 명시적으로 요청되었지만 -f존재하지 않는 경우 특히 그렇습니다. 보다makefile 재작성 매뉴얼 작성더 많은 정보를 알고 싶습니다.

관련 정보