Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
272 views
in Technique[技术] by (71.8m points)

wxwidgets - CMake FindwxWidgets fails only on first invocation of "configure" command

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...