gcc는 다음 헤더 파일을 어떻게 찾습니까?


10

나는 sys/ptrace.hC 프로그램에 포함 시켰다.

의 출력은 /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -v다음과 같은 경로를 제공 곳 헤더 파일 GCC의 모습

#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
 /usr/include
End of search list.

gcc -M내 프로그램의 출력은 다음 헤더 파일 위치를 제공합니다.

    pt.o: pt.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \
 /usr/include/_G_config.h /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \
 /usr/include/x86_64-linux-gnu/sys/ptrace.h

이후 /usr/include/x86_64-linux-gnu/최초의 출력에 포함되지 않은, 어떻게 GCC는 찾을 않습니다 sys/ptrace.h?

편집하다:

echo '#include <sys/ptrace.h>' | gcc -fsyntax-only -xc -v -H -결과 의 출력

Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) 

재귀 적으로 /usr/include.. 보고있는 문제는 무엇입니까?
Ramhound

재귀 적으로 보이는 것처럼 보이지 않습니다. 그렇다면 sys / 접두사를 포함시킬 필요가 없습니다. 예를 들어 ptrace.h 만 포함하면 작동하지 않습니다.
user912083132

난 당신이 포함 생각하지 않습니다 /sys/ptrace.h하지만 sys/ptrace.h오른쪽?
user253751

이것은 GCC에 대한 "멀티 아치"패치의 버그 일 것입니다. 디렉토리 /usr/include/x86_64-linux-gnu 시스템 포함 디렉토리로 취급되며로 인쇄되는 검색 경로 목록에 포함 되어야 합니다 gcc -v. 누군가 어떻게 그 버그를 달성했는지 잘 모르겠습니다. 내가 정확하게 기억한다면, 시스템 포함 디렉토리를 추가하는 가장 확실한 방법은에 의해 인쇄 된 디렉토리를 추가하는 것입니다 -v. (GCC 전 처리기의 ~ 50 %를 썼지 만 15 년 전에는 무언가를 기억하지 못할 수도 있습니다.)
zwol

@Ramhound 아래에서 재귀 적으로 검색 하지는 않습니다/usr/include . 그것은 세계의 거의 모든 C 라이브러리를 망칠 것입니다.
zwol

답변:


12

더 짧은 대답.

귀하의 질문은의 출력에 관한 cc1 -v것이지만 CPP (C 전 처리기)에는 영향을 미치지 않으며 전체 컴파일 체인에 혼합되어 포함됩니다. cpp -v시스템에서 실행 하는 경우 출력이 비슷 cc1 -v하지만 적어도 /usr/include/x86_64-linux-gnu경로가 추가 된 포함 조합이 포함됩니다 .

더 긴 대답.

이후 /usr/include/x86_64-linux-gnu/최초의 출력에 포함되지 않은, 어떻게 GCC는 찾을 않습니다 sys/ptrace.h?

기술적 /usr/include/x86_64-linux-gnu/으로 첫 번째 출력에는 명시 적으로 설정되어 있지 않지만 /usr/include/확실하게 설정됩니다. 이것이 공식 GNU GCC 문서에 설명 된 기본 검색 경로입니다 .

GCC는 여러 곳에서 헤더를 찾습니다. 일반적인 유닉스 시스템에서는 달리 지시하지 않으면 다음에서 요청 된 헤더를 찾습니다 #include <file>.

  • / usr / local / include
  • libdir / gcc / target / version / include
  • / usr / target / include
  • / usr / include

그리고 여기에 더 설명되어 있습니다 :

GCC는 #include "file"현재 파일을 포함하는 디렉토리에서 먼저 요청 된 헤더를 찾은 다음 -iquote옵션에 지정된 디렉토리 에서 요청 된 헤더를 찾은 다음 같은 위치에서 꺾쇠 괄호로 요청 된 헤더를 찾습니다 . 예를 들어 /usr/include/sys/stat.h# 이 포함 된 경우 include "types.h"GCC는에서 types.h먼저 /usr/include/sys찾은 다음 일반적인 검색 경로를 찾습니다.

