Bagaimana cara gcc menemukan file header berikut?


10

Saya sudah memasukkan sys/ptrace.hke dalam program C.

Output dari /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -vmemberikan path berikut di mana gcc mencari file header

#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.

output gcc -Muntuk program saya memberikan lokasi file header berikut

    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

Karena /usr/include/x86_64-linux-gnu/tidak terkandung dalam output pertama, bagaimana gcc menemukan sys/ptrace.h?

EDIT:

Keluaran echo '#include <sys/ptrace.h>' | gcc -fsyntax-only -xc -v -H -hasil dalam

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) 

Secara rekursif melihat /usr/include.. Masalah apa yang Anda coba selesaikan?
Ramhound

Itu tidak terlihat seperti itu secara rekursif. Jika ya, tidak perlu menyertakan sys / awalan. Termasuk ptrace.h saja, misalnya, tidak berfungsi.
user912083132

Saya tidak berpikir Anda termasuk /sys/ptrace.htetapi sys/ptrace.h, kan?
user253751

Ini hampir pasti merupakan bug di patch "multiarch" ke GCC. Direktori /usr/include/x86_64-linux-gnu ini diperlakukan sebagai suatu sistem termasuk direktori dan harus dimasukkan dalam daftar pencarian jalan dicetak oleh gcc -v. Saya tidak yakin bagaimana seseorang berhasil mencapai bug itu; jika saya ingat benar, cara yang paling jelas untuk menambahkan sistem termasuk direktori tidak menambahkannya dengan apa yang dicetak oleh -v. (Saya menulis ~ 50% dari preprosesor GCC, tapi itu 15 tahun yang lalu, jadi saya mungkin salah
mengingat

@Ramhound Ini pasti tidak tidak rekursif mencari di bawah /usr/include. Itu akan menghancurkan hampir semua perpustakaan C di dunia.
zwol

Jawaban:


12

Jawaban yang lebih pendek.

Pertanyaan Anda adalah tentang output dari cc1 -v, tetapi itu tidak memperhitungkan CPP (C Pra-Prosesor) dan itu termasuk yang dicampur ke dalam seluruh rantai kompilasi. Jika Anda menjalankan cpp -vpada sistem Anda Anda harus melihat, campuran termasuk yang terlihat mirip dengan output cc1 -vtetapi dengan setidaknya /usr/include/x86_64-linux-gnujalan ditambahkan di sana.

Jawaban yang lebih panjang.

Karena /usr/include/x86_64-linux-gnu/tidak terkandung dalam output pertama, bagaimana gcc menemukan sys/ptrace.h?

Secara teknis, /usr/include/x86_64-linux-gnu/tidak secara eksplisit diatur dalam output pertama, tetapi /usr/include/pasti. Dan itu adalah jalur pencarian default seperti yang dijelaskan dalam dokumentasi resmi GNU GCC :

GCC mencari di beberapa tempat berbeda untuk tajuk. Pada sistem Unix normal, jika Anda tidak menginstruksikan sebaliknya, ia akan mencari header yang diminta #include <file>dalam:

  • / usr / local / termasuk
  • libdir / gcc / target / versi / termasuk
  • / usr / target / include
  • / usr / termasuk

Dan selanjutnya dijelaskan di sini:

GCC mencari header yang diminta dengan #include "file"pertama di direktori yang berisi file saat ini, kemudian di direktori seperti yang ditentukan oleh -iquoteopsi, kemudian di tempat yang sama ia akan mencari header yang diminta dengan kurung sudut. Misalnya, jika /usr/include/sys/stat.hberisi # include "types.h", GCC mencari types.hpertama di /usr/include/sys, lalu di jalur pencarian yang biasa.

Jadi ini menyiratkan bahwa x86_64-linux-gnu/jalan dimasukkan begitu saja ke dalam /usr/include/*/sys/seperti ini:

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

Setidaknya itulah yang awalnya saya pikirkan dalam versi sebelumnya dari pertanyaan ini . Tetapi setelah memeriksa situs ini , penjelasan tentang apa yang terjadi sedikit lebih terperinci dan tanggapan langsung dari situs tersebut terhadap konten yang setara dengan apa yang saya posting di atas diposting kembali di bawah ini; penekanan berani adalah milikku:

tapi itu semacam jawaban plin-plan (dan juga tidak lengkap). Tentunya harus ada cara agar GCC memberi tahu Anda dengan tepat di mana ia akan berakhir mencari file header-nya? Yah, meskipun lebih mudah untuk menganggap GCC sebagai aplikasi monolitik tunggal yang mengambil file kode sumber dan mengeluarkan program kerja, secara teknis kumpulan program lain yang berantai bersama untuk menghasilkan file objek akhir yang dikompilasi. Yang pertama adalah CPP, kependekan dari C Pre-Processor , yang tugasnya adalah mencari arahan kompiler seperti #includedan memodifikasi kode sumber seperti yang ditentukan oleh mereka; dalam hal menyertakan, dengan menyalin isi dari file lain ke yang sekarang. Anda dapat melihat di mana mencari file-file ini dengan memberikannya tanda -v:

Ketahuilah bahwa CPP (C Pre-Processor) adalah langkah pertama dalam proses kompiler, mari kita lihat output "include" cpp -vpada sistem pengujian Ubuntu 12.04.5 saya:

#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

Di sana Anda bisa melihat dengan jelas /usr/include/x86_64-linux-gnu. Dan untuk membandingkan, berikut ini adalah keluaran “sertakan” yang serupa /usr/lib/gcc/x86_64-linux-gnu/4.6/cc1 -vpada sistem pengujian Ubuntu 12.04.5 yang sama:

#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

Perhatikan bagaimana /usr/include/x86_64-linux-gnudimasukkan dengan jelas ke dalam campuran dengan tindakan CPP (C Pra-Prosesor) awal. Dan posting di situs itu melanjutkan untuk menjelaskan dari mana jalur itu berasal; lagi-lagi penekanan yang berani adalah milikku:

jalur ini sebenarnya dibangun ke dalam CPP (yang merupakan bagian dari GCC) pada waktu kompilasi; jika karena alasan apa pun Anda akhirnya menghapus salah satu direktori itu, masih akan diperiksa untuk setiap kompilasi. Setiap direktori dicari dalam urutan yang tercantum di sini; jika file ditemukan /usr/local/include, tiga direktori berikutnya tidak akan diperiksa.

Jadi semuanya bermuara pada CPP (C Pre-Processor) yang disebut sebagai bagian pertama dari rantai kompilasi C.


Mengapa x86_64-linux-gnu / terdorong ke tengah?
user912083132

@ user912083132: Itulah $TARGETbagian yang saya sebutkan dalam jawaban dan komentar saya. Ini adalah output config.guessketika GCC dikompilasi, atau yang diberikan kepada configureskripnya dengan --targetbendera. Pertanyaan sebenarnya adalah, bagaimana jalur itu bisa dirakit? Apakah itu hanya kembali melalui daftar yang sama, menambahkan $TARGETmasing-masing, setelah gagal menemukan tajuk pertama kali?
Warren Young

@ user912083132 Memperbarui jawaban saya dengan beberapa informasi yang baru didapat. Silakan baca kembali; jawaban menjelaskan itu berasal dari CPP (C Pra-Prosesor).
JakeGould

2

Pendeknya mempelajari kode sumber GCC, saya tidak bisa memberi Anda "mengapa", tetapi saya dapat memberi tahu Anda bahwa versi GCC yang saya miliki di sini kembali ke /usr/include/$TARGETsetelah menghabiskan pilihan yang Anda dan JakeGould temukan . Anda bisa melihatnya seperti ini:

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

dimana foo.cberisi a #include <sys/ptrace.h>.

Anda memerlukan -fargumen di sini karena gccmenumbuhkan anak-anak untuk melakukan pekerjaan kompilasi yang sebenarnya. Anda perlu 2>&1karena stracemenulis hasilnya ke stderr, bukan stdout.

Perhatikan Anda mendapatkan ENOENTkesalahan untuk semua direktori yang didokumentasikan sebelum akhirnya mencoba salah satu yang berhasil.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.