Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library
-
Hallo,
ich bin gerade am üben mit einer shared library. Ich habe es hinbekommen, das die Bibltiohek geladen wird und auch funktioniert. Jetzt ist es aber so das ich von den includes Dateien in dem Hauptprogramm eine Klasse Node gibt, die von der Bibliothek kommt:includes/Node.h
class Node { public: bool isCDATA = false; bool isRoot = false; Node* parent; std::vector<Node*> children; std::string id; std::string name; std::string content; std::unordered_map<std::string,std::string> attributes; Node() = default; virtual std::string toXML(); virtual void toString(); virtual void destroy(); };
lib/Node.h
class Node { public: bool isCDATA = false; bool isRoot = false; Node* parent; std::vector<Node*> children; std::string id; std::string name; std::string content; std::unordered_map<std::string,std::string> attributes; virtual std::string toXML(); virtual void toString(); virtual void destroy(); Node() = default; };
Ich konnte bei den anderen Methoden durch das virtual flag sagen das von der Bibliothek geladen wird aber beim Konstruktor kann ich kein virtual setzen.
Ich habe es probiert mit dem Node() = default weil ich es dann definiert sein sollte. Der Fehler der dann aber kommt ist folgender:[1/1] Linking CXX executable xmlparserrunner FAILED: xmlparserrunner : && /Library/Developer/CommandLineTools/usr/bin/c++ -g -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX15.1.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/opt/homebrew/opt/sqlite/lib CMakeFiles/xmlparserrunner.dir/main.cpp.o -o xmlparserrunner && : Undefined symbols for architecture arm64: "vtable for Node", referenced from: Node::Node() in main.cpp.o NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
Nach der Fehlermeldung her müsste ja eine definition ausreichen des Konstruktors aber das hat nicht geholfen. Das Repository zu dem ganzen Projekt ist: https://github.com/hendrik-weiler/xmlparser-cpp
Das Hauptprogramm besteht aus folgenden Dateien:
CMakeLists.txt
cmake_minimum_required(VERSION 3.30) project(xmlparserrunner) set(CMAKE_CXX_STANDARD 20) include_directories(/Volumes/Expansion/xmlparser-cpp/includes) add_executable(xmlparserrunner main.cpp)
main.cpp
#include <iostream> #include "XMLParser.h" #include "XMLParserLoader.h" int main() { // Load the dynamic library XMLParserLoader loader("/Volumes/Expansion/xmlparser-cpp/cmake-build-debug/libxmlparser.dylib"); XMLParser* myClassInstance = loader.create(); myClassInstance->parse(R"( <?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:f="http://xmlns.jcp.org/jsf/core"> <f:view> <h:outputLabel value="Hello, world"/> </f:view> </html> )"); std::vector<Node*> myClassInstanceElements = myClassInstance->getElementsByName("html"); for (Node* node : myClassInstanceElements) { //std::cout << "Node: " << node->name << std::endl; node->attributes["id"] = "test"; Node* child = new Node(); child->name = "child"; node->children.push_back(child); std::cout << node->toXML() << std::endl; } //std::cout << myClassInstance->toXML() << std::endl; std::string version = myClassInstance->getDeclarationAttribute("xml", "version"); std::string encoding = myClassInstance->getDeclarationAttribute("xml", "encoding"); std::cout << "Version: " << version << std::endl; std::cout << "Encoding: " << encoding << std::endl; loader.destroy(myClassInstance); return 0; }
Hat jemand eine Idee was getan werden muss, damit die Klasse Node instanziiert werden kann?
-
Warum hast du jeweils 2 verschiedene Headerdateien für
Parser
undNode
(in "include" und "lib")?
Du solltest nur auf die Header in "lib" zugreifen (welche auch die Shared Library zum Kompilieren benutzt) bzw. die Shared Library sollte dafür extra einen eigenen (Unter-)Ordner bereitstellen, den dann auch das Hauptprojekt benutzt.Dann wäre auch
Node() = default;
im Hauptprojekt bekannt.
-
@hendrik-weiler Du linkst beim Bauen nicht mit der Bibliothek, sondern lädst diese zur Laufzeit via
dlopen
et al. Ich denke hier liegt der Hase im Pfeffer. Falls du das wirklich so machen willst, müsstest du die VTables ebenfalls zur Verfügung stellen. Das hieße wahrscheinlich, dem Linker beim Kompilieren ein Symbol mit einem compiler-spezifischen, dekorierten Namen für den VTable der Klasse zur Verfügung zu stellen, an dessen Adresse dann nach dem Laden der Bibliothek die VTable-Daten zu finden sein werden (mit Name Mangling, für die KlasseNode
und GCC/Clang ist das dann sowas wie_ZTVNode
oder so ähnlich, in deinem Fall vermutlichvtable for node
, wenn das tatsächlich der Symbolname ist) .Das dürfte zwar gehen, aber es ist ziemlich fummelig und auch nicht sonderlich flexibel: Wie Dynamic Dispatch (virtuelle Member-Funktionen) implementiert ist, ist compiler-spezifisch, genau wie die Namen dieser zusätzlichen Symbole, auf die der Compiler Referenzen erzeugt, wenn er deine
main.cpp
kompiliert.Zum Üben kann man sich da schon mal dran wagen, ansonsten würde ich aber eher empfehlen, direkt gegen die Shared Library zu linken und auf den
XMLParserLoader
zu verzichten. Dann sollten Compiler und Linker eigentlich alles richtig "verdrahten" und das Laden der Library übernimmt dann der dynamische Loader des Betriebssystems. C++ und Shared Libraries sind eh so ne Sache: Wenn man sich da nicht auf ein simples C-Interface beschränkt, sondern auch C++-Objekte hin- und her reicht, funktioniert das meist nur, wenn Bibliothek und Executable mit dem selben Compiler gebaut wurden - nicht selten müssen sogar die Compiler-Flags im wesentlichen übereinstimmen. Gründe sind neben Name Mangling auch unterschiedliche Implementierungen und Layouts verschiedener Standardbibliothek-Objekte.
-
@Th69 sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
Warum hast du jeweils 2 verschiedene Headerdateien für
Parser
undNode
(in "include" und "lib")?
Du solltest nur auf die Header in "lib" zugreifen (welche auch die Shared Library zum Kompilieren benutzt) bzw. die Shared Library sollte dafür extra einen eigenen (Unter-)Ordner bereitstellen, den dann auch das Hauptprojekt benutzt.Dann wäre auch
Node() = default;
im Hauptprojekt bekannt.Das könnte eventuell auch funktionieren, wenn man den Compiler dazu bringen kann, den VTable im Hauptprogramm zu erzeugen. Derzeit sollte der ja in der Shared Library sein, wird aber beim Kompilieren nicht bekannt gemacht und der Table wird auch nicht mit geladen, wenn ich das richtig sehe.
-
Ich habe es jetzt so versucht wie Th69 es vorgeschlagen hat. Ich habe die Dateien so geordnet, das nurnoch eine Datei eine existiert. https://github.com/hendrik-weiler/xmlparser-cpp/tree/main/lib/includes (Ich habe auch neu comittet auf github)
Aber wenn ich versuche das Hauptprogramm wieder zu starten kommt wieder der gleiche Fehler:: && /Library/Developer/CommandLineTools/usr/bin/c++ -g -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX15.1.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/opt/homebrew/opt/sqlite/lib CMakeFiles/xmlparserrunner.dir/main.cpp.o -o xmlparserrunner && : Undefined symbols for architecture arm64: "vtable for Node", referenced from: Node::Node() in main.cpp.o NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
Nach copilot sollte der Name des symbols einzigartig sein und man solle es mit namespaces probieren, damit es einzigartig ist. Ich habe jetzt eine Namespace um die Klassen hinzugefügt. Das Resultat ist aber gleich geblieben.
-
@hendrik-weiler sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
Ich habe es jetzt so versucht wie Th69 es vorgeschlagen hat. Ich habe die Dateien so geordnet, das nurnoch eine Datei eine existiert. https://github.com/hendrik-weiler/xmlparser-cpp/tree/main/lib/includes (Ich habe auch neu comittet auf github)
Aber wenn ich versuche das Hauptprogramm wieder zu starten kommt wieder der gleiche Fehler:Ich bin mir auch nicht sicher, ob es tatsächlich hilft, wenn man einen beim Kompilieren der
main.cpp
erzeugten VTable nutzt. Schließlich muss dieser die Adressen der in der Bibliothek liegenden Implementationen der virtuellen Funktionen enthalten, damit die Klasse ordentlich funktionieren kann (die Funktionen inNode.cpp
). Diese kennt der Compiler aber nicht, wenn er diemain.cpp
baut, da du die Bibliothek erst zur Laufzeit lädst.Die simplen Lösungen sind vermutlich entweder direkt gegen die Bibliothek zu linken (also ohne
dlopen
/LoadLibrary
), oder die virtuellen Funktioneninline
zu deklarieren und ebenfalls im Header unterzubringen.Beim Laden der Bibliothek zur Laufzeit befürchte ich, dass es an dir liegt, dem Compiler/Linker den VTable zur Verfügung zu stellen, während die
main.cpp
gebaut wird, und diesen dann auch noch mit den korrekten Daten zu füllen. Das könnte sogar auch noch solche Details wie Relokationen beinhalten, wenn die Bibliothek an beliebige Speicheradressen geladen werden kann und somit auch die Adressen der virtuellen Funktionen erst zur Laufzeit bekannt sind.Nach copilot sollte der Name des symbols einzigartig sein und man solle es mit namespaces probieren, damit es einzigartig ist. Ich habe jetzt eine Namespace um die Klassen hinzugefügt. Das Resultat ist aber gleich geblieben.
Also manchmal verzapfen KIs nen ganz schönen Blech. Klar darf es bei Symbol-Namen keine Kollisionen geben, aber dein Problem ist ja nicht, dass du zu viele Symbole mit dem Namen hast, sondern gar keins
-
Ok ich habe es jetzt versucht mit static linking und so funktioniert es.
Danke für die Hilfe.
-
@hendrik-weiler sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
Ok ich habe es jetzt versucht mit static linking und so funktioniert es.
Danke für die Hilfe.Es muss nicht gleich static linking sein. Gegen die
.so
/.dylib
/.dll
linken sollte reichen (falls du das nicht eh damit meinst).BTW: Ich hab die Problematik nochmal etwas recherchiert und die übliche Lösung scheint zu sein, die Klassen-Instanz nicht im Client der Shared Library zu erzeugen (
main.cpp
, Zeile29
), sondern in der Bibliothek selbst über eine Factory-Funktion. Das Problem tritt ja beim Aufruf des Konstruktors auf, wenn der Compiler eine (unsichtbare) Referenz auf den VTable erzeugt. Polymorphe Objekte (mitvirtual
-Funktionen) haben ja einen versteckten Pointer auf diesen. Innerhalb der Library ist der VTable ja bekannt, da Teil des Objektcodes, außerhalb müsste der anderweitig zur Verfügung gestellt werden - zumindest wenn man die mitdlopen
/LoadLibrary
etc lädt.
-
Wenn ich es linke mit
target_include_directories(xmlparserrunner PRIVATE /Volumes/Expansion/xmlparser-cpp/lib/includes) target_link_libraries(xmlparserrunner PRIVATE /Volumes/Expansion/xmlparser-cpp/cmake-build-debug/libxmlparser.dylib)
Bekomme ich diese Fehler:
Undefined symbols for architecture arm64: "vtable for Node", referenced from: Node::Node() in main.cpp.o NOTE: a missing vtable usually means the first non-inline virtual member function has no definition. "vtable for XMLParser", referenced from: XMLParser::XMLParser() in main.cpp.o NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
Mit static linking linke ich mit target_link_libraries eine .a Datei und damit geht es.
Ich habe es jetzt auch probiert mit einer Factory-Funktion für die Node Klasse. Das hat funktioniert https://github.com/hendrik-weiler/xmlparser-cpp/commit/f5ab976bdfda68d76ecfe831e6c8e31654020af6
-
@hendrik-weiler sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
Wenn ich es linke mit
target_include_directories(xmlparserrunner PRIVATE /Volumes/Expansion/xmlparser-cpp/lib/includes) target_link_libraries(xmlparserrunner PRIVATE /Volumes/Expansion/xmlparser-cpp/cmake-build-debug/libxmlparser.dylib)
Bekomme ich diese Fehler:
Das ist merkwürdig. Ich hätte erwartet, dass das genau so klappt wie mit der statischen
.a
-Library. Hier sollte sich der Linker eigentlich den VTable aus der.dylib
holen, wo er ja offensichtlich existiert, wenn ...Ich habe es jetzt auch probiert mit einer Factory-Funktion für die Node Klasse. Das hat funktioniert https://github.com/hendrik-weiler/xmlparser-cpp/commit/f5ab976bdfda68d76ecfe831e6c8e31654020af6
... DAS funktioniert. Als würde der nicht exportiert.
Ich muss aber auch zugeben, dass ich in C++ nur wenig mit dynamischen Bibliotheken mache. Die Projekte, mit denen ich zu tun habe sind meistens statisch gelinkt. Und wenn nicht, dann sind es fast nur C-Bibliotheken.
Ich bin mir auch nicht ganz sicher, ob man auf MacOS auch gegen die dynamische Bibliothek selbst linkt. Unter Windows mit den DLLs muss man z.B. gegen eine Importbibliothek (
.lib
oder.a
) für die DLL linken. Das ist aber so wie du es hier machst z.B. unter Linux mit den.so
-Bibliotheken üblich, daher vermute ich, dass das so in Ordnung ist. Ansonsten gäbe es auch sicher eine andere Fehlermeldung.NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
Wenn du experimentierfreudig bist, kannst du auch noch was ganz doofes probieren: Statt den virtuellen Destruktor
default
zu machen, probier's mal mit einem expliziten leeren Destruktor in derNode.cpp
. Ich erinnere mich vage an ein ähnlich gelagertes Problem und ich meine, das war eine Sache, die wir probiert hatten. Ich weiß aber nicht mehr, ob das wirklich die Lösung war.Edit: Ich seh grad
Node
hat als Basisklasse keinen virtuellen Destruktor. Gib der mal einen, auch wenn es nur ein Default-Destruktor ist. Sonst passieren komische Sachen - normalerweise aber nicht beim Linken sondern eher wenn man eindelete
einer abgeleiteten Klasse über einen Basisklassen-Pointer macht.
-
@hendrik-weiler Ich habe gerade nur kurz auf dem Smartphone geschaut, aber soweit ich das sehe exportiert deine Bibliothek die Symbole einfach nicht.
Unter Windows gibt es dafür
__declspec(dllexport)
. Unter Linux gibt es soweit ich weiß__attribute__((visibility("default")))
.
Normalerweise definiert man sich ein Makro dafür, das, je nach dem ob die Library kompiliert wird oder inkludiert wird, das entsprechende Export Flag gesetzt wird.Wenn du in der Suchmaschine deiner Wahl nach "Export symbols of shared c++ library" suchst, solltest du dazu jede Menge finden.
-
@Schlangenmensch sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
@hendrik-weiler Ich habe gerade nur kurz auf dem Smartphone geschaut, aber soweit ich das sehe exportiert deine Bibliothek die Symbole einfach nicht.
Ich würde davon ausgehen, dass Symbole sehr wohl exportiert werden, da sonst der Fehler z.B. auch bei der Konstruktor-Funktion auftreten würde. Es fehlt der VTable, und den kann man ohne Tricksereien sowieso nicht explizit exportieren.
-
@Finnegan Bei den im GitHub eingecheckten Branches wird aus Node nichts exportiert. Und im ersten Beitrag stehenden Code auch nicht. Kann natürlich sein, dass der Export beim Pasten verloren gegangen ist und ins GitHub nicht gepusht wurde, weil es nicht funktioniert, aber der eine Branche heißt extra "Shared Library".
Der XMLParser wird unter Windows exportiert, aber der dazugehörige Import fehlt. Und für andere Systeme ist das EXPORT Macro leer.
Daher ist da, zumindest was den eingecheckten Code betrifft, was im Argen. Ob das ursächlich für den Fehler ist, weiß ich nicht.
-
@Schlangenmensch sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
Unter Linux gibt es soweit ich weiß
__attribute__((visibility("default")))
.Das heißt "default", weil es auch gemacht wird, wenn nix da steht (sofern nicht via Compiler-Flag der Default anders eingestellt wurde). Ich weiß zwar nicht, wie es unter MacOS ist, würde mich aber nur wenig wundern, wenn dort auch alles exportiert wird sofern man es nicht explizit unterbindet. Würde tatsächlich gar nichts exportiert, gäbe es nicht nur beim VTable "Undefinded symbols".
-
Ich habe es jetzt getestet indem ich der Klasse Node das Export Macro hinzugefügt habe:
#define EXPORT __attribute__((visibility("default")))
und so konnte ich auch ohne Factory-Funktion eine neue Instanz erzeugen.
Edit: Ich habe es jetzt noch auf Ubuntu und Windows 11 getestet. Auf Ubuntu kommt folgender Fehler:
xmlparser-runner.cpp:(.text._ZN4NodeC2Ev[_ZN4NodeC5Ev]+0xc): undefined reference to `vtable for Node' /usr/bin/ld: xmlparser-runner.cpp:(.text._ZN4NodeC2Ev[_ZN4NodeC5Ev]+0x10): undefined reference to `vtable for Node'
In windows 11:
\Programs\CLion\bin\mingw\bin/ld.exe: CMakeFiles/xmlparser_runner.dir/main.cpp.obj:main.cpp:(.rdata$.refptr._ZTV4Node[.refptr._ZTV4Node]+0x0): undefined reference to `vtable for Node'
Die Factory Methode ging aber auf allen Systemen.
-
@hendrik-weiler sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
Ich habe es jetzt getestet indem ich der Klasse Node das Export Macro hinzugefügt habe:
#define EXPORT attribute((visibility("default")))und so konnte ich auch ohne Factory-Funktion eine neue Instanz erzeugen.
Wenn das zutrifft, dann nehme ich zurück, was ich in meiner Antwort an @Schlangenmensch geschrieben habe, bin dann aber ganz schön verwirrt. Eigentlich hatte ich ja mental abgespeichert, dass unter unixoiden Systemen grundsätzlich erstmal alle Symbole exportiert werden und man das mit
__attribute__((visibility("hidden")))
selektiv unterbindet - es sei denn man gibt dem Compiler den-fvisibility=hidden
-Parameter mit, dann wird standardmäßig nichts exportiert (vielleicht wird das ja irgendwo gemacht?). Auch frage ich mich, weshalb z.B. dernode->toXML()
-Aufruf inmain.cpp
kein "Undefined symbol" erzeugt, wenn die Klasse explizit exportiert werden muss. Diese Member-Funktion liegt ja in der Bibliothek, wenn ich das richtig sehe. Seltsam.Die Factory Methode ging aber auf allen Systemen.
Das wäre meine Wahl für eine Shared Library: Erstellen und Zerstören der Objekte in Bibliotheks-Funktionen. Immerhin gibt es auch Systeme/Setups, wo die Shared Libraries einen eigenen Heap haben können, da ist es besser wenn das alles über die Lib läuft. Ein
delete
oderfree
auf einen Speicherbereich aus dem falschen Heap wird kein Happy End haben
-
@Finnegan sagte in Undefined symbols vtable for Node Node::Node() in main.cpp.o bei shared library:
Wenn das zutrifft, dann nehme ich zurück, was ich in meiner Antwort an @Schlangenmensch geschrieben habe, bin dann aber ganz schön verwirrt. Eigentlich hatte ich ja mental abgespeichert, dass unter unixoiden Systemen grundsätzlich erstmal alle Symbole exportiert werden und man das mit
__attribute__((visibility("hidden")))
selektiv unterbindet - es sei denn man gibt dem Compiler den-fvisibility=hidden
-Parameter mit, dann wird standardmäßig nichts exportiert (vielleicht wird das ja irgendwo gemacht?)AFAIK ist das mit gcc immer noch der standard das alles exportiert wird.
hendrik.weiler nutzt cmake. Gut möglich das cmake dem compiler parameter -fvisibility=hidden setzt
Eventuell durch das aktivieren des C++20 standards durch das cmake makroset(CMAKE_CXX_STANDARD 20)
Um zu sehen welche parameter an den compiler übergeben werden kann man den verbose modus nutzen.
z.b. so:make VERBOSE=1
-
Ich habe
make VERBOSE=1
in ubuntu ausprobiert. Das wurde geloggt:/home/parallels/.local/lib/python3.10/site-packages/cmake/data/bin/cmake -S/home/parallels/Documents/xmlparser-cpp-shared-library -B/home/parallels/Documents/xmlparser-cpp-shared-library --check-build-system CMakeFiles/Makefile.cmake 0 Re-run cmake file: Makefile older than: CMakeLists.txt -- Configuring done (0.0s) -- Generating done (0.0s) -- Build files have been written to: /home/parallels/Documents/xmlparser-cpp-shared-library /home/parallels/.local/lib/python3.10/site-packages/cmake/data/bin/cmake -E cmake_progress_start /home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles /home/parallels/Documents/xmlparser-cpp-shared-library//CMakeFiles/progress.marks make -f CMakeFiles/Makefile2 all make[1]: Entering directory '/home/parallels/Documents/xmlparser-cpp-shared-library' make -f CMakeFiles/xmlparser.dir/build.make CMakeFiles/xmlparser.dir/depend make[2]: Entering directory '/home/parallels/Documents/xmlparser-cpp-shared-library' cd /home/parallels/Documents/xmlparser-cpp-shared-library && /home/parallels/.local/lib/python3.10/site-packages/cmake/data/bin/cmake -E cmake_depends "Unix Makefiles" /home/parallels/Documents/xmlparser-cpp-shared-library /home/parallels/Documents/xmlparser-cpp-shared-library /home/parallels/Documents/xmlparser-cpp-shared-library /home/parallels/Documents/xmlparser-cpp-shared-library /home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/DependInfo.cmake "--color=" Dependencies file "CMakeFiles/xmlparser.dir/lib/Document.cpp.o.d" is newer than depends file "/home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/compiler_depend.internal". Dependencies file "CMakeFiles/xmlparser.dir/lib/Lexer.cpp.o.d" is newer than depends file "/home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/compiler_depend.internal". Dependencies file "CMakeFiles/xmlparser.dir/lib/Parser.cpp.o.d" is newer than depends file "/home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/compiler_depend.internal". Dependencies file "CMakeFiles/xmlparser.dir/lib/Token.cpp.o.d" is newer than depends file "/home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/compiler_depend.internal". Dependencies file "CMakeFiles/xmlparser.dir/lib/includes/Node.cpp.o.d" is newer than depends file "/home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/compiler_depend.internal". Dependencies file "CMakeFiles/xmlparser.dir/lib/includes/XMLParser.cpp.o.d" is newer than depends file "/home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/compiler_depend.internal". Dependencies file "CMakeFiles/xmlparser.dir/library.cpp.o.d" is newer than depends file "/home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles/xmlparser.dir/compiler_depend.internal". Consolidate compiler generated dependencies of target xmlparser make[2]: Leaving directory '/home/parallels/Documents/xmlparser-cpp-shared-library' make -f CMakeFiles/xmlparser.dir/build.make CMakeFiles/xmlparser.dir/build make[2]: Entering directory '/home/parallels/Documents/xmlparser-cpp-shared-library' [ 12%] Building CXX object CMakeFiles/xmlparser.dir/library.cpp.o /usr/bin/c++ -Dxmlparser_EXPORTS -std=gnu++20 -fPIC -MD -MT CMakeFiles/xmlparser.dir/library.cpp.o -MF CMakeFiles/xmlparser.dir/library.cpp.o.d -o CMakeFiles/xmlparser.dir/library.cpp.o -c /home/parallels/Documents/xmlparser-cpp-shared-library/library.cpp [ 25%] Building CXX object CMakeFiles/xmlparser.dir/lib/includes/XMLParser.cpp.o /usr/bin/c++ -Dxmlparser_EXPORTS -std=gnu++20 -fPIC -MD -MT CMakeFiles/xmlparser.dir/lib/includes/XMLParser.cpp.o -MF CMakeFiles/xmlparser.dir/lib/includes/XMLParser.cpp.o.d -o CMakeFiles/xmlparser.dir/lib/includes/XMLParser.cpp.o -c /home/parallels/Documents/xmlparser-cpp-shared-library/lib/includes/XMLParser.cpp [ 37%] Building CXX object CMakeFiles/xmlparser.dir/lib/Parser.cpp.o /usr/bin/c++ -Dxmlparser_EXPORTS -std=gnu++20 -fPIC -MD -MT CMakeFiles/xmlparser.dir/lib/Parser.cpp.o -MF CMakeFiles/xmlparser.dir/lib/Parser.cpp.o.d -o CMakeFiles/xmlparser.dir/lib/Parser.cpp.o -c /home/parallels/Documents/xmlparser-cpp-shared-library/lib/Parser.cpp [ 50%] Building CXX object CMakeFiles/xmlparser.dir/lib/Document.cpp.o /usr/bin/c++ -Dxmlparser_EXPORTS -std=gnu++20 -fPIC -MD -MT CMakeFiles/xmlparser.dir/lib/Document.cpp.o -MF CMakeFiles/xmlparser.dir/lib/Document.cpp.o.d -o CMakeFiles/xmlparser.dir/lib/Document.cpp.o -c /home/parallels/Documents/xmlparser-cpp-shared-library/lib/Document.cpp [ 62%] Building CXX object CMakeFiles/xmlparser.dir/lib/includes/Node.cpp.o /usr/bin/c++ -Dxmlparser_EXPORTS -std=gnu++20 -fPIC -MD -MT CMakeFiles/xmlparser.dir/lib/includes/Node.cpp.o -MF CMakeFiles/xmlparser.dir/lib/includes/Node.cpp.o.d -o CMakeFiles/xmlparser.dir/lib/includes/Node.cpp.o -c /home/parallels/Documents/xmlparser-cpp-shared-library/lib/includes/Node.cpp [ 75%] Linking CXX shared library libxmlparser.so /home/parallels/.local/lib/python3.10/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/xmlparser.dir/link.txt --verbose=1 /usr/bin/c++ -fPIC -shared -Wl,-soname,libxmlparser.so.0 -o libxmlparser.so.0.1.4 CMakeFiles/xmlparser.dir/library.cpp.o CMakeFiles/xmlparser.dir/lib/includes/XMLParser.cpp.o CMakeFiles/xmlparser.dir/lib/Token.cpp.o CMakeFiles/xmlparser.dir/lib/Lexer.cpp.o CMakeFiles/xmlparser.dir/lib/Parser.cpp.o CMakeFiles/xmlparser.dir/lib/Document.cpp.o CMakeFiles/xmlparser.dir/lib/includes/Node.cpp.o /home/parallels/.local/lib/python3.10/site-packages/cmake/data/bin/cmake -E cmake_symlink_library libxmlparser.so.0.1.4 libxmlparser.so.0 libxmlparser.so make[2]: Leaving directory '/home/parallels/Documents/xmlparser-cpp-shared-library' [100%] Built target xmlparser make[1]: Leaving directory '/home/parallels/Documents/xmlparser-cpp-shared-library' /home/parallels/.local/lib/python3.10/site-packages/cmake/data/bin/cmake -E cmake_progress_start /home/parallels/Documents/xmlparser-cpp-shared-library/CMakeFiles 0
Da steht auch nichts von dem flag drin.
Ich habe auch versucht den Compiler-Flag in cmake zu setzen mit:target_compile_options(xmlparser PRIVATE -fvisibility=default)
Das Projekt wurde zwar neu erstellt aber die Instanziierung wirft wieder den gleichen Fehler:
xmlparser-runner.cpp:(.text._ZN4NodeC2Ev[_ZN4NodeC5Ev]+0xc): undefined reference to `vtable for Node' /usr/bin/ld: xmlparser-runner.cpp:(.text._ZN4NodeC2Ev[_ZN4NodeC5Ev]+0x10): undefined reference to `vtable for Node'