feat: support with plugin build

This commit is contained in:
insleker 2026-05-21 12:46:25 +08:00
parent d877661507
commit 0ec592a2be
8 changed files with 219 additions and 159 deletions

4
.gitignore vendored
View File

@ -70,4 +70,6 @@ Testing/
# user # user
**/CMakeUserPresets.json **/CMakeUserPresets.json
/test_package/bin /test_package/test_package
*.exe
_tmp_install

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.21) cmake_minimum_required(VERSION 3.23)
project(webots_controller LANGUAGES C CXX) project(webots_controller LANGUAGES C CXX)
option(WEBOTS_CONTROLLER_NO_PLUGINS "Disable runtime plugin loading (dlopen/LoadLibrary paths)." ON) option(WEBOTS_CONTROLLER_NO_PLUGINS "Disable runtime plugin loading (dlopen/LoadLibrary paths)." ON)

View File

@ -1,7 +1,7 @@
from conan import ConanFile from conan import ConanFile
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
from conan.tools.files import copy from conan.tools.files import copy
from conan.tools.microsoft import is_msvc
class WebotsControllerConan(ConanFile): class WebotsControllerConan(ConanFile):
name = "webots-controller" name = "webots-controller"
@ -26,6 +26,18 @@ class WebotsControllerConan(ConanFile):
if self.settings.os == "Windows": if self.settings.os == "Windows":
del self.options.fPIC del self.options.fPIC
def configure(self):
# plugins use dlopen therefore ABI need to be match (same compiler type and compiler version)
if self.options.get_safe("no_plugins", True):
return
if self.settings.os == "Windows" and is_msvc(self):
raise ValueError("Official windows webots is build under msys2 mingw(gcc), rather than MSVC.")
def requirements(self):
# self.requires("stb/cci.20240531")
pass
def layout(self): def layout(self):
cmake_layout(self) cmake_layout(self)
@ -34,7 +46,7 @@ class WebotsControllerConan(ConanFile):
deps.generate() deps.generate()
tc = CMakeToolchain(self) tc = CMakeToolchain(self)
tc.variables["BUILD_SHARED_LIBS"] = bool(self.options.shared) # tc.variables["BUILD_SHARED_LIBS"] = bool(self.options.shared)
tc.variables["WEBOTS_CONTROLLER_NO_PLUGINS"] = bool(self.options.no_plugins) tc.variables["WEBOTS_CONTROLLER_NO_PLUGINS"] = bool(self.options.no_plugins)
tc.generate() tc.generate()
@ -50,4 +62,4 @@ class WebotsControllerConan(ConanFile):
def package_info(self): def package_info(self):
self.cpp_info.libs = ["webots_cpp_controller", "webots_controller"] self.cpp_info.libs = ["webots_cpp_controller", "webots_controller"]
self.cpp_info.includedirs = ["include/controller/cpp", "include/controller/c"] self.cpp_info.includedirs = ["include", "include/controller/cpp", "include/controller/c"]

13
lefthook.yml Normal file
View File

@ -0,0 +1,13 @@
pre-commit:
commands:
cmake-format:
glob: "{**/CMakeLists.txt,**/*.cmake}"
run: uvx --with pyyaml --from cmakelang cmake-format -i {staged_files}
stage_fixed: true
# clang-format:
# run: uvx run-clang-format -i ./src ./include ./tests
# stage_fixed: true
# post-checkout:
# commands:
# inkr-skill-sync:
# run: uvx --from git+https://github.com/existedinnettw/inkr-harness-tools.git inkr-skill-sync .local .agents --recursive

View File

