Can't compile using wxWidgets as DLL Topic is solved

If you are using wxDev-C++ for your wxWidgets design, please ask your questions here instead of in IDE Related.
Post Reply
Guido
Earned a small fee
Earned a small fee
Posts: 20
Joined: Mon Apr 23, 2007 6:52 pm
Location: Italy

Can't compile using wxWidgets as DLL

Post by Guido » Tue May 08, 2007 12:34 pm

I want to reduce the size of my executables.
So I compiled the wxWidgets as DLL with MSYS using as a reference this: http://www.wxwidgets.org/wiki/index.php ... MSYS-MinGW
and the last post in this topic (changing DLL=1 with SHARED =1): http://forums.wxwidgets.org/viewtopic.php?t=10121
this is the procedure I followed:
I created a new build directory
with MSYS I ran configure to 'configure' the custom built wxWidgets ( $ ../configure --with-msw --enable-debug )
I made the wx ( $ make SHARED=1)
I installed it into MSYS ( $ make install SHARED=1)

As a result I got ten dlls:
wxbase28d_gcc_custom.dll
wxbase28d_net_gcc_custom.dll
wxbase28d_xml_gcc_custom.dll
wxmsw28d_adv_gcc_custom.dll
wxmsw28d_aui_gcc_custom.dll
wxmsw28d_core_gcc_custom.dll
wxmsw28d_html_gcc_custom.dll
wxmsw28d_qa_gcc_custom.dll
wxmsw28d_richtext_gcc_custom.dll
wxmsw28d_xrc_gcc_custom.dll

At this point I wanted to recompile an old project made with wxDev-C++ 6.10.2 (that uses the MingW compiler) to obtain a size reduced executable.
Firstable I tried putting WXUSINGDLL=1 in Tools->Complier Options->Add these commands to the Make Line:
But nothing changes: I get an .exe of 3MB that doesn' need the DLL (because I think it still links statically to the wxWidgets libraries)
Then i changed the ProjectApp.h from this:

Code: Select all

#ifndef __PROJECT1FRMApp_h__
#define __PROJECT1FRMApp_h__

#ifdef __BORLANDC__
	#pragma hdrstop
#endif

#ifndef WX_PRECOMP
	#include <wx/wx.h>
#else
	#include <wx/wxprec.h>
#endif
to this:

Code: Select all

#ifndef __PROJECT1FRMApp_h__
#define __PROJECT1FRMApp_h__

//I added the following line
#define WXUSINGDLL 

#ifdef __BORLANDC__
	#pragma hdrstop
#endif

#ifndef WX_PRECOMP
	#include <wx/wx.h>
#else
	#include <wx/wxprec.h>
#endif
But the project doesn't compile: i get a lot of
[Linker Error] undefined reference to `_imp___...'
Thiking that the problem is that the compiler can't find the DLLs I cut&pasted the ten DLLs I got from the compilation of wxWidgets first in C:\...\Dev-Cpp\lib and then in C:\...\Dev-Cpp\bin but nothing changes.

So what's wrong? Anybody could help me?
I tried a lot of searches in the forum but I did't find something that could explain the error.

P.S.My OS is Windows XP and the compiler used by wxDev-C++ is MingW
Last edited by Guido on Wed May 09, 2007 1:45 pm, edited 1 time in total.

lowjoel
Moderator
Moderator
Posts: 1511
Joined: Sun Jun 19, 2005 11:37 am
Location: Singapore
Contact:

Post by lowjoel » Tue May 08, 2007 1:35 pm

Can Guru or Tony please help this dude, I personally use a different dir system, but I think that he's got his library path... sorta mixed up.

The Make line is sent to make, it doesn't affect the compiler unless you have overridden the makefile or use MAKE variables in your project options.

Joel

tbreina
Moderator
Moderator
Posts: 1289
Joined: Thu Nov 25, 2004 7:38 pm
Location: Coronado, CA

Re: Can't compile using wxWidgets as DLL

Post by tbreina » Tue May 08, 2007 4:42 pm

Guido wrote:I want to reduce the size of my executables.
So I compiled the wxWidgets as DLL with MSYS using as a reference this: http://www.wxwidgets.org/wiki/index.php ... MSYS-MinGW
...
But the project doesn't compile: i get a lot of
[Linker Error] undefined reference to `_imp___...'
Thiking that the problem is that the compiler can't find the DLLs I cut&pasted the ten DLLs I got from the compilation of wxWidgets first in C:\...\Dev-Cpp\lib and then in C:\...\Dev-Cpp\bin but nothing changes.
I think you've probably mixed and match directories between the DLL version and the monolithic version of wxWidgets.

