Создание списка всех символов препроцессора, определенных в заголовках
Скажем, я использую некоторую библиотеку C или С++, созданную из заголовков и некоторых исходных файлов, которые скомпилированы в статическую или общую библиотеку, с которой я могу связать.
В заголовках библиотеки (десятки... или сотни файлов) определены некоторые макросы/символы.
Теперь я хочу использовать эту библиотеку в проекте, который также определяет некоторые макросы и символы. Конечно, я хочу избежать столкновений имен,
как это сообщалось иногда, особенно с windows.h. Но в целом я хочу сохранить контроль над тем, что действительно экспортируется из этого заголовка.
Я могу создать список определенных символов с опциями препроцессора gcc:
gcc -E -dM include/great_lib.h | sort -V >symbols.txt
Это выводит в файле symbol.txt отсортированный список всех определенных символов, включенных в файл пользователя, когда он включает этот заголовок.
Однако он дает только символ не файл, в котором он был определен.
У меня такое ощущение, что это может быть полезной информацией. Например, чтобы проверить, переопределен ли какой-либо системный макрос в "great_lib.h" или его потомках.
Несчастье, после проверки опций препроцессора gcc, я не вижу способа сделать это с помощью gcc.
Например, вместо того, чтобы указывать только мне:
#define M_PI 3.14159265358979323846
он произведет
#define M_PI 3.14159265358979323846; /usr/include/math.h
Возможно, что-то с опцией -dN? Но его вывод запутан для меня, он требует дальнейшей обработки текста, и я не понимаю, как информация накладывается.
Или более простой способ?
Похожие вопросы:
Ответы
Ответ 1
Опция -dD выводит предварительно обработанный источник вместе с макросами. Сюда входят строки, указывающие текущий исходный файл, например
# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.5.2/../../../../include/_mingw.h" 1 3
Вы можете написать небольшую программу, которая (i) отслеживает текущий исходный файл, анализируя эти строки; (ii) выводит все строки, начинающиеся с #define
(и \t# define
и т.д.), за которым следует текущее имя исходного файла; (iii) отбрасывает все другие строки (исходный код, декларации и т.д.).
Ответ 2
Быстрый способ unix:
find "$PATH_TO_LIB" -name "*.h" | xargs grep "^[ \t]*#[ \t]*define"
Затем вы можете использовать sed и sort, чтобы немного почистить форматирование.
Кроме того, согласно руководству gcc, gcc предупредит вас об этом.
http://gcc.gnu.org/onlinedocs/cpp/Undefining-and-Redefining-Macros.html
Если макрос переопределяется с определением, которое не так же, как и предыдущее, препроцессор выдает предупреждение и изменяет макрос, чтобы использовать новое определение. Если новое определение фактически одинаково, переопределение тихо игнорируется. Это позволяет, например, двум различным заголовкам определять общий макрос. Препроцессор будет жаловаться только в том случае, если определения не совпадают.
Ответ 3
Не изобретайте колесо, неуклюже. Все, что gcc -dM дает вам квадратное колесо: -)
Любая программа ctags
(для vi) или etags
(для emacs) будет извлекать эту информацию (какой идентификатор определен/объявлен в каком файле). В качестве бонуса вы получите его в форме, которая непосредственно понимается редакторами, позволяя вам поместить курсор на идентификатор, а затем перейти к его объявлению/определению.
Используйте инструменты в панели инструментов, используйте философию Unix, чтобы один инструмент хорошо справился.