Sollte ich die Quelle der Bibliotheken hinzufügen, anstatt sie zu verlinken?


14

Ich bin relativ neu in C ++, daher bin ich mir nicht sicher, wie ich mit kleinen Abhängigkeiten (z. B. einer Skriptsprache oder einem JSON / YAML / XML-Parser) am besten umgehen soll.

Soll ich separate Projekte erstellen und diese als statische Bibliothek verknüpfen oder gibt es Nachteile, wenn ich nur die .h / .cpp-Dateien in mein Hauptprojekt lege?

Letzteres scheint viel einfacher zu sein, da ich mehrere Stunden mit inkompatiblen Bibliotheken verbracht habe (andere Compilereinstellungen beim Erstellen der Bibliothek), aber ich möchte C ++ nicht falsch lernen.

Wenn es vorzuziehen ist, sie als separate Bibliotheken zu speichern, wie kann ich die Kompilierungsflags am besten synchronisieren, damit die .lib / .a-Dateien erfolgreich mit meiner Anwendung verknüpft werden?

(Ich arbeite derzeit mit MSVC 2015, aber das Ziel ist es, unter Mac OS X und iOS mit XCode / clang zu kompilieren, sodass ich mit mindestens 3 verschiedenen Arten von Bibliotheken arbeiten muss (Win x86, Mac x64, ARM). )


5
Schauen Sie in ABIss und sie werden in Sie schauen
Basilevs

1
Beachten Sie, dass einige Bibliotheken auf diese Weise verwendet werden sollen . Das bevorzugte Verwendungsmuster der SQLite- Bibliothek besteht darin, die zusammengeführte Quell- und Header-Datei in den Quellbaum einer C- oder C ++ - Anwendung zu kopieren, um sie in die ausführbare Datei zu kompilieren.
Mark Benningfield

Antworten:


6

TLDR;

Sollten Sie die Quelle hinzufügen? JA
Soll X die Quelle hinzufügen? HÄNGT DAVON AB

Hier kommt das Warum ...

Damals war die Kompilierungszeit ein Thema, das auch kleinere Projekte hatten. Das Kompilieren Ihrer Quellen und die Tatsache, dass Sie sich nie Gedanken über das Zwischenspeichern von Compiler-Ergebnissen machen mussten, hat auf jeden Fall einige angesprochen. Das ist ein Punkt für Bibliotheken, der für Sie irrelevant ist.

Ein weiterer wichtiger Punkt ist die Versionierung. Müssen Sie wirklich jede Bibliothek separat versionieren? Tests gegen jeden durchführen? Verteilen Sie es unter vielen Teammitgliedern? Bibliotheken sind toll, wenn Sie es tun, und bequem zu bewegen, aber auch hier scheint es Ihnen egal zu sein.

Letztendlich ist dies ein zusätzlicher Aufwand, und das Löschen der Quelldateien ist in Ihrem Fall einfacher, was das Löschen der Quellen wichtiger macht als die Verwendung von Bibliotheken. Wie Sie bemerkt haben, müssen Sie, sobald Sie eine einzelne Compiler-Einstellungsänderung vorgenommen haben, alle Abhängigkeiten auf andere Weise verfolgen.

Ich weiß das alles aus Erfahrung:

Für Swift-Projekte verwende ich auf jeden Fall Frameworks (Bibliotheken) und verknüpfe diese, da die Konfiguration mit Xcode einfach ist. Ich brauche dort auch wirklich die Versionierung, Tests und Entkopplung, deshalb.

