Hello,
I'm new to Code::Blocks and wxWidgets and was wondering if anyone knew of any good techniques for reducing the size of a "Hello World" application using wxWidgets and compiled by mingw. I followed the wiki page tutorial for compiling a Unicode, release build, monolithic DLL with mingw-make, but the final DLL was about 9MB! I got the sample program of Code::Blocks to compile and run correctly with the DLL, but I don't want the program size to be so large. (By the way, I believe there were two instances of C-strings that needed to be converted to Unicode strings with a macro in the sample source code outputted by C::B.)
I also built a Unicode, release build, non-monolithic library (not a DLL) and had success with getting that to work and link with the sample code using C::B and mingw, but the resulting .exe was about 5MB. I removed some extra libraries like opengl and obdc that I wasn't using, but that didn't help the size of the exe much.
With MS VC++ 6.0, I was able to compile the wxWidgets library (release + non Unicode + non DLL), and could link it into a "Hello World" application resulting in an .exe size of only 960KB. I only included the base and core wxWidget libraries and the typical Windows libraries. I would really like to use Code::Blocks instead, especially since it is open-source and contains wxSmith, but I just can't seem to be able to keep the size of the resulting application down.
I tried linking the library I built with MS VC++ 6.0 compiling with the mingw compiler of C::B, but I got a number of link errors. I tried doing that in hopes that I'd get the reduced size I could achieve with VC++. Here is some of the output:
Project : wxWidgets application
Compiler : GNU GCC Compiler (called directly)
Directory : E:\Documents and Settings\Marty\Desktop\xw-vslib-nounicode\
--------------------------------------------------------------------------------
Switching to target: default
Precompiling header: wx_pch.h
Compiling: main.cpp
Linking executable: E:\Documents and Settings\Marty\Desktop\xw-vslib-nounicode\wxWidgets.exe
.objs\main.o: In function `ZN8wxStringaSERKS_':
E:/wxWidgets-2.6.3/include/wx/window.h:(.text+0x4c): undefined reference to `wxAppConsole::CheckBuildOptions(char const*, char const*)'
.objs\main.o: In function `WinMain':
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:297: undefined reference to `wxEntry(HINSTANCE__*, HINSTANCE__*, char*, int)'
.objs\main.o: In function `ZN7MyFrameC2EP7wxFrameRK8wxString':
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:22: undefined reference to `wxFrameNameStr'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:22: undefined reference to `wxDefaultSize'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:22: undefined reference to `wxDefaultPosition'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:23: undefined reference to `wxMenuBar::wxMenuBar()'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:32: undefined reference to `wxFrameBase::SetMenuBar(wxMenuBar*)'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:32: undefined reference to `wxFrame::~wxFrame()'
.objs\main.o: In function `ZN7MyFrameC1EP7wxFrameRK8wxString':
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:22: undefined reference to `wxFrameNameStr'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:22: undefined reference to `wxDefaultSize'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:22: undefined reference to `wxDefaultPosition'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:23: undefined reference to `wxMenuBar::wxMenuBar()'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:32: undefined reference to `wxFrameBase::SetMenuBar(wxMenuBar*)'
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:32: undefined reference to `wxFrame::~wxFrame()'
.objs\main.o: In function `ZN7MyFrameD2Ev':
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:36: undefined reference to `wxFrame::~wxFrame()'
.objs\main.o: In function `ZN7MyFrameD1Ev':
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:36: undefined reference to `wxFrame::~wxFrame()'
.objs\main.o: In function `ZN7MyFrameD0Ev':
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:36: undefined reference to `wxFrame::~wxFrame()'
.objs\main.o: In function `ZN7MyFrame6OnQuitER14wxCommandEvent':
E:/Documents and Settings/Marty/Desktop/xw-vslib-nounicode/main.cpp:41: undefined reference to `wxWindowBase::Close(bool)'
...
Did anyone ever manage to make a wxWidgets application with a file size that is less than 2MB? Also, does anyone know why the functions are not linking correctly when I use the MS VC++ 6.0 library? I am assuming that mingw's link program is not compatable with VC++ libraries.
Thanks! Btw, C::B looks really great and I hope to use it for all of my C++ applications from now on!
Look at the wxWidgets site, there is a section in the FAQ dealing with this issue.
In short words, it boils down to this:
1. wxWidgets is huge
2. GCC does not do a good job deadstripping code here, so it is even bigger
3. strip your executables and use an exe packer
Unluckily, there is no real solution. If you are courageous, you can try to disable wxWidgets components that you don't need, but chances are good that you'll just break it, and the gains are not *that* big, either.
I appreciate the quick reply! I just took a look and saw the section in the FAQ you were talking about. It said that most developers use MSVC++ to compile their wxWidgets applications because it (most likely) outputs the smallest size. I also stripped my executables of the debug information but that didn't help too much. I'm going to take a look at some exe packers.
I want to note that if you're really worried about executable size, you can still use the MSVC compiler inside Code::Blocks and even with wxSmith. :)
See here: http://wiki.codeblocks.org/index.php?title=Integrating_Microsoft_Visual_C_6_with_Code::Blocks_IDE
Thanks a lot for the link and fast reply. I didn't realize MS VC++ 6 would work with C::B. I followed all of the instructions, and got C::B to compile the sample Windows GUI application with the VC++ 6 compiler. However, when I tried opening up my previous project and compiled, I had to remove a lot of compiler arguments that were not being recognized. This removed the pre-compiled header functionality and I'm not really sure at the present moment how to fix that.
Also, I now get a large number of link errors that state the "MSVCRT.lib" library is conflicting with others, but the strange thing is that it is not listed in the included libraries of C::B. I suppose it is automatically included. I'm am going to take a look into figuring out the command line argument for not including it.
Here is some sample output:
Switching to target: default
main.cpp
Linking executable: E:\Documents and Settings\Martin Piecyk\Desktop\xw-vslib-nounicode\wxWidgets.exe
MSVCRT.lib(MSVCRT.dll) : error LNK2005: _free already defined in LIBC.lib(free.obj)
MSVCRT.lib(MSVCRT.dll) : error LNK2005: _malloc already defined in LIBC.lib(malloc.obj)
MSVCRT.lib(MSVCRT.dll) : error LNK2005: _toupper already defined in LIBC.lib(toupper.obj)
Ok, now I figured out how to stop MSVCRT.lib (and LIBC.lib, I forgot to mention this one in my last post) from automatically being included. In the linker options, I had to add these arguments:
/NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBC
But now when I compile, I'm getting link errors about missing the delete operator. The libraries I included were:
wxmsw26_core
wxbase26
shell32
comctl32
kernel32
user32
gdi32
comdlg32
Here is the error I am getting. The delete operator seems to be the only thing I am missing. Does anyone have any ideas?
wxbase26.lib(clntdata.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
wxmsw26_core.lib(timercmn.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
wxmsw26_core.lib(timer.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
wxmsw26_core.lib(dcprint.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
wxmsw26_core.lib(clipcmn.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
In the meantime I compiled the Unicode library version of wxWidgets with VSC++6 and created a new project in C::B which uses it and I get the same error, (except this time the library name includes a "u" for Unicode.)
wxbase26u.lib(ipcbase.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
wxbase26u.lib(regconf.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
wxbase26u.lib(dir.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
wxbase26u.lib(dde.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
...
Just in case, the commandline I give to the MSVC compiler when I compile a simple wxWidgets program (Release, Unicode) is:
Compiler: wx-config --cflags --prefix=D:\Develop\src\wxWidgets-2.6.3vc
/MD /DWIN32 /D__WXMSW__ /D_UNICODE /ID:\Develop\src\wxWidgets-2.6.3vc\lib\vc_lib\mswu
/ID:\Develop\src\wxWidgets-2.6.3vc\include /I. /D_WINDOWS /GR /EHsc
Linker: wx-config --libs --prefix=D:\Develop\src\wxWidgets-2.6.3vc
/LIBPATH:D:\Develop\src\wxWidgets-2.6.3vc\lib\vc_lib wxmsw26u_xrc.lib wxmsw26u_html.lib wxmsw26u_adv.lib
wxmsw26u_core.lib wxbase26u_xml.lib wxbase26u_net.lib wxbase26u.lib wxtiff.lib wxjpeg.lib wxpng.lib wxzlib.lib
wxregexu.lib wxexpat.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib
comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib wsock32.lib odbc32.lib