简体   繁体   中英

How does Cmake find files?

I am trying to compile freepv ( http://freepv.sourceforge.net/ ) using cmake.

freepv needs some modules such as zlib. I download the developer version of this module and copied it into my hard disk.

Included in cmake there is a file that tells cmake where to find zlib library.

#########################################################################
#                                               #
#               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)

My question is :

where should I copy the files that I downloaded for zlib?

Can I copy some where in my hard disk and then set an environment variable called: ZLIB_INCLUDE_DIR ?

How CMake FIND_PATH works?

You didn't tell if you are on Windows or Linux/Unix etc., as the script above does things differently for the two parts.

Lets start with non-windows:

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

This just searches for a file named zlib.h in the two given directories and sets the CMAKE Variable ZLIB_INCLUDE_DIR to the dir where the file was found.

Same thing happens for the libraries, but strangely the other way round for fun (looks like a bug, imagine you have zlib installed in /usr/lib and /usr/local/lib and this mixes up include and libraries of two different version).

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

So the easy way would be to just call FindZLIB instead, which works better... (see http://www.cmake.org/cmake/help/cmake2.6docs.html#module:FindZLIB ).

For the Windows platform its strange as well:

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

This looks for the zlib.h file in all the default include directories set in CMAKE_INCLUDE_PATH (see http://www.cmake.org/Wiki/CMake_Useful_Variables ) and if its not found there, in the path set in the environment variable include .

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

For the dll ist similar, just this time CMAKE_LIBRARY_PATH is searched or the content of the environment variable LIB.

But yes, if you already know the right path, you can simply do:

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

and ignore the whole code above...

The function find_path looks for a given file and returns the path to the containing directory if found.

By default the function looks for the file inside the directories listed in the variable CMAKE_SYSTEM_INCLUDE_PATH .

If you have further directories where your module might be located, these can be appended to the variable CMAKE_INCLUDE_PATH , which is by default empty.

A common pattern is to look for a header, which contains the version information. From there, it's easier to find the library files and the include directories (since the folder structure is kinda fixed).

Below a simple example of a Find module for finding an installed library (eg Xerces) using find_path with PATH_SUFFIXES to find the directory containing a specific file.

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
)

Again, if the files being searched for are in custom folders, these can be added to CMAKE_INCLUDE_PATH (using LIST(APPEND CMAKE_INCLUDE_PATH folder1 folder2,...) ). These folders will be also searched when using find_path or find_file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM