find_library chooses the static library instead of

2019-07-13 21:20发布

问题:

This has been asked on SO before and there's even a related bug on this in CMAKE. However, my issue is a variation and the answer is not clear.

My wrinkle is that I'm cross-compiling for Windows on Linux using MinGW. Static libs are named like this libGLESv2.dll.a and libiconv.dll.a for the DLLs libGLESv2.dll and iconv.dll respectively.

Examples:

find_library(FOUND_LIB_X NAMES "zlib1.dll" PATHS ${CMAKE_FIND_ROOT_PATH}/bin/)
finds this: zlib1.dll

find_library(FOUND_LIB_Y NAMES "libGLESv2.dll" PATHS ${CMAKE_FIND_ROOT_PATH}/bin/)
finds this: libGLESv2.dll.a

find_library(FOUND_LIB_Y NAMES "iconv.dll" PATHS ${CMAKE_FIND_ROOT_PATH}/bin/)
finds this: libiconv.dll.a

The CMAKE bug seems to be referring to traditional situations where the static lib is named blah.lib (Windows) or blah.a (Linux). In this cross-compiler situation with mingw on Linux, they are named blah.dll.a

I need it to find the file literally called iconv.dll and nothing else. If it doesn't literally find that, then abort. Am I using the wrong CMAKE function? (don't use find_library()?)

回答1:

CMake uses definite order between iterating library names and directories when search the library. E.g., according to documentation,

When more than one value is given to the NAMES option this command by default will consider one name at a time and search every directory for it.

That is, with libraries at dir1/name2 and dir2/name1

find_library(MYLIB NAMES name1 name2 PATHS dir1 dir2)
message(${MYLIB})

will print dir2/name1.

Specifying NAMES_PER_DIR option reverse the choice:

find_library(MYLIB NAMES name1 name2 NAMES_PER_DIR PATHS dir1 dir2)
message(${MYLIB})

will print dir1/name2.

Things are different with trying library's prefix and suffix:

Each library name given to the NAMES option is first considered as a library file name and then considered with platform-specific prefixes (e.g. lib) and suffixes (e.g. .so).

It seems that checking for lib<name>.so is performed immediately after <name> when iterating directories.

That is, with libraries at dir1/libname.so and dir2/name

find_library(MYLIB NAMES name PATHS dir1 dir2)
message(${MYLIB})

will print dir1/libname.so.

That is why libiconv.dll.a is found in your case: lib/ directory is searched as system specific path at step 5 of find_library search algorithm, but directory bin/, specified as PATH option, is searched only at step 6.

The simplest way to find what you want is to use NO_DEFAULT_PATH option, so searching in lib/ will not be performed at all:

find_library(FOUND_LIB_Y
    NAMES "iconv.dll"
    PATHS ${CMAKE_FIND_ROOT_PATH}/bin/
    NO_DEFAULT_PATH
)


标签: dll cmake mingw