Wie geht man mit Bibliotheken von Drittanbietern mit völlig unterschiedlichen Build-Systemen um?

Lesezeit: 9 Minuten

Der C++ (und C, obwohl es dort weniger wichtig ist) Standard besagt, dass alle Übersetzungseinheiten in einem Programm die gleiche Definition haben müssen; und dazu gehören Dinge wie Compiler-Schalter. Unter MSVC++ muss man beispielsweise auf die richtige Version der C-Laufzeitbibliothek (/MT gegen /MD gegen /MTd gegen /MDd) in allen Übersetzungseinheiten.

Es gibt jedoch ein paar Abhängigkeiten von Drittanbietern, die wir verwenden möchten, und es gibt ein paar Dinge:

  • Sie alle verwenden unterschiedliche Build-Systeme (Es gibt eine Autoconf, eine CMake und eine, die anscheinend ein eigenes handgerolltes Ding hat..)
  • Die Build-Systeme stellen diese Art von Schaltern nicht alle in ihrer Konfiguration bereit, und die fest codierten sind in verschiedenen Systemen unterschiedlich eingestellt. (zB eine Bibliothek zwingt /MD und /MDdwährend andere Kräfte /MT und /MTd)

Wir sind uns nicht sicher, wie wir mit solchen Dingen am besten umgehen. Folgende Möglichkeiten haben wir besprochen:

  • Erstellen Sie unser eigenes Build-System um Abhängigkeiten von Drittanbietern herum.
    • PRO: Wir wissen, dass die Dinge zusammenpassen werden
    • PRO: Wir wissen, dass wir plattformübergreifenden Support auf die richtige Weise leisten können
    • CONTRA: Wir wissen nicht genau, wie jedes der Build-Systeme von Drittanbietern funktioniert
    • CONTRA: Viel, viel Arbeit
    • CON: Unterbrechungen, wenn sich die Abhängigkeit von Drittanbietern ändert
  • Versuchen Sie, die Build-Systeme von Drittanbietern zu verwenden, und versuchen Sie, sie so zu ändern, dass sie das tun, was wir brauchen.
    • PRO: Scheint weniger Arbeit zu sein
    • CONTRA: Wir könnten das Drittanbietersystem knacken
    • CON: Unterbrechungen, wenn sich die Abhängigkeit von Drittanbietern ändert
    • CONTRA: Zwingt unseren eigenen Build dazu, wirklich kompliziert zu sein

Wir wissen jedoch nicht, was wir tun sollen; und wir können nicht glauben, dass wir mit solchen Problemen allein sind. Sollten wir eine der oben genannten Optionen verwenden oder eine dritte Alternative, an die ich nicht gedacht habe?

  • Ein eigenes Build-System zu haben, erschien mir ein bisschen viel. Wenn die Verwendung von crt (MD, MT usw.) durch Ihr Programm gleich bleibt, sollte das Bearbeiten der Parameter der conf-Tools ein weniger zeitaufwändiger Ansatz sein. weil Sie immer eine Kopie des Originals haben können.

    – sittlich

    1. Juni 2012 um 17:12 Uhr

  • In welcher Form werden diese Fremdcodes geliefert? DLLs? oder objs?

    – Pizza

    1. Juni 2012 um 17:51 Uhr

  • @ Pizza: Quellen, meistens. Aber oft generieren Teile der Build-Skripte Konfigurations-Header und andere solche Dinge, die für den Build notwendig sind.

    – Billy ONeal

    1. Juni 2012 um 17:56 Uhr

  • Wenn diese Drittanbieter unverzichtbar sind und Sie beabsichtigen, sie über einen längeren Zeitraum zu verwenden, ist es besser, ein eigenes Build-System zu erstellen. Es wird eine Menge Arbeit sein, aber Sie werden ein tieferes Verständnis für den Aufbau und die Wartung dieser Drittanbieter erhalten und auf lange Sicht nützlich sein. Es ist, als würdest du jetzt oder später sloggen. Nur meine 2 Cent. 🙂

    – Jay

    1. Juni 2012 um 18:13 Uhr

  • Ohne den Abhängigkeitsbaum sehr schwer zu quantifizieren. Wie viele “Diamanten” (lib B hängt von lib A ab, lib C hängt von lib A ab, lib D hängt von lib B ab und lib C) hast du? Ich würde dazu neigen, bei Ihrem “Haupt”-Build-System (msbuild?) Zu bleiben und zu versuchen, Makefiles zu erstellen, die das nachahmen, was die Build-Systeme von Drittanbietern tun – nicht so schwer, wenn sie eine “sehr ausführliche” Option haben

    – Josh Greifer

    1. Juni 2012 um 18:29 Uhr

