Reputation: 89
Given a simple program:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev,
LPSTR lpCmdLine, int nCmdShow)
{
return 0;
}
If I run g++ a.cpp
it works fine.
However, running g++ -c a.cpp && ar rcs a.a a.o && g++ a.a
gives the following error:
c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/4.8.1/../../../../i686-w64-mingw32/lib/../lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x39): undefined reference to `WinMain@16'
collect2.exe: error: ld returned 1 exit status
Any insight as to why this occurs? How can I link a program with only .a files?
Upvotes: 3
Views: 3753
Reputation: 769
I am using Code::Blocks. Today i have same problem with WinMain in static library. Changing order of libraries does not works in my case. I finally solved it by adding -lmingw32
to Project/Build options/Linker settings/Other linker options.
Upvotes: 0
Reputation: 20878
The gcc ld
linker handles *.a
static libraries a little differently from *.o
object files. In particular, symbols from the static library do not get included into the final binary image executable unless an object file or another static library linked in earlier uses it.
Additionally, the order you pass in the static libraries matter for ld
. For example, say libb.a
needs a function that's in liba.a
. If you link it like so:
g++ -Wall example.cpp -o example.exe -la -lb
This will fail to resolve because when liba
is processed it doesn't see what symbols -lb
requires (libb
hasn't been processed yet). The only symbols retrieved from liba.a
is everything it has seen up to that point.
If you apply the above process to your question it becomes clear why WinMain
isn't getting resolved.
g++ a.a
When ld
processes a.a
it says "oh nothing is using WinMain
so I won't include it"; and that is true up that point of processing since no other object files are provided before it.
What you don't see above is that mingw, by default, also includes a bunch of important boilerplate code needed for your program to work. One of these is crt0_c.o
from mingw32.a
which makes up part of the mingw runtime that does call your WinMain
.
There are two ways to ensure that WinMain
from your a.a
gets included:
Use -Wl,--whole-archive
to force inclusion of all symbols in a.a
so they're available for symbol resolution. Append -Wl,--no-whole-archive
afterwards so it doesn't erroneously apply this to other libraries that comes after. eg.
g++ -o example.exe -Wl,--whole-archive a.a -Wl,--no-whole-archive
The second way is to include mingw32.a
manually before a.a
so WinMain
becomes a pending unresolved symbol when a.a
is processed:
g++ -o example.exe -lmingw32 a.a
or
g++ -o example.exe libmingw32.a a.a
But you'll probably need to fully qualify the path to libmingw32.a
or else the linker won't find it.
Upvotes: 7
Reputation: 2470
.a files are static libraries, as far as the linker is concerned. The linker only takes objects out of the archives that define symbols that are currently unresolved. Thus, without any object files referencing symbols defined in the .a files, they won't be pulled in. The linker output in your example is empty, thus WinMain is not defined.
Actually it appears to work when you define the standard main(). I assume that's because of there being a reference to main() required by the language standard. There is also a gcc / ld command line option to generate a reference to a symbol. Try adding -u WinMain@16
before the .a file.
Upvotes: 0