6 Stimmen

g++ schlägt auf mysteriöse Weise nur fehl, wenn sich eine .h in einem bestimmten Verzeichnis befindet

Ich bin ein extrem seltsames Problem in einem frischen OSX 10.4.11 + Xcode 2.5 Installation erleben. Ich habe es auf einen minimalen Testfall reduziert. Hier ist test.cpp:

#include "macros.h"

int main (void)
{
    return 1;
}

Und hier ist 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__

Dies kompiliert und funktioniert einwandfrei, wenn sich beide Dateien im selben Verzeichnis befinden. JEDOCH, wenn ich macros.h in /usr/include/gfc2 ablege (es ist Teil einer benutzerdefinierten Bibliothek, die ich verwende) und das #include in test.cpp ändere, schlägt die Kompilierung mit diesem Fehler fehl:

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

Ich habe diesen Fehler recherchiert und die meisten Kommentare deuten auf ein "dangling extern C" hin, was überhaupt nicht der Fall zu sein scheint.

Ich bin hier völlig ratlos. Nimmt g++ aus irgendeinem Grund an, dass alles in /usr/include/gfc2 C ist, obwohl es in einer .cpp-Datei enthalten ist, in der nirgends extern "C" steht?

Irgendwelche Ideen?

EDIT : Es wird kompiliert, wenn ich den vollständigen Pfad in der #include , d.h. #include "/usr/include/gfc2/macros.h"

EDIT2 : Es ist nicht die falsche Kopfzeile enthalten. Ich habe dies überprüft mit cpp , g++ -E und Umbenennung macros.h a foobarmacros.h

7voto

John Marshall Punkte 6615

G++ könnte in der Tat davon ausgehen, dass alles in /usr/include C ist. Versuchen Sie, Ihren Code mit -E zu kompilieren und die Zeilenmarkierungen in der Präprozessorausgabe zu studieren:

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

Sie werden wahrscheinlich Dinge sehen wie

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

Le site 4 ist der Präprozessor, der G++ darauf hinweist, dass es alles in extern "C" auf der Annahme, dass die alten Header-Dateien Ihrer Plattform in /usr/include aus der Zeit vor C++ stammen. Siehe Ausgabe des Präprozessors im CPP-Handbuch.

Heutzutage ignoriert G++ diesen Hinweis meist, da die C-Header der meisten Plattformen nicht mehr alt sind. Siehe die NO_IMPLICIT_EXTERN_C Zielmakro im GCC Internals Handbuch. Aber es kann sein, dass in dieser alten Version von Xcode GCC ohne NO_IMPLICIT_EXTERN_C und somit es auf den Hinweis des Präprozessors hören. (Dieser wird gesetzt, wenn GCC selbst gebaut wird - ich glaube nicht, dass es einen Kommandozeilenschalter gibt, um ihn zu überschreiben).

Möglicherweise können Sie dies umgehen, indem Sie den Inhalt Ihrer Header-Datei in extern "C++" .

1voto

bk1e Punkte 23191

Es ist ein Schuss ins Blaue, aber gibt es eine weitere Datei mit dem Namen macros.h irgendwo unter /usr/include oder in Ihrer GCC-Installation? GCC verfügt über eine Funktion zum Einbinden von Headern, genannt #include_next was die Ursache für Ihr Problem sein könnte.

Eine Sache, die Sie tun können, um Ihre Daten zu disambiguieren macros.h von jedem anderen macros.h in den Include-Pfad einfügen, ist es als gfc2/macros.h . Auf diese Weise durchsucht der Compiler jedes Verzeichnis im Include-Pfad nach einem Unterverzeichnis namens gfc2 mit einer Datei namens macros.h Dadurch wird die Gefahr eines Zusammenstoßes verringert. Es verhindert auch, dass Sie zusätzliche /usr/include/gfc2 in den Include-Pfad aufnehmen.

ÜBRIGENS, #include "file.h" durchsucht zuerst das aktuelle Verzeichnis. Um dies zu überspringen und direkt zum Include-Pfad zu gehen, verwenden Sie #include <file.h> :

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

Eine andere Möglichkeit besteht darin, einen Dateinamen zu wählen, der mit größerer Wahrscheinlichkeit eindeutig ist, z. B. gfc2macros.h .

0voto

neverlord Punkte 868

Nun, es sieht wirklich seltsam aus...

Wie ruft XCode g++ auf? Ich glaube nicht, dass g++ spontan entscheidet, dass eine Include-Datei C-Linkage hat, nur weil sie in einem anderen Verzeichnis liegt. Haben Sie versucht, Ihr Projekt von Hand zu kompilieren? Versuchen Sie "g++ main.cpp -I/usr/include/gfc2/". Wenn dies Ihr Problem löst, dann liegt es nicht an g++. Vielleicht kompiliert XCode die Header vor?

0voto

Haben Sie versucht, nicht die Datei test.cpp überhaupt ändern, aber stattdessen, wenn Sie kompilieren auch sagen:

-I/usr/include/gfc2/

0voto

remcycles Punkte 858

Sie können mit dem Verbose-Flag sehen, wo g++ nach Includes sucht:

g++ -v -o test test.cpp

Dies führt den Präprozessor aus und zeigt, was tatsächlich in der Datei enthalten und kompiliert ist:

g++ -E test.cpp | less

Wenn die falschen Dateien eingebunden werden (oder Ihr Header in einen anderen eingewickelt wird, wie bk1e vorschlägt), können Sie das anhand dieser Ausgabe herausfinden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X