1

I have the following code to try find wxWidgets 3.1 pre-built libraries using CMake 3.7.1.

set(wxWidgets_ROOT_DIR M:/wxWidgets)
set(wxWidgets_LIB_DIR M:/wxWidgets/lib/gcc510TDM_x64_dll)
set(wxWidgets_CONFIGURATION mswud)
find_package(wxWidgets 3.1 REQUIRED COMPONENTS core base stc)
include(${wxWidgets_USE_FILE})
target_link_libraries(MyTarget ${wxWidgets_LIBRARIES})

The generator is "CodeBlocks - MinGW Makefiles". And it is on Windows 7. So the FindwxWidgets module's search style is "win32".

The strange thing is that this code always fails on the first invocation of "configure" command/button, when the CMake cache is not yet set. And it will succeed on subsequent invocation of "configure". And the error message is

CMake Error at M:/cmake-3.7.1-win64-x64/share/cmake-3.7/Modules/FindPackageHandleStandardArgs.cmake:138 (message):
  Could NOT find wxWidgets (missing: wxWidgets_LIBRARIES
  wxWidgets_INCLUDE_DIRS) (Required is at least version "3.1")
Call Stack (most recent call first):
  M:/cmake-3.7.1-win64-x64/share/cmake-3.7/Modules/FindPackageHandleStandardArgs.cmake:378 (_FPHSA_FAILURE_MESSAGE)
  M:/cmake-3.7.1-win64-x64/share/cmake-3.7/Modules/FindwxWidgets.cmake:929 (find_package_handle_standard_args)
  CMakeLists.txt:16 (find_package)

I'm new to CMake. Is this normal? Is FindwxWidgets module supposed to work this way?

Below are the contents of CMake cache after the first (failed) "configure":

//Cleared.
wxWidgets_LIB_DIR:PATH=wxWidgets_LIB_DIR-NOTFOUND
...
...
//wxWidgets_LIB_DIR
WX_LIB_DIR:INTERNAL=wxWidgets_LIB_DIR-NOTFOUND
//wxWidgets_ROOT_DIR
WX_ROOT_DIR:INTERNAL=M:/wxWidgets

Below are the contents of CMake cache after subsequent (successful) "configure":

//Path to a file.
_filename:FILEPATH=M:/wxWidgets/include/wx/version.h

//Set wxWidgets configuration (mswud;mswu)
wxWidgets_CONFIGURATION:STRING=mswud

//Cleared.
wxWidgets_LIB_DIR:PATH=wxWidgets_LIB_DIR-NOTFOUND

//Location of wxWidgets resource file compiler binary (wxrc)
wxWidgets_wxrc_EXECUTABLE:FILEPATH=wxWidgets_wxrc_EXECUTABLE-NOTFOUND
...
...
//Details about finding wxWidgets
FIND_PACKAGE_MESSAGE_DETAILS_wxWidgets:INTERNAL=[M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxmsw31ud_core.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxbase31ud.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxmsw31ud_stc.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxpngd.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxtiffd.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxjpegd.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxzlibd.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxregexud.a;M:/wxWidgets/lib/gcc510TDM_x64_dll/libwxexpatd.a;winmm;comctl32;rpcrt4;wsock32][M:/wxWidgets/lib/gcc510TDM_x64_dll/mswud;M:/wxWidgets/include][v3.1.0(3.1)]
//wxWidgets_LIB_DIR
WX_LIB_DIR:INTERNAL=M:/wxWidgets/lib/gcc510TDM_x64_dll
//wxWidgets_ROOT_DIR
WX_ROOT_DIR:INTERNAL=M:/wxWidgets

I omitted keys that are for individual wxWidgets components, such as "WX_zlib:FILEPATH", or "WX_zlib-ADVANCED:INTERNAL", etc.

thebat
  • 2,029
  • 4
  • 21
  • 30
  • 1
    `Is this normal?` - No, normally search algorithm should give *persistent* results. Code of `FindwxWidgets.cmake` uses some "clean" logic when it finds things under directories other than `wxWidgets_ROOT_DIR` or `wxWidgets_LIB_DIR`. Probably, such logic cause the behaviour you observe. Could you provide **content of CMake cache** after the first(failed) "configure" and the second one? This would give a key. Only cache entries started with `wx` or `WX_` are interested. BTW, the example uses driver letter in upper case (`C:/`), but your code use lower case (`m:/`). This may have a sence. – Tsyvarev Jan 10 '17 at 17:51
  • @Tsyvarev Based on your comment, I reran cmake-gui and captured CMake cache contents. I updated the question accordingly. Thanks! – thebat Jan 10 '17 at 19:26
  • 1
    @Tsyvarev I found a workaround. I removed set commands for both `wxWidgets_ROOT_DIR` and `wxWidgets_LIB_DIR`. Instead, I set the environment variable `wxWidgets_ROOT_DIR`, and moved pre-built library files into one of the locations that FindwxWidgets.cmake will look for. – thebat Jan 11 '17 at 05:41

2 Answers2

1

