Định nghĩa tiền xử lý kết xuất GCC


Câu trả lời:


304

Có, sử dụng -E -dMtùy chọn thay vì -c. Ví dụ (đưa chúng ra thiết bị xuất chuẩn):

 gcc -dM -E - < /dev/null

Dành cho C ++

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

Từ hướng dẫn gcc :

Thay vì đầu ra bình thường, hãy tạo một danh sách các lệnh '#define' cho tất cả các macro được xác định trong quá trình thực thi bộ tiền xử lý, bao gồm các macro được xác định trước. Điều này cung cấp cho bạn một cách để tìm hiểu những gì được xác định trước trong phiên bản tiền xử lý của bạn. Giả sử bạn không có tập tin foo.h, lệnh

touch foo.h; cpp -dM foo.h

sẽ hiển thị tất cả các macro được xác định trước.

Nếu bạn sử dụng -dM mà không có tùy chọn -E, -dM được hiểu là từ đồng nghĩa của -fdump-rtl-mach.


4
gcc tồn tại trên các hệ thống trong đó / dev / null có nghĩa là không có gì.
Pavel P

4
@Pavel sau đó bạn có thể sử dụng một tệp trống, với gcc hoặc bộ tiền xử lý - cpp.
philant

16
Tôi đã thêm một cách tiếp cận di động hơn như một câu trả lời thay thế: cũng echo | gcc -dM -E -hoạt động trên windows.
Pavel P

4
Có thể xác định nơi (nghĩa là, trong tập tin) những định nghĩa đó đến từ đâu?
edam

2
Ngoài ra, trên Windows, cpp -dM -E - < NULcó thể được sử dụng.
René Nyffalanger

78

Tôi thường làm theo cách này:

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

Lưu ý rằng một số định nghĩa tiền xử lý phụ thuộc vào các tùy chọn dòng lệnh - bạn có thể kiểm tra các tùy chọn này bằng cách thêm các tùy chọn có liên quan vào dòng lệnh trên. Ví dụ: để xem các tùy chọn SSE3 / SSE4 nào được bật theo mặc định:

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

và sau đó so sánh điều này khi -msse4được chỉ định:

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

Tương tự, bạn có thể thấy các tùy chọn khác nhau giữa hai bộ tùy chọn dòng lệnh khác nhau, ví dụ: so sánh bộ tiền xử lý xác định cho các mức tối ưu hóa -O0(không có) và -O3(đầy đủ):

$ 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

Câu trả lời muộn - Tôi thấy các câu trả lời khác hữu ích - và muốn thêm một chút.


Làm cách nào để loại bỏ các macro tiền xử lý đến từ một tệp tiêu đề cụ thể?

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

hoặc (cảm ơn @mymedia cho gợi ý):

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

Cụ thể, tôi muốn xem SOMAXCONN được định nghĩa trên hệ thống của tôi. Tôi biết tôi chỉ có thể mở tệp tiêu đề tiêu chuẩn, nhưng đôi khi tôi phải tìm kiếm xung quanh một chút để tìm vị trí tệp tiêu đề. Thay vào đó tôi chỉ có thể sử dụng một lớp lót này:

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

1
bạn có thể sử dụng tùy chọn trình biên dịch bao gồm để tránh các đường ống
mymedia

31

Cách tiếp cận đơn giản ( gcc -dM -E - < /dev/null) hoạt động tốt cho gcc nhưng không thành công cho g ++. Gần đây tôi yêu cầu một bài kiểm tra cho tính năng C ++ 11 / C ++ 14. Các đề xuất cho tên macro tương ứng của chúng được công bố tại https://isocpp.org/std/ Hiểu-document / sd-6-sg10-feature-test-recommendations . Nhưng:

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

luôn luôn thất bại, vì nó âm thầm gọi trình điều khiển C (như thể được gọi bởi gcc). Bạn có thể thấy điều này bằng cách so sánh đầu ra của nó với gcc hoặc bằng cách thêm tùy chọn dòng lệnh cụ thể của g ++ như (-std = c ++ 11) phát ra thông báo lỗi cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C.

Bởi vì (không phải C ++) gcc sẽ không bao giờ hỗ trợ "Mẫu bí danh" (xem http://www.open-std.org/jtc1/sc22/wg21/docs/ con 2007 / n2258.pdf ), bạn phải thêm -x c++tùy chọn vào buộc yêu cầu trình biên dịch C ++ (Tín dụng cho việc sử dụng các -x c++tùy chọn thay vì tệp giả trống đi đến yuyichao, xem bên dưới):

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

Sẽ không có đầu ra vì g ++ (phiên bản 4.9.1, mặc định là -std = gnu ++ 98) không bật tính năng C ++ 11 theo mặc định. Để làm như vậy, sử dụng

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

mà cuối cùng mang lại

#define __cpp_alias_templates 200704

lưu ý rằng g ++ 4.9.1 không hỗ trợ "Mẫu bí danh" khi được gọi với -std=c++11.


7
Bạn không phải sử dụng một tập tin giả. GCC hỗ trợ -xđối số g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cppnên hoạt động.
yuyichao

@yuyichao Cảm ơn bạn, điều này làm cho nó dễ sử dụng hơn. Tôi đã không biết tùy chọn -x. Nâng cao nhận xét của bạn và tích hợp nó vào câu trả lời ban đầu.
ẩn sĩ

23

Một cách tiếp cận di động hoạt động tốt như nhau trên Linux hoặc Windows (nơi không có / dev / null):

echo | gcc -dM -E -

Đối với c ++, bạn có thể sử dụng (thay thế c++11bằng bất kỳ phiên bản nào bạn sử dụng):

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

Nó hoạt động bằng cách báo gcc cho stdin tiền xử lý (được tạo ra bởi echo) và in tất cả các định nghĩa tiền xử lý (tìm kiếm -dletters). Nếu bạn muốn biết định nghĩa nào được thêm vào khi bạn bao gồm tệp tiêu đề, bạn có thể sử dụng -dDtùy chọn tương tự -dM nhưng không bao gồm các macro được xác định trước:

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

Tuy nhiên, lưu ý rằng đầu vào trống vẫn tạo ra nhiều định nghĩa với -dDtùy chọn.


6
@rubenvb nó không liên quan. điểm quan trọng là có dòng cmd hoạt động tốt như nhau trên windows và ít nhất là unix. Nếu bạn sử dụng NUL, bạn sẽ quay lại hình vuông: nó sẽ không hoạt động trên các hệ thống không có nó.
Pavel P

2
thêm câu trả lời đầy đủ cho C ++, hoạt động trên cả Windows và Linux (mặc dù sorthoạt động hơi khác nhau):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous

Điều này tạo ra đầu ra trống trong git-bash.
Lennart Rolland

@LennartRolland có gcc không? Trong git-bash của tôi, tôi không thể chạy gcc
Pavel P

@pavel Tôi sử dụng mingw32 gcc đi kèm với phân phối nhị phân Qt5 cho windows.
Lennart Rolland

3

Trong khi làm việc trong một dự án lớn có hệ thống xây dựng phức tạp và khó có thể nhận (hoặc sửa đổi) lệnh gcc / g ++, có một cách khác để xem kết quả của việc mở rộng macro. Chỉ cần xác định lại macro và bạn sẽ nhận được đầu ra tương tự như sau:

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

Tôi đang tìm kiếm những lá cờ cảnh báo được sử dụng cho nó. Bạn có biết ?
Welgriv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.