gcc ค้นหาไฟล์ส่วนหัวต่อไปนี้อย่างไร


10

ฉันได้รวมsys/ptrace.hเข้ากับโปรแกรม C ของฉันแล้ว

ผลลัพธ์ของ/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

นี่เป็นข้อผิดพลาดในแพทช์ "multiarch" กับ GCC ไดเรกทอรี/usr/include/x86_64-linux-gnu จะถูกถือว่าเป็นระบบรวมถึงไดเรกทอรีและควรgcc -vได้รับการรวมอยู่ในรายการค้นหาเส้นทางพิมพ์โดย ฉันไม่แน่ใจว่ามีคนจัดการเพื่อให้บรรลุข้อผิดพลาดนั้น; -vถ้าผมจำไม่ผิดวิธีที่ชัดเจนที่สุดในการเพิ่มระบบรวมถึงไดเรกทอรีไม่เพิ่มไปยังสิ่งที่พิมพ์โดย (ฉันเขียน ~ preprocessor ของ GCC ประมาณ 50% แต่นั่นก็เป็น 15 ปีที่แล้วดังนั้นฉันอาจจะเข้าใจผิดบางอย่าง)
zwol

@Ramhound มันแน่นอนที่สุดไม่ได้/usr/includeซ้ำค้นหาด้านล่าง นั่นจะทำลายห้องสมุดซีทุกแห่งในโลก
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 ค้นหาในส่วนต่าง ๆ ของส่วนหัว บนระบบ Unix ปกติถ้าคุณไม่แนะนำเป็นอย่างอื่นระบบจะค้นหาส่วนหัวที่ขอด้วย#include <file>ใน:

  • / usr / / พื้นที่ ได้แก่
  • libdir / gcc / เป้าหมาย / รุ่น / ได้แก่
  • / usr / เป้าหมาย / ได้แก่
  • / usr / รวม

และอธิบายเพิ่มเติมได้ที่นี่:

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 เป็นแอพพลิเคชั่นแบบเสาหินเดียวที่ใช้ในซอร์สโค้ดไฟล์และแยกโปรแกรมที่ทำงานออกมา แต่ในทางเทคนิคแล้วมันเป็นคอลเลกชันของโปรแกรมอื่น ๆ ตัวแรกของเหล่านี้คือ CPP ย่อมาจากC Pre-Processorซึ่งมีหน้าที่ในการค้นหาคำสั่งคอมไพเลอร์เช่น #includeและปรับเปลี่ยนซอร์สโค้ดตามที่พวกเขาระบุ ในกรณีของการรวมโดยการคัดลอกเนื้อหาของไฟล์อื่นลงในไฟล์ปัจจุบัน คุณสามารถดูว่าไฟล์เหล่านี้ค้นหาตำแหน่งใดโดยส่งผ่านแฟล็ก -v:

รู้ว่า CPP (C Pre-Processor) เป็นขั้นตอนแรกในกระบวนการของคอมไพเลอร์ลองดูที่ผลลัพธ์ "รวมถึง" ของcpp -vระบบทดสอบ Ubuntu 12.04.5 ของ Ubuntu:

#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 "..." 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 Pre-Processor) เริ่มต้น และโพสต์ในเว็บไซต์นั้นจะอธิบายเพิ่มเติมเกี่ยวกับเส้นทางที่มาจาก; การเน้นตัวหนาอีกครั้งคือของฉัน:

เส้นทางนี้สร้างขึ้นจริงใน CPP (ซึ่งเป็นส่วนหนึ่งของ GCC) ในเวลารวบรวม ถ้าด้วยเหตุผลใดก็ตามที่คุณท้ายการลบหนึ่งในไดเรกทอรีเหล่านั้นก็จะยังคงถูกตรวจสอบในการรวบรวมแต่ละ แต่ละไดเรกทอรีจะถูกค้นหาตามลำดับที่แสดงไว้ที่นี่ หากพบไฟล์ใน/usr/local/includeสามไดเรกทอรีถัดไปจะไม่ถูกตรวจสอบ

ดังนั้นทุกอย่างจะไหลลงสู่ CPP (C Pre-Processor) ที่ถูกเรียกว่าเป็นส่วนแรกของห่วงโซ่การคอมไพล์ C


ทำไม x86_64-linux-gnu / เข้าสู่กลาง?
user912083132

@ user912083132: นั่นคือ$TARGETส่วนที่ฉันพูดถึงในคำตอบและความคิดเห็นของฉัน มันเป็นผลลัพธ์ของconfig.guessเมื่อ GCC รวบรวมหรือที่มอบให้กับconfigureสคริปต์ด้วยการ--targetตั้งค่าสถานะ คำถามจริงก็คือการรวมเส้นทางนั้นได้อย่างไร? มันเพิ่งกลับไปที่รายการเดียวกันต่อท้าย$TARGETแต่ละรายการหลังจากล้มเหลวในการค้นหาส่วนหัวในครั้งแรกผ่านหรือไม่
Warren Young

@ user912083132 อัปเดตคำตอบของฉันด้วยข้อมูลที่รวบรวมใหม่ โปรดอ่านอีกครั้ง คำตอบอธิบายว่ามันมาจาก CPP (C Pre-Processor)
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วางไข่ให้เด็กทำงานรวบรวมจริง คุณต้องการ2>&1เพราะstraceกำลังเขียนผลลัพธ์ไปยัง stderr ไม่ใช่ stdout

ขอให้สังเกตว่าคุณได้รับENOENTข้อผิดพลาดสำหรับไดเรกทอรีเอกสารทั้งหมดก่อนที่จะลองไดเรกทอรีที่ประสบความสำเร็จในที่สุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.