Compile a C++ program with only dependency on kernel32.dll and user32.dll?
I'm working with Visual Stud开发者_运维百科io 2005.
I want to compile a simple program that will work with any Windows 32bit version independent of what c++ runtime library version installed.
This program will call to GetModuleHandle
and GetProcAddress
functions without any other function calls, and then exit, when the exit code is the function address.
How to compile a C++ program with only dependency on kernel32.dll and user32.dll, without any c++ runtime library?
You'll need to define your own entry point instead of using main
or WinMain
. Your entry point is a void function taking no arguments. You have to specify its name to the linker with /entry:funcName
(where funcName
gets replaced by whatever name you gave the function you want to use as the entry point).
When you do this you'll also have to specify the subsystem to the linker, as in /subsystem:console
. It normally deduces the subsystem based on the name of function it finds (i.e., main
-> console, WinMain
-> Windows), but when you use your own entry point, you have to specify it explicitly. Although you probably don't want to very often, you can specify the subsystem explicitly even when you don't specify your own entry point, so (for example) you can use main
as the entry point to a windows subsystem program, or WinMain
as the entry point to a console program.
Set /NODEFAULTLIB
under your project options. In newer versions of Visual C++, you'll also have to turn off stack overrun checks, because those cause the compiler to automatically insert calls to library functions.
EDIT: If you really mean "run on ANY 32-bit Windows version", you're also going to have to use editbin
to change the subsystem version field in the PE header. Otherwise you're restricted to (IIRC) Windows 2000 and later when building with the VC++ 2005 linker, and newer versions of VC++ are even worse (requiring XP by default). Windows 2000 is 5.0, you'd want to specify 3.5 or thereabouts to allow all versions of NT in addition to Win9x.
I'm not sure why everyone's advising against using the standard library. This method assumes you want your code to run on Windows 2000 or later and don't mind losing support for Win 9x. You can still use the C/C++ standard library - You can use the /MT
option in your project's C/C++ Code Generation pages, which will link in the standard library statically.
However, two notes, the first from me: the idea of having a dynamically linked standard library is that any bugs in it will get patched by Windows Update (in theory). If you link the library in statically, you need to redistribute your application to fix standard library bugs. So it isn't advised.
Secondly, from the MSDN article on compiler options:
Caution Do not mix static and dynamic versions of the run-time libraries. Having more than one copy of the run-time libraries in a process can cause problems, because static data in one copy is not shared with the other copy. The linker prevents you from linking with both static and dynamic versions within one .exe file, but you can still end up with two (or more) copies of the run-time libraries. For example, a dynamic-link library linked with the static (non-DLL) versions of the run-time libraries can cause problems when used with an .exe file that was linked with the dynamic (DLL) version of the run-time libraries. (You should also avoid mixing the debug and non-debug versions of the libraries in one process.)
In short, doing this can cause confusion if you try to build in other components linked against a dynamically-linked standard library.
Of course, the other downside is that this will make your executable larger, too.
Edit: the result, under depends.exe, looks like this: (of course, I'm using 64-bit Windows, which is only available for XP and later... if you want to know what this looks like on 32-bit windows, imagine if the 64
s weren't there!).
Check the tiny c libs. Also statically link.
You actually don't need User32.dll either, the only ones you truly cannot remove are Kernel32.dll and Ntdll.dll - those are injected into your process space by PsCreateProcess (i.e. the kernel half of how the kernel creates a new process).
精彩评论