Bei Mono (C #) -Projekten für Unity begann ich mit dem angesagten Ansatz, das Projekt in Bibliotheken aufzuteilen, zu kompilieren und zu testen. Das war großartig. Aber als ich die Bibliotheken in Unity fallen ließ, traten alle möglichen Probleme auf , aus der gehackten Version von Mono Unity, um einfach das manchmal unterschiedliche Verhalten des Codes beim Wechseln der Plattform zu beschreiben. Es war ein echtes Problem, hier keine einzige IDE für die Verwaltung aller Bibliotheken zu haben. Daher war es ein enormer Gewinn für die Produktivität, alle Quellen in Unity zu integrieren.

Am wichtigsten für Sie ist schließlich ein C ++ - Spielprojekt, an dem ich gearbeitet habe. Für dieses Spiel wurden eine Spiel-Engine, ein Netzwerk-Echtzeit-Client, ein Netzwerk-HTTP-Client, eine KI und ein Persistenzspeicher geschrieben, und zwar nur auf der Clientseite. Wofür habe ich mich entschieden? CLion + Bibliotheken. Obwohl ich Bibliotheken benutzte, fühlte es sich nicht so an, als ob ich es wäre. Alle Quellen befanden sich im CLion IDE-Projekt, und durch das Erstellen von CMakeLists konnte ich alle Builds auslösen und mit einem einzigen Strich verknüpfen.

Zusammenfassend würde ich sagen, dass die Verwendung von Bibliotheken eine zukunftssichere Lösung ist, aber auch eine vorzeitige Optimierung, wenn sie nicht benötigt wird. Soweit ich Ihre Situation beurteilen kann, ist der Wechsel von MSVC zu Xcode ein Problem, wenn Sie mehrere Build-Ziele haben. Also, legen Sie es nur in und halten so viel Isolation wie möglich , wenn die Zeit , wenn Sie könnten zu verwenden Bibliotheken benötigen.

PS: Ich habe in diesen Tagen ein ähnliches Dilemma mit Docker. Soll ich komponieren Soll ich nur lokal laufen? .. etc. Auch Elixir, da es Ihnen erlaubt, Anwendungen innerhalb derselben Anwendung zu erstellen .. Sollte ich das tun? Oder trennen Sie die App in die sogenannten Micro-Services? ... usw. Es gibt keine Silberkugel, messen Sie sich immer als YMMV.


2

Das Verknüpfen mit C ++ - Bibliotheken erfordert viel Aufwand und erfordert viel Wissen und Mühe, um es richtig zu machen. Es kann für C ++ - Lernende einschüchternd sein.


Häufig berücksichtigen die Autoren / Betreuer einer bestimmten C ++ - Bibliothek dies und empfehlen dies auf die eine oder andere Weise.

Mit anderen Worten, wenn die Autoren / Betreuer beabsichtigen, dass die Bibliothek durch Header (* .h und .hpp) oder durch Quelle ( .h * oder .c ) eingeschlossen wird, hätte dies in der Readme- Datei klar gesagt oder Dokumentation.


Bibliotheken, die plattformübergreifend entworfen und verwaltet werden (und mit mehreren C ++ - Compilerherstellern und -Umgebungen kompatibel sind), verfügen häufig über ein Makefile-System oder ein Build-Konfigurationssystem (z. B. CMake). Diese Systeme werden verwendet, um Header-Shims zu generieren, die Plattformunterschiede ausgleichen, und um Skripts zu generieren, mit denen der Compiler und der Linker für Quelldateien mit den richtigen Befehlszeilenoptionen und in der richtigen Reihenfolge aufgerufen werden. Je nach Plattform und Konfiguration können diese Erstellungssysteme bestimmte Header oder Quelldateien einschließen oder ausschließen oder bestimmte Präprozessorsymbole definieren oder deren Definition aufheben.


Ein Widerspruch gegen die Empfehlung des Autors / Betreuers ist möglich, erfordert aber immer einen umfangreichen Portierungsaufwand. Der für diese Portierung erforderliche Arbeitsaufwand kann mit der Portierung in eine andere C ++ - Umgebung vergleichbar sein.


Da Visual C ++ ein eigenes Build-System verwendet, das auf einer Projektbeschreibungsdatei (teilweise XML-basiert) basiert, unterscheidet es sich erheblich von dem unter Linux verwendeten skriptbasierten Build-System. Der von CMake verwendete Ansatz besteht darin, dass CMake die Konfigurationseinstellungen übernimmt und dann die gesamte Visual C ++ - Projektstruktur mit den Konfigurationsoptionen ausgibt, die in den * .vcxproj-Dateien gespeichert sind.

Wenn während der C ++ - Verknüpfung mit Visual C ++ Probleme auftreten, können die Buildeinstellungen in * .vcxproj-Dateien über die Visual Studio-GUI (über das Dialogfeld mit den Projekteigenschaften) geändert werden. Dies setzt voraus, dass Sie die Bedeutung und die Konsequenzen eines Dutzend wichtiger C ++ - Kompilierungs- und Verknüpfungseinstellungen genau kennen.

Jetzt kommt der dümmste Teil der Verwendung von Visual C ++: Wenn Sie ein Dutzend verschiedener Bibliotheken von Drittanbietern verwenden, müssen Sie die Build-Einstellungen für alle ändern, indem Sie in jede * .vcxproj-Datei gehen und dieselbe Änderung in der GUI für ein Dutzend wiederholen mal. Ein Ärger, aber es kann getan werden, wenn Sie wissen, wie man es richtig macht.

Die meisten Visual C ++ - Lerner lernen diese Einstellungen auf die harte Tour, indem sie Visual C ++ - Compiler- und Linker-Fehler beobachten, die durch ihren Fehlercode identifiziert werden. Zum Beispiel kann man LNK2005 mit der oberflächlichen Bedeutung von "Das Symbol Symbol wurde mehr als einmal definiert" nachschlagen, aber mit dem Verständnis, dass die doppelte Definition nicht durch einen unachtsamen Programmierfehler entstanden ist, sondern aufgrund einiger Fehler hätte passieren können Konflikte oder fehlerhafte Anwendung von Kompilierungs- und Verknüpfungsoptionen.


Um eine spezifischere und nützlichere Antwort auf Ihre Situation zu erhalten, müssen Sie die Namen der Bibliotheken kennen, die Sie verwenden möchten, sowie die Verknüpfungsfehler oder andere Schwierigkeiten, auf die Sie stoßen. Antworten auf diese Fragen finden Sie möglicherweise in den Diskussionsforen der jeweiligen Bibliothek. Diese Fragen sind in der Regel mit "Verknüpfungsproblemen", "Windows" und "Visual C ++" gekennzeichnet.

Ein Leitfaden für Anfänger und Experten zu diesem Thema ist möglich, wird jedoch projektspezifisch sein. Unterschiedliche Präferenzen, die von verschiedenen Projekten ausgewählt wurden, erfordern eine vollständige Überarbeitung des Handbuchs.


Wenn Sie CMake zur Ausgabe von .vcxproj verwenden, anstatt das .vcxproj zu ändern, können Sie die CMake-Konfiguration ändern
Caleth

1

Ich würde ja sagen, solange es einfacher ist. Es gibt eine ganze Reihe von Vorteilen:

  1. Dies führt zu schnellerem und besserem Code, insbesondere wenn Sie die Verbindungszeitoptimierung aktivieren.

  2. Ihre IDE wird es mehr mögen, z. B. können Sie (hoffentlich) zur Implementierung (.cpp) von Bibliothekscode springen und nicht nur zur Schnittstelle (.h), was äußerst nützlich ist, wenn Sie mit schlecht dokumentiertem Code arbeiten (d. H der meiste Code).

  3. Es erlaubt Ihnen oft, die Abhängigkeit als Git-Submodul hinzuzufügen, was eine etwas hackige, aber eigentlich ziemlich gute Möglichkeit ist, Abhängigkeiten zu haben (für C ++ jedenfalls, das so gut wie keine vernünftigen Build-Systeme hat). Es macht es wirklich einfach, die Bibliothek zu aktualisieren und verschiedene Versionen zu testen.

  4. Sie müssen sich keine Sorgen machen, dass eine Abhängigkeit mit MSVC ++ 2013 kompiliert wird, während Sie beispielsweise 2017 verwenden. Oder geteilt gegen statisches MSVCRT.

  5. Sie können einfach im Debug-Modus erstellen und in die Bibliothek eintreten.

Der einzige Grund, warum ich denke, dass Sie nicht würden tun möchten, ist, wenn die Bibliothek groß ist und ein komplexes Build-System hat, das Sie nicht in Ihrer replizieren möchten, z. B. Boost oder LLVM. Aber für einfache Bibliotheken gibt es eigentlich keinen Nachteil.

Als Beispiel verwende ich libusb in einigen Projekten und muss Windows unterstützen. libusb verwendet Autotools, was ein Witz eines Build-Systems ist und auf Windows sowieso nicht wirklich funktioniert. Sie bieten vorkompilierte Binärdateien, sind jedoch mit MSVC ++ 2013 erstellt und funktionieren nicht mit 2017. Die mit Abstand einfachste Lösung bestand darin, meinem Projekt alle relevanten C- und H-Dateien hinzuzufügen.


2
1) wirklich? Eine statische Bibliothek ist nur eine Sammlung von Objektdateien, so als hätten Sie sie gerade kompiliert.
Baldrickk

Sie können ein Archiv von .oDateien erstellen, mit -fltodenen kompiliert wurde , die jedoch keine statische Bibliothek sind. Für Clang handelt es sich um LLVM-Bitcodedateien. Und es wird offensichtlich nicht funktionieren, wenn Sie statische Bibliotheken verwenden, die von jemand anderem bereitgestellt werden.
Timmmm

OK, lassen Sie uns diese Diskussion aktualisieren - ich freue mich darauf, einige weitere Dinge zu lernen :)
Baldrickk
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.