web-dev-qa-db-fra.com

Dépendances d'exécution de Visual Studio 2015 ou comment se débarrasser de Universal CRT?

Compilé quelques .dll utilisant Visual Studio 2015, et essayé de déployer sur certaines anciennes fenêtres 7/64 bits. J'ai également essayé de deviner quelles DLL sont nécessaires pour démarrer l'application et copié MSVCP140.DLL & VCRUNTIME140.DLL - mais l'application n'a pas pu charger la DLL vs2015. Commencé à analyser ce qui ne va pas - et le marcheur de dépendances a montré les dépendances des DLL suivantes:

API-MS-WIN-CRT-MATH-L1-1-0.DLL
API-MS-WIN-CRT-HEAP-L1-1-0.DLL
API-MS-WIN-CRT-CONVERT-L1-1-0.DLL
API-MS-WIN-CRT-STRING-L1-1-0.DLL
API-MS-WIN-CRT-STDIO-L1-1-0.DLL
API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL
API-MS-WIN-CRT-FILESYSTEM-L1-1-0.DLL
API-MS-WIN-CRT-TIME-L1-1-0.DLL

Cela était particulièrement surprenant car, à ma connaissance, CRT est responsable du démarrage de dll/exe, il ne fournit aucun service de niveau supérieur.

Ok, j'ai essayé de comprendre comment les éliminer ou du moins les minimiser.

Trouvé un article: https://blogs.msdn.Microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/

Il mentionne la publication de bibliothèques statiques - j'ai donc pensé que je pouvais créer un lien contre elles et me débarrasser de l'enfer de dépendance * L1-1-0.DLL *, mais peu importe ce que j'ai essayé - je n'ai pas réussi. J'ai essayé de lier contre libvcruntime.lib, libucrt.lib, libcmt.lib, j'ai essayé de désactiver en utilisant l'option de l'éditeur de liens "/nodefaultlib:vcruntime.lib", et j'ai même essayé d'ajouter le répertoire d'inclusion $ (UniversalCRT_IncludePath), et aussi de remplacer certains de définir comme j'ai essayé de deviner qu'ils fonctionnent - aucune de mes tentatives n'a aidé.

En tant que solution intermédiaire, je reviens à l'utilisation de Visual studio 2013, où les DLL CRT ne sont que deux: msvcp120.dll, msvcr120.dll.

Bien sûr, vous recommanderez probablement d'installer les exécutions de Visual studio 2015, mais l'une de nos exigences est de prendre en charge un exécutable autonome - qui fonctionne sans aucune installation - donc une installation supplémentaire est hors de question pour l'instant.

Pouvez-vous me recommander autre chose que d'attendre Visual studio 2017 pour arriver?

23
TarmoPikaro

(Mis à jour le 11.10.2016).

Il est possible de se débarrasser du CRT universel en le liant statiquement, j'y reviendrai plus tard, mais jetons un coup d'œil si vous continuez à utiliser le CRT universel en tant que tel.

Selon l'article https://blogs.msdn.Microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ - il est possible de lancer votre application à l'aide des distributables universels crt dll du dossier suivant: C:\Program Files (x86)\Windows Kits\10\Redist\ucrt

Il y a 41 fichiers totalement dans la liste avec une taille totale de 1,8 Mo. (exemple pour plate-forme 64 bits)

Bien sûr, cela ne suffit pas, vous aurez également besoin de vcruntime140.dll et msvcp140.dll provenant du dossier suivant: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT

Donc, après cela, vous expédierez 43 DLL supplémentaires en plus de votre application.

Il est également possible de compiler statiquement la bibliothèque ucrt à l'intérieur de votre application, après quoi vous n'aurez pas besoin de 43 dll - mais le lien statique le fera après la liaison ou non - dépend de votre application - combien de dll et quelles api sont utilisées. Généralement, après que ucrt soit lié à deux DLL différentes, ils ne partagent pas nécessairement les mêmes globaux entre eux, ce qui peut entraîner des erreurs.

Vous devez établir un lien avec vcruntime.lib/msvcrt.lib, mais ce n'est pas suffisant - il y a _VCRTIMP= et _ACRTIMP= définit ce qui doit être désactivé pour extraire des fonctions de ucrt.

Si vous utilisez premake5, vous pouvez configurer votre projet comme ceci:

defines { "_VCRTIMP="}
linkoptions { "/nodefaultlib:vcruntime.lib" }
links { "libvcruntime.lib" }

suivi par:

defines { "_ACRTIMP="}
linkoptions { "/nodefaultlib:msvcrt.lib" }
links { "libcmt.lib" }

Les définitions ne sont pas documentées par Microsoft - il est donc possible qu'elles soient susceptibles de changer à l'avenir.

Outre vos propres projets, vous devrez recompiler toutes les bibliothèques statiques utilisées dans vos projets.

En ce qui concerne les bibliothèques de boost - j'ai également réussi à compiler boost, en utilisant boostrapper b2.exe

