Странное разъединение между Eclipse CDT, включенными системными заголовками и базовой сборкой C - PullRequest
9 голосов
/ 01 декабря 2011

У меня странная проблема с включаемыми файлами и очевидное несоответствие между процессом сборки Eclipse и его отчетами об ошибках. Я подробно расскажу о том, как воспроизвести эту проблему, чтобы мы могли как можно быстрее сузить причины.

Eclipse 3.7.1 (Indigo SR1) для разработчиков Linux на C / C ++, Ubuntu 10.10, 64-битная

Все началось, когда я импортировал существующий проект, который сам по себе "отлично" работает: я думал, что Eclipse значительно поможет в навигации по файлам и выяснении, что и для чего. Однако некоторые системные заголовки #include d, по-видимому, не дают правильного эффекта в представлении Eclipse. Это было очень загадочно, и в ходе исследования мне удалось воссоздать проблему в крошечной песочнице.

Шаг первый: создайте новый проект C (File: New: C Project), используя образец Hello World ANSI C Project. Параметры Executable: Hello World ANSI C Project/Linux GCC, остальные Empty проекты установлены на Linux GCC, а GNU Autotools установлены на Hello World ANSI C Autotools Project. Назовите это "привет". Обязательно создайте make-файл автоматически (Расширенные настройки, я считаю, что это по умолчанию).

Шаг второй: Настройте путь включения. Используя Project: Properties: C/C++ General: Paths and Symbols: Includes: GNU C, установите путь поиска на /usr/local/include, /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include, /usr/include. Второй путь зависит от точной версии gcc, которую вы установили. Это не имеет большого значения, если путь сборки включает как минимум /usr/include.

Теперь, если вы откроете hello.c, это выглядит очень просто, и Eclipse вполне счастлив, за исключением return EXIT_SUCCESS;, который не может разрешить EXIT_SUCCESS. Замените EXIT_SUCCESS на ноль (0), и Eclipse даст все ясно. Выберите Project: Build Project, чтобы сгенерировать исполняемый файл.

Откройте окно командной строки и перейдите в подпапку hello/Debug вашей рабочей области Eclipse. Оказавшись там, вы можете запустить исполняемый файл со строкой ./hello.

Теперь начинается самое интересное. Изменить hello.c следующим образом:

#include <fcntl.h>
int main(void) {
    printf("Hello World!\n");

    int zz = SPLICE_F_MOVE;
    printf("zz (SPLICE_F_MOVE) is '%d'\n", zz);

    printf("Bye World!\n");
    return 0;
}

В строке int zz... вы получите ошибку: "Symbol 'SPLICE_F_MOVE' could not be resolved". Если вы создадите проект, вы увидите похожую ошибку в представлении консоли: "error: 'SPLICE_F_MOVE' undeclared".

Теперь, если вы измените преамбулу на:

#define _GNU_SOURCE
#include <fcntl.h>

Вы все еще получаете сообщение об ошибке в строке int zz (в редакторе), но проект будет построен правильно! Вы можете подтвердить это, запустив двоичный файл в окне командной строки, которое вы открыли ранее. Это действительно странно, так как проверка /usr/include/fcntl.h покажет, что это #include s <bits/fcntl.h>, и этот последний заголовок #define s SPLICE_F_MOVE (и множество других) в блоке, охраняемом #ifdef __USE_GNU (__USE_GNU получает #define d, если _GNU_SOURCE равно #define d). Почему на земле наше #define _GNU_SOURCE не распространяется должным образом в перспективе рабочего пространства?

Итак, это моя проблема в двух словах: почему редактор (и все Eclipse CDT) сообщает об ошибке (очевидно, отказываясь правильно обрабатывать включение), но что базовая сборка завершается успешно?

Ответы [ 3 ]

1 голос
/ 21 декабря 2013

У меня были похожие проблемы при работе с GNU и не-GNU-совместимыми наборами инструментов для кросс-компиляции различных микроконтроллеров.CDT сообщает о множестве ошибок, но фактическая сборка работает отлично, даже если все включенные заголовки правильно расположены в настройках проекта.

Проблема заключается в том, как CDT работает в отличие от вашей сборки системы.CDT является автономным лексером, парсером и препроцессором и не использует цепочку инструментов, которую вы используете для сборки.Обычно это будет работать нормально, если вы установите параметры проекта, соответствующие параметрам, сгенерированным в качестве аргументов командной строки, для ваших инструментов сборки, но многие цепочки инструментов часто включают скрытые неявные определения как часть их самого компилятора / препроцессора.В моем опыте документация для имплицитных / скрытых определений обычно отрывочна и неполна, поэтому практически невозможно определить, какие определения заданы для данной цепочки инструментов (иногда даже зависят от параметров сборки) и что они означают.Хотя может показаться, что у вас есть все правильные определения, определенные для достижения того, с чем у вас возникли проблемы, я обычно нахожу (особенно в GNU), что есть некоторые, которые вам не хватает, которые не позволяют переключателю обрабатываться так, как выожидается.

Когда я отлаживаю что-то подобное, я сначала проверяю, что сначала найдены все заголовки в каталоге моего проекта, если они имеют имена, совпадающие с именами в других каталогах, затем я медленно начинаю перемещать заголовки из стандартной папки include в мой проект.папка.CDT не очень хорошо показывает, какие возможные версии заголовочного файла он анализирует первым, и он часто извлекает настройки системной среды, когда вы меньше всего этого ожидаете, но сначала он ищет заголовки в папке вашего проекта (если у вас нетНе устанавливайте путь системных заголовков в настройках вашего проекта, чтобы иметь приоритет).Перемещая системные заголовки из местоположения, которое вы просматриваете, в каталог вашего проекта, вы точно знаете, какой заголовочный файл анализируется CDT.Кроме того, если вы перестроите свой индекс после выполнения перемещения, а затем откроете файл в Eclipse, CDT укажет, какие переключатели, по его мнению, включены или отключены путем закрашивания или свертывания ветвей, не включенных в заголовке.Следование этому процессу решало именно эту проблему для меня каждый раз, обнаруживая, когда у меня были пути к нескольким копиям одного и того же заголовка, случайно дублированные заголовки, определялись или включались при неожиданных переключателях и т. Д.

0 голосов
/ 08 июня 2012

Может быть, эта проблема исходит от самого Иджндиго. Вы пробовали то же самое с последним Indigo SR2? Я открыл несколько ошибок для Indigo и его SR1 в Eclipse Bugzilla.

0 голосов
/ 11 февраля 2012

У меня та же проблема, но я даже не сделал ничего сложного для ее создания - я просто создал проект hello world того типа, который вы описали, и получил ту же ошибку.Обратите внимание, что, однако, в моем случае это может произойти из-за сбойной установки Cygwin - например, у меня были другие ошибки, связанные с невозможностью включить файлы .h, и полное удаление / переустановкаcygwin удалил эти ошибки, но ошибка «Символ ... Не удалось устранить» остается.

Затем я решил сделать второй такой проект, и они обасообщить о такой ошибке в представлении «проблемы», но только один проектов фактически показывает подчеркнутую ошибку и т. д. в редакторе (!)

...