diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt
index 0942ae4e5..39e30068a 100644
--- a/xs/CMakeLists.txt
+++ b/xs/CMakeLists.txt
@@ -313,7 +313,12 @@ add_custom_command(
 )
 
 # Define the Perl XS shared library.
-add_library(XS SHARED
+if(APPLE)
+    set(XS_SHARED_LIBRARY_TYPE MODULE)
+else()
+    set(XS_SHARED_LIBRARY_TYPE SHARED)
+endif()
+add_library(XS ${XS_SHARED_LIBRARY_TYPE}
     ${XS_MAIN_CPP}
     ${LIBDIR}/libslic3r/utils.cpp
     ${LIBDIR}/perlglue.cpp
@@ -325,6 +330,11 @@ add_library(XS SHARED
     # Used by Perl xsubpp to generate XS.cpp
     ${CMAKE_CURRENT_LIST_DIR}/xsp/typemap.xspt
 )
+if(APPLE)
+    set_target_properties(XS PROPERTIES BUNDLE TRUE)
+    # Ignore undefined symbols of the perl interpreter, they will be found in the caller image.
+    target_link_libraries(XS "-undefined dynamic_lookup")
+endif()
 target_link_libraries(XS libslic3r libslic3r_gui admesh clipper nowide polypartition poly2tri)
 if(SLIC3R_DEBUG)
     target_link_libraries(Shiny)
@@ -394,7 +404,9 @@ target_compile_options(XS PRIVATE ${PerlEmbed_CCFLAGS})
 #    set(CMAKE_CXX_FLAGS_RELEASE /Od)
 #    set(CMAKE_C_FLAGS_RELEASE /Od)
 #endif()
-target_link_libraries(XS ${PERL_LIBRARY})
+if (NOT APPLE)
+    target_link_libraries(XS ${PERL_LIBRARY})
+endif()
 
 ## REQUIRED packages