cmvr-es/cmake/FindExternalLib.cmake

214 lines
7.1 KiB
CMake
Raw Normal View History

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)
2026-01-27 11:38:07 +08:00
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()
2026-02-05 17:31:18 +08:00
# 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")
2026-07-28 16:32:58 +08:00
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.*"
)
2026-07-02 08:29:19 +08:00
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.*"
)
2026-07-02 08:29:19 +08:00
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()
2026-02-11 15:23:11 +08:00
# ---- bin: if dependency provides tools, install them to <prefix>/bin ----
2026-01-27 11:38:07 +08:00
if(EXISTS "${FULL_PATH}/bin")
2026-02-11 15:23:11 +08:00
file(GLOB _BIN_FILES
LIST_DIRECTORIES false
"${FULL_PATH}/bin/*"
)
if(_BIN_FILES)
list(APPEND INSTALL_BIN_FILES ${_BIN_FILES})
2026-01-27 11:38:07 +08:00
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 <prefix>/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)
2026-07-02 08:29:19 +08:00
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()
2026-01-27 11:38:07 +08:00
# ---- install third-party tools into <prefix>/bin ----
if(INSTALL_BIN_FILES)
list(REMOVE_DUPLICATES INSTALL_BIN_FILES)
install(PROGRAMS ${INSTALL_BIN_FILES} DESTINATION bin)
2026-02-11 15:23:11 +08:00
# After installing, patch RPATH of installed tools to $ORIGIN/../lib
2026-01-27 11:38:07 +08:00
# 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
2026-02-11 15:23:11 +08:00
2026-01-27 11:38:07 +08:00
echo '[install] patch rpath under: ${CMAKE_INSTALL_PREFIX}/bin'
2026-02-11 15:23:11 +08:00
# -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
2026-01-27 11:38:07 +08:00
fi
done
echo '[install] done (bin rpath)'"
)
]])
2026-02-11 15:23:11 +08:00
2026-01-27 11:38:07 +08:00
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()