function(setup_external_libs ARCH) set(REQUEST_FILE "${PROJECT_SOURCE_DIR}/request.txt") if(NOT EXISTS "${REQUEST_FILE}") message(WARNING "request.txt not found at: ${REQUEST_FILE}") return() endif() file(STRINGS ${REQUEST_FILE} LINES) set(LIB_COUNT 0) set(INCLUDE_DIRS) set(LIBRARY_DIRS) set(PREFIX_PATHS) # For install set(INSTALL_SO_FILES) set(INSTALL_BIN_FILES) # 安装proto 的 protoc 和 grpc_cpp_plugin foreach(REL_PATH ${LINES}) # Skip comments / empty lines if(REL_PATH MATCHES "^[ \t]*#.*$" OR REL_PATH STREQUAL "") continue() endif() string(STRIP "${REL_PATH}" REL_PATH) set(FULL_PATH "${PROJECT_SOURCE_DIR}/dependency/${ARCH}/${REL_PATH}") if(NOT EXISTS "${FULL_PATH}") message(WARNING "Library path does not exist: ${FULL_PATH}") continue() endif() list(APPEND PREFIX_PATHS "${FULL_PATH}") string(REGEX REPLACE ".*/([^/]+)/?$" "\\1" LIB_NAME "${REL_PATH}") set(HAS_INCLUDE FALSE) set(HAS_LIB FALSE) # ---- include dirs ---- if(EXISTS "${FULL_PATH}/include") list(APPEND INCLUDE_DIRS "${FULL_PATH}/include") set(HAS_INCLUDE TRUE) else() list(APPEND INCLUDE_DIRS "${FULL_PATH}") set(HAS_INCLUDE TRUE) endif() # OpenCV4 headers live in include/opencv4/opencv2/... if(EXISTS "${FULL_PATH}/include/opencv4/opencv2") list(APPEND INCLUDE_DIRS "${FULL_PATH}/include/opencv4") endif() # ---- library dirs ---- if(EXISTS "${FULL_PATH}/lib") file(GLOB _BUNDLED_LIBSTDCXX_FILES "${FULL_PATH}/lib/libstdc++.so" "${FULL_PATH}/lib/libstdc++.so.*" ) if(_BUNDLED_LIBSTDCXX_FILES) message(STATUS "${LIB_NAME}: excluding vendor lib directory from global " "link paths because it contains a private libstdc++") else() list(APPEND LIBRARY_DIRS "${FULL_PATH}/lib") endif() set(HAS_LIB TRUE) # Collect shared libs for install: *.so and *.so.* file(GLOB _SO_FILES "${FULL_PATH}/lib/*.so" "${FULL_PATH}/lib/*.so.*" ) list(FILTER _SO_FILES EXCLUDE REGEX "/libstdc\\+\\+\\.so(\\..*)?$") if(_SO_FILES) list(APPEND INSTALL_SO_FILES ${_SO_FILES}) endif() else() # No lib/ dir: check libs in base dir file(GLOB _LIB_FILES "${FULL_PATH}/*.so" "${FULL_PATH}/*.so.*" "${FULL_PATH}/*.dylib" "${FULL_PATH}/*.dll" "${FULL_PATH}/*.lib" "${FULL_PATH}/*.a" ) if(_LIB_FILES) list(APPEND LIBRARY_DIRS "${FULL_PATH}") set(HAS_LIB TRUE) # Only install Linux shared libs from base dir file(GLOB _SO_FILES2 "${FULL_PATH}/*.so" "${FULL_PATH}/*.so.*" ) list(FILTER _SO_FILES2 EXCLUDE REGEX "/libstdc\\+\\+\\.so(\\..*)?$") if(_SO_FILES2) list(APPEND INSTALL_SO_FILES ${_SO_FILES2}) endif() else() message(WARNING " ${LIB_NAME}: No library files found in: ${FULL_PATH}") endif() endif() # ---- bin: if dependency provides tools, install them to /bin ---- if(EXISTS "${FULL_PATH}/bin") file(GLOB _BIN_FILES LIST_DIRECTORIES false "${FULL_PATH}/bin/*" ) if(_BIN_FILES) list(APPEND INSTALL_BIN_FILES ${_BIN_FILES}) endif() endif() if(HAS_INCLUDE OR HAS_LIB) math(EXPR LIB_COUNT "${LIB_COUNT} + 1") endif() endforeach() # ---- CMAKE_PREFIX_PATH ---- if(PREFIX_PATHS) list(APPEND CMAKE_PREFIX_PATH ${PREFIX_PATHS}) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endif() # ---- include_directories ---- if(INCLUDE_DIRS) list(REMOVE_DUPLICATES INCLUDE_DIRS) include_directories(${INCLUDE_DIRS}) endif() # ---- link_directories ---- if(LIBRARY_DIRS) list(REMOVE_DUPLICATES LIBRARY_DIRS) link_directories(${LIBRARY_DIRS}) endif() # ---- install third-party shared libs into /lib ---- if(INSTALL_SO_FILES) list(REMOVE_DUPLICATES INSTALL_SO_FILES) list(LENGTH INSTALL_SO_FILES INSTALL_SO_FILES_LIST_LEN) message(STATUS "Will install ${INSTALL_SO_FILES_LIST_LEN} third-party shared libs into DESTINATION lib" ) install(FILES ${INSTALL_SO_FILES} DESTINATION lib) install(CODE [[ file(GLOB _bundled_stdlib_files "${CMAKE_INSTALL_PREFIX}/lib/libstdc++.so" "${CMAKE_INSTALL_PREFIX}/lib/libstdc++.so.*") if(_bundled_stdlib_files) file(REMOVE ${_bundled_stdlib_files}) endif() ]]) # After installing, patch RPATH of installed shared libs to $ORIGIN install(CODE [[ execute_process(COMMAND bash -lc "set -e echo '[install] patch rpath under: ${CMAKE_INSTALL_PREFIX}/lib' if ! command -v patchelf >/dev/null 2>&1; then echo '[install] patchelf not found, skip' exit 0 fi find '${CMAKE_INSTALL_PREFIX}/lib' -maxdepth 1 -type f -name '*.so*' \ -exec patchelf --set-rpath '$ORIGIN' {} + echo '[install] done'" ) ]]) endif() # ---- install third-party tools into /bin ---- if(INSTALL_BIN_FILES) list(REMOVE_DUPLICATES INSTALL_BIN_FILES) install(PROGRAMS ${INSTALL_BIN_FILES} DESTINATION bin) # After installing, patch RPATH of installed tools to $ORIGIN/../lib # After installing, patch RPATH of installed tools to $ORIGIN/../lib install(CODE [[ execute_process(COMMAND bash -lc "set -e if ! command -v patchelf >/dev/null 2>&1; then echo '[install] patchelf not found, skip patch bin rpath' exit 0 fi echo '[install] patch rpath under: ${CMAKE_INSTALL_PREFIX}/bin' # -perm -111: any executable bit set find '${CMAKE_INSTALL_PREFIX}/bin' -maxdepth 1 -type f -perm -111 | while read -r f; do # only patch ELF binaries (skip scripts/text) if file -b \"$f\" 2>/dev/null | grep -qi 'ELF'; then patchelf --set-rpath '$ORIGIN/../lib' \"$f\" || true fi done echo '[install] done (bin rpath)'" ) ]]) endif() if(LIB_COUNT GREATER 0) message(STATUS "Successfully setup ${LIB_COUNT} external libraries for ${ARCH}") else() message(WARNING "No external libraries were successfully setup") endif() endfunction()