ตัวประมวลผลก่อนดัมพ์ GCC กำหนด


248

มีวิธีสำหรับ gcc / g ++ เพื่อถ่ายโอนข้อมูลตัวประมวลผลล่วงหน้าที่กำหนดจากบรรทัดคำสั่งหรือไม่? ผมหมายถึงสิ่งที่ชอบ__GNUC__, __STDC__และอื่น ๆ

คำตอบ:


304

ใช่ใช้-E -dMตัวเลือกแทน -c ตัวอย่าง (ส่งออกไปยัง stdout):

 gcc -dM -E - < /dev/null

สำหรับ C ++

 g++ -dM -E -x c++ - < /dev/null

จากคู่มือ gcc :

แทนที่จะสร้างเอาต์พุตปกติให้สร้างรายการคำสั่ง `#define 'สำหรับมาโครทั้งหมดที่กำหนดในระหว่างการเรียกใช้งานโปรเซสเซอร์ล่วงหน้ารวมถึงมาโครที่กำหนดไว้ล่วงหน้า วิธีนี้ช่วยให้คุณสามารถค้นหาสิ่งที่กำหนดไว้ล่วงหน้าในเวอร์ชันของตัวประมวลผลล่วงหน้าของคุณ สมมติว่าคุณไม่มีไฟล์ foo.h คำสั่ง

touch foo.h; cpp -dM foo.h

จะแสดงมาโครที่กำหนดไว้ล่วงหน้าทั้งหมด

หากคุณใช้ -dM โดยไม่มีตัวเลือก -E ระบบจะตีความ -dM เป็นคำพ้องสำหรับ -fdump-rtl-mach


4
gcc มีอยู่ในระบบที่ / dev / null ไม่มีความหมาย
Pavel P

4
@Pavel จากนั้นคุณสามารถใช้ไฟล์ที่ว่างเปล่าไม่ว่าจะเป็น gcc หรือ preprocessor - cpp
philant

16
ฉันได้เพิ่มวิธีการพกพามากขึ้นเป็นคำตอบทางเลือก: echo | gcc -dM -E -ทำงานบน windows เช่นกัน
Pavel P

4
เป็นไปได้หรือไม่ที่จะกำหนดว่า (เช่นไฟล์ใด) ที่กำหนดมาจากไหน
edam

2
หรือcpp -dM -E - < NULสามารถใช้บน Windows ได้
René Nyffenegger

78

ฉันมักจะทำเช่นนี้:

$ gcc -dM -E - < /dev/null

โปรดทราบว่าการกำหนดพรีโปรเซสเซอร์บางตัวนั้นขึ้นอยู่กับตัวเลือกบรรทัดคำสั่ง - คุณสามารถทดสอบสิ่งเหล่านี้ได้โดยการเพิ่มตัวเลือกที่เกี่ยวข้องเข้ากับบรรทัดคำสั่งด้านบน ตัวอย่างเช่นเพื่อดูว่าตัวเลือก SSE3 / SSE4 ใดที่เปิดใช้งานโดยค่าเริ่มต้น:

$ gcc -dM -E - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSSE3__ 1

แล้วเปรียบเทียบสิ่งนี้เมื่อ-msse4มีการระบุ:

$ gcc -dM -E -msse4 - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSSE3__ 1

ในทำนองเดียวกันคุณสามารถดูว่าตัวเลือกใดที่แตกต่างกันระหว่างชุดตัวเลือกบรรทัดคำสั่งที่ต่างกันสองชุดเช่นเปรียบเทียบตัวประมวลผลล่วงหน้ากำหนดระดับการปรับให้เหมาะสม-O0(ไม่มี) และ-O3(เต็ม):

$ gcc -dM -E -O0 - < /dev/null > /tmp/O0.txt
$ gcc -dM -E -O3 - < /dev/null > /tmp/O3.txt
$ sdiff -s /tmp/O0.txt /tmp/O3.txt 
#define __NO_INLINE__ 1        <
                               > #define __OPTIMIZE__ 1

45

ตอบล่าช้า - ฉันพบคำตอบอื่น ๆ ที่เป็นประโยชน์ - และต้องการเพิ่มอีกเล็กน้อย


ฉันจะถ่ายทำมาโครตัวประมวลผลล่วงหน้าที่มาจากไฟล์ส่วนหัวได้อย่างไร

echo "#include <sys/socket.h>" | gcc -E -dM -

หรือ (ขอบคุณ @mymedia สำหรับคำแนะนำ):

gcc -E -dM -include sys/socket.h - < /dev/null

โดยเฉพาะอย่างยิ่งฉันต้องการที่จะเห็นสิ่งที่ SOMAXCONN ถูกกำหนดไว้ในระบบของฉัน ฉันรู้ว่าฉันสามารถเปิดไฟล์ส่วนหัวมาตรฐานได้ แต่บางครั้งฉันต้องค้นหาข้อมูลเล็กน้อยเพื่อค้นหาตำแหน่งไฟล์ส่วนหัว แต่ฉันสามารถใช้สายการบินเดียวนี้แทน:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 

1
คุณสามารถใช้ - รวมตัวเลือกคอมไพเลอร์เพื่อหลีกเลี่ยงไปป์
mymedia

31

วิธีการง่าย ๆ ( gcc -dM -E - < /dev/null) ทำงานได้ดีสำหรับ gcc แต่ล้มเหลวสำหรับ g ++ เมื่อเร็ว ๆ นี้ฉันต้องการการทดสอบสำหรับคุณลักษณะ C ++ 11 / C ++ 14 คำแนะนำสำหรับชื่อแมโครที่สอดคล้องกันของพวกเขามีการเผยแพร่ที่https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations แต่:

g++ -dM -E - < /dev/null | fgrep __cpp_alias_templates

มักจะล้มเหลวเพราะมันเงียบ ๆเรียก C-ไดรเวอร์ (เช่นถ้าเรียกโดยgcc) คุณสามารถดูสิ่งนี้ได้โดยการเปรียบเทียบเอาต์พุตกับ gcc หรือโดยการเพิ่มตัวเลือกบรรทัดคำสั่งเฉพาะ g ++ เช่น (-std = c ++ 11) ซึ่งส่งข้อความข้อผิดพลาดcc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for Cซึ่งส่งเสียงเกิดข้อผิดพลาด

เนื่องจาก (ไม่ใช่ C ++) gcc จะไม่สนับสนุน "Templates Aliases" (ดูhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf ) คุณต้องเพิ่ม-x c++ตัวเลือกในการ บังคับให้เรียกใช้คอมไพเลอร์ C ++ (เครดิตสำหรับการใช้-x c++ตัวเลือกแทนไฟล์ดัมมี่ที่ว่างเปล่าไปที่หยูเฉาดูด้านล่าง):

g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates

จะไม่มีเอาต์พุตเนื่องจาก g ++ (แก้ไข 4.9.1 ค่าเริ่มต้นที่ -std = gnu ++ 98) ไม่ได้เปิดใช้งานคุณลักษณะ C ++ 11 ตามค่าเริ่มต้น ในการทำเช่นนั้นให้ใช้

g++ -dM -E -x c++ -std=c++11 /dev/null | fgrep __cpp_alias_templates

ซึ่งในที่สุดก็ให้ผลตอบแทน

#define __cpp_alias_templates 200704

สังเกตว่ากรัม ++ 4.9.1 ไม่สนับสนุน "แม่นามแฝง" -std=c++11เมื่อเรียกด้วย


7
คุณไม่จำเป็นต้องใช้ไฟล์จำลอง GCC สนับสนุนการ-xโต้แย้งดังนั้นg++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cppควรใช้งานได้
yuyichao

@ yuyichao ขอบคุณสิ่งนี้ทำให้การใช้งานง่ายขึ้น ฉันไม่รู้ตัวเลือก -x ยกระดับความคิดเห็นของคุณและรวมไว้ในคำตอบเดิม
hermannk

23

วิธีการพกพาที่ทำงานได้ดีบน Linux หรือ Windows (ในกรณีที่ไม่มี / dev / null):

echo | gcc -dM -E -

สำหรับ c ++ คุณสามารถใช้ (แทนที่c++11ด้วยเวอร์ชันที่คุณใช้):

echo | gcc -x c++ -std=c++11 -dM -E -

มันทำงานโดยบอก gcc เพื่อ preprocess stdin (ซึ่งผลิตโดย echo) และพิมพ์กำหนด preprocessor ทั้งหมด (ค้นหา-dletters) หากคุณต้องการทราบว่ามีการเพิ่มคำนิยามใดบ้างเมื่อคุณรวมไฟล์ส่วนหัวคุณสามารถใช้-dDตัวเลือกที่คล้ายกับ -dM แต่ไม่รวมมาโครที่กำหนดไว้ล่วงหน้า:

echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -

หมายเหตุอย่างไรก็ตามอินพุตว่างนั้นยังคงสร้าง-dDตัวเลือกจำนวนมากด้วย


6
@rubenvb มันไม่เกี่ยวข้อง จุดคือมีบรรทัด cmd ที่ทำงานได้ดีบน windows และ unix อย่างน้อย หากคุณใช้NULคุณจะกลับไปที่รูปสี่เหลี่ยมจัตุรัส: มันจะไม่ทำงานบนระบบที่ไม่มี
Pavel P

2
เพิ่มคำตอบแบบเต็มสำหรับ C ++ ทำงานได้ทั้ง Windows และ Linux (แม้ว่าsortจะทำงานแตกต่างกันเล็กน้อย):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous

สิ่งนี้สร้างเอาต์พุตว่างใน git-bash
Lennart Rolland

@ LenartRolland มี gcc ไหม? ใน git-bash ของฉันฉันไม่สามารถเรียกใช้ gcc ได้
Pavel P

@pavel ฉันใช้ mingw32 gcc ที่มาพร้อมกับการกระจายไบนารี Qt5 สำหรับ Windows
Lennart Rolland

3

ในขณะที่ทำงานในโครงการขนาดใหญ่ที่มีระบบการสร้างที่ซับซ้อนและเป็นเรื่องยากที่จะได้รับ (หรือแก้ไข) คำสั่ง gcc / g ++ โดยตรงมีวิธีอื่นในการดูผลลัพธ์ของการขยายแมโคร เพียงแค่กำหนดแมโครใหม่แล้วคุณจะได้ผลลัพธ์คล้ายกับการแสดงผลต่อไปนี้:

file.h: note: this is the location of the previous definition
#define MACRO current_value

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