I had the same issue, using the generator for Visual Studio 2015x64, until I added the line setting WX_ROOT_DIR:

SET(WX_ROOT_DIR ${wxwidgets_path})
SET(wxWidgets_CONFIGURATION mwsu)
SET(wxWidgets_ROOT_DIR ${wxwidgets_path})
SET(wxWidgets_LIB_DIR ${wxwidgets_path}/vc_x64_lib)
FIND_PACKAGE(wxWidgets REQUIRED QUIET)
ooak
  • 680
  • 6
  • 8
  • I can confirm using `${WX_ROOT_DIR}` without cache works on PSDK 7.1 + wxWidgets 3.0.5 + CMake 3.22.3. – Joel Mar 10 '22 at 19:32
0

Script FindwxWidgets.cmake has non-intuitive logic, so hinting with wxWidgets_LIB_DIR path is tricky:

  1. Hint wxWidgets_ROOT_DIR should be in some canonical form, where driver letter is uppercase:

    set(wxWidgets_ROOT_DIR "M:/wxWidgets")
    
  2. Hint wxWidgets_LIB_DIR should be cached variable:

    set(wxWidgets_LIB_DIR "M:/wxWidgets/lib/gcc510TDM_x64_dll"
        CACHE PATH "wxWidgets_LIB_DIR ")
    

This is what happens in your case.

First "configure" invocation:

  1. Cache is empty.
  2. The script detects (with find_path) root directory of the library, and stores result into WX_ROOT_PATH cached variable.
  3. The script finds that value of WX_ROOT_PATH variable differs from value of wxWidgets_ROOT_DIR. Because of that, it modifies value of cached variable WX_ROOT_PATH to value of wxWidgets_ROOT_DIR.
  4. Additionaly, because of difference detected at previous step, the script set cached variable wxWidgets_LIB_DIR to -NOTFOUND.
  5. The script tries to detect (with find_path) library directory without hint wxWidgets_LIB_DIR. Of course, this fails. Result (-NOTFOUND) would be stored into cached variable wxWidgets_LIB_DIR, but it already has this value.

Setting cached variable wxWidgets_LIB_DIR at step 4 clears non-cache variable with the same name, so futher searches are failed.

On the second "configure" invocation:

  1. Variables WX_ROOT_PATH and wxWidgets_LIB_DIR are already in cache.
  2. find_path() do nothing, as WX_ROOT_PATH is already in cache.
  3. Values of WX_ROOT_PATH (cached) and wxWidgets_ROOT_DIR(non-cached) are the same.
  4. Setting of cached variable wxWidgets_LIB_DIR is not performed (whole step isn't performed).
  5. find_path still cannot find the library path, but value of cached variable wxWidgets_LIB_DIR is already -NOTFOUND, so it is not modified.

Non-cached variable wxWidgets_LIB_DIR (which is set by yours) is not cleared, and it is used in the futher searches. (non-cache variable shadows cache one, see * Variable types in CMake * in documentation for set command). So this configuration succeed.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • 1
    I really like your answer. I modified the code as suggested, it consistently failed with the same error every time. :( But I think that you point me towards the right direction. – thebat Jan 10 '17 at 21:59
  • Oops, actually it is *wxWidgets_ROOT_DIR* cache variable which is set at the step 2 by `find_path`. So, step 3 at the first "configure" invocation is inevitable and it clears *wxWidgets_ROOT_DIR*. As a fast workaround, you may set both *wxWidgets_ROOT_DIR* and *WX_ROOT_DIR* cached variables: `set(wxWidgets_ROOT_DIR "M:/wxWidgets" CACHE PATH "wxWidgets_ROOT_DIR")`, `set(WX_ROOT_DIR "M:/wxWidgets" CACHE PATH "wxWidgets_ROOT_DIR")`, but this is a hack, of course. I will think about nicer decision. – Tsyvarev Jan 10 '17 at 22:22
  • I tried to set both hints as cache entries, and even with `FORCE`. It either always fails, or fails on first invocation. I don't think those hints actually work. – thebat Jan 11 '17 at 05:49
  • @thebat Did you find something that did work? – J. Gwinner Dec 15 '22 at 04:11
  • 1
    @J.Gwinner I hacked around it. It is not pretty but works. (1) Removed line `set(wxWidgets_ROOT_DIR M:/wxWidgets)`, and set an environment variable called `wxWidgets_ROOT_DIR`. (2) Removed line `set(wxWidgets_LIB_DIR M:/wxWidgets/lib/gcc510TDM_x64_dll)`, and put wxWidgets DLL files into the default folder expected by the find wxWidgets cmake module, i.e. `{Your wxWidgets' Root}\lib\gcc_dll`. – thebat Dec 15 '22 at 18:51
  • @thebat Thanks! I'll see if that fixes our problem. – J. Gwinner Dec 15 '22 at 21:43
  • What fixed our problem was to do a complete build of WxWidgets. Turns out, the previous version was checked in, but just the DLL's needed for our project by a prev. dev. The new CMake doesn't like that, it won't detect the library until it's the full library. – J. Gwinner Feb 20 '23 at 18:55