diff --git a/webots_ros2_driver/CMakeLists.txt b/webots_ros2_driver/CMakeLists.txt index 54ec02e92..cf21f5833 100644 --- a/webots_ros2_driver/CMakeLists.txt +++ b/webots_ros2_driver/CMakeLists.txt @@ -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 @@ -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 ) @@ -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 @@ -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 @@ -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 diff --git a/webots_ros2_driver/webots/lib/controller/python/controller/wb.py b/webots_ros2_driver/webots/lib/controller/python/controller/wb.py index 8783d6048..c58f31557 100644 --- a/webots_ros2_driver/webots/lib/controller/python/controller/wb.py +++ b/webots_ros2_driver/webots/lib/controller/python/controller/wb.py @@ -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)) diff --git a/webots_ros2_driver/webots/lib/controller/python/vehicle/driver.py b/webots_ros2_driver/webots/lib/controller/python/vehicle/driver.py index e2e7b2eb5..d262307ef 100644 --- a/webots_ros2_driver/webots/lib/controller/python/vehicle/driver.py +++ b/webots_ros2_driver/webots/lib/controller/python/vehicle/driver.py @@ -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)) diff --git a/webots_ros2_driver/webots/resources/Makefile.include b/webots_ros2_driver/webots/resources/Makefile.include index e616ed624..d73aa7cec 100644 --- a/webots_ros2_driver/webots/resources/Makefile.include +++ b/webots_ros2_driver/webots/resources/Makefile.include @@ -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 @@ -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" @@ -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" @@ -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)))") @@ -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 diff --git a/webots_ros2_driver/webots/resources/Makefile.os.include b/webots_ros2_driver/webots/resources/Makefile.os.include index 59e04a0d6..520dd6538 100644 --- a/webots_ros2_driver/webots/resources/Makefile.os.include +++ b/webots_ros2_driver/webots/resources/Makefile.os.include @@ -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 diff --git a/webots_ros2_driver/webots/src/controller/c/Makefile b/webots_ros2_driver/webots/src/controller/c/Makefile index cecfd0087..2b0c8c081 100644 --- a/webots_ros2_driver/webots/src/controller/c/Makefile +++ b/webots_ros2_driver/webots/src/controller/c/Makefile @@ -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 @@ -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 @@ -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) diff --git a/webots_ros2_driver/webots/src/controller/cpp/Makefile b/webots_ros2_driver/webots/src/controller/cpp/Makefile index 7f1c36b1e..a0e6c8333 100644 --- a/webots_ros2_driver/webots/src/controller/cpp/Makefile +++ b/webots_ros2_driver/webots/src/controller/cpp/Makefile @@ -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 @@ -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 $@) diff --git a/webots_ros2_driver/webots/src/controller/java/Makefile b/webots_ros2_driver/webots/src/controller/java/Makefile index d916553a0..a8191f632 100644 --- a/webots_ros2_driver/webots/src/controller/java/Makefile +++ b/webots_ros2_driver/webots/src/controller/java/Makefile @@ -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 diff --git a/webots_ros2_driver/webots_ros2_driver/utils.py b/webots_ros2_driver/webots_ros2_driver/utils.py index 73f3a8477..68cd9350d 100644 --- a/webots_ros2_driver/webots_ros2_driver/utils.py +++ b/webots_ros2_driver/webots_ros2_driver/utils.py @@ -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 @@ -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: @@ -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' @@ -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...') diff --git a/webots_ros2_driver/webots_ros2_driver/webots_launcher.py b/webots_ros2_driver/webots_ros2_driver/webots_launcher.py index f493edfb5..33a21a879 100644 --- a/webots_ros2_driver/webots_ros2_driver/webots_launcher.py +++ b/webots_ros2_driver/webots_ros2_driver/webots_launcher.py @@ -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: diff --git a/webots_ros2_msgs/CMakeLists.txt b/webots_ros2_msgs/CMakeLists.txt index 19bf8911b..4e334d38b 100644 --- a/webots_ros2_msgs/CMakeLists.txt +++ b/webots_ros2_msgs/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.15) project(webots_ros2_msgs) # Default to C11