我有兩個C語言文件:foo.c
和bar.h
(可能還有許多其他文件)。我想要一個在foo.c
中使用並在bar.h
中定義的所有預處理器宏的列表。如何確定foo.c中的哪些預處理器宏源自bar.h?
或者,如果那是太難了,甚至它同時出現在foo.c
和bar.h
所有預處理宏(但不任何標識,單詞或一段文字)的列表。
我該如何獲得?
我有兩個C語言文件:foo.c
和bar.h
(可能還有許多其他文件)。我想要一個在foo.c
中使用並在bar.h
中定義的所有預處理器宏的列表。如何確定foo.c中的哪些預處理器宏源自bar.h?
或者,如果那是太難了,甚至它同時出現在foo.c
和bar.h
所有預處理宏(但不任何標識,單詞或一段文字)的列表。
我該如何獲得?
您可以從gcc的預處理選項的輸出中拼湊這些信息。
爲了得到實際使用的文件,你可以使用-E -dU
選項,預處理文件宏的列表,也包括在任何宏的第一使用#define
命令。 (它也產生#undef
命令與#ifdef
或#if defined(...)
測試未定義的名字。)(必須使用-E
選項 - 僅預處理 - 爲-dU
要妥善處理。)
由於-dU
不抑制預處理輸出,您只需查看#define
指令就可以對其進行過濾。對於某些應用程序,您可能還希望通過僅查看相關文件中實際使用的用途來進一步對其進行過濾,因爲報告還包括通過包含文件使用宏。但是在這種情況下,與頭文件中實際定義的宏的交集可能就足夠了。
所以習慣宏的列表中file.c
:
gcc -E -dU file.c | grep -Eo '^#define [_A-Za-z][_A-Za-z0-9]*'
(grep的-Eo
刪除宏定義。)
可以近似的頭實際上被定義宏的列表文件中使用稍微大方grep
調用,這樣的事情:
grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' header.h
這將拿起宏DEFI即使條件失敗,也會在條件部分中進行劃分,並且會在註釋中看到類似#define
指令的行。通常,這些都不會造成很多問題。
您可以使用gcc的-E -dM
或-E -dD
選項來獲取標題中所有定義的列表,但這兩個選項都會插入由標題包含的標題定義的宏。 (-dM
也包含預定義的宏。)因此,除非您對由於包含頭文件而定義的所有宏感興趣,否則您確實需要做更多工作來專注於頭文件實際定義的宏。
然後你只需要找到兩個列表的交集。一種方法是單獨提取宏名稱(awk '{print $2}'
),sort -u
兩個列表,然後合併它們,最後通過uniq -d
傳遞它們,只查看兩個列表中的條目。 (以下兩個限定殼功能used_and_defined
你會調用used_and_defined foo.c bar.h
)
used() {
gcc -E -dU "$1" |
grep -Eo '^#define [_A-Za-z][_A-Za-z0-9]*' |
cut -f2 -d' ' |
sort -u
}
defined() {
grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' "$1" |
awk '{ print $2 }' |
sort -u
}
used_and_defined() {
cat <(used "$1") <(defined "$2") | sort | uniq -d
}
或者你可以完成整個操作與awk
used_and_defined() {
awk '/^[[:space:]]*#[[:space:]]*define/ {
gsub(/[ (].*/, "", $2);
if (NR == FNR) ++macros[$2];
else if (macros[$2]) print $2;
}' \
<(grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' "$2") \
<(gcc -E -dU "$1")
}
一種策略(誠然笨重)可以是:
的foreach宏標識符SOME_MACRO在bar.h
,運行
gcc -E -DSOME_MACRO=recognizable_value foo.c | grep recognizable_value
即預處理源和檢測是否發生了膨脹。請注意,這對於僅在#if
指令等中使用的宏不起作用。
一個gcc
特異性(但clang
有相同的選項相同的語義)是使用-dD
除了-E
:
gcc -E -dD -o foo.i [other options] foo.c
將在輸出中保留#define
行,以及# nnn "/path/to/file.h"
指令,以便您應該能夠確定哪個宏屬於哪個文件。如果你想提取來自bar.h
的宏,根據你期望在bar.h
中找到的宏的數量,你最喜歡的編輯器的搜索命令可能就足夠了,或者一個小的awk/perl/python/...腳本會幫幫我。
我不認爲這有一個普遍的答案,回答這種問題很難,這是一個好的主意,因爲它是一個好主意(例如'BAR_BLAH()'以表明BLAH )'宏來自'bar.h')。您可以嘗試刪除'#include「bar.h」'並查看是否有未定義的引用錯誤。 – unwind
@unwind:如果我控制了名字,我可能沒有這個問題......這不是我自己的代碼。 – einpoklum
gcc特定的技術是否可以接受? – rici