2009-09-29 28 views
1

Lors du développement et du déploiement d'applications Windows natives, j'ai souvent besoin d'installer un runtime avant de pouvoir exécuter mon binaire, ou de lier statiquement la bibliothèque avec mon binaire. Par exemple, après avoir créé un projet "Win32 Console" avec Visual Studio 2008, tenter d'exécuter le programme sur une nouvelle image Windows 7 entraîne:Produire de petits binaires Windows

L'application n'a pas pu démarrer car sa configuration côte-à-côte est incorrect. Consultez le journal des événements de l'application ou utilisez l'outil sxstrace.exe de la ligne de commande pour plus de détails.

Des problèmes comme celui-ci ont été évoqués dans other posts sur StackOverflow. Comment développer des applications qui ne requièrent pas nécessitent des runtimes qui ne sont pas déjà sur le système d'exploitation cible (par exemple, ne nécessitent pas l'installation de packages redistribuables ou d'assemblages côte à côte privés/partagés)? Comment éviter d'utiliser msvc [mpr] 90.dll et simplement utiliser l'API Windows dans \ windows \ system32 *. {Dll, sys}?

Je pense au code qui sort de la démoscene, mais qui n'est souvent pas disponible.

Répondre

4

D'autres ont déjà répondu en ce qui concerne la liaison statique CRT. Si vous voulez aussi un petit binaire en même temps, alors votre meilleur pari est de renoncer complètement au CRT, et d'utiliser seulement les fonctions de l'API Win32 autant que possible. Vous obtiendrez toujours du code CRT, notamment lié au démarrage (c'est-à-dire qui appelle main) et à l'arrêt (atexit gestion etc), mais sinon le lieur ne liera pas les fonctions CRT que vous n'utilisez pas.

Vous pouvez éviter de lier complètement le CRT à l'aide du commutateur du compilateur /Zl. Cela signifie que main ne fonctionnera plus, cependant - vous aurez besoin de définir WinMain (le nom n'a pas d'importance, mais la signature doit correspondre, et il doit être __stdcall), et vous devrez spécifier le nom de votre WinMain-like fonctionne comme un point d'entrée via le commutateur /entry:. Cela vous permettra d'économiser ~ 30 Ko de code CRT (testé sur un .cpp avec un vide main).

Si vous optez pour cette dernière option, vous devrez peut-être également gérer le problème des intrinsèques du compilateur. Certaines fonctions sont nominalement définies par le CRT (et déclarées dans ses en-têtes), mais sont traitées spécialement par le compilateur, de sorte qu'il insère des instructions d'assemblage optimisées au point de l'appel si possible - exemples: memset, strlen, et un bon nombre de fonctions dans <math.h>; une liste complète peut être trouvée here.Puisque vous n'avez pas de CRT, si vous avez besoin de ces fonctions, ou que vous préférez l'éviter, mais préférez l'intrinsèque en raison des performances améliorées (difficile à faire mieux que memset, par exemple), vous devez les déclarer vous-même et utiliser #pragma intrinsic. .: par exemple

// Contains macros and typedef only, so safe to include without CRT. 
// We need it here for size_t. 
#include <stddef.h> 

extern "C" 
{ 
    int abs(int); 
    void* memset(void*, int, size_t); 
} 

#pragma intrinsic(abs, memset) 

int __stdcall main(void*, void*, char*, int) 
{ 
    char tmp[10]; 
    memset(tmp, abs(-123), 10); 
    return 0; 
} 

Le peut être compilé avec ci-dessus:

cl /c /Zl foo.cpp 
link /entry:main foo.obj 
2

Utilisez le CRT statique. Cela ne crée pas de dépendance sur msvc * .dll. Le CRT est directement lié à votre programme. Cela ne crée pas de dépendances, mais augmente la taille de votre exécutable.

Plus d'informations sur les différentes options CRT here.

3

Reliez le CRT de manière statique via le commutateur /MT (et de la même manière MFC, si vous l'utilisez). La liaison statique limite quelque peu ce que vous pouvez faire avec les DLL, mais pour les exécutables simples cela fonctionne comme un charme. (Et si vous expédiez des DLL, vous pouvez toujours envoyer des assemblys privés de toute façon.)

0

Liez statiquement le runtime. MS Visual C++ a l'option/MT pour cela (par défaut est/MD)

0

Je pense que d'une façon de le faire est de tout simplement pas utiliser Visual Studio et comptent plutôt sur la ligne de commande outils SDK. (Vous pouvez encore trouver comment config VS à faire ce que vous voulez, mais cela semble plus dur.) .: par exemple

cl /c app.cpp 
link app.obj ws2_32.lib 
+0

Cela encore apporter le CRT, et est pas vraiment différent d'utiliser VS. –

+0

Ouais, vous pouvez modifier VS pour faire la même chose, mais par défaut VS provoque le problème dans le message original - quelque chose qui ne se produit pas lorsque je fais les choses de la manière suggérée. Tout de même, votre réponse était certainement le résultat le plus éclairant. – Yang