web-dev-qa-db-fra.com

#include tous les fichiers .cpp dans une seule unité de compilation?

J'ai récemment eu des raisons de travailler avec certains projets Visual Studio C++ avec les configurations habituelles Debug et Release, mais aussi avec 'Release All' et 'Debug All', que je n'avais jamais vus auparavant.

Il s'avère que l'auteur des projets a un seul ALL.cpp qui inclut tous les autres fichiers .cpp. Les configurations * All ne font que construire ce fichier ALL.cpp. Il est bien entendu exclu des configurations habituelles, et les configurations habituelles ne construisent pas ALL.cpp

Je me demandais simplement si c'était une pratique courante? Quels avantages apporte-t-il? (Ma première réaction a été que ça sentait mauvais.)

Quels types de pièges êtes-vous susceptible de rencontrer avec cela? Je peux penser, par exemple, si vous avez des espaces de noms anonymes dans vos .cpps, ils ne sont plus "privés" de ce cpp, mais sont également visibles dans d’autres cpps?

Tous les projets construisent des DLL, donc avoir des données dans des espaces de noms anonymes ne serait pas une bonne idée, non? Mais les fonctions seraient OK?

À votre santé.

66
Steve Folly

Certains (et Google-en mesure) le désignent comme un "build unitaire". Il relie incroyablement vite et compile raisonnablement rapidement aussi. C'est génial pour les constructions sur lesquelles vous n'avez pas besoin de parcourir, comme une version de compilation à partir d'un serveur central, mais ce n'est pas nécessairement pour la construction incrémentielle.

Et c'est un PITA à maintenir.

EDIT: voici le premier lien Google pour plus d’informations: http://buffered.io/posts/the-magic-of-unity-builds/

Ce qui est rapide, c'est que le compilateur n'a besoin que de tout lire une fois, de le compiler, puis de le lier, plutôt que de le faire pour chaque fichier .cpp.

Bruce Dawson a beaucoup mieux écrit à ce sujet sur son blog: http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/

55
MSN

Unity construit des vitesses de construction améliorées pour trois raisons principales. La première raison est que tous les fichiers d'en-tête partagés ne doivent être analysés qu'une seule fois. Beaucoup de projets C++ ont beaucoup de fichiers d'en-tête qui sont inclus dans la plupart ou la totalité des fichiers CPP et leur analyse redondante constitue le coût principal de la compilation, en particulier si vous avez beaucoup de fichiers source courts. Les fichiers d'en-tête précompilés peuvent aider à réduire ce coût, mais en général, de nombreux fichiers d'en-tête ne sont pas précompilés.

La prochaine raison principale pour laquelle les versions d'unité améliorent les vitesses de génération est que le compilateur est appelé moins de fois. Faire appel au compilateur a un coût de démarrage.

Enfin, la réduction de l'analyse des en-têtes redondants entraîne une réduction du code-gén redondant pour les fonctions en ligne, de sorte que la taille totale des fichiers objet est réduite, ce qui accélère la liaison.

Les builds Unity peuvent aussi donner un meilleur code.

Les versions de Unity sontPASplus rapides en raison d’une réduction des E/S du disque. J'ai profilé de nombreuses versions avec xperf et je sais de quoi je parle. Si vous avez suffisamment de mémoire, le cache de disque du système d'exploitation évite les E/S redondantes. Les lectures ultérieures d'un en-tête proviennent du cache de disque du système d'exploitation. Si vous ne disposez pas de suffisamment de mémoire, la génération d'unités pourrait même aggraver les temps de génération en forçant l'empreinte mémoire du compilateur à dépasser la mémoire disponible et à être paginée.

Les E/S de disque coûtent cher. C'est pourquoi tous les systèmes d'exploitation mettent en cache de manière agressive les données afin d'éviter les E/S de disque redondantes.

47
Bruce Dawson

Je me demande si ALL.cpp tente de regrouper l'ensemble du projet au sein d'une seule unité de compilation, afin d'améliorer la capacité du compilateur d'optimiser la taille du programme.

Normalement, certaines optimisations ne sont effectuées que dans des unités de compilation distinctes, telles que la suppression du code en double et l'inline.

Cela dit, il me semble que je me souviens que les compilateurs récents (Microsoft, Intel, mais je ne pense pas que cela inclut GCC) peuvent effectuer cette optimisation sur plusieurs unités de compilation. Je suppose donc que cette «astuce» n’est pas nécessaire.

Cela dit, il serait curieux de voir s’il existe vraiment une différence.

6
Arafangion

Je suis d'accord avec Bruce. D'après mon expérience, j'avais essayé d'implémenter Unity Build pour l'un de mes projets .dll comportant une tonne d'en-tête et beaucoup de .cpps; pour réduire le temps de compilation global sur le VS2010 (les options de construction incrémentielle avaient déjà été épuisées), mais plutôt que de réduire le temps de compilation, la mémoire est devenue insuffisante et la construction n'a même pas pu terminer la compilation.

Cependant pour ajouter; J'ai trouvé que l'activation de l'option Compilation multi-processeurs dans Visual Studio permettait de réduire considérablement le temps de compilation; Je ne suis pas sûr si une telle option est disponible sur d'autres compilateurs de plate-forme.

2
spforay

Nous avons un projet multi-plateforme pour MacOS et Windows. Nous avons beaucoup de grands modèles et de nombreux en-têtes à inclure. Nous avons réduit de moitié le temps de génération avec Visual Studio 2017 msvc à l'aide d'en-têtes précompilés. Pour MacOS, nous avons essayé plusieurs jours pour réduire le temps de construction, mais les en-têtes précompilés ne réduisaient que le temps de construction à 85%. L'utilisation d'un seul fichier .cpp était la percée. Nous créons simplement ce ALL.cpp avec un script. Notre ALL.cpp contient une liste d'inclusions de tous les fichiers .cpp de notre projet. Nous réduisons le temps de construction à 30% avec XCode 9.0. Le seul inconvénient était que nous devions donner des noms à tous les espaces de noms d'unités de compilation non nommés privés dans .cpp-Files. Sinon, les noms locaux entreront en conflit.

0
Stephanie

En plus de la réponse excellente de Bruce Dawson , le lien suivant permet de mieux comprendre le pour et le contre de la construction d'unité - https://github.com/onqtam/ucm#unity-builds

0
onqtam