First, you didn't need to use MSYS to compile. All you needed to do was use the same MingW compiler that wxDev-C++ uses. I'm not sure if it will matter, but it might be a good idea to give it a try. Mal has a list of instructions (just modify them to use the DLL just like you did for MSYS): http://forums.wxwidgets.org/viewtopic.php?t=1764. Again, it may not make a difference, but it doesn't hurt.

Second, I would keep the lib and include directories for your DLL version of wxWidgets separate from the ones for your monolithic version (i.e. the one that came included). Essentially, just change all of your include and lib paths from the original to your new wxWidgets libraries.

Finally, if this still doesn't work, then please send the compiler output. It may help to see the errors that are being thrown. It will also help to see if you're including the right directories.

Let me know and we'll work you through the process...

-Tony
Everybody's got something to hide except for me and my monkey.

Guido
Earned a small fee
Earned a small fee
Posts: 20
Joined: Mon Apr 23, 2007 6:52 pm
Location: Italy

Re: Can't compile using wxWidgets as DLL

Post by Guido » Tue May 08, 2007 6:48 pm

tbreina wrote:First, you didn't need to use MSYS to compile. All you needed to do was use the same MingW compiler that wxDev-C++ uses. I'm not sure if it will matter, but it might be a good idea to give it a try. Mal has a list of instructions (just modify them to use the DLL just like you did for MSYS): http://forums.wxwidgets.org/viewtopic.php?t=1764
Ok, I compiled again wxWidget following the istructions of the link you posted (this is how I modified the make command in the batch file:
mingw32-make -f makefile.gcc MONOLITHIC=1 SHARED=1 BUILD=release so this time i got only one allinclusive dll library).
Second, I would keep the lib and include directories for your DLL version of wxWidgets separate from the ones for your monolithic version (i.e. the one that came included). Essentially, just change all of your include and lib paths from the original to your new wxWidgets libraries.
To see the differences first I tried to compile the project Just copy&pasting the dll in Dev-Cpp/lib and putting the #define WXUSINGDLL line in the ProjectApp.h
This is the output of the compiler:

Code: Select all

Compilatore: Default GCC compiler
Building Makefile: "C:\Prova\Makefile.win"
Esecuzione di  make...
mingw32-make.exe -f "C:\Prova\Makefile.win" all 
windres.exe --input-format=rc -o Objects/MingW/Progetto1_private.res --include-dir "C:/PROGRA~1/Dev-Cpp/include/common" Objects/MingW/PROGET~1.RC -O coff g++.exe Objects/MingW/Progetto1App.o Objects/MingW/Progetto1Frm.o Objects/MingW/Progetto1_private.res -o "Output\MingW\Progetto1.exe" -L"C:/Programmi/Dev-Cpp/Lib" -mwindows -lwxmsw28 -lwxmsw28_gl -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregex -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lwsock32 -lodbc32 -lopengl32   Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x19): undefined reference to `_imp___ZN12wxAppConsole17CheckBuildOptionsEPKcS1_'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x30): undefined reference to `_imp___ZN5wxAppC2Ev'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x52): undefined reference to `_imp___ZN12wxAppConsole14ms_appInstanceE'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x83): undefined reference to `_imp___Z7wxEntryP11HINSTANCE__S0_Pci'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xa8): undefined reference to `_imp___ZN12wxStringBase4nposE'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xbb): undefined reference to `_imp___ZN12wxStringBase8InitWithEPKcjj'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xd1): undefined reference to `_imp__wxDefaultSize' Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xdb): undefined reference to `_imp__wxDefaultPosition'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x182): undefined reference to `_imp___ZN12wxAppConsole12ms_appInitFnE'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text$_ZN15Progetto1FrmAppD1Ev[Progetto1FrmApp::~Progetto1FrmApp()]+0x14): undefined reference to `_imp___ZN5wxAppD2Ev'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text$_ZN15Progetto1FrmAppD0Ev[Progetto1FrmApp::~Progetto1FrmApp()]+0x15): undefined reference to `_imp___ZN5wxAppD2Ev'
collect2: ld returned 1 exit status mingw32-make.exe: *** [Output/MingW/Progetto1.exe] Error 1 Esecuzione terminata
Then I did like you suggested: I kept separated the new dll library and the ones included in sxDev-C++ then in Project Options I added C:\wxWidgets\wxWidgets-2.8.3\lib\gcc_dll (where the dll library was created) in Library Directories and in Include Directories I added C:\wxWidgets\wxWidgets-2.8.3\include and C:\wxWidgets\wxWidgets-2.8.3\contrib\include
This thime the compiler output was:

