Cmake如何查找文件?

时间:2014-04-21 14:41:50

标签: c++ cmake

我正在尝试使用cmake编译freepv(http://freepv.sourceforge.net/)。

freepv需要一些模块,比如zlib。我下载了该模块的开发者版本并将其复制到我的硬盘中。

cmake中包含一个文件,告诉cmake在哪里找到zlib库。

#########################################################################
#                                               #
#               FreePV's Script                     #
#                                               #
#***********************************************************************#
#  This FreePV script tries to find jpeg library and header files       #
#  ZLIB_INCLUDE_DIR, headers path.                          #
#  ZLIB_LIBRARIES, libraries needed.                        #
#  ZLIB_FOUND, either true or false.                        #
#########################################################################

IF(WIN32)
    FIND_PATH(ZLIB_INCLUDE_DIR zlib.h 
        ${CMAKE_INCLUDE_PATH} 
        $ENV{include}
    )
    SET(ZLIB_NAMES z zlib zlib1 zlib1d zdll)
    FIND_LIBRARY(ZLIB_LIBRARY
        NAMES ${ZLIB_NAMES} 
        PATHS ${CMAKE_LIBRARY_PATH} $ENV{lib}
    ) 
ELSE(WIN32)

    FIND_PATH(ZLIB_INCLUDE_DIR zlib.h
        /usr/local/include
        /usr/include
    )
    SET(ZLIB_NAMES z zlib zdll)
    FIND_LIBRARY(ZLIB_LIBRARY
        NAMES ${ZLIB_NAMES}
        PATHS /usr/lib /usr/local/lib
    )

ENDIF(WIN32)

IF (ZLIB_INCLUDE_DIR AND ZLIB_LIBRARY)
   SET(ZLIB_FOUND TRUE)
   SET(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
ENDIF (ZLIB_INCLUDE_DIR AND ZLIB_LIBRARY)

IF(NOT ZLIB_FOUND)
   IF (ZLIB_FIND_REQUIRED)
      MESSAGE(FATAL_ERROR "Could not find ZLIB")
   ENDIF (ZLIB_FIND_REQUIRED)
ENDIF(NOT ZLIB_FOUND)

我的问题是:

我应该在哪里复制我为zlib下载的文件?

我可以复制硬盘中的某些位置,然后设置一个名为ZLIB_INCLUDE_DIR的环境变量吗?

CMake FIND_PATH如何工作?

2 个答案:

答案 0 :(得分:0)

你没有告诉你是在Windows或Linux / Unix等,因为上面的脚本对这两个部分做了不同的事情。

让我们从非Windows开始:

FIND_PATH(ZLIB_INCLUDE_DIR zlib.h
    /usr/local/include
    /usr/include
)

这只是在两个给定目录中搜​​索名为zlib.h的文件,并将CMAKE变量ZLIB_INCLUDE_DIR设置为找到该文件的目录。

同样的事情发生在库中,但奇怪的是另一种方式来获得乐趣(看起来像一个bug,想象你在/ usr / lib和/ usr / local / lib中安装了zlib,这混合了包括和两个库不同的版本)。

SET(ZLIB_NAMES z zlib zdll)
FIND_LIBRARY(ZLIB_LIBRARY
    NAMES ${ZLIB_NAMES}
    PATHS /usr/lib /usr/local/lib
)

因此,简单的方法就是拨打FindZLIB,而不是更好......(请参阅http://www.cmake.org/cmake/help/cmake2.6docs.html#module:FindZLIB)。

对于Windows平台,它也很奇怪:

FIND_PATH(ZLIB_INCLUDE_DIR zlib.h 
    ${CMAKE_INCLUDE_PATH} 
    $ENV{include}
)

这将查找CMAKE_INCLUDE_PATH中设置的所有默认包含目录中的zlib.h文件(请参阅http://www.cmake.org/Wiki/CMake_Useful_Variables),如果未在此处找到,则在环境变量include中设置的路径中查找

SET(ZLIB_NAMES z zlib zlib1 zlib1d zdll)
FIND_LIBRARY(ZLIB_LIBRARY
    NAMES ${ZLIB_NAMES} 
    PATHS ${CMAKE_LIBRARY_PATH} $ENV{lib}
) 

对于dll类似,这次只搜索CMAKE_LIBRARY_PATH或环境变量LIB的内容。

但是,是的,如果你已经知道了正确的道路,你可以做到:

SET(ZLIB_INCLUDE_DIR /path/to/the/zlib/include/dir)
SET(ZLIB_LIBRARIES /path/to/the/libary)
SET(ZLIB_FOUND TRUE)

并忽略上面的整个代码......

答案 1 :(得分:0)

函数 find_path 查找给定文件,如果找到则返回包含目录的路径。

默认情况下,该函数在变量 CMAKE_SYSTEM_INCLUDE_PATH 中列出的目录中查找文件。

如果您的模块可能位于其他目录,则可以将这些目录附加到变量 CMAKE_INCLUDE_PATH 中,该变量默认为空。

一种常见的模式是查找包含版本信息的标题。从那里,可以更轻松地找到库文件和包含目录(因为文件夹结构有点固定)。

下面是使用 find_path 和 PATH_SUFFIXES 查找已安装库(例如 Xerces)的 Find 模块的简单示例,以查找包含特定文件的目录。

FindXerces.cmake:

# We check if the xerces_INCLUDE_DIR variable is set already, maybe it can be
# defined as a cache variable that the user can use to point to the lib's installation. 
if (NOT xerces_INCLUDE_DIR)

    # We're looking for a file named XercesVersion.hpp
    # By default, CMake looks into C:/Program Files(x86), since it is listed 
    # under CMAKE_SYSTEM_INCLUDE_DIRECTORIES. 
    # With the PATH_SUFFIXES option we can tell cmake to look inside 
    # subdirectories within the default search directories 
    # e.g. C:/Program Files(x86)/xerces-c/include/xercesc/util
    find_path(xerces_VERSION_PATH 
        XercesVersion.hpp
        PATH_SUFFIXES "xerces-c/include/xercesc/util"
    )
    
    # If the file is found, the variable xerces_VERSION_PATH will be populated.
    if(xerces_VERSION_PATH)
        # We can set some further variables to locate the libs and include dirs.
        set(xerces_LOCATION ${xerces_VERSION_PATH}/../../..)
        set(xerces_LIBS_DIR ${xerces_LOCATION}/lib)
        set(xerces_INCLUDE_DIR ${xerces_LOCATION}/include)
    endif()

    message(STATUS ${xerces_LOCATION})

endif()

# With the variables set previously we look for the libraries.
find_library(xerces_LIBRARY_DEBUG
    NAMES "xerces-c_${XercesC_VERSION_MAJOR}D"
    HINTS ${xerces_LOCATION}/lib
)

find_library(xerces_LIBRARY_RELEASE
    NAMES "xerces-c_{XercesC_VERSION_MAJOR}"
    HINTS ${xerces_LOCATION}/lib
)

set(xerces_VERSION ${XercesC_VERSION})

include(SelectLibraryConfigurations)

select_library_configurations(xerces)

include(FindPackageHandleStandardArgs)

find_package_handle_standard_args(xerces
    FOUND_VAR
        xerces_FOUND
    REQUIRED_VARS
        xerces_INCLUDE_DIR
        xerces_LIBRARIES
        xerces_VERSION
)

同样,如果要搜索的文件位于自定义文件夹中,则可以将这些文件添加到 CMAKE_INCLUDE_PATH(使用 LIST(APPEND CMAKE_INCLUDE_PATH folder1 folder2,...))。使用 find_path 或 find_file 时也会搜索这些文件夹。