@ -2,78 +2,77 @@ set(WEBOTS_HEADERS_ROOT "${CMAKE_SOURCE_DIR}/include/controller/c")
set(WEBOTS_INCLUDE_ROOT "${CMAKE_SOURCE_DIR}/include") set(WEBOTS_INCLUDE_ROOT "${CMAKE_SOURCE_DIR}/include")
set(WEBOTS_STB_DIR "${CMAKE_SOURCE_DIR}/src/stb") set(WEBOTS_STB_DIR "${CMAKE_SOURCE_DIR}/src/stb")
file(GLOB_RECURSE WEBOTS_CONTROLLER_C_PUBLIC_HEADERS CONFIGURE_DEPENDS
"${WEBOTS_HEADERS_ROOT}/webots/*.h")
file(GLOB_RECURSE WEBOTS_CONTROLLER_PLUGIN_PUBLIC_HEADERS CONFIGURE_DEPENDS
"${WEBOTS_INCLUDE_ROOT}/plugins/*.h")
if(NOT EXISTS "${WEBOTS_HEADERS_ROOT}/webots") if(NOT EXISTS "${WEBOTS_HEADERS_ROOT}/webots")
message(FATAL_ERROR "Missing required repo path: ${WEBOTS_HEADERS_ROOT}/webots") message(
FATAL_ERROR "Missing required repo path: ${WEBOTS_HEADERS_ROOT}/webots")
endif() endif()
if(NOT EXISTS "${WEBOTS_STB_DIR}/stb_image.h") if(NOT EXISTS "${WEBOTS_STB_DIR}/stb_image.h")
message(FATAL_ERROR "Missing required repo path: ${WEBOTS_STB_DIR}/stb_image.h") message(
FATAL_ERROR "Missing required repo path: ${WEBOTS_STB_DIR}/stb_image.h")
endif() endif()
set(WEBOTS_CONTROLLER_C_CORE_SOURCES set(WEBOTS_CONTROLLER_C_CORE_SOURCES
abstract_camera.c abstract_camera.c
accelerometer.c accelerometer.c
altimeter.c altimeter.c
ansi_codes.c ansi_codes.c
base64.c base64.c
brake.c brake.c
camera.c camera.c
compass.c compass.c
connector.c connector.c
console.c console.c
default_robot_window.c default_robot_window.c
device.c device.c
display.c display.c
distance_sensor.c distance_sensor.c
emitter.c emitter.c
file.c file.c
g_image.c g_image.c
g_pipe.c g_pipe.c
gps.c gps.c
gyro.c gyro.c
image.c image.c
inertial_unit.c inertial_unit.c
joystick.c joystick.c
keyboard.c keyboard.c
led.c led.c
lidar.c lidar.c
light_sensor.c light_sensor.c
microphone.c microphone.c
motion.c motion.c
motor.c motor.c
mouse.c mouse.c
node.c node.c
pen.c pen.c
percent.c percent.c
position_sensor.c position_sensor.c
radar.c radar.c
range_finder.c range_finder.c
receiver.c receiver.c
request.c request.c
robot.c robot.c
scheduler.c scheduler.c
sha1.c sha1.c
skin.c skin.c
speaker.c speaker.c
string.c string.c
supervisor.c supervisor.c
system.c system.c
tcp_client.c tcp_client.c
touch_sensor.c touch_sensor.c
vacuum_gripper.c vacuum_gripper.c)
)
set(WEBOTS_CONTROLLER_C_PLUGIN_SOURCES set(WEBOTS_CONTROLLER_C_PLUGIN_SOURCES dynamic_library.c html_robot_window.c
dynamic_library.c radio.c remote_control.c robot_window.c)
html_robot_window.c
radio.c
remote_control.c
robot_window.c
)
set(WEBOTS_CONTROLLER_C_STUB_SOURCES set(WEBOTS_CONTROLLER_C_STUB_SOURCES no_plugins_stubs.c)
no_plugins_stubs.c
)
set(WEBOTS_CONTROLLER_C_SOURCES ${WEBOTS_CONTROLLER_C_CORE_SOURCES}) set(WEBOTS_CONTROLLER_C_SOURCES ${WEBOTS_CONTROLLER_C_CORE_SOURCES})
if(WEBOTS_CONTROLLER_NO_PLUGINS) if(WEBOTS_CONTROLLER_NO_PLUGINS)
@ -82,27 +81,48 @@ else()
list(APPEND WEBOTS_CONTROLLER_C_SOURCES ${WEBOTS_CONTROLLER_C_PLUGIN_SOURCES}) list(APPEND WEBOTS_CONTROLLER_C_SOURCES ${WEBOTS_CONTROLLER_C_PLUGIN_SOURCES})
endif() endif()
# add_library without STATIC/SHARED follows BUILD_SHARED_LIBS automatically in cmake. # add_library without STATIC/SHARED follows BUILD_SHARED_LIBS automatically in
# cmake.
add_library(webots_controller ${WEBOTS_CONTROLLER_C_SOURCES}) add_library(webots_controller ${WEBOTS_CONTROLLER_C_SOURCES})
add_library(webots-controller::webots_controller ALIAS webots_controller) add_library(webots-controller::webots_controller ALIAS webots_controller)
target_sources(
webots_controller
PUBLIC FILE_SET
webots_c_headers
TYPE
HEADERS
BASE_DIRS
"${WEBOTS_HEADERS_ROOT}"
FILES
${WEBOTS_CONTROLLER_C_PUBLIC_HEADERS}
FILE_SET
webots_plugin_headers
TYPE
HEADERS
BASE_DIRS
"${WEBOTS_INCLUDE_ROOT}"
FILES
${WEBOTS_CONTROLLER_PLUGIN_PUBLIC_HEADERS})
if(WIN32) if(WIN32)
set_target_properties(webots_controller PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) set_target_properties(webots_controller PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS
ON)
target_link_libraries(webots_controller PRIVATE ws2_32) target_link_libraries(webots_controller PRIVATE ws2_32)
endif() endif()
target_include_directories(webots_controller target_include_directories(
PUBLIC webots_controller
$<BUILD_INTERFACE:${WEBOTS_HEADERS_ROOT}> PUBLIC $<BUILD_INTERFACE:${WEBOTS_INCLUDE_ROOT}>
$<INSTALL_INTERFACE:include/controller/c> $<BUILD_INTERFACE:${WEBOTS_HEADERS_ROOT}> $<INSTALL_INTERFACE:include>
PRIVATE $<INSTALL_INTERFACE:include/controller/c>
${WEBOTS_STB_DIR} PRIVATE ${WEBOTS_STB_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(webots_controller PRIVATE LIBCONTROLLER_VERSION="R2025a") target_compile_definitions(webots_controller
PRIVATE LIBCONTROLLER_VERSION="R2025a")
if(WEBOTS_CONTROLLER_NO_PLUGINS) if(WEBOTS_CONTROLLER_NO_PLUGINS)
target_compile_definitions(webots_controller PUBLIC WEBOTS_CONTROLLER_NO_PLUGINS=1) target_compile_definitions(webots_controller
PUBLIC WEBOTS_CONTROLLER_NO_PLUGINS=1)
endif() endif()
if(UNIX) if(UNIX)
@ -115,5 +135,8 @@ if(UNIX)
endif() endif()
endif() endif()
install(TARGETS webots_controller) install(
install(DIRECTORY "${WEBOTS_HEADERS_ROOT}/webots" DESTINATION "include/controller/c") TARGETS webots_controller FILE_SET webots_c_headers
DESTINATION "include/controller/c"
FILE_SET webots_plugin_headers
DESTINATION "include")

View File

@ -1,58 +1,71 @@
set(WEBOTS_CONTROLLER_CPP_SOURCES set(WEBOTS_CONTROLLER_CPP_SOURCES
Accelerometer.cpp Accelerometer.cpp
Altimeter.cpp Altimeter.cpp
Brake.cpp Brake.cpp
Camera.cpp Camera.cpp
Compass.cpp Compass.cpp
Connector.cpp Connector.cpp
Device.cpp Device.cpp
Display.cpp Display.cpp
DistanceSensor.cpp DistanceSensor.cpp
Emitter.cpp Emitter.cpp
Field.cpp Field.cpp
GPS.cpp GPS.cpp
Gyro.cpp Gyro.cpp
InertialUnit.cpp InertialUnit.cpp
Joystick.cpp Joystick.cpp
Keyboard.cpp Keyboard.cpp
LED.cpp LED.cpp
Lidar.cpp Lidar.cpp
LightSensor.cpp LightSensor.cpp
Motion.cpp Motion.cpp
Motor.cpp Motor.cpp
Mouse.cpp Mouse.cpp
Node.cpp Node.cpp
Pen.cpp Pen.cpp
PositionSensor.cpp PositionSensor.cpp
Proto.cpp Proto.cpp
Radar.cpp Radar.cpp
RangeFinder.cpp RangeFinder.cpp
Receiver.cpp Receiver.cpp
Robot.cpp Robot.cpp
Skin.cpp Skin.cpp
Speaker.cpp Speaker.cpp
Supervisor.cpp Supervisor.cpp
TouchSensor.cpp TouchSensor.cpp
VacuumGripper.cpp VacuumGripper.cpp)
)
file(GLOB_RECURSE WEBOTS_CONTROLLER_CPP_PUBLIC_HEADERS CONFIGURE_DEPENDS
"${CMAKE_SOURCE_DIR}/include/controller/cpp/webots/*.hpp")
add_library(webots_cpp_controller ${WEBOTS_CONTROLLER_CPP_SOURCES}) add_library(webots_cpp_controller ${WEBOTS_CONTROLLER_CPP_SOURCES})
add_library(webots-controller::webots_cpp_controller ALIAS webots_cpp_controller) add_library(webots-controller::webots_cpp_controller ALIAS
webots_cpp_controller)
target_sources(
webots_cpp_controller
PUBLIC FILE_SET
webots_cpp_headers
TYPE
HEADERS
BASE_DIRS
"${CMAKE_SOURCE_DIR}/include/controller/cpp"
FILES
${WEBOTS_CONTROLLER_CPP_PUBLIC_HEADERS})
if(WIN32) if(WIN32)
set_target_properties(webots_cpp_controller PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) set_target_properties(webots_cpp_controller
PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif() endif()
target_include_directories(webots_cpp_controller target_include_directories(
PUBLIC webots_cpp_controller
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include/controller/cpp> PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include/controller/cpp>
$<INSTALL_INTERFACE:include/controller/cpp> $<INSTALL_INTERFACE:include/controller/cpp>)
)
target_link_libraries(webots_cpp_controller target_link_libraries(webots_cpp_controller PUBLIC webots_controller)
PUBLIC
webots_controller
)
install(TARGETS webots_cpp_controller) install(
install(DIRECTORY "${CMAKE_SOURCE_DIR}/include/controller/cpp/webots" DESTINATION "include/controller/cpp") TARGETS webots_cpp_controller
# `include "../../c/webots/types.h"` in `Robot.hpp`
FILE_SET webots_cpp_headers DESTINATION "include/controller/cpp")

View File

@ -20,38 +20,35 @@ if(WIN32 AND DEFINED ENV{MINGW_HOME})
list(APPEND _extra_runtime_dirs "$ENV{MINGW_HOME}/bin") list(APPEND _extra_runtime_dirs "$ENV{MINGW_HOME}/bin")
endif() endif()
# Webots controllers rely on seeing shared deps in the same directory as the executable. # Webots controllers rely on seeing shared deps in the same directory as the
install(TARGETS test_package # executable. Destination therefore change to "."
RUNTIME_DEPENDENCY_SET test_package_runtime_deps install(
RUNTIME DESTINATION bin TARGETS test_package RUNTIME_DEPENDENCY_SET test_package_runtime_deps
LIBRARY DESTINATION lib RUNTIME DESTINATION .
ARCHIVE DESTINATION lib) LIBRARY DESTINATION .
ARCHIVE DESTINATION .)
if(WIN32) if(WIN32)
set(_runtime_dep_pre_excludes set(_runtime_dep_pre_excludes "^api-ms-win-.*" "^ext-ms-.*")
"^api-ms-win-.*" set(_runtime_dep_post_excludes ".*/system32/.*" ".*/Windows/.*"
"^ext-ms-.*") ".*/SysWOW64/.*")
set(_runtime_dep_post_excludes
".*/system32/.*"
".*/Windows/.*"
".*/SysWOW64/.*")
else() else()
set(_runtime_dep_pre_excludes set(_runtime_dep_pre_excludes
[[libc\.so\..*]] [[libc\.so\..*]] [[libgcc_s\.so\..*]] [[libm\.so\..*]]
[[libgcc_s\.so\..*]] [[libstdc\+\+\.so\..*]] [[ld-linux-x86-64\.so\..*]])
[[libm\.so\..*]] set(_runtime_dep_post_excludes [[^/lib.*]] [[^/usr/lib.*]])
[[libstdc\+\+\.so\..*]]
[[ld-linux-x86-64\.so\..*]])
set(_runtime_dep_post_excludes
[[^/lib.*]]
[[^/usr/lib.*]])
endif() endif()
install( install(
RUNTIME_DEPENDENCY_SET test_package_runtime_deps RUNTIME_DEPENDENCY_SET
PRE_EXCLUDE_REGEXES ${_runtime_dep_pre_excludes} test_package_runtime_deps
POST_EXCLUDE_REGEXES ${_runtime_dep_post_excludes} PRE_EXCLUDE_REGEXES
${_runtime_dep_pre_excludes}
POST_EXCLUDE_REGEXES
${_runtime_dep_post_excludes}
DIRECTORIES DIRECTORIES
${CONAN_RUNTIME_LIB_DIRS} ${CONAN_RUNTIME_LIB_DIRS}
${CMAKE_SYSROOT}/lib ${CMAKE_SYSROOT}/lib
${_extra_runtime_dirs}) ${_extra_runtime_dirs}
DESTINATION
.)

View File

@ -25,6 +25,6 @@ class TestPackageConan(ConanFile):
cmake = CMake(self) cmake = CMake(self)
cmake.install() cmake.install()
if can_run(self): if can_run(self):
exe = os.path.join(self.source_folder, "bin", "test_package") exe = os.path.join(self.source_folder, "test_package")
self.run(exe, env="conanrun") self.run(exe, env="conanrun")