Code: Select all

Compilatore: Default GCC compiler
Building Makefile: "C:\Prova\Makefile.win"
Esecuzione di  make...
mingw32-make.exe -f "C:\Prova\Makefile.win" all 
windres.exe --input-format=rc -o Objects/MingW/Progetto1_private.res --include-dir "C:/PROGRA~1/Dev-Cpp/include/common" Objects/MingW/PROGET~1.RC -O coff g++.exe Objects/MingW/Progetto1App.o Objects/MingW/Progetto1Frm.o Objects/MingW/Progetto1_private.res -o "Output\MingW\Progetto1.exe" -L"C:/Programmi/Dev-Cpp/Lib" -L"C:/wxWidgets/wxWidgets-2.8.3/lib/gcc_dll" -mwindows -lwxmsw28 -lwxmsw28_gl -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregex -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lwsock32 -lodbc32 -lopengl32   Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x19): undefined reference to `_imp___ZN12wxAppConsole17CheckBuildOptionsEPKcS1_'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x30): undefined reference to `_imp___ZN5wxAppC2Ev'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x52): undefined reference to `_imp___ZN12wxAppConsole14ms_appInstanceE'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x83): undefined reference to `_imp___Z7wxEntryP11HINSTANCE__S0_Pci'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xa8): undefined reference to `_imp___ZN12wxStringBase4nposE'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xbb): undefined reference to `_imp___ZN12wxStringBase8InitWithEPKcjj'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xd1): undefined reference to `_imp__wxDefaultSize' 
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0xdb): undefined reference to `_imp__wxDefaultPosition'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text+0x182): undefined reference to `_imp___ZN12wxAppConsole12ms_appInitFnE'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text$_ZN15Progetto1FrmAppD1Ev[Progetto1FrmApp::~Progetto1FrmApp()]+0x14): undefined reference to `_imp___ZN5wxAppD2Ev'
Objects/MingW/Progetto1App.o:Progetto1App.cpp:(.text$_ZN15Progetto1FrmAppD0Ev[Progetto1FrmApp::~Progetto1FrmApp()]+0x15): undefined reference to `_imp___ZN5wxAppD2Ev'
collect2: ld returned 1 exit status mingw32-make.exe: *** [Output/MingW/Progetto1.exe] Error 1 Esecuzione terminata
I don't know, maybe the error is in how I modify the ProjectApp.h (I just add the #define WXUSINGDLL line, everything else is unchanged and I don't modify ProjectApp.cpp ProjectFrm.h and ProjectFrm.cpp)

tbreina
Moderator
Moderator
Posts: 1289
Joined: Thu Nov 25, 2004 7:38 pm
Location: Coronado, CA

Post by tbreina » Wed May 09, 2007 7:47 am

I went ahead and built the DLL library on my machine to figure out how to get it to work. I can try to make it a devpak if you'd like, but here are the steps:

1. Create the DLL like you did with MingW.

First copy c:\wxWidgets-2.8.3\Include\wx\msw\setup.h up to c:\wxWidgets-2.8.3\Include\wx (so one directory up).

Now build the DLL:

Code: Select all

set WXWIN=c:\wxWidgets-2.8.3
set path=c:\PROGRA~1\Dev-Cpp\bin;%path% 

mingw32-make -f makefile.gcc BUILD=release MONOLITHIC=1 USE_OPENGL=1 RUNTIME_LIBS=static USE_RTTI=0 USE_EXCEPTIONS=1 SHARED=1
Now we should have a directory called c:\wxWidgets-2.8.3\lib\gcc_dll which contains monolithic dlls of wxWidgets (which are needed at runtime) and the static libs (which are the ones you'll link to at compile time).

2. I chose to keep the new include and lib files where they were (so in C:\wxWidgets-2.8.3\include and C:\wxWidgets-2.8.3\lib\gcc_lib respectively).

Start wxDev-C++ and go to Tools->Compiler Options->Directories->C++ Includes. Delete all of the include directories and instead use these:

Code: Select all

C:\Program Files\Dev-Cpp\include
C:\wxWidgets-2.8.3\include
C:\wxWidgets-2.8.3\lib\gcc_dll\msw
C:\wxWidgets-2.8.3\include\wx
C:\wxWidgets-2.8.3\include\wx\msw
C:\wxWidgets-2.8.3\include\wx\generic
C:\wxWidgets-2.8.3\include\wx\private
C:\wxWidgets-2.8.3\include\wx\msdos
C:\wxWidgets-2.8.3\include\wx\html
C:\wxWidgets-2.8.3\include\wx\protocol
C:\wxWidgets-2.8.3\include\wx\richtext
C:\wxWidgets-2.8.3\include\wx\univ
C:\wxWidgets-2.8.3\include\wx\xrc
C:\wxWidgets-2.8.3\include\wx\xml
Go to the Libraries tab and replace the current entry with this:

Code: Select all

C:\wxWidgets-2.8.3\lib\gcc_dll
Hit the OK button.

3. Now create a new wxWidgets project (File->New->Project->wxWidgets frame). Go to Project->Project Options->Parameters. In the text box labeled "Preprocessor Definitions" add the entry "WXUSINGDLL" (without the quotes). This takes the place of the #define statement you've been adding to your C++ programs (so it shouldn't be needed in the code). You can modify the template file if you like so that the WXUSINGDLL is always included when you create new projects.

4. Go ahead and build your project. Note that there are 3 DLLs you'll need to actually run the project: wxmsw28_gcc_custom.dll, wxmsw28_gl_gcc_custom.dll, and mingwm10.dll. The first 2 are in your c:\wxWidgets-2.8.3\lib\gcc_dll directory and the third is in your C:\Program Files\Dev-Cpp\bin directory. You'll need to either copy these in the same directory as your executable or into a common directory like c:\windows\system.

-Tony
Everybody's got something to hide except for me and my monkey.

Guido
Earned a small fee
Earned a small fee
Posts: 20
Joined: Mon Apr 23, 2007 6:52 pm
Location: Italy

Post by Guido » Wed May 09, 2007 1:56 pm

tbreina wrote:I went ahead and built the DLL library on my machine to figure out how to get it to work.
Thank you very very much!!! :D You've been really kind!
I followed all the steps you wrote and now everything works perfeclty :D

So maybe the mistake was in the fact that I didn't modified the libraries and include paths in Tools->Compiler Options->... but only in Project Options->Directories->...

Just another question.
Do you think is really necessary to delete all of the old librearies and include directories paths? Or could I just add the new paths so for each project I will be able to decide if compiling it with the dll or the static libraries just by putting (or not) WXUSINGDLL amongst the "Preprocessor Definitions"?

Thanks again :D

tbreina
Moderator
Moderator
Posts: 1289
Joined: Thu Nov 25, 2004 7:38 pm
Location: Coronado, CA

Post by tbreina » Wed May 09, 2007 2:35 pm

Guido wrote:
tbreina wrote:So maybe the mistake was in the fact that I didn't modified the libraries and include paths in Tools->Compiler Options->... but only in Project Options->Directories->...

Just another question.
Do you think is really necessary to delete all of the old librearies and include directories paths? Or could I just add the new paths so for each project I will be able to decide if compiling it with the dll or the static libraries just by putting (or not) WXUSINGDLL amongst the "Preprocessor Definitions"?

Thanks again :D
I think the problem was that we add the include/lib directories for the Tools->Compiler Options BEFORE those in the Project->Project Options. So the monolithic, non-DLL stuff was being grabbed first by make.exe. I'll try to remember to correct this in the next version so that the directories specified in the Project Options are declared first (so that they take precedence).

There's probably no need to delete those directories in Tools->Compiler Options so long as you put the DLL directories at the TOP of the list.

Another way to do it. You can declare a new compiler profile. So you'll have one profile for MingW monolithic, non-DLL; one for MS VC++; and one for MingW monolithic, DLL. This way you can switch between compiler profiles on the fly and build in whatever way you like. This is probably the better than changing the default MingW profile (as I instructed).

-Tony
Everybody's got something to hide except for me and my monkey.

Guido
Earned a small fee
Earned a small fee
Posts: 20
Joined: Mon Apr 23, 2007 6:52 pm
Location: Italy

Post by Guido » Wed May 09, 2007 3:28 pm

Understood, thank you very much for the thorough explanation!

Post Reply