CMake best practice using shared libraries version

2019-08-14 23:03发布

I'm organizing my "development policies in C" and distributing some codes in static and shared libs.

Static libs are ok, but I found a "gap" about shared libraries in documentation: How to specify the SOVERSION on "find_library".

At this moment I'm building libraries this way:

cmake_minimum_required (VERSION 2.8.11)

set (INSTALL_BIN_DIR "" CACHE PATH "full binary path")
set (INSTALL_LIB_DIR "$ENV{HOME}/embedded/llib/lib" CACHE PATH "full binary path")
set (INSTALL_INCLUDE_DIR "$ENV{HOME}/embedded/llib/include" CACHE PATH "full include path")
set (SRC_DIR "src" CACHE PATH "Source files path")
set (H_DIR  "include" CACHE PATH "Source files path")

set (C_FILES )
list (
    APPEND C_FILES
    ${SRC_DIR}/cJSON.c
    )

set (H_FILES )
list (
    APPEND H_FILES
    ${H_DIR}/cJSON.h
    )

# Define Project name
project (cJSON)

# Create a library called "cJSON" which includes the source and header files.
add_library (cJSON SHARED "${C_FILES}")

#set_target_properties(cJSON PROPERTIES
#   PUBLIC_HEADER "include/cJSON.h")

include_directories (include)
# Make sure the compiler can find include files for our Hello library
# when other libraries or executables link to Hello
#target_include_directories (cJSON PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

set_target_properties (cJSON 
                        PROPERTIES 
                            VERSION 1.0 SOVERSION 1
                            PUBLIC_HEADER "${H_FILES}" 
                    )

install(TARGETS cJSON 
# IMPORTANT: Add the foo library to the "export-set"
  EXPORT cJSONTargets
  LIBRARY
  RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
  LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
  PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}" COMPONENT dev
  )

Running cmake, make and make install it results in:

lrwxrwxrwx 1 takaite takaite    13 Dez  7 11:52 libcJSON.so -> libcJSON.so.1
lrwxrwxrwx 1 takaite takaite    15 Dez  7 11:52 libcJSON.so.1 -> libcJSON.so.1.0
-rw-r--r-- 1 takaite takaite 27194 Dez  7 15:03 libcJSON.so.1.0

And in another library, I'm including this way:

cmake_minimum_required (VERSION 2.8.11)

set (INSTALL_BIN_DIR "" CACHE PATH "full binary path")
set (INSTALL_LIB_DIR "$ENV{HOME}/embedded/llib/lib" CACHE PATH "full binary path")
set (INSTALL_INCLUDE_DIR "$ENV{HOME}/embedded/llib/include" CACHE PATH "full include path")
set (SRC_DIR "src" CACHE PATH "Source files path")
set (H_DIR  "include" CACHE PATH "Source files path")

set (C_FILES )
list (
    APPEND C_FILES
    ${SRC_DIR}/dict.c
    )

set (H_FILES )
list (
    APPEND H_FILES
    ${H_DIR}/dict.h
    )


# Define Project name
project (dict)

set (CMAKE_FIND_LIBRARY_SUFFIXES_BKP ${CMAKE_FIND_LIBRARY_SUFFIXES})
# Set lib version to be used
set (CMAKE_FIND_LIBRARY_SUFFIXES ".so.1")

find_library (
    CJSON_LIB 
    NAMES cJSON 
    PATHS ${INSTALL_LIB_DIR}
    )
set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BKP})

message ("cJSON_lib: ${CJSON_LIB}")

# Create a library called "cJSON" which includes the source and header files.
add_library (dict SHARED "${C_FILES}" ${CJSON_LIB})

include_directories (${H_DIR} ${INSTALL_INCLUDE_DIR})
# Make sure the compiler can find include files for our Hello library
# when other libraries or executables link to Hello
#target_include_directories (cJSON PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

set_target_properties (dict 
                        PROPERTIES 
                            VERSION 1.0 SOVERSION 1
                            PUBLIC_HEADER "${H_FILES}"
                    )

install(TARGETS dict 
# IMPORTANT: Add the foo library to the "export-set"
  EXPORT DictTargets
  LIBRARY
  RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
  LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
  PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}" COMPONENT dev
  )

I can't believe this is the right way to do it. Could any one show me a better way?

标签: linux cmake
1条回答
不美不萌又怎样
2楼-- · 2019-08-14 23:47

For search specific soversion of library you can use precise filename in NAMES option for find_library:

find_library (
    CJSON_LIB 
    NAMES libcJSON.so.1
    PATHS ${INSTALL_LIB_DIR}
    )

From the documentation for find_library:

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). Therefore one may specify library file names such as libfoo.a directly. This can be used to locate static libraries on UNIX-like systems.


Note, that different soversions of the same library are assumed to be ABI compatible with each other. So it is rarely needed to search specific soversion of the library.

Changes in the library, which introduce ABI incopatibility should be accompanied with changing library's version. E.g: libcJSON2.so. So you cannot accidentally find incompatible library using find_library.

查看更多
登录 后发表回答