且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

CMake使用foreach和find_library返回库的完整路径

更新时间:2023-02-03 12:59:06

命令 find_library 设置缓存变量, unset 只删除简单变量的定义。



提供,您需要将特殊值 FOUND_LIB-NOTFOUND 存储到变量 FOUND_LIB find_library 可搜索另一个库,而变量已包含上一个库的路径:

  FOREACH(LIB $ {VTKLIBS})
SET(FOUND_LIBFOUND_LIB-NOTFOUND)
FIND_LIBRARY(FOUND_LIB $ {LIB})
LIST(APPEND VTKLIBS_DIR $ {FOUND_LIB})
MESSAGE(Lib:$ {LIB})
MESSAGE(Found Lib:$ {FOUND_LIB})
ENDFOREACH(LIB)
pre>

实际上,这是一种技巧,因为 cached 变量 FOUND_LIB isn通过简单的 set 命令更改。但是当 find_library 实现尝试读取变量的缓存值时,它实际上读取了具有相同名称的 simple 变量的值。



因为 find_library 只处理 * - NOTFOUND ,那么你为变量赋值空值的技巧就不起作用了。



@arrowd指出,更好的方法是使用不同的变量名称在不同的 find_library()调用:

  FOREACH(LIB $ {VTKLIBS })
FIND_LIBRARY(FOUND_LIB _ $ {LIB} $ {LIB})
LIST(APPEND VTKLIBS_DIR $ {FOUND_LIB _ $ {LIB}})
MESSAGE(Lib:$ {LIB}
MESSAGE(Found Lib:$ {FOUND_LIB _ $ {LIB}})
ENDFOREACH(LIB)

每个 find_library 调用的结果将被单独存储,并且在下一次调用cmake时将不会再次搜索同一个库。此外,这种方法允许用户修改(在缓存中)到具体库的路径,而不会影响其他库。


I used a list to store names of libraries, and I would like to use foreach and find_library to find full path of each library. But find_library just returned the path of the first library. I checked this post, but problem still exist. My CMake version is 3.4.3.

SET(VTKLIBS_DIR)

FOREACH(LIB ${VTKLIBS})
        SET(FOUND_LIB)
        FIND_LIBRARY(FOUND_LIB ${LIB})
        LIST(APPEND VTKLIBS_DIR ${FOUND_LIB})
        MESSAGE("Lib: ${LIB}")
        MESSAGE("Found Lib: ${FOUND_LIB}")
        UNSET(FOUND_LIB)
ENDFOREACH(LIB)

Command find_library sets cached variable, but simple form of command unset remove only simple variable's definition.

As noted by the link you provide, you need to store special value FOUND_LIB-NOTFOUND to the variable FOUND_LIB for force find_library to search another library while variable already contains path to the previous library:

FOREACH(LIB ${VTKLIBS})
        SET(FOUND_LIB "FOUND_LIB-NOTFOUND")
        FIND_LIBRARY(FOUND_LIB ${LIB})
        LIST(APPEND VTKLIBS_DIR ${FOUND_LIB})
        MESSAGE("Lib: ${LIB}")
        MESSAGE("Found Lib: ${FOUND_LIB}")
ENDFOREACH(LIB)

Actually, this is some kind of trick, as cached variable FOUND_LIB isn't changed by simple set command. But when find_library implementation attempts to read cached value of the variable, it actually read value of simple variable with the same name.

Because find_library treats only *-NOTFOUND cached values as "library not found", your trick with assigning empty value to the variable doesn't work.

The better approach, as noted by @arrowd, would be using different names for variable, used in different find_library() call:

FOREACH(LIB ${VTKLIBS})
        FIND_LIBRARY(FOUND_LIB_${LIB} ${LIB})
        LIST(APPEND VTKLIBS_DIR ${FOUND_LIB_${LIB}})
        MESSAGE("Lib: ${LIB}")
        MESSAGE("Found Lib: ${FOUND_LIB_${LIB}}")
ENDFOREACH(LIB)

Such a way results for every find_library call will be stored separately, and the same library will not be searched again at the next time cmake being invoked. Also, such approach allows user to modify (in cache) paths to concrete libraries without affecting other ones.