Author Topic: How to reduce the size of wxWidgets .exes produced by mingw?  (Read 13198 times)

marty

  • Guest
How to reduce the size of wxWidgets .exes produced by mingw?
« on: August 08, 2006, 12:12:47 am »
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:

Code
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!

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #1 on: August 08, 2006, 12:20:57 am »
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.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

takeshimiya

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #2 on: August 08, 2006, 12:54:52 am »
Here is the link: http://www.wxwidgets.org/wiki/index.php/Reducing_Executable_Size

Quote
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 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

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #3 on: August 08, 2006, 01:37:31 am »
Quote
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.

Quote
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:
Code
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)

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #4 on: August 08, 2006, 01:51:58 am »
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?

Code
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)

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #5 on: August 08, 2006, 02:18:19 am »
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.)

Code
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)
...

takeshimiya

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #6 on: August 08, 2006, 02:43:21 am »
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
Code
/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
Code
/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

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #7 on: August 08, 2006, 02:49:36 am »
After changing the link arguments from

/NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBC

to

/NODEFAULTLIB:LIBC

the application compiled with no errors. However, when I ran the default application produced by C::B, no frame showed up and a runtime error occurred. I changed the source code to the "Hello world" tutorial on wxWidget's website (which I can get to compile and run correctly in the VS IDE) and this time there was no runtime error, but an infinite loop seemed to be running and no frame showed up. I am very confused. Does anyone have any tips with my problem?

Otherwise, I think I'll use C::B and mingw for development (since I can get that to work with wxWidgets and C::B has more features than VS6 such as the expandable brackets and wxSmith) and then load the same exact source files into the VS IDE when I'm ready to release the wxWidgets application (which will be the only time I care about the size).

I'm just curious, but does anyone know if the Linux versions of gcc and g++ produce large wxWidgets executables like their Windows counterparts?

Thanks.

sethjackson

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #8 on: August 08, 2006, 02:53:01 am »
After changing the link arguments from

/NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBC

to

/NODEFAULTLIB:LIBC

the application compiled with no errors. However, when I ran the default application produced by C::B, no frame showed up and a runtime error occurred. I changed the source code to the "Hello world" tutorial on wxWidget's website (which I can get to compile and run correctly in the VS IDE) and this time there was no runtime error, but an infinite loop seemed to be running and no frame showed up. I am very confused. Does anyone have any tips with my problem?

Otherwise, I think I'll use C::B and mingw for development (since I can get that to work with wxWidgets and C::B has more features than VS6 such as the expandable brackets and wxSmith) and then load the same exact source files into the VS IDE when I'm ready to release the wxWidgets application (which will be the only time I care about the size).

I'm just curious, but does anyone know if the Linux versions of gcc and g++ produce large wxWidgets executables like their Windows counterparts?

Thanks.

On my OpenBSD box the C++ (not wxWidgets) hello world is half the size of the Windows version with the same version of GCC.
I have tried compiling wx so I really don't know......

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #9 on: August 08, 2006, 03:08:25 am »
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
Code
/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
Code
/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

Takeshi, I noticed that in my "E:\wxWidgets-2.6.3" directory I have "wx-config.in". Does this mean I have to ./configure wxWidgets to produce "wx-config"?

Anyway, I copied this to my compiler command line:

/MD /DWIN32 /D__WXMSW__ /D_UNICODE /D_WINDOWS /GR /EHsc

and now the executable works! Thanks a million Takeshi.

On my OpenBSD box the C++ (not wxWidgets) hello world is half the size of the Windows version with the same version of GCC.
I have tried compiling wx so I really don't know......

Ok, so non-Windows GCC is more likely better in outputted program's size than the Windows GCC for non-wxWidgets. Thank you.

takeshimiya

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #10 on: August 08, 2006, 03:23:40 am »
Otherwise, I think I'll use C::B and mingw for development (since I can get that to work with wxWidgets and C::B has more features than VS6 such as the expandable brackets and wxSmith) and then load the same exact source files into the VS IDE when I'm ready to release the wxWidgets application (which will be the only time I care about the size).
Or a more comfortable approach: have an "GCC Debug" target, and a "VC Release" target, all inside in Code::Blocks.

