cmvr-es/cmake/FindExternalLib.cmake
xtkuang 28f1dd1bf8 feat: add gRPC motor control over Modbus TCP
Add synchronous and streaming MotorService APIs backed by the PLC Modbus TCP runtime and protocol driver. Extend AUBO JSON commands and isolate vendor libstdc++ paths while keeping build-tree tests runnable.
2026-07-30 15:09:07 +08:00

215 lines
7.2 KiB
CMake

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 <prefix>/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()
set(CMVR_EXTERNAL_LIBRARY_DIRS "${LIBRARY_DIRS}" PARENT_SCOPE)
# ---- 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)
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 <prefix>/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()