Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webots_ros2_driver native MacOS support #733

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
25 changes: 18 additions & 7 deletions webots_ros2_driver/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.15)
project(webots_ros2_driver)

# Check which ROS distribution is used, ros2control depends of that
Expand Down Expand Up @@ -40,13 +40,18 @@ else()
find_package(PythonLibs 3.10 EXACT REQUIRED)
endif()

if(APPLE)
# Don't build a fat binary and use simple UNIX pipes for jobserver
set(MAKE_BUILD_VARS "NO_FAT_BINARY=1" "MAKEFLAGS=--jobserver-style=pipe")
endif()

add_custom_target(compile-lib-controller ALL
COMMAND ${CMAKE_COMMAND} -E env "WEBOTS_HOME=${CMAKE_CURRENT_SOURCE_DIR}/webots" make release -f Makefile > /dev/null 2>&1
COMMAND ${CMAKE_COMMAND} -E env "WEBOTS_HOME=${CMAKE_CURRENT_SOURCE_DIR}/webots" ${MAKE_BUILD_VARS} make release -f Makefile
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/webots/src/controller
)

add_custom_target(compile-lib-vehicle ALL
COMMAND ${CMAKE_COMMAND} -E env "WEBOTS_HOME=${CMAKE_CURRENT_SOURCE_DIR}/webots" make release -f Makefile > /dev/null 2>&1
COMMAND ${CMAKE_COMMAND} -E env "WEBOTS_HOME=${CMAKE_CURRENT_SOURCE_DIR}/webots" ${MAKE_BUILD_VARS} make release -f Makefile
DEPENDS compile-lib-controller
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/webots/projects/default/libraries/vehicle
)
Expand Down Expand Up @@ -80,8 +85,14 @@ ament_python_install_package(vehicle
ament_python_install_package(${PROJECT_NAME}
PACKAGE_DIR ${PROJECT_NAME})

# Driver
set(CMAKE_INSTALL_RPATH "$ORIGIN/../controller")
if(UNIX AND NOT APPLE)
set(DYN_LOADER_PREFIX "$ORIGIN")
elseif(APPLE)
set(DYN_LOADER_PREFIX "@executable_path")
endif()

set(CMAKE_INSTALL_RPATH "${DYN_LOADER_PREFIX}/../controller")

add_executable(driver
src/Driver.cpp
src/WebotsNode.cpp
Expand Down Expand Up @@ -129,7 +140,7 @@ install(TARGETS driver
)

# Dynamic IMU
set(CMAKE_INSTALL_RPATH "$ORIGIN/controller")
set(CMAKE_INSTALL_RPATH "${DYN_LOADER_PREFIX}/controller")
add_library(
${PROJECT_NAME}_imu
SHARED
Expand Down Expand Up @@ -157,7 +168,7 @@ install(TARGETS ${PROJECT_NAME}_imu
)

# Dynamic RGBD
set(CMAKE_INSTALL_RPATH "$ORIGIN/controller")
set(CMAKE_INSTALL_RPATH "${DYN_LOADER_PREFIX}/controller")
add_library(
${PROJECT_NAME}_rgbd
SHARED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
elif sys.platform == 'win32':
path = os.path.join('lib', 'controller', 'Controller.dll')
elif sys.platform == 'darwin':
path = os.path.join('Contents', 'lib', 'controller', 'libController.dylib')
path = os.path.join('lib', 'controller', 'libController.dylib')

wb = ctypes.cdll.LoadLibrary(os.path.join(os.environ['WEBOTS_HOME'], path))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def loadApi() -> ctypes.cdll:
car = 'car.dll'
driver = 'driver.dll'
elif sys.platform == 'darwin':
path = os.path.join('Contents', 'MacOS', 'lib', 'controller')
path = os.path.join('lib', 'controller')
car = 'libcar.dylib'
driver = 'libdriver.dylib'
ctypes.cdll.LoadLibrary(os.path.join(os.environ['WEBOTS_HOME'], path, car))
Expand Down
15 changes: 11 additions & 4 deletions webots_ros2_driver/webots/resources/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ endif

ifeq ($(OSTYPE),darwin)
ifdef NO_FAT_BINARY
PROCESSOR := $(shell uname -m)
WBCFLAGS += -target $(PROCESSOR)-apple-macos11
DYNAMIC_LINK_FLAGS += -target $(PROCESSOR)-apple-macos11
endif
Expand All @@ -337,14 +338,14 @@ ifdef USE_CXX
ifndef EXCLUDE_CONTROLLERS
DYNAMIC_LIBRARIES += -L"$(WEBOTS_CONTROLLER_LIB_PATH)" -lController
ifdef USE_C_API
ifeq ($(OSTYPE),darwin)
ifdef BUILD_MACOS_BUNDLE
INCLUDE += -I"$(WEBOTS_HOME)/Contents/include/controller/c"
else
INCLUDE += -I"$(WEBOTS_HOME)/include/controller/c"
endif
else
DYNAMIC_LIBRARIES += -lCppController
ifeq ($(OSTYPE),darwin)
ifdef BUILD_MACOS_BUNDLE
INCLUDE += -I"$(WEBOTS_HOME)/Contents/include/controller/cpp"
else
INCLUDE += -I"$(WEBOTS_HOME)/include/controller/cpp"
Expand All @@ -365,7 +366,7 @@ else
LINKER = $(CC)
endif
ifndef EXCLUDE_CONTROLLERS
ifeq ($(OSTYPE),darwin)
ifdef BUILD_MACOS_BUNDLE
INCLUDE += -I"$(WEBOTS_HOME)/Contents/include/controller/c"
else
INCLUDE += -I"$(WEBOTS_HOME)/include/controller/c"
Expand Down Expand Up @@ -405,7 +406,11 @@ endif

ifeq ($(OSTYPE),darwin)
ifdef WEBOTS_LIBRARY
INSTALL_NAME ?= @rpath/Contents/lib/controller/$(MAIN_TARGET)
ifdef BUILD_MACOS_BUNDLE
INSTALL_NAME ?= @rpath/Contents/lib/controller/$(MAIN_TARGET)
else
INSTALL_NAME ?= @rpath/$(MAIN_TARGET)
endif
LFLAGS += -Xlinker -rpath -Xlinker @loader_path/.. -install_name $(INSTALL_NAME)
else
CALLING_MAKEFILE_DIR := $(shell dirname "$(realpath $(firstword $(MAKEFILE_LIST)))")
Expand Down Expand Up @@ -436,6 +441,8 @@ ifdef USE_ODE
endif
ifeq ($(OSTYPE),darwin)
DYNAMIC_LINK_FLAGS += -flat_namespace -undefined suppress
endif
ifdef BUILD_MACOS_BUNDLE
DYNAMIC_LIBRARIES += "$(WEBOTS_HOME)/Contents/Resources/projects/plugins/physics/physics.a"
INCLUDE += -I"$(WEBOTS_HOME)/Contents/include/ode" -I"$(WEBOTS_HOME)/Contents/include"
else
Expand Down
7 changes: 5 additions & 2 deletions webots_ros2_driver/webots/resources/Makefile.os.include
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ else
LIB_PREFIX = lib
ifeq ($(OSTYPE),linux)
SHARED_LIB_EXTENSION = .so
WEBOTS_LIB_PATH=$(WEBOTS_HOME)/lib/webots
WEBOTS_CONTROLLER_LIB_PATH=$(WEBOTS_HOME)/lib/controller
else # macOS
SHARED_LIB_EXTENSION = .dylib
endif
ifdef BUILD_MACOS_BUNDLE
WEBOTS_LIB_PATH=$(WEBOTS_HOME)/Contents/lib/webots
WEBOTS_CONTROLLER_LIB_PATH=$(WEBOTS_HOME)/Contents/lib/controller
else
WEBOTS_LIB_PATH=$(WEBOTS_HOME)/lib/webots
WEBOTS_CONTROLLER_LIB_PATH=$(WEBOTS_HOME)/lib/controller
endif
endif
17 changes: 11 additions & 6 deletions webots_ros2_driver/webots/src/controller/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ WEBOTS_DEPENDENCY_PATH ?= $(WEBOTS_HOME_PATH)/dependencies
ifeq ($(OSTYPE),darwin)
CFLAGS = -mmacosx-version-min=$(MACOSX_MIN_SDK_VERSION) -fpascal-strings -Wno-deprecated-declarations -I/Developer/Headers/FlatCarbon -Wall -fno-common
INCLUDE = -I$(WEBOTS_HOME_PATH)/include/controller/c -I$(WEBOTS_HOME_PATH)/include
LD_FLAGS = -mmacosx-version-min=$(MACOSX_MIN_SDK_VERSION) -dynamiclib -install_name @rpath/Contents/lib/controller/libController.dylib -compatibility_version 1.0 -current_version 1.0.0
LD_FLAGS = -mmacosx-version-min=$(MACOSX_MIN_SDK_VERSION) -dynamiclib -compatibility_version 1.0 -current_version 1.0.0
ifdef BUILD_MACOS_BUNDLE
LD_FLAGS += -install_name @rpath/Contents/lib/controller/libController.dylib
else
LD_FLAGS += -install_name @rpath/libController.dylib
endif
SHARED_LIBS = -lz
TARGET = $(WEBOTS_CONTROLLER_LIB_PATH)/libController.dylib
CC = gcc
Expand Down Expand Up @@ -137,9 +142,11 @@ endif

endif

ifeq ($(OSTYPE),darwin)
X86_64_OBJECTS = $(addprefix $(OBJDIR)/x86_64/, $(OBJECTS))


ifdef FAT_BINARY
ARM64_OBJECTS = $(addprefix $(OBJDIR)/arm64/, $(OBJECTS))
X86_64_OBJECTS = $(addprefix $(OBJDIR)/x86_64/, $(OBJECTS))

$(TARGET): $(OBJDIR)/x86_64/libController.dylib $(OBJDIR)/arm64/libController.dylib
@echo "# creating fat binary: $$"\(WEBOTS_HOME\)/lib/controller/libController.dylib
Expand All @@ -157,9 +164,7 @@ $(OBJDIR)/arm64/libController.dylib: $(ARM64_OBJECTS)
@$(CC) $(LD_FLAGS) -target arm64-apple-macos11 -o $@ $(ARM64_OBJECTS) $(SHARED_LIBS)
@chmod a-x $@

endif

ifeq ($(OSTYPE),linux)
else
$(TARGET): $(OBJECTS)
@echo "# linking "$@
@$(CC) $(LD_FLAGS) -o $(TARGET) $(addprefix $(OBJDIR)/, $(OBJECTS)) $(SHARED_LIBS)
Expand Down
11 changes: 7 additions & 4 deletions webots_ros2_driver/webots/src/controller/cpp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ SHAREDLIBS = -L$(WEBOTS_CONTROLLER_LIB_PATH) -lController
CPPFLAGS = -c -fPIC -Wall -mmacosx-version-min=$(MACOSX_MIN_SDK_VERSION)
CPPINCLUDES = -I$(WEBOTS_HOME_PATH)/include/controller/c -I$(WEBOTS_HOME_PATH)/include/controller/cpp
LIBCONTROLLER = $(WEBOTS_CONTROLLER_LIB_PATH)/libController.dylib
ifdef BUILD_MACOS_BUNDLE
LDFLAGS += -install_name @rpath/Contents/lib/controller/libCppController.dylib
else
LD_FLAGS += -install_name @rpath/libCppController.dylib
endif
TARGET = $(WEBOTS_CONTROLLER_LIB_PATH)/libCppController.dylib
endif

Expand All @@ -117,10 +121,9 @@ endif

all debug profile release: $(TARGET)

ifeq ($(OSTYPE),darwin)

X86_64_OBJECTS = $(addprefix $(BUILD_GOAL_DIR)/x86_64/,$(OBJECTS))
ARM64_OBJECTS = $(addprefix $(BUILD_GOAL_DIR)/arm64/,$(OBJECTS))
ifdef FAT_BINARY
ARM64_OBJECTS = $(addprefix $(BUILD_GOAL_DIR)/arm64/,$(OBJECTS))
X86_64_OBJECTS = $(addprefix $(BUILD_GOAL_DIR)/x86_64/,$(OBJECTS))

$(TARGET): $(BUILD_GOAL_DIR)/x86_64/libCppController.dylib $(BUILD_GOAL_DIR)/arm64/libCppController.dylib
@echo "# creating fat" $(notdir $@)
Expand Down
7 changes: 6 additions & 1 deletion webots_ros2_driver/webots/src/controller/java/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,12 @@ CFLAGS1 = -isysroot $(MACOSX_SDK_PATH) -mmacosx-version-min=$(MACO
PLATFORM_INCLUDE = -I"$(MACOSX_SDK_PATH)/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers"
TARGET = $(WEBOTS_CONTROLLER_LIB_PATH)/java/lib$(LIBNAME).jnilib
CFLAGS2 = -c -Wall -isysroot $(MACOSX_SDK_PATH) -mmacosx-version-min=$(MACOSX_MIN_SDK_VERSION) -Wno-unused-function
JNILIB_FLAGS = -dynamiclib -install_name @rpath/Contents/lib/controller/java/libJavaController.jnilib -Wl,-rpath,@loader_path/../../..
JNILIB_FLAGS = -dynamiclib -Wl,-rpath,@loader_path/../../..
ifdef BUILD_MACOS_BUNDLE
JNILIB_FLAGS += -install_name @rpath/Contents/lib/controller/java/libJavaController.jnilib
else
JNILIB_FLAGS += -install_name @rpath/java/libJavaController.jnilib
endif
JAVA_INCLUDES = -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/darwin"
LIBCONTROLLER = $(WEBOTS_CONTROLLER_LIB_PATH)/libController.dylib
LIBCPPCONTROLLER = $(WEBOTS_CONTROLLER_LIB_PATH)/libCppController.dylib
Expand Down
28 changes: 26 additions & 2 deletions webots_ros2_driver/webots_ros2_driver/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ def __str__(self):
def short(self):
return self.version.replace('revision ', 'rev').replace(' ', '-')


def is_wsl():
return 'microsoft-standard' in uname().release

Expand Down Expand Up @@ -182,8 +181,14 @@ def version_min(found, minimum):
paths = [
'C:\\Program Files\\Webots' # Windows default install
]

# Add automatic installation path to pathes list
paths.append(os.path.join(str(Path.home()), '.ros', 'webots' + minimum_version.short(), 'webots'))
auto_webots_path = os.path.join(str(Path.home()), '.ros', 'webots' + minimum_version.short())

if sys.platform == 'darwin':
paths.append(os.path.join(auto_webots_path, 'Webots.app', 'Contents'))
else:
paths.append(os.path.join(auto_webots_path, 'Webots'))

# Check if default pathes contain target version of Webots
for path in paths:
Expand Down Expand Up @@ -211,6 +216,9 @@ def on_download_progress_changed(count, block_size, total_size):
if is_wsl():
archive_name = f'webots-{minimum_version.short()}_setup.exe'
archive_path = os.path.join('/mnt/c/Temp', archive_name)
elif sys.platform == 'darwin':
archive_name = f'webots-{minimum_version.short()}.dmg'
archive_path = os.path.join(installation_directory, archive_name)
else:
installation_path = os.path.abspath(os.path.join(installation_directory, 'webots'))
archive_name = f'webots-{minimum_version.short()}-x86-64.tar.bz2'
Expand All @@ -234,6 +242,22 @@ def on_download_progress_changed(count, block_size, total_size):
subprocess.check_output(f'{archive_path} /SILENT /ALLUSERS', shell=True)
os.remove(archive_path)
os.environ['WEBOTS_HOME'] = '/mnt/c/Program Files/Webots'
elif sys.platform == 'darwin':
print('Installing Application Bundle...')

bundle_path = Path(os.path.join(installation_directory, 'webots_mnt', 'Webots.app'))
target_dir = Path(os.path.join(installation_directory, f'webots{minimum_version.short()}'))

if not bundle_path.exists():
print(subprocess.check_output(f'hdiutil attach {archive_path} -mountpoint {installation_directory}/webots_mnt', shell=True))
target_dir.mkdir(parents=True, exist_ok=True)
shutil.copytree(bundle_path, os.path.join(target_dir, 'Webots.app'))

if Path(os.path.join(installation_directory, 'webots_mnt')).exists():
subprocess.check_output(f'hdiutil detach {installation_directory}/webots_mnt', shell=True)

os.environ['WEBOTS_HOME'] = os.path.join(target_dir, 'Webots.app', "Contents")
os.environ['WEBOTS_HOME_PATH'] = os.path.join(target_dir, 'Webots.app', 'Contents')
else:
installation_subdirectory = os.path.join(installation_directory, 'webots' + minimum_version.short())
print('Extracting...')
Expand Down
2 changes: 2 additions & 0 deletions webots_ros2_driver/webots_ros2_driver/webots_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ def __init__(self, output='screen', world=None, gui=True, mode='realtime', strea
webots_path = get_webots_home()
if self.__is_wsl:
webots_path = os.path.join(webots_path, 'msys64', 'mingw64', 'bin', 'webots.exe')
elif sys.platform == 'darwin':
webots_path = os.path.join(webots_path, 'MacOS', 'webots')
else:
webots_path = os.path.join(webots_path, 'webots')
else:
Expand Down
2 changes: 1 addition & 1 deletion webots_ros2_msgs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.15)
project(webots_ros2_msgs)

# Default to C11
Expand Down