따라서 이것은 x86_64-linux-gnu/경로가 다음 /usr/include/*/sys/과 같이 단순히 삽입 되었음을 의미합니다 .

/usr/include/x86_64-linux-gnu/sys/ptrace.h

적어도이 질문의 이전 버전 에서 처음 생각한 것입니다 . 그러나이 사이트를 확인한 후에 는 무슨 일이 일어나고 있는지에 대한 설명이 조금 더 자세하며 해당 사이트에서 위의 게시물과 동등한 내용에 대한 직접적인 응답은 아래에 다시 게시됩니다. 대담한 강조는 내 것이다 :

그러나 그것은 일종의 소원 한 답답하고 불완전한 답변입니다. GCC가 헤더 파일을 찾는 위치를 정확하게 알려주는 방법이 반드시 있어야합니까? 글쎄, GCC를 소스 코드 파일을 받아 작업 프로그램을 내뿜는 단일 모 놀리 식 응용 프로그램으로 생각하는 것이 편리하지만, 최종적으로 컴파일 된 객체 파일을 생성하기 위해 서로 연결되는 다른 프로그램의 모음입니다. 첫 번째는 C Pre-Processor의 약자 인 CPP로, 컴파일러 지시어를 찾아서 #include지정된대로 소스 코드를 수정해야합니다. 포함하는 경우, 다른 파일의 내용을 현재 파일로 복사합니다. -v 플래그를 전달하여 이러한 파일을 찾는 위치를 확인할 수 있습니다.

CPP (C Pre-Processor)가 컴파일러 프로세스의 첫 번째 단계라는 것을 알고 cpp -vUbuntu 12.04.5 테스트 시스템 의“include”출력을 살펴 보자 .

#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

거기에서 당신은 명확하게 볼 수 있습니다 /usr/include/x86_64-linux-gnu. 비교 /usr/lib/gcc/x86_64-linux-gnu/4.6/cc1 -v를 위해, 동일한 Ubuntu 12.04.5 테스트 시스템 에서 유사한 "include"출력이 있습니다.

#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed
 /usr/include

/usr/include/x86_64-linux-gnu초기 CPP (C 전 처리기) 작업을 통해 믹스에 어떻게 명확하게 삽입 되는지 확인하십시오 . 그리고 그 사이트의 게시물은 그 경로가 어디에서 왔는지 설명하기 위해 계속 진행됩니다. 다시 대담한 강조는 내 것입니다 :

이 경로는 실제로 컴파일 타임에 CPP (GCC의 일부)에 내장되어 있습니다. 어떤 이유로 든 해당 디렉토리 중 하나를 삭제하면 각 컴파일에서 여전히 확인됩니다. 각 디렉토리는 여기에 나열된 순서대로 검색됩니다. 에 파일이 있으면 /usr/local/include다음 세 디렉토리는 확인되지 않습니다.

따라서 C 컴파일 체인의 첫 번째 부분으로 불리는 CPP (C Pre-Processor)로 귀결됩니다.


x86_64-linux-gnu /가 왜 중간에 퍼져 있습니까?
user912083132

@ user912083132 : 그것은 $TARGET내 답변과 의견에서 언급 한 부분입니다. 그것은의 출력의 config.guessGCC의 컴파일, 또는 어떤이 주어졌다 때 configure와 스크립트 --target플래그. 진짜 질문은, 그 길은 어떻게 어떻습니까? $TARGET처음부터 헤더를 찾지 못한 후 동일한 목록을 다시 추가 하여 각 목록에 추가 합니까?
워렌 영

@ user912083132 새로 수집 한 정보로 답변을 업데이트했습니다. 다시 읽으십시오. 대답은 CPP (C 전 처리기)에서 나온 것입니다.
JakeGould

2

GCC 소스 코드를 살펴 보지 않으면 "이유"를 줄 수는 없지만 여기서 내가 가지고있는 GCC 버전은 /usr/include/$TARGET사용자 와 JakeGould가 찾은 선택을 모두 마친 후에 되돌아 간다고 말할 수있다 . 다음과 같이 볼 수 있습니다.

$ strace -f -e open gcc -c foo.c -o foo.o 2>&1 | grep ptrace.h

여기서는를 foo.c포함합니다 #include <sys/ptrace.h>.

실제 컴파일 작업을 수행하기 위해 자식을 생성 -f하기 때문에 여기 에 논쟁 이 필요합니다 gcc. stdout이 아닌 stderr에 결과를 기록 2>&1하기 때문에 필요합니다 strace.

공지 사항 당신이 얻을 ENOENT마침내 성공 하나를 시도하기 전에 문서화 된 모든 디렉토리에 대한 오류를.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.