How to build standalone wxWidgets application

Do you have a question about makefiles, a compiler or IDE you are using and need to know how to set it up for wxWidgets or why it doesn't compile but other IDE's do ? Post your questions here.
ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

How to build standalone wxWidgets application

Post by ValeV » Tue Mar 12, 2019 3:30 pm

I made a wxWidgets project, where, when making a project, I checked "use wxWIdgets DLL", "wxWidgets is build as a monolithic library", "enable unicode" and "create and use precompiled header".

I made a working program out of it. When I wanted to run it with running .exe file (in [project folder]/bin/Release/), it says it's missing wxmsw312u_gcc_custom.dll.

So I googled and and found out that I must uncheck "use wxWidgets DLL" when making a new wxWidgets project. I did that, ran new project, and got "wx/setup.h: no such file or directory".

So now I don't know how to proceed. I don't know much about wxWidgets, I learn new stuff on the go.

My build.cfg file content (I think it shows how I built wxWidgets):
WXVER_MAJOR=3
WXVER_MINOR=1
WXVER_RELEASE=2
BUILD=release
MONOLITHIC=1
SHARED=1
UNICODE=1
TOOLKIT=MSW
TOOLKIT_VERSION=
WXUNIV=0
CFG=
VENDOR=custom
OFFICIAL_BUILD=0
DEBUG_FLAG=1
DEBUG_INFO=default
RUNTIME_LIBS=dynamic
USE_EXCEPTIONS=1
USE_RTTI=1
USE_THREADS=1
USE_AUI=1
USE_GUI=1
USE_HTML=1
USE_MEDIA=1
USE_OPENGL=1
USE_QA=0
USE_PROPGRID=1
USE_RIBBON=1
USE_RICHTEXT=1
USE_STC=1
USE_WEBVIEW=1
USE_XRC=1
COMPILER=gcc
COMPILER_VERSION=
CC=gcc
CXX=g++
CFLAGS=
CPPFLAGS=
CXXFLAGS=-fno-keep-inline-dllexport
LDFLAGS=

Basically I am stuck on how to make a standalone application out of my existing project. Any help will be much appreciated.

Cheer!
-ValeV

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3087
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: How to build standalone wxWidgets application

Post by ONEEYEMAN » Tue Mar 12, 2019 5:04 pm

Hi,
How did you build the wxWidgets?
I presume that you are using Code::Blocks with the MinGW/gcc.
The settings for your project in C::B have to match the settings you build the library with.

So if you build the library as "Monol,ithic, DLL" you (initial) settings are correct.

Now, since you are saying that the project was built successfully but didn't run:

all you needed to do is grab the appropriate DLL (in your case wxmsw312u_gcc_custom.dll) and copy it to the directory where your executable is. Continue doing so until the program is able to run.

If you want to avoid this - rebuild wxWidgets as static, non-monolithic library, then create a new project with appropriate settings, build and run.

Thank you.

P.S.: Why did you want to use "monolithic" build?

ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

Re: How to build standalone wxWidgets application

Post by ValeV » Wed Mar 13, 2019 7:15 am

ONEEYEMAN wrote:
Tue Mar 12, 2019 5:04 pm
Hi,
How did you build the wxWidgets?
I presume that you are using Code::Blocks with the MinGW/gcc.
The settings for your project in C::B have to match the settings you build the library with.

So if you build the library as "Monol,ithic, DLL" you (initial) settings are correct.

Now, since you are saying that the project was built successfully but didn't run:

all you needed to do is grab the appropriate DLL (in your case wxmsw312u_gcc_custom.dll) and copy it to the directory where your executable is. Continue doing so until the program is able to run.

If you want to avoid this - rebuild wxWidgets as static, non-monolithic library, then create a new project with appropriate settings, build and run.

Thank you.

P.S.: Why did you want to use "monolithic" build?
Thank you for your answer.
Yes you are right, I have CodeBlocks with MinGW

I will first try copying DLL files, if that won't work, I will rebuild wxWidgets.


>Why did you want to use "monolithic" build?

To be honest I have no idea what that means. I followed some guide from wiki on how to build wxWidgets and used settings from there.

How do I have to build wxWidgets, so that I will be able to have a standalone .exe application at the end, without additional DLL files?
Also, will my already existing application work with this new build?

ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

Re: How to build standalone wxWidgets application

Post by ValeV » Wed Mar 13, 2019 7:30 am

UPDATE: I copied missing DLL file and ran the program successfully, BUT the program is crashing and not working as it does when I run it from CodeBlocks.

I suppose my solution is to rebuild wxWidgets? What are the options I should use?

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3087
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: How to build standalone wxWidgets application

Post by ONEEYEMAN » Wed Mar 13, 2019 2:30 pm

Hi,
First:
Monolithic build means you will have one huge library to link against. This sometimes produces issues during compile/run-time (not always).
So, while it is supported, usually its not recommended, especially for people who just started playing with wxWidgets.

Second:
In order to have a standalone application without any additional DLL you should just follow instructions in my previous reply - rebuild wxWidgets with appropriate set of options, re-create a project and rebuild. There is no other way. Mixing wxWidgets build will not work. You have to rebuild everything.

Finally, third:
What do you mean by "program crashing"? Does it gives you nice assert dialog or it gives crash dialog from Windows?
Can you provide a backtrace at the time of the crash?
Keep in mind that rebuilding everything like we discuss in point 2 will not fix the crash/assert.

Thank you.

ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

Re: How to build standalone wxWidgets application

Post by ValeV » Wed Mar 13, 2019 3:02 pm

Thank you for replying.

I rebuilt wxWidgets as "C:\MinGW\bin\mingw32-make -f makefile.gcc -j4 BUILD=release MONOLITHIC=1 RUNTIME_LIBS=static SHARED=0 UNICODE=1", copy pasted project code and I made it work in CodeBlocks, but as a standalone application it crashes when I use boost library (read_ini from property_tree). If you have some experience I would really appreciate it. I made stackoverflow question here: https://stackoverflow.com/questions/551 ... pplication.

1) Where can I see if this library is too huge? I can rebuilt wxWidgets without monolithic, but I want to have some idea if it will help at all, because it will take me some time.

2) I rebuilt as I wrote in first paragraph.

3) It gives general windows crash dialog ("A problem caused the program to stop working correctly. Please close the program."). I dont know how to check what error it throws (check my overflow question for code I am using)


So I don't really know how to proceed now. I didn't find anything useful googling ...

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3087
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: How to build standalone wxWidgets application

Post by ONEEYEMAN » Wed Mar 13, 2019 3:14 pm

Hi,
You need to rebuild the library and the project the third time. ;-)

Use following command:

Code: Select all

C:\MinGW\bin\mingw32-make -f makefile.gcc -j4 BUILD=debug MONOLITHIC=0 RUNTIME_LIBS=static SHARED=0
First, the latest wxWidgets release will default the build to a "UNICODE", so you don't have to specify it.
I removed the "MONOLITHIC" option - as I wrote it's better to have multi-lib build.
Finally this will produce the debug build of the library, which means you might get a proper backtrace during the crash/assert and see where the problem is.

Also, this should be the rule of thumb - create a debug build of the library if you just starting a project, because it will always contain bugs. ALWAYS!!!

And it will simplify your life as well as the life of people who will help you either here or in SO, as you will be able to produce the backtrace at the time of the crash.

Thank you.

ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

Re: How to build standalone wxWidgets application

Post by ValeV » Wed Mar 13, 2019 4:58 pm

Thank you, that's wonderful.

I rebuilt like you said. Then I restarted CodeBlocks and made new project:
-create debug configuration (only this one, not release)
-enable unicode (all others are unchecked
-selected all additional libraries to add to project

When I run the project, I get these errrors:

Code: Select all

||=== Build: Debug in asdf (compiler: GNU GCC Compiler) ===|
ld.exe||cannot find -lwxmsw31ud_dbgrid|
ld.exe||cannot find -lwxbase31ud_odbc|
ld.exe||cannot find -lwxmsw31ud_qa|
||error: ld returned 1 exit status|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 4 second(s)) ===|

Build log (if needed):

Code: Select all

-------------- Build: Debug in asdf (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -DwxUSE_UNICODE -Wall -g -D__WXDEBUG__ -std=c++11 -IC:\wxWidgets-3.1.2\include -IC:\wxWidgets-3.1.2\lib\gcc_lib\mswud -c "C:\Users\M0097932\Desktop\firstTest\DataGetter mono\asdf\asdfApp.cpp" -o obj\Debug\asdfApp.o
mingw32-g++.exe -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -DwxUSE_UNICODE -Wall -g -D__WXDEBUG__ -std=c++11 -IC:\wxWidgets-3.1.2\include -IC:\wxWidgets-3.1.2\lib\gcc_lib\mswud -c "C:\Users\M0097932\Desktop\firstTest\DataGetter mono\asdf\asdfMain.cpp" -o obj\Debug\asdfMain.o
windres.exe -IC:\wxWidgets-3.1.2\include -IC:\wxWidgets-3.1.2\lib\gcc_lib\mswud  -J rc -O coff -i C:\Users\M0097932\Desktop\FIRSTT~1\DATAGE~4\asdf\resource.rc -o obj\Debug\resource.res
mingw32-g++.exe -LC:\wxWidgets-3.1.2\lib\gcc_lib -o bin\Debug\asdf.exe obj\Debug\asdfApp.o obj\Debug\asdfMain.o  obj\Debug\resource.res -mthreads   -lwxmsw31ud_richtext -lwxmsw31ud_xrc -lwxmsw31ud_aui -lwxmsw31ud_dbgrid -lwxbase31ud_odbc -lwxmsw31ud_media -lwxbase31ud_net -lwxmsw31ud_gl -lwxmsw31ud_qa -lwxbase31ud_xml -lwxmsw31ud_adv -lwxmsw31ud_html -lwxmsw31ud_core -lwxbase31ud -lwxpngd -lwxjpegd -lwxtiffd -lwxzlibd -lwxregexud -lwxexpatd -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lcomctl32 -lwsock32 -lodbc32 -lshlwapi -lversion -mwindows
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lwxmsw31ud_dbgrid
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lwxbase31ud_odbc
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lwxmsw31ud_qa
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 4 second(s))
4 error(s), 0 warning(s) (0 minute(s), 4 second(s))
I can remove linked libraries "dbgrid" and "odbc", as said by doublemax (viewtopic.php?t=45446), but that still leaves me with "ud_qa" library, for which I haven't found the cure for yet.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3087
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: How to build standalone wxWidgets application

Post by ONEEYEMAN » Wed Mar 13, 2019 5:06 pm

Hi,
Are you trying to build an old project?
Yes you shuold get rid of the libraries referenced by doublemax - they are not part of wxWidgets since version 3.0.
For "qa" library please check the build directory and find the appropriate file name. Or you can just get rid of it - its not specifically relevant.

Right now the main point is to make the application run.

Thank you.

ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

Re: How to build standalone wxWidgets application

Post by ValeV » Thu Mar 14, 2019 9:09 am

ONEEYEMAN wrote:
Wed Mar 13, 2019 5:06 pm
Hi,
Are you trying to build an old project?
Yes you shuold get rid of the libraries referenced by doublemax - they are not part of wxWidgets since version 3.0.
For "qa" library please check the build directory and find the appropriate file name. Or you can just get rid of it - its not specifically relevant.

Right now the main point is to make the application run.

Thank you.
Hey!

New day, new challenges.

So, I rebuilt like you said, created new project (with just unicode option checked), removed linked libraries, recreated GUI in wxSmith and copy pasted the code. I ran it and it works.

However (ofcourse there is however), the program still crashes at same place (right before read_ini(), like described on my stack overflow question).

I am starting to blame boost library, although it seems strange to me that I can't catch the exception with " catch(...)".

Do you have any more ideas what I can try to do? If not, I will remove boost and write the code myself, although it will be pain in the a.

User avatar
doublemax
Moderator
Moderator
Posts: 13182
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to build standalone wxWidgets application

Post by doublemax » Thu Mar 14, 2019 9:41 am

Does the code from the SO question work in a project without wxWidgets?
Does it work when you pass a hard-coded path to read_ini?
If not, I will remove boost and write the code myself, although it will be pain in the a.
wxWidgets can read INI files. Check wxFileConfig.
https://docs.wxwidgets.org/trunk/classw ... onfig.html

But removing boost should not be necessary. I'm sure there is a solution for this.
Use the source, Luke!

ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

Re: How to build standalone wxWidgets application

Post by ValeV » Thu Mar 14, 2019 11:16 am

>Does the code from the SO question work in a project without wxWidgets?

I created simple console application and it doesnt work if ran as standalone application (but it does if ran through IDE).

Code: Select all

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

int main()
{
    using boost::property_tree::ptree;
    ptree tree;
    try
    {
        read_ini("C:\\Users\\M0097932\\Desktop\\firstTest\\torque_trac2_L0.eds", tree);
    }
    catch(...)
    {
        std::cout << "error" << std::endl;
    }
    for (auto& section : tree)
    {
        std::cout << '[' << section.first << "]\n";
        for (auto& key : section.second)
            std::cout << key.first << "=" << key.second.get_value<std::string>() << "\n";
    }

    std::cout << "readed" << std::endl;
}

So we can say it's not a problem with wxWidgets, but with boost or with IDE.

I want to try wxFileConfig to read ini file. Do you maybe have some example code up your sleeve on how to read ini file and print data?

User avatar
doublemax
Moderator
Moderator
Posts: 13182
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to build standalone wxWidgets application

Post by doublemax » Thu Mar 14, 2019 11:44 am

What happens if you use the hardcoded path in the wxWidgets version of the code?

Here's a random .INI file i found:

Code: Select all

[1018]
ParameterName=Identity object
ObjectType=0x9
SubNumber=3

[1018sub0]
ParameterName=Number of entries
ObjectType=0x7
DataType=0x0005
AccessType=ro
DefaultValue=3
PDOMapping=0
LowLimit=1
HighLimit=4

[1018sub1]
ParameterName=Vender ID
ObjectType=0x7
DataType=0x0007
AccessType=ro
DefaultValue=0x0400005A
PDOMapping=0
And here the wxFileConfig code to read it:

Code: Select all

#include "wx/fileconf.h"

wxFileConfig conf("", "", wxT("d:\\_test2.ini") );

// accessing data directly
{
  conf.SetPath( "/1018" );
  wxString parameter_name = conf.Read( "ParameterName", "" );
  wxString ObjectType = conf.Read( "ObjectType", "" );
  wxLogMessage("parameter_name = %s", parameter_name);
  wxLogMessage("ObjectType = %s", ObjectType);
}

{
// alternative version with absolute path
  wxString parameter_name = conf.Read( "/1018/ParameterName", "" );
  wxString ObjectType = conf.Read( "/1018/ObjectType", "" );
  wxLogMessage("parameter_name = %s", parameter_name);
  wxLogMessage("ObjectType = %s", ObjectType);
}

// iterating over all entries:
{
  wxString group;
  long group_index;

  conf.SetPath("/");
  bool has_group = conf.GetFirstGroup(group, group_index);
  while( has_group )
  {
    conf.SetPath( group );

    wxString entry;
    long entry_index;

    bool has_entry = conf.GetFirstEntry( entry, entry_index );
    while( has_entry )
    {
      wxString value = conf.Read( entry, "" );
      wxLogMessage("group=%s entry=%s value=%s", group, entry, value );

      has_entry = conf.GetNextEntry( entry, entry_index );
    }

    conf.SetPath("/");
    has_group = conf.GetNextGroup(group, group_index);
  }
}
Use the source, Luke!

ValeV
Knows some wx things
Knows some wx things
Posts: 33
Joined: Wed Jan 30, 2019 1:39 pm

Re: How to build standalone wxWidgets application

Post by ValeV » Thu Mar 14, 2019 11:49 am

>What happens if you use the hardcoded path in the wxWidgets version of the code?

Sorry, I forgot to answer you in previous comment. The program behaves the same - works in IDE, crashes as stand. app.

EDIT: I used your code to read my INI file and it works fine in IDE and as a standalone application. So I think I will use wxFileConfig and see how for I can go with it.


EDIT 2: How do I create global variable of type wxFileConfig?

If I put it at the start of Main.cpp file:

Code: Select all

wxFileConfig conf;
)

and put

Code: Select all

conf("", "", FileDialog1->GetPath());
somewhere in the code, I get an error "no match for call to (wxFileConfig)(const char[1], const char[1], wxString).

Where if I use local variable (wxFileConfig conf("", "", FileDialog1->GetPath());) this line works. I need it global though.

User avatar
doublemax
Moderator
Moderator
Posts: 13182
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to build standalone wxWidgets application

Post by doublemax » Thu Mar 14, 2019 7:04 pm

If I put it at the start of Main.cpp file:
You should never have any instance of a wxWidgets object as a global variable.

The usual way is this:
- add a member variable to your wxApp class, e.g. wxFileConfig *m_conf;

- in MyApp::OnInit():

Code: Select all

m_conf = new wxFileConfig("", "", "path-to-inifile.ini");
wxConfigBase::Set(m_conf);           // this sets the global configuration object
Now, anywhere in your program you can use this to get the pointer:

Code: Select all

wxConfigBase *conf = wxConfigBase::Get(false); 
in MyApp::OnExit()

Code: Select all

wxConfigBase::Set(NULL);
delete m_conf;
Use the source, Luke!

Post Reply