boost>call b2 threading=multi toolset=msvc-14.0 address-model=64 --stagedir=release_64bit --build-dir=intermediate_64but release link=static,shared --with-atomic --with-thread --with-date_time --with-filesystem define=_VCRTIMP= define=_ACRTIMP=

Lors du dépannage des problèmes de liaison - notez que non résolu __imp* noms de fonction à cause de l'utilisation de mots clés dllimport - et si vous établissez un lien avec libvcruntime.lib, vous ne devriez pas avoir de __imp* les références.

4
TarmoPikaro

J'ai pu résoudre ce problème en définissant le C/C++ > Code Generation > Runtime Library option de compilation

  • Pour le débogage: à partir de /MDd à /MTd
  • Pour publication: de /MD à /MT

Cela a supprimé tous les API-MS-WIN-CRT-* et les références de DLL d'exécution et ont provoqué la liaison statique de tout le code CRT.

Les détails sur le nouveau CRT universel VS2015 (dynamique et statique) sont ici: https://msdn.Microsoft.com/en-us/library/abx4dbyh.aspx

27
Ton Plooij

Moi aussi, je me battais pour lier statiquement une solution avec plusieurs dépendances de bibliothèque de composants/projets, en important des fonctions de diverses parties de MSVCRT, UCRT et du noyau. L'espoir était que l'EXE résultant pourrait être simplement copié là où il était nécessaire (ce n'était pas un produit qui justifierait une installation complète de MSI).

Après avoir presque abandonné, j'ai trouvé que la meilleure solution était de suivre les directives cachées dans niversal C Runtime annonce , en particulier:

Nous déconseillons fortement la liaison statique des bibliothèques Visual C++, pour des raisons de performances et de facilité de maintenance

Il suffit de supprimer toutes les options de l'éditeur de liens "spéciales" que vous avez essayées, de revenir à/MT |/MD (CRT multi-thread DLL Release | Debug) choix de bibliothèque d'exécution et cela fonctionne partout, par exemple plus récent Stations de travail Windows 10, serveurs 2012 R2 et Windows 7). Il suffit d'installer/de redistribuer MSVCRT (VC_Redist * .exe) et KB2999226 (UCRT via Windows Update) comme Microsoft nous le dit, car comme ils disent aussi:

Le CRT universel est un composant du système d'exploitation Windows . Il est inclus dans le cadre de Windows 10, à partir de l'aperçu technique de janvier, et il est disponible pour les anciennes versions du système d'exploitation via Windows Update.

Donc, logiquement, la seule dépendance de déploiement supplémentaire que nos solutions C++ ajoutent pour le client est le MSVCRT, car l'UCRT devrait déjà être présent sur les machines à jour/bien entretenues. Bien sûr, cela ajoute un peu d'incertitude; vous ne pouvez pas simplement copier l'EXE et l'exécuter sur n'importe quelle machine, bonne ou mauvaise.

Si vous produisez un package de déploiement décent comme un MSI, il est simple de l'inclure lorsque vous avez des outils comme WIX. A noter également que depuis le SDK récent, vous pouvez inclure localement les 40 DLL impaires, mais cela ne satisfait pas le principe de mise à jour de sécurité, donc je ne le ferais pas.

C'est vraiment la seule façon prise en charge pour le faire, voir un autre exemple ici . Cet article suggère également que nous lions contre "mincore_downlevel.lib" qui est une astuce importante, cruciale pour savoir si vous obtenez ces "api-ms-win *" manquant DLL erreurs. Par exemple:

  1. Version du SDK du projet définie sur 10, lien avec mincore.lib = S'exécute uniquement sur Windows 10, mais pas sur le serveur 8.1/2012 R2 ou Windows 7/2008 R2.
  2. Version du SDK du projet définie sur 8.1, lien avec mincore.lib = S'exécute sur le serveur Windows 10 et 8.1/2012 R2, mais pas sur le serveur Windows 7/2008 R2.
  3. Version du SDK du projet définie sur 10, lien avec mincore_downlevel.lib = Fonctionne sur tous!

En résumé:

  1. Ne liez pas statiquement, laissez les runtimes par défaut DLL C sélectionnés dans les paramètres du projet).
  2. Vous n'avez pas besoin des anciens SDK, vous pouvez développer avec le dernier SDK de Windows 10, mais vous devez créer un lien avec "mincore_downlevel.lib" et non "mincore.lib" si vous souhaitez prendre en charge les anciennes versions de Windows.
  3. Pour la facilité d'utilisation, ajoutez ceci à votre targetver.h ou stdafx.h qui documente également votre choix (supprimez l'autre ligne):
// Libraries
#pragma comment(lib, "mincore.lib")             // Lowest OS support is same as SDK
#pragma comment(lib, "mincore_downlevel.lib")   // Support OS older than SDK
8
Tony Wall

J'avais trop de mal à trouver les DLL d'exécution requises pour exécuter une application qui a été construite dans Visual Studio 2015.

Ici, j'ai trouvé les choses suivantes qui permettent à l'application construite VS-2015 de s'exécuter.

Remarque: Placez les versions de DLL en fonction de l'architecture de votre processeur système (x86, x64 ..).

1
Nilesh Sironja