I'm just curious, but does anyone know if the Linux versions of gcc and g++ produce large wxWidgets executables like their Windows counterparts?
In linux you'll have very small executable sizes thanks to this:
-Most distros already include stdlib++ as a shared library.
-Most distros already include wxWidgets as a shared library.
-Most distros already include wxWidgets dependencies (libpng, libjpeg, zlib, etc) as shared libraries.

On windows on the other side, when using linking to stdlib++ you always link statically, you can't link dinamycally to it
(unless you use another STL implementation).
As for the wxWidgets libraries and it's dependencies, you can link dinamycally to them, but obviously they don't come with Windows. :P


Takeshi, I noticed that in my "E:\wxWidgets-2.6.3" directory I have "wx-config.in". Does this mean I have to ./configure wxWidgets to produce "wx-config"?
Oh no, ignore that part :P It's just a program I've wrote myself that I'm wanting to get some time to integrate with C::B wizards.

Anyway, I copied this to my compiler command line:
/MD /DWIN32 /D__WXMSW__ /D_UNICODE /D_WINDOWS /GR /EHsc
and now the executable works! Thanks a million Takeshi.
:D

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #11 on: August 08, 2006, 03:32:21 am »
Cool, thanks for all of the information! I didn't know most of it.

I'm going to go with the "GCC Debug" and "VC Release" method, especially since I already have Unicode libraries of wxWidgets compiled for each.

After trial-and-error, I know for sure that the "/EHsc" compile switch made both the tutorial and sample output for C::B run correctly. (When it's removed the programs fail.) I am curious what it does. After looking at Google I think it has to do something with exception handling and I tried accessing cl.exe through the command line to get information but it wouldn't run because of a dll problem.

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #12 on: August 08, 2006, 03:49:43 am »
Hmmm... Shouldn't the content on

http://wiki.codeblocks.org/index.php?title=FAQ
Quote
Q: Is it possible to use Visual C++ 6.0 with Code::Blocks?

A: MSVC++ 6 is not a C++ compiler. It was made before the C++ standard, so it compiles some language that isn't C++. Upgrade.

be changed to link to the page you showed me, Takeshi?

http://wiki.codeblocks.org/index.php?title=Integrating_Microsoft_Visual_C_6_with_Code::Blocks_IDE

Anyway, the wiki doesn't really answer the question.

takeshimiya

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #13 on: August 08, 2006, 03:58:39 am »
After trial-and-error, I know for sure that the "/EHsc" compile switch made both the tutorial and sample output for C::B run correctly. (When it's removed the programs fail.) I am curious what it does. After looking at Google I think it has to do something with exception handling and I tried accessing cl.exe through the command line to get information but it wouldn't run because of a dll problem.

The "dll problem" you get there is likely to be the abscence of the dlls in your path.
That's why MS have included a vcsetvars32.bat (or something like) so you can use the compiler from command line without cluttering your path.

Hmmm... Shouldn't the content on

http://wiki.codeblocks.org/index.php?title=FAQ
Quote
Q: Is it possible to use Visual C++ 6.0 with Code::Blocks?

A: MSVC++ 6 is not a C++ compiler. It was made before the C++ standard, so it compiles some language that isn't C++. Upgrade.

be changed to link to the page you showed me, Takeshi?

http://wiki.codeblocks.org/index.php?title=Integrating_Microsoft_Visual_C_6_with_Code::Blocks_IDE

Anyway, the wiki doesn't really answer the question.

Of course, it haves to be changed accordingly, it's a Wiki after all, so you're encouraged to edit it yourself. :)

marty

  • Guest
Re: How to reduce the size of wxWidgets .exes produced by mingw?
« Reply #14 on: August 08, 2006, 04:12:13 am »
Done. Thanks again for your help!