Sie müssen streng genommen nicht alle Ihre Bibliotheken mit derselben Laufzeit verknüpfen. Unter der Annahme, dass es sich um DLLs handelt, ist es nur dann ein Problem, wenn sie CRT-Datenstrukturen über die DLL-Grenze übergeben. Ein … Erstellen FILE* in einer DLL, die eine Laufzeit verwendet, und die Verwendung von einer DLL, die mit einer anderen Laufzeit verknüpft ist, ist ein Rezept für eine Katastrophe. Berufung malloc oder new aus einer DLL mit einer Laufzeit und free/delete von einem anderen wird viele lustige Probleme verursachen.

Aber solange alle CRT-bezogenen Dinge intern in der DLL aufbewahrt werden, können Sie sicher auf eine DLL verlinken, die eine andere CRT verwendet. Das bedeutet auch, dass Ihr Debug-Build eine Bibliothek verwenden kann, die mit der Release-CRT verknüpft ist. Nochmals, solange Sie nicht versuchen, CRT-Datenstrukturen über Bibliotheken hinweg zu mischen.

Beachten Sie auch, dass die meisten Compiler-Flags die ABI nicht beeinflussen und daher sicher zwischen Bibliotheken (oder Dateien) unterschiedlich sein können. Diejenigen, die den ABI ändern, sind im Allgemeinen offensichtlich, z. B. wenn Sie das Packen oder die Stapelausrichtung erzwingen.

Was wir also tun, ist im Grunde Folgendes:

  • Wo immer möglich, bauen wir die Bibliothek selbst auf. In den meisten Fällen bedeutet dies, dass wir mit relativ einfachen Mitteln steuern können, mit welcher Laufzeit es verknüpft werden soll. Dies erfordert möglicherweise eine sehr kleine Anpassung des Build-Systems, aber normalerweise ist es nur eine Frage der Angabe, ob ein Debug- oder ein Release-Build erstellt werden soll, wofür die meisten Build-Systeme Optionen haben. (Und wenn die Bibliothek Visual Studio für ihr Build-System verwendet, versuchen wir, es nach Möglichkeit auf 2010 zu aktualisieren.)
  • Wir verwenden das eigene Build-System der Bibliothek. Alles andere ist nur ein Rezept für Elend. Sie möchten darauf vertrauen können, dass das Build-System tatsächlich mit dem Quellcode der Bibliothek synchron gehalten wird, und der einfachste Weg, dies sicherzustellen, besteht darin, das Build-System zu verwenden, das mit dem Quellcode geliefert wird.
  • Wenn es nicht praktikabel ist, die Bibliothek zu erstellen, verwenden wir sie einfach so, wie sie ist, und müssen dann nur die Laufzeitumgebung verteilen, mit der sie verknüpft ist. Wir versuchen, dies zu vermeiden, aber es ist sicher genug, wenn keine andere Option verfügbar ist.
  • Wenn wir eine Bibliothek aufbauen, dokumentieren wir exakt wie es in unserem internen Wiki gemacht wurde. Dies ist eine große Hilfe, wenn wir auf eine neuere Version der Bibliothek aktualisieren oder sie neu erstellen müssen.

Wir sind derzeit auf drei verschiedene VS-Laufzeiten (2005, 2008 und 2010) angewiesen, was mühsam zu bewältigen ist, aber es funktioniert. Und für ein oder zwei von ihnen verwenden wir immer die Release-Version, sogar in Debug-Builds unseres eigenen Codes.

Es ist ein bisschen chaotisch zu pflegen, aber es funktioniert. Und ich kann mir wirklich keinen besseren Weg vorstellen, es zu tun.

Natürlich sollten Sie die Anzahl Ihrer Abhängigkeiten von Drittanbietern minimieren, und wenn Sie sich für eine Bibliothek eines Drittanbieters entscheiden, sollte das Build-System definitiv ein zu berücksichtigender Faktor sein. Einige sind viel schmerzhafter zu arbeiten als andere.

Aber am Ende werden Sie wahrscheinlich einige Bibliotheken verwenden müssen, die einfach keine gut erzogenen Build-Systeme haben oder deren Erstellung so schmerzhaft wäre, dass sich der Aufwand einfach nicht lohnt, oder wo Sie können. t Erstellen Sie eine Debug-Version der Bibliothek. Und dann nimm einfach, was du kriegen kannst. Lassen Sie es die Laufzeit verwenden, die es verwenden möchte.

  • Das CRT-Zeug ist nicht intern in der DLL 🙁 (Eigentlich sind einige der Abhängigkeiten statische Bibliotheken, überhaupt keine DLLs)

    – Billy ONeal

    1. Juni 2012 um 19:31 Uhr


  • Spaß, Spaß … Ich finde, dass Verzweiflung und ein bisschen mit dem eigenen Kopf gegen die Wand zu schlagen, manchmal die vernünftigste Herangehensweise ist …

    – jalf

    2. Juni 2012 um 13:50 Uhr

  • Lol – vielleicht fühlt sich jemand zuerst besser, aber was macht es mit dem Build-Problem? 🙂

    – Billy ONeal

    3. Juni 2012 um 6:31 Uhr

  • Nun, ich ziehe es vor, auf die helle Seite zu schauen. Es wird das Build-Problem nicht machen schlechter.

    – jalf

    3. Juni 2012 um 8:38 Uhr

Ich nehme an, dass Sie absichtlich keine bestimmten Bibliotheken erwähnen?

Wie auch immer, Sie sollten sich fragen, ob Sie diesen Drittanbietercode wirklich benötigen dein Bausystem.

Die von uns verwendeten Bibliotheken von Drittanbietern werden einmal kompiliert (mit ihren jeweiligen Build-Skripten) und auf die richtigen VC-Schalter überprüft, und dann wird die DLL- oder LIB-Datei in die Quellcodeverwaltung der App eingecheckt, die die Bibliothek verwendet.

Die Kompilierung einer Bibliothek eines Drittanbieters ist also etwas, das wir nur einmal pro Release eines Drittanbieters durchführen, und wir belasten unser Build-System nicht mit den Feinheiten des Erstellens der Bibliotheken von Drittanbietern.

Ich denke, es gibt gültige Argumente für beide Ansätze, und vielleicht können Sie einige Details in der Frage angeben, warum Sie die Bibliotheken von Drittanbietern in Ihrem Build-System benötigen/möchten.

  • Ich bin vollkommen einverstanden. Wenn Sie nicht ständig Live-Änderungen an den Bibliotheken von Drittanbietern vornehmen, gibt es keinen Grund, sie immer wieder neu zu erstellen. Und wenn Sie ständig Live-Änderungen einspielen, dann haben Sie andere Probleme (dh Sie verwenden eine instabile Version der Bibliothek und Änderungen umgehen wahrscheinlich den Code-Überprüfungsprozess, den Sie normalerweise verwenden).

    – jamesdlin

    1. Juni 2012 um 19:10 Uhr

Du hast Recht – Du bist nicht allein mit solchen Problemen!

Unserer Erfahrung nach ist eine lockere Kopplung von Abhängigkeiten (eine ausgefallene Art, Dateien manuell zu kopieren, denke ich) und das Ändern des Build-Systems von Drittanbietern am effektivsten – insbesondere beim Erstellen für Windows.

Ein paar Dinge, die wir als nützlich empfunden haben:-

Dokumentieren Sie die Änderungen, die Sie für die jeweilige Version anwenden mussten (wir verwenden eine Wiki-Seite) und fügen Sie alle Schritte / Abhängigkeiten hinzu, die hier erforderlich sind (z. B. Perl-Interpreter zum Erstellen von OpenSSL erforderlich) und führen Sie alle enthaltenen Tests durch, bevor Sie den Build verwenden.

Wir haben festgestellt, dass es hier sehr hilfreich ist, die Ausgabebibliotheken so umzubenennen, dass sie konsistent gemäß der ABI gekennzeichnet sind, anstatt die Namen zu verwenden, die von Drittanbietern generiert wurden.

Daher landet die C++-Abhängigkeit X von Drittanbietern in unserer Verzeichnisstruktur (an SVN gebunden) als

X/[version_number]/include (Header-Dateien zur Verwendung von lib)

X/[version_number]/lib/Windows (manuell erstellt, getestet und in libs umbenannt)

z.B

X-vc100.lib X-vc100-gd.lib

etc

(Wir haben unsere Namen tatsächlich von Boost-Namen kopiert http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html#library-naming da sie völlig vernünftig schienen)

Dann kann die jeweilige Abhängigkeit von Drittanbietern von Ihrem Build-System ausgewählt werden (für VS verwenden wir ein geerbtes Eigenschaftsblatt mit allen Abhängigkeiten, die als Benutzermakros benannt sind, sodass einfach $(x_inc) zu den Include-Verzeichnissen für ein Projekt hinzugefügt werden kann und $(x_lib ) zu den libs hinzugefügt – diese Makros wählen dann die Version und abi aus, die für dieses bestimmte Projekt erforderlich sind.

Es gibt keine endgültige Antwort, es hängt davon ab, wie die Codeschnittstelle des Drittanbieters gestaltet ist. Wenn die Schnittstelle eng gekoppelt ist, zum Beispiel gemeinsam genutzte, nicht undurchsichtige Datentypen, ist es besser, sie mit Ihrem eigenen Build und Ihren eigenen Optionen neu zu erstellen. Sie müssen die Schnittstelle analysieren und festlegen, wie sie integriert werden sollen. Andererseits können sie, wenn die Schnittstelle einfach ist und leicht entkoppelt werden kann, als DLL erstellt und bei Bedarf aufgerufen werden. Natürlich haben Sie unterschiedliche Versionen der C-Bibliotheken, die in die Anwendung geladen werden, und alle haben unterschiedliche Instanzen von io-Puffer, Speicherverwaltung usw.

Wenn Ihnen der Quellcode zur Verfügung steht, ist es besser, mehr Zeit in die Integration in Ihren eigenen Build zu investieren.

1345770cookie-checkWie geht man mit Bibliotheken von Drittanbietern mit völlig unterschiedlichen Build-Systemen um?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy