Dois-je ajouter la source des bibliothèques au lieu de les lier?

14

Je suis relativement nouveau en C ++, donc je ne sais pas comment gérer au mieux les petites dépendances (par exemple, un langage de script ou un analyseur JSON / YAML / XML).

Dois-je créer des projets séparés et les lier en tant que bibliothèque statique, ou y a-t-il des inconvénients à simplement placer les fichiers .h / .cpp dans mon projet principal?

Ce dernier semble beaucoup plus facile parce que j'ai passé plusieurs heures à traiter des bibliothèques incompatibles (réglage différent du compilateur lors de la construction de la bibliothèque), mais je ne veux pas commencer à apprendre le C ++ dans le mauvais sens.

S'il est préférable de les conserver en tant que bibliothèques distinctes, comment mieux synchroniser les drapeaux de compilation pour que les fichiers .lib / .a soient correctement liés à mon application?

(Je travaille actuellement avec MSVC 2015, mais l'objectif est de compiler sur Mac OS X et iOS en utilisant XCode / clang, de sorte que je dois gérer au moins 3 types de bibliothèques différents (Win x86, Mac x64, ARM) )

Michael Stum
la source
5
Contemplez ABIss et ils se pencheront sur vous
Basilevs
1
Gardez à l'esprit que certaines bibliothèques sont destinées à être utilisées de cette façon. Le modèle d'utilisation préféré de la bibliothèque SQLite consiste à déposer le fichier source et en-tête fusionné dans l'arborescence source d'une application C ou C ++ à compiler dans l'exécutable.
Mark Benningfield

Réponses:

6

TLDR;

Devez- vous ajouter la source? OUI
Faut - X ajouter la source? DÉPEND

Voici le pourquoi ...

À l'époque, le temps de compilation était un problème rencontré par des projets encore plus petits. Compiler vos sources et ne jamais vous soucier de la mise en cache des résultats du compilateur était certainement attrayant pour certains. C'est un point pour les bibliothèques qui ne vous concernent pas.

Un autre important est le versioning. Avez-vous vraiment besoin de versionner chaque bibliothèque séparément? Exécuter des tests contre chacun? Le distribuer à plusieurs membres de l'équipe? Les bibliothèques sont géniales si vous le faites, et pratiques pour vous déplacer, mais encore une fois, il semble que vous ne vous en souciez pas non plus.

Le dernier point ici est, c'est une surcharge supplémentaire, et la suppression des fichiers source est plus facile dans votre cas, ce qui donne un point très fort à la suppression des sources plutôt qu'à l'utilisation de bibliothèques. Comme vous l'avez remarqué, une fois que vous avez modifié un seul paramètre du compilateur, vous devez chasser toutes les dépendances autrement.

Je sais tout cela par expérience:

Pour les projets Swift, j'utilise définitivement des frameworks (bibliothèques) et des liens avec eux, car il est facile de configurer en utilisant Xcode. J'ai aussi vraiment besoin de versions, de tests et de découplage, c'est pourquoi.

Pour les projets Mono (C #), pour Unity, j'ai commencé avec l'approche hip de décomposer le projet en bibliothèques, compilé et testé chacun, ce qui était super ... mais une fois que j'ai déposé les bibliothèques dans Unity, toutes sortes de problèmes se sont produits , de la version piratée de Mono Unity au simple comportement parfois différent du code lors du changement de plate-forme. Ne pas avoir un seul IDE ici pour gérer toutes les bibliothèques a été une vraie douleur, donc mettre toutes les sources dans Unity a été un énorme gain de productivité.

Enfin, le plus pertinent pour vous, un projet de jeu C ++ sur lequel j'ai travaillé. Un moteur de jeu, un client réseau en temps réel, un client HTTP réseau, une IA et un magasin de persistance ont été écrits pour ce jeu, juste du côté client. Pour quoi ai-je opté? Bibliothèques CLion +. Même si j'utilisais des bibliothèques, je n'avais pas l'impression de l'être. Toutes les sources étaient dans le projet CLion IDE, et en composant CMakeLists, j'ai pu déclencher toutes les générations et les lier en un seul coup.

En conclusion , je dirais que l'utilisation des bibliothèques est une solution évolutive, mais aussi une optimisation prématurée si elle n'est pas nécessaire. Pour autant que je sache de votre situation, le passage de MSVC à Xcode sera une douleur si vous avez plusieurs cibles de construction. Donc, déposez-le et maintenez autant d'isolement que possible pour le moment où vous devrez peut- être utiliser des bibliothèques.

PS: J'ai un dilemme similaire ces jours-ci avec Docker. Dois-je composer? Dois-je simplement courir localement? .. etc. Aussi Elixir, car il vous permet de créer des applications dans la même application .. Dois-je faire cela? Ou séparer l'application en soi-disant micro-services? ... etc. Il n'y a pas de solution miracle, mesurez-vous toujours comme YMMV.

Mazyod
la source
2

La liaison avec les bibliothèques C ++ nécessite beaucoup de tracas et nécessite beaucoup de connaissances et d'efforts pour le faire correctement. Cela peut être intimidant pour les apprenants C ++.


Souvent, les auteurs / mainteneurs d'une bibliothèque C ++ spécifique auront cela à l'esprit et recommanderont d'une manière ou d'une autre.

En d'autres termes, si les auteurs / mainteneurs voulaient que la bibliothèque soit incluse par des en-têtes (* .h et .hpp uniquement), ou inclue par source ( .h * ou .c ), cela l'aurait dit clairement dans le fichier Lisezmoi ou documentation.


Les bibliothèques conçues et maintenues pour être multiplateformes (et compatibles avec plusieurs fournisseurs et environnements de compilateurs C ++) auront souvent un système de makefile ou un système de configuration de construction (comme CMake). Ces systèmes sont utilisés pour générer des shims d'en-tête qui atténuent les différences de plate-forme et pour générer des scripts qui invoqueront le compilateur et l'éditeur de liens sur les fichiers source en utilisant les options de ligne de commande appropriées et dans la séquence correcte. Selon la plate-forme et la configuration, ces systèmes de génération peuvent inclure ou exclure certains en-têtes ou fichiers source, ou ils peuvent définir ou annuler la définition de certains symboles de préprocesseur.


Aller contre la recommandation des auteurs / mainteneurs est possible, mais cela nécessite toujours un effort de portage important. La quantité de travail requise pour cet effort de portage peut être comparable au portage vers un autre environnement C ++.


Étant donné que Visual C ++ utilise son propre système de génération basé sur un fichier de description de projet (partiellement basé sur XML), il est assez différent du système de génération basé sur des scripts utilisé sous Linux. L'approche utilisée par CMake consiste à ce que CMake prenne les paramètres de configuration, puis émette l'intégralité de la structure du projet Visual C ++, avec les options de configuration intégrées dans les fichiers * .vcxproj.

Si des problèmes surviennent lors de la liaison C ++ avec Visual C ++, les paramètres de génération dans les fichiers * .vcxproj peuvent être modifiés à l'aide de l'interface graphique de Visual Studio (à l'aide de la boîte de dialogue des pages de propriétés du projet). Cela suppose que vous comprenez parfaitement les significations et les conséquences d'une douzaine de paramètres importants de compilation et de liaison C ++.

Vient maintenant la partie la plus stupide de l'utilisation de Visual C ++: si vous utilisez une douzaine de bibliothèques tierces différentes, la modification des paramètres de construction pour chacune d'entre elles signifie entrer dans chaque fichier * .vcxproj et répéter la même modification sur l'interface graphique pendant une douzaine fois. Un problème, mais cela peut être fait, si vous savez comment le faire correctement.

La plupart des apprenants Visual C ++ apprennent ces paramètres à la dure, en observant les erreurs du compilateur et de l'éditeur de liens Visual C ++, identifiées par leur code d'erreur. Par exemple, on peut rechercher LNK2005, avec la signification superficielle de "Le symbole a été défini plus d'une fois", mais étant entendu que la définition en double ne résulte pas d'une erreur de programmation imprudente, mais qu'elle aurait pu se produire à cause de certains conflits ou applications incorrectes des options de compilation et de liaison.


Pour fournir une réponse plus spécifique et utile à votre situation, il faudra connaître les noms des bibliothèques que vous comptez utiliser, ainsi que les erreurs de liaison ou autres difficultés que vous rencontrez. Vous pouvez trouver des réponses existantes à ces questions dans les forums de discussion de la bibliothèque respective. Ces questions ont tendance à être étiquetées avec "problèmes de liaison", "fenêtres" et "C ++ visuel".

Un guide du débutant à l'expert sur cette question est possible, mais il sera spécifique au projet. Différentes préférences choisies par différents projets nécessiteront une réécriture complète du guide.

rwong
la source
Si vous utilisez CMake pour émettre .vcxproj, plutôt que de modifier le .vcxproj, vous pouvez modifier la configuration de CMake
Caleth
1

Je dirais oui, tant que c'est plus facile. Il y a beaucoup d'avantages:

  1. Il en résultera un code plus rapide et meilleur, surtout si vous activez l'optimisation de la durée de liaison.

  2. Votre IDE l'aimera plus, par exemple, il vous permettra (espérons-le) de passer à l' implémentation (.cpp) du code de bibliothèque, plutôt qu'à l'interface (.h), ce qui est extrêmement utile lorsque vous travaillez avec du code mal documenté (c.-à-d. la plupart du code).

  3. Il vous permet souvent d'ajouter la dépendance en tant que sous-module git, qui est un moyen légèrement hacky mais en fait assez bon d'avoir des dépendances (pour C ++ de toute façon, qui n'a pratiquement pas de systèmes de construction sensés). Il est très facile de mettre à jour la bibliothèque et de tester différentes versions.

  4. Vous n'avez pas à vous soucier de la compilation d'une dépendance avec MSVC ++ 2013, lorsque vous utilisez 2017 par exemple. Ou MSVCRT partagé vs statique.

  5. Vous pouvez facilement créer en mode débogage et entrer dans la bibliothèque.

La seule raison pour laquelle je pense que vous ne voudriez pas faire cela, c'est si la bibliothèque est grande et a un système de construction complexe que vous ne voulez pas répliquer dans le vôtre, par exemple Boost ou LLVM. Mais pour les bibliothèques simples, il n'y a pas vraiment d'inconvénient.

Par exemple, j'utilise libusb dans quelques projets et j'ai besoin de supporter Windows. libusb utilise des autotools qui sont une blague d'un système de build et ne fonctionnent pas vraiment sous Windows de toute façon. Ils fournissent des binaires précompilés mais ils sont construits avec MSVC ++ 2013 et ne fonctionneront pas avec 2017. La solution la plus simple était de loin simplement d'ajouter tous les fichiers .c et .h pertinents à mon projet.

Timmmm
la source
2
1) vraiment? Une bibliothèque statique n'est qu'une collection de fichiers objets, comme si vous veniez de les compiler.
Baldrickk
Vous pouvez créer une archive de .ofichiers qui ont été compilés -fltomais qui ne sont pas vraiment une bibliothèque statique - pour Clang, ce sont des fichiers de code bit LLVM. Et cela ne fonctionnera évidemment pas si vous utilisez des bibliothèques statiques fournies par quelqu'un d'autre.
Timmmm
ok, permet de mettre à jour cette discussion - J'ai hâte d'apprendre d'autres choses :)
Baldrickk