CMake : how to link a library WITHOUT automatic search function FIND_PACKAGE?

前端 未结 3 1593
独厮守ぢ
独厮守ぢ 2020-12-24 04:18

I wonder how to find/link a library without any FIND_PACKAGE.

Assume that we have a \"personal\" library called testlib :

/perso/testlib/include/test         


        
相关标签:
3条回答
  • 2020-12-24 05:06

    CMake has a good documentation.

    1. Static linkage (if i understand you correct) is archived by passing the STATIC keyword to add_library
    2. I would suggest to not do that (I'm not a CMake expert) but it sounds like the expense would be to large.
    3. There is no difference, ${MYVARIABLE_INCLUDE_DIR} ist just a variable name it whatever you want. But i would suggest that you follow the naming convention.
    4. One libary is always one .lib/.a file so there should be no problem just use the add_library& target_link_libraries& add_dependencies function.
    5. The library name is always the name that you pass to add_library. However Gmp or gMP would be the same as CMake is case intensitive
    0 讨论(0)
  • 2020-12-24 05:18

    You can use target_link_libraries(myexecutable mylib) to link to the library "mylib". The compiler will use its default way to find the specified library (e.g. it will look for libmylib.a on Linux). The compiler will only look in the link_directories(directory1 directory2 ...), so you could try that command to add the required directories to the search path.

    When "mylib" is also compiled with CMake this will be recognized and everything should work automatically.

    When you want the user to specify a directory you can use a cached CMake variable. set(MYPATH "NOT-DEFINED" CACHE PATH "docstring").

    For more complex stuff it is very advisable to write a CMake find module that can be used with find_package. I suggest you take a look at the FindALSA.cmake which can be used as a good starting point.

    The interesting part is at the end:

    if(ALSA_FOUND)
      set( ALSA_LIBRARIES ${ALSA_LIBRARY} )
      set( ALSA_INCLUDE_DIRS ${ALSA_INCLUDE_DIR} )
    endif()
    
    mark_as_advanced(ALSA_INCLUDE_DIR ALSA_LIBRARY)
    

    The ALSA_LIBRARY and ALSA_INCLUDE_DIR variables are user configurable and stored in the cache, while ALSA_LIBRARIES and ALSA_INCLUDE_DIRS as well as ALSA_FOUND get computed and are the ones that the user of the find module is supposed to use.

    Typically one would use the find module like this:

    find_package(ALSA REQUIRED)
    include_directories(${ALSA_INCLUDE_DIRS})
    target_link_libraries(myexe ${ALSA_LIBRARIES})
    

    I'm sure you can adapt this for your personal library.

    0 讨论(0)
  • 2020-12-24 05:21

    Usually when you want to link against a library that doesn't have a find_package module (e.g. it's an uncommon library, or it's your own library), then you can use the basic commands (the find_X commands) to set variables with the paths you need. Then you use those variables as with find_package (include_directories, target_link_libraries).

    If you're going to be using this library from multiple packages, you may want to create a find_package module; basically it's using the same commands with certain conventions.

    Either of these allow you to specify paths (in the CMake module) to look in, and they allow the user to override the paths (the variables show up as options in ccmake/cmake-gui).

    I'd be glad to add an example of one or both of these methods, just let me know what you're looking for.

    If you just want a quick-and-dirty solution, you could do this, but I wouldn't recommend it:

    include_directories(/perso/testlib/include)
    add_executable(myexecutable myexecutable.cpp)
    target_link_libraries(myexecutable
        /perso/testlib/lib/testlib1.a
        /perso/testlib/lib/testlib2.a)
    

    Regarding your question about target_link_libraries (#5), you can do it several ways. If you want you can provide the full name (e.g. target_link_libraries(myexe libfoo.a)), but I think it's better (more portable I suppose) to use the short name (e.g. target_link_libraries(myexe foo). You can also include linker flags; I'm not sure where I read it, but I think it may translate the -L and -l flags for different linkers.

    For example, if I have a bunch of libraries in the same directory, and I know the names, I might find the directory, store it in a variable, and then do this:

    # First, find and set TESTLIB_LIBRARY_DIR, e.g. with find_path
    # ...
    
    # This assumes the libraries are e.g. 'libtestlib1.a' and 'libtestlib2.a'
    set(TESTLIB_LIBRARIES
        -L${TESTLIB_LIBRARY_DIR)
        -l testlib1
        -l testlib2)
    
    add_executable(myexecutable myexecutable.cpp)
    target_link_libraries(myexecutable ${TESTLIB_LIBRARIES})
    

    If you want to make your own find_package module (like trenki mentioned, FindALSA.cmake seems to be a good starting point), you can use it by adding the directory to the CMAKE_MODULE_PATH; for example, if you put your module(s) in a cmake/modules/ subdirectory:

    # Look for extra CMake modules in a subdirectory of this project
    set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/" ${CMAKE_MODULE_PATH})
    

    One possible issue with FindALSA.cmake: I'm not sure CMAKE_CURRENT_LIST_DIR will work. So I think you should make this change (the second work for me in a module I wrote):

    # Change this line
    include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
    
    # To this (with no path/extension it will search the CMake modules path):
    include(FindPackageHandleStandardArgs)
    

    And to get the usage of FIND_PACKAGE_HANDLE_STANDARD_ARGS, look at FindPackageHandleStandardArgs.cmake in the CMake Modules directory.

    0 讨论(0)
提交回复
热议问题