g ++ перестал работать загадочно, только если.h находится в определенном каталоге

Я испытываю чрезвычайно странную проблему в новом OSX 10.4.11 + установка Xcode 2.5. Я уменьшил его до минимального тестового сценария. Вот test.cpp:

#include "macros.h"

int main (void)
{
    return 1;
}

И вот macros.h:

#ifndef __JUST_TESTING__
#define __JUST_TESTING__

template<typename T> void swap (T& pT1, T& pT2)
{
    T pTmp = pT1;
    pT1 = pT2;
    pT2 = pTmp;
}

#endif //__JUST_TESTING__

Это компилирует и работает просто великолепно, если оба файла находятся в том же каталоге. ОДНАКО, если я поместил macros.h в/usr/include/gfc2 (это - часть пользовательской библиотеки, которой я пользуюсь), и измените #include в test.cpp, сбоях компиляции с этой ошибкой:

/usr/include/gfc2/macros.h:4: error: template with C linkage

Я исследовал ту ошибку, и большинство комментариев указывает "повисшему экстерну C", который, кажется, не имеет место вообще.

Я в полной растерянности здесь. G ++ по некоторым причинам принятие всего в /usr/include/gfc2 C то, даже при том, что он включен из .cpp файла, который не говорит что экстерн "C" где-нибудь?

Какие-либо идеи?

РЕДАКТИРОВАНИЕ: Это действительно компилирует, если я использую полный путь в #include, т.е. #include "/usr/include/gfc2/macros.h"

EDIT2: это не включает неправильный заголовок. Я проверил это использование cpp, g++ -E, и переименование macros.h кому: foobarmacros.h

6
задан George Stocker 24 May 2010 в 12:39
поделиться

6 ответов

G ++ действительно может предполагать, что все в / usr / include написано на C.Попробуйте скомпилировать свой код с -E и изучить маркеры строк в выходных данных препроцессора:

g++ -E test.cpp | grep '^#'

Вы, вероятно, увидите такие вещи, как

# 1 "/usr/include/gfc2/macros.h" 1 3 4

4 - это препроцессор, намекающий G ++, что он должен обернуть все extern "C" , исходя из предположения, что древние файлы заголовков вашей платформы в / usr / включают предшествующие C ++. См. Выход препроцессора в руководстве по CPP.

В наши дни G ++ в основном игнорирует эту подсказку, потому что заголовки C для большинства платформ уже устарели. См. Целевой макрос NO_IMPLICIT_EXTERN_C в руководстве GCC Internals. Но может случиться так, что в этой старой версии Xcode настроен GCC без NO_IMPLICIT_EXTERN_C и, таким образом, слушает подсказку препроцессора. (Это устанавливается при сборке самого GCC - я не думаю, что есть переключатель командной строки, чтобы переопределить его.)

Вы можете обойти это, заключив содержимое файла заголовка в extern "C ++" .

7
ответ дан 16 December 2019 в 21:38
поделиться

Да, у меня была аналогичная проблема. Jboss не мог начать с Eclipse Galileo в течение 50 секунд по умолчанию поэтому просто изменило время запуска сервера, дважды щелкнув значок Jboss server в окне Server рядом с консолью и журналом ошибок (НЕ в окнах - > preferences- > сервер). Он открывает редактор сервера, а затем увеличивает время запуска до 300 Тогда это сработало.!!!

-121--1442970-

Вероятно, следует использовать UserType или UserColliceType. Или можно использовать пользовательский тюплейзер.

см. основную документацию по гибернации для концепций и документацию по гибернации для эквивалентного подхода к аннотациям.

Дайте мне знать, если это не то, о чем вы просите.

-121--2536122-

Ну, это действительно выглядит странно...

Как XCode вызывает g++? Я не думаю, что g++ спонтанно решает, что файл включения имеет связь С только потому, что он находится в другом каталоге. Вы пытались составить свой проект вручную? Попробуйте "g++ main.cpp" -I/usr/include/gfc2/. Если это решает вашу проблему, чем это не g++. Может быть, XCode выполняет предварительную компиляцию заголовков?

0
ответ дан 16 December 2019 в 21:38
поделиться

Это выстрел в темноте, но есть ли другой файл с именем macros.h где-нибудь под / usr / include или в вашей установке GCC? GCC имеет средство для упаковки заголовков, называемое #include_next , которое может быть причиной вашей проблемы.

Единственное, что вы можете сделать, чтобы отделить ваш macros.h от любого другого macros.h в пути включения, - это включить его как gfc2 / macros.h . Таким образом, компилятор будет искать в каждом каталоге пути включения подкаталог с именем gfc2 , содержащий файл с именем макросов.h , уменьшая вероятность столкновения. Это также избавляет вас от необходимости добавлять / usr / include / gfc2 в путь включения.

Кстати, #include "file.h" сначала выполняет поиск в текущем каталоге. Чтобы пропустить это и сразу перейти к пути включения, используйте #include :

#include <stdio.h>
#include <gfc2/macros.h>

Другой подход - выбрать имя файла, которое с большей вероятностью будет уникальным, например gfc2macros. h .

1
ответ дан 16 December 2019 в 21:38
поделиться

Вы можете увидеть, где g ++ ищет включения, с помощью подробного флага:

g++ -v -o test test.cpp

И это просто запустит препроцессор и покажет, что фактически включено в файл и скомпилирован:

g++ -E test.cpp | less

Если включаются не те файлы (или ваш заголовок заворачивается в другой, как предлагает bk1e), вы сможете выяснить это с помощью этого вывода.

0
ответ дан 16 December 2019 в 21:38
поделиться

Вы пробовали вообще не изменять файл test.cpp, но вместо этого при компиляции также говорите:

-I/usr/include/gfc2/
0
ответ дан 16 December 2019 в 21:38
поделиться

I просто столкнулся с этой проблемой при компиляции проекта C ++, который мы обычно строим на 10.5 и 10.6 (Xcode 3.0+) на машине 10.4 PPC с установленным Xcode 2.5. Похоже, что препроцессор обрабатывает все, что добавлено в путь включения gcc, с помощью '-isystem', как будто это должно быть «extern C». Замена -isystem на -I решила проблему.

0
ответ дан 16 December 2019 в 21:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: