What is the correct order for linking the wxWidgets lib files?

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.
Post Reply
rbaleksandar
In need of some credit
In need of some credit
Posts: 1
Joined: Fri Sep 17, 2021 9:09 am

What is the correct order for linking the wxWidgets lib files?

Post by rbaleksandar »

I've just started with wxWidgets (have approx. a decade with Qt though) and trying to configure, build and link against it using CMake

Code: Select all

ExternalCode
This proved to be a very challenging task since - at least from what I've seen - at least on Windows wxWidget is not really meant to be added in any other way then either adding the binaries (DLL and LIB files) after downloading those from the official website or using

Code: Select all

add_subdirectory()
I have successfully managed to configure a relatively minimal build of wxWidgets by sifting through whatever documentation (sadly very poor quality with a lot of dead links, unclear information, lack of consistency etc.), forum posts, blog posts and tutorials and several days of experimentation and build it both as shared and static library. Monolithic is currently something that seems rather impossible at least on Windows and using

Code: Select all

ExternalProject
with just configuring stuff through CMake arguments.

Anyway I have successfully linked a small example with a window and a button in it against the static version. I had to add some Windows-related stuff (such as

Code: Select all

WIN32
flag to my executable to enable the Windows Subsystem as well as link against the

Code: Select all

comctl32
) but in the end my executable got generated and I can use it (at least on my computer using Win10 Pro, MSVC v141, Visual Studio 2017 and CMake 3.21).

The following struck me though: the order is very important. I assume that if one configures wxWidgets the standard way and uses

Code: Select all

find_package()
the order of the LIB files (both in case of a static (only LIB files) and shared (LIB and DLL files)) is guaranteed (if not the developers should consider fixing it). However since I am currently just

Code: Select all

file(GLOB ...)
the LIB and DLL files, populating my own

Code: Select all

WXWIDGETS_LIBRARIES
variable (along with the one for the include directories of course) with the LIB files and copying all library files (incl. DLL) to my binary output directory I found myself in front of a wall of unresolved external symbols:

Code: Select all

8>main.obj : error LNK2001: unresolved external symbol "protected: static class wxAppConsole * (__cdecl* wxAppConsoleBase::ms_appInitFn)(void)" (?ms_appInitFn@wxAppConsoleBase@@1P6APEAVwxAppConsole@@XZEA)
8>main.obj : error LNK2001: unresolved external symbol "protected: static class wxAppConsole * wxAppConsoleBase::ms_appInstance" (?ms_appInstance@wxAppConsoleBase@@1PEAVwxAppConsole@@EA)
8>button.obj : error LNK2001: unresolved external symbol "void (__cdecl* wxTheAssertHandler)(class wxString const &,int,class wxString const &,class wxString const &,class wxString const &)" (?wxTheAssertHandler@@3P6AXAEBVwxString@@H000@ZEA)
8>button.obj : error LNK2001: unresolved external symbol "bool wxTrapInAssert" (?wxTrapInAssert@@3_NA)
8>button.obj : error LNK2001: unresolved external symbol "char const * const wxPanelNameStr" (?wxPanelNameStr@@3QBDB)
8>button.obj : error LNK2001: unresolved external symbol "class wxSize const wxDefaultSize" (?wxDefaultSize@@3VwxSize@@B)
8>button.obj : error LNK2001: unresolved external symbol "class wxPoint const wxDefaultPosition" (?wxDefaultPosition@@3VwxPoint@@B)
8>button.obj : error LNK2001: unresolved external symbol "class wxEventTypeTag<class wxCommandEvent> const wxEVT_BUTTON" (?wxEVT_BUTTON@@3V?$wxEventTypeTag@VwxCommandEvent@@@@B)
8>button.obj : error LNK2001: unresolved external symbol "class wxEventTypeTag<class wxFocusEvent> const wxEVT_SET_FOCUS" (?wxEVT_SET_FOCUS@@3V?$wxEventTypeTag@VwxFocusEvent@@@@B)
8>button.obj : error LNK2001: unresolved external symbol "class wxEventTypeTag<class wxChildFocusEvent> const wxEVT_CHILD_FOCUS" (?wxEVT_CHILD_FOCUS@@3V?$wxEventTypeTag@VwxChildFocusEvent@@@@B)
8>button.obj : error LNK2001: unresolved external symbol "class wxEventTypeTag<class wxNavigationKeyEvent> const wxEVT_NAVIGATION_KEY" (?wxEVT_NAVIGATION_KEY@@3V?$wxEventTypeTag@VwxNavigationKeyEvent@@@@B)
8>button.obj : error LNK2001: unresolved external symbol "class wxValidator const wxDefaultValidator" (?wxDefaultValidator@@3VwxValidator@@B)
8>button.obj : error LNK2001: unresolved external symbol "char const * const wxFrameNameStr" (?wxFrameNameStr@@3QBDB)
8>button.obj : error LNK2001: unresolved external symbol "char const * const wxButtonNameStr" (?wxButtonNameStr@@3QBDB)
8>C:\Users\rcr-aa\CMakeBuilds\ef5b5ada-ee42-7735-988a-ae37c735ccff\build\debug\moped.exe : fatal error LNK1120: 14 unresolved externals
I have used the same order that I found to be working (mostly by deciphering https://wiki.wxwidgets.org/WxWidgets_Build_Libraries and https://docs.wxwidgets.org/3.0/page_libs.html):

Code: Select all

	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/debug/libpng16d.lib
        # zlib, jpeg etc.
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_xrc.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_qa.lib

	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_adv.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_aui.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_gl.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_html.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_propgrid.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_ribbon.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_stc.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxscintillad.lib

	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxbase31ud_xml.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxmsw31ud_core.lib
	C:/Users/rcr-aa/CMakeBuilds/ef5b5ada-ee42-7735-988a-ae37c735ccff/build/deps/build/wxwidgets/lib/vc_x64_lib/wxbase31ud.lib
I manually set the order above since currently I'm looking into the correct one. Once I determine it, I will create a regular expression ruleset to automatically sort my paths regardless of any prefixes and suffixes.

Here are the details of my

Code: Select all

ExternalProject
. Note that all

Code: Select all

DEPS
variables point to predefined valid paths. Also not that EXPAT, ZLIB, LIBJPEG-TURBO and LIBPNG are defined elsewhere as external dependencies themselves (mostly because I am already using those and don't want to depend on wxWidgets on anything but the GUI components hence me choosing

Code: Select all

sys
and not

Code: Select all

builtin
as a setting for these dependencies). Everything is still work in progress:

Code: Select all

message("Processing dependency wxWidgets")
ExternalProject_Add(wxWidgets
	PREFIX ${CMAKE_CURRENT_BINARY_DIR}/deps/wxwidgets
	
	INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
	DOWNLOAD_DIR ${DEPS_SRC}/wxwidgets
	TMP_DIR ${DEPS_TMP}/wxwidgets
	STAMP_DIR ${DEPS_STAMP}/wxwidgets
	LOG_DIR ${DEPS_LOG}/wxwidgets
	BINARY_DIR ${DEPS_BUILD}/wxwidgets
	SOURCE_DIR ${DEPS_NATIVE}/wxwidgets

	INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "Skipping install step for dependency libzmq"
	INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}

	DEPENDS zlib libpng jpeg libexpat

	BUILD_ALWAYS OFF

	# For build configurations see https://wiki.wxwidgets.org/WxWidgets_Build_Configurations
	# For configuration symbols see https://docs.wxwidgets.org/3.0/page_wxusedef.html
	# For building applications see https://docs.wxwidgets.org/trunk/plat_msw_install.html
	CMAKE_ARGS
		"-DCMAKE_BUILD_TYPE=Release"
#		"-DBUILD=release"
		"-DwxBUILD_STATIC=OFF"
		"-DwxBUILD_SHARED=ON"
#		"-DwxBUILD_MONOLITHIC=ON"			# FIXME Doesn't work due to a call of wx_webview_copy_webview2_loader() which - probably due to missing proper configuration - is marked as an unknown CMake command
		"-DwxBUILD_PRECOMP=ON"
		"-DwxBUILD_TESTS=OFF"
		"-DwxBUILD_DEMOS=OFF"
		"-DwxBUILD_BENCHMARKS=OFF"
		"-DwxUSE_GUI=ON"
		"-DwxUSE_OPENGL=ON"
		"-DwxUSE_CRASHREPORT=OFF"
		"-DwxUSE_FS_ARCHIVE=OFF"
		"-DwxUSE_FS_INET=OFF"
		"-DwxUSE_SOCKETS=OFF"
		"-DwxUSE_MEDIACTRL=OFF"
		"-DwxUSE_MEDIA=ON"
		#"-wxUSE_MEMORY_TRACING=OFF"	# Error - unknow parameter?
		"-DwxUSE_PROTOCOL=OFF"
		"-DwxUSE_URL=OFF"
		"-DwxUSE_LIBTIFF=OFF"		# TODO Add libTiff to external project dependencies and use here
		"-DwxUSE_RICHTEXT=OFF"
		"-DwxUSE_XML=ON"
		"-DwxUSE_HTML=ON"
		"-DwxUSE_HELP=ON"
		"-DwxUSE_WXHTML_HELP=OFF"
		"-DwxUSE_LOG=OFF"
		"-DwxUSE_LOGGUI=OFF"		# Apparantely turning off logging doesn't disable this...
		"-DwxUSE_LOGWINDOW=OFF" 	# Apparantely turning off logging doesn't disable this...
		"-DwxUSE_WEBVIEW=OFF"	        # Can perhaps be used to load external GoogleMaps or OpenStreetMaps
		"-DwxUSE_LIBLZMA=OFF"
		"-DwxUSE_REGEX=OFF"
		"-DwxUSE_SOUND=OFF"
		"-DwxUSE_GIF=OFF"
#		"-DRUNTIME_LIBS=static"		# Could be good for distribution - statically links the C/C++ runtime libraries (e.g. msvcrt.dll)
		"-DwxUSE_EXPAT=sys"
		"-DEXPAT_LIBRARIES=${EXPAT_LIBRARIES}"
		"-DEXPAT_LIBRARY=${EXPAT_LIBRARIES}"		# There seems to be a bug that also requires this to be defined (ERROR: Could NOT find EXPAT (missing: EXPAT_LIBRARY) (found version "2.2.6"))
		"-DEXPAT_INCLUDE_DIRS=${EXPAT_INCLUDE_DIRS}"
		"-DwxUSE_ZLIB=sys"
		"-DZLIB_LIBRARY=${ZLIB_LIBRARIES}"
		"-DZLIB_INCLUDE_DIRS=${ZLIB_INCLUDE_DIRS}"
		"-DwxUSE_LIBJPEG=sys"
		"-DJPEG_LIBRARY=${JPEG_LIBRARIES}"
		"-DJPEG_INCLUDE_DIR=${JPEG_INCLUDE_DIRS}"
		"-DwxUSE_LIBPNG=sys"
		"-DPNG_LIBRARY=${PNG_LIBRARIES}"
		"-DPNG_PNG_INCLUDE_DIR=${PNG_INCLUDE_DIRS}"
)
# Extract the full binary and source path where the lib and header files reside
ExternalProject_Get_property(wxWidgets BINARY_DIR)
ExternalProject_Get_property(wxWidgets SOURCE_DIR)
set(WXWIDGETS_LIBRARIES "")
# Copy shared libraries (lib file also for Windows) into the binary directory of the main project. Set required variables for other dependencies to use
if(WIN32)
	# From wxWidgets CMakeLists.txt: the general structure of a dll is wx<component><version>u<build type suffix><_subcomponet>_<compiler>_<vendor>
	# For example a debug release for a custom vendor (vendor is MSVC only) for MSVC of the base component for version 3.16 looks like this:
	# wxbase316ud_vc_custom.dll
	# For the same but adding XML subcomponent we get:
	# wxbase316ud_xml_vc_custom.dll
	# If we change the component (MSW = Microsoft Windows platform) and subcomponent (media) we get:
	# wxmsw316ud_media_vc_custom.dll
	# The lib files are easier but still contain build type suffix as well as version
	# TODO See how to configure wxWidgets to build in a more conform (with the other dependencies) way that does not create directories based on used compiler and architecture
	file(GLOB WXWIDGETS_LIB_FILES "${BINARY_DIR}/lib/vc_x64_dll/wx*.lib") # TODO Add option for DLL and STATIC. If static, vc_x64_lib otherwise vc_x64_dll
	set(WXWIDGETS_LIBRARIES "${WXWIDGETS_LIB_FILES}" CACHE FILEPATH "wxWidgets dynamic library (Windows)" FORCE)
	# Due to the default configuration putting the lib and dll in different dirs copying command
	# needs to be done twice
	file(TO_NATIVE_PATH "${BINARY_DIR}/lib/vc_x64_dll" BAT_SRC_DIR)	# TODO Add option for DLL and STATIC. If static, vc_x64_lib otherwise vc_x64_dll
	add_custom_command(
		TARGET wxWidgets POST_BUILD
		COMMAND cmd /c ${DEPS_NATIVE}/copy_files.bat -e "dll" -s "${BAT_SRC_DIR}\\" -d "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\\"
		COMMAND cmd /c ${DEPS_NATIVE}/copy_files.bat -e "lib" -s "${BAT_SRC_DIR}\\" -d "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\\"
		# Copy setup.h to include directory of wxwidgets. This file is generated during the 
		# configuration of wxWidgets and is not available before that
		COMMAND cmd /c ${DEPS_NATIVE}/copy_files.bat -e "h" -s "${BINARY_DIR}\\lib\\vc_x64_dll\\mswu\\wx\\" -d "${DEPS_NATIVE}\\wxwidgets\\include\\wx" # TODO Add option for DLL and STATIC. If static, vc_x64_lib otherwise vc_x64_dll
		# Copy XRC executable
		COMMAND cmd /c ${DEPS_NATIVE}/copy_files.bat -e "exe" -s "${BINARY_DIR}\\lib\\vc_x64_dll\\" -d "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\\" # TODO Add option for DLL and STATIC. If static, vc_x64_lib otherwise vc_x64_dll
	)
elseif(UNIX)
	# TODO
else()
	message(FATAL_ERROR "Unsupported platform")
endif()
set(WXWIDGETS_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "wxWidgets include dirs" FORCE)
list(APPEND DEPS_LIBRARIES ${WXWIDGETS_LIBRARIES})
list(APPEND DEPS_INCLUDE_DIRS ${WXWIDGETS_INCLUDE_DIRS})
Can someone tell me what the linking order actually is?
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: What is the correct order for linking the wxWidgets lib files?

Post by doublemax@work »

In Visual Studio the library order is not relevant, it's smart enough to handle that (other than MinGW/GCC). The problem must lie somewhere else.

This seems to be just a cmake issue, which i can't help with.
Maybe this helps (Although it's for wxGTK): viewtopic.php?p=208038#p208038

I have successfully managed to configure a relatively minimal build of wxWidgets by sifting through whatever documentation (sadly very poor quality with a lot of dead links, unclear information, lack of consistency etc.), forum posts, blog posts and tutorials and several days of experimentation and build it both as shared and static library.
I think you're over-dramatizing things here. If you're using Visual Studio (and it looks like you are), this works out of the box using the provided solution files. It takes just a few minutes to build the libraries and the "minimal" sample.
stahta01
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 548
Joined: Fri Nov 03, 2006 2:00 pm

Re: What is the correct order for linking the wxWidgets lib files?

Post by stahta01 »

Please give the wxWidgets library version you are using?
And, please give how you built wxWidgets or what binary you are using for wxWidgets.

If using an binary of wxWidgets, it need to be built by an Compiler that is compatible with the compiler you are using.

Tim S.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: What is the correct order for linking the wxWidgets lib files?

Post by ONEEYEMAN »

Hi,
It is very simple to build wxWidgets and start developing with the library using MSVC.

Get the source code.
Start MSVC
so I am Open wxWidgets\build\msw\wx_vcN.sln (I use 2017, so for me N = 15)
Select Build->Batch Build
Click "Select ALL", the "Build".
Go drink some coffee.
OPen the wxWidgets\sampoles\minimal\minimal_vc15.sln
Build
Run

Using "CMake" or any other configuration tool to incorporate wxWidgets in the existing project or create a distribution that a user can build should come much much later.
You immediate task should be to build the library and start the development process.

Thank you.
Post Reply