.
This commit is contained in:
parent
2711845b21
commit
52a3d0e556
17 changed files with 1005 additions and 36 deletions
239
.github/workflows/build_macos_bridge.yml
vendored
Normal file
239
.github/workflows/build_macos_bridge.yml
vendored
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
name: Build macOS with Linux bridge runtime
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
prepare_linux_bridge_runtime:
|
||||
name: Prepare Linux bridge runtime
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: 'false'
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: "~4.3.0"
|
||||
useLocalCache: true
|
||||
useCloudCache: true
|
||||
|
||||
- name: Apt-Install Dependencies
|
||||
uses: ./.github/actions/apt-install-deps
|
||||
|
||||
- name: Build Linux deps
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for attempt in 1 2 3; do
|
||||
echo "Build Linux deps attempt $attempt"
|
||||
if ./build_linux.sh -drlL; then
|
||||
exit 0
|
||||
fi
|
||||
if [ "$attempt" -lt 3 ]; then
|
||||
echo "Transient dependency download/build failure, retrying after backoff"
|
||||
sleep $((attempt * 20))
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
|
||||
- name: Configure linux bridge host build
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -S . -B build -G "Ninja Multi-Config" -DORCA_TOOLS=ON
|
||||
|
||||
- name: Build linux host runtime
|
||||
shell: bash
|
||||
run: |
|
||||
cmake --build build --config Release --target pjarczak_bambu_linux_host
|
||||
bash tools/pjarczak_bambu_linux_host/package_linux_host_runtime.sh build
|
||||
tar -czvf linux_host_runtime_${{ github.sha }}.tar.gz -C tools/pjarczak_bambu_linux_host/runtime linux-x86_64
|
||||
|
||||
- name: Upload linux host runtime artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: linux_host_runtime_${{ github.sha }}
|
||||
path: ./linux_host_runtime_${{ github.sha }}.tar.gz
|
||||
if-no-files-found: error
|
||||
|
||||
build_macos_arm64:
|
||||
name: Build macOS arm64
|
||||
runs-on: macos-15
|
||||
needs: prepare_linux_bridge_runtime
|
||||
env:
|
||||
ORCA_UPDATER_SIG_KEY: ${{ secrets.ORCA_UPDATER_SIG_KEY }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: 'false'
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: "~4.3.0"
|
||||
useLocalCache: true
|
||||
useCloudCache: true
|
||||
|
||||
- name: Download linux host runtime artifact
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: linux_host_runtime_${{ github.sha }}
|
||||
path: ${{ github.workspace }}/linux_host_runtime_artifact
|
||||
|
||||
- name: Extract linux host runtime artifact on macOS arm64
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "$GITHUB_WORKSPACE/tools/pjarczak_bambu_linux_host/runtime"
|
||||
tar -xzf "$GITHUB_WORKSPACE/linux_host_runtime_artifact/linux_host_runtime_${{ github.sha }}.tar.gz" -C "$GITHUB_WORKSPACE/tools/pjarczak_bambu_linux_host/runtime"
|
||||
|
||||
- name: Install mac tools
|
||||
shell: bash
|
||||
run: |
|
||||
brew install libtool
|
||||
mkdir -p "$GITHUB_WORKSPACE/deps/build/arm64"
|
||||
|
||||
- name: Build macOS arm64 deps
|
||||
shell: bash
|
||||
run: |
|
||||
./build_release_macos.sh -dx -1 -a arm64 -t 11.3
|
||||
|
||||
- name: Build macOS arm64 app bundle
|
||||
shell: bash
|
||||
run: |
|
||||
./build_release_macos.sh -s -n -x -1 -a arm64 -t 11.3
|
||||
|
||||
- name: Pack macOS arm64 app bundle
|
||||
shell: bash
|
||||
run: |
|
||||
tar -czvf OrcaSlicer_Mac_bundle_arm64_${{ github.sha }}.tar.gz -C build/arm64 OrcaSlicer
|
||||
|
||||
- name: Upload macOS arm64 app bundle
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: OrcaSlicer_Mac_bundle_arm64_${{ github.sha }}
|
||||
path: ${{ github.workspace }}/OrcaSlicer_Mac_bundle_arm64_${{ github.sha }}.tar.gz
|
||||
if-no-files-found: error
|
||||
|
||||
build_macos_x86_64:
|
||||
name: Build macOS x86_64
|
||||
runs-on: macos-15-intel
|
||||
needs: prepare_linux_bridge_runtime
|
||||
env:
|
||||
ORCA_UPDATER_SIG_KEY: ${{ secrets.ORCA_UPDATER_SIG_KEY }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: 'false'
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: "~4.3.0"
|
||||
useLocalCache: true
|
||||
useCloudCache: true
|
||||
|
||||
- name: Download linux host runtime artifact
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: linux_host_runtime_${{ github.sha }}
|
||||
path: ${{ github.workspace }}/linux_host_runtime_artifact
|
||||
|
||||
- name: Extract linux host runtime artifact on macOS x86_64
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "$GITHUB_WORKSPACE/tools/pjarczak_bambu_linux_host/runtime"
|
||||
tar -xzf "$GITHUB_WORKSPACE/linux_host_runtime_artifact/linux_host_runtime_${{ github.sha }}.tar.gz" -C "$GITHUB_WORKSPACE/tools/pjarczak_bambu_linux_host/runtime"
|
||||
|
||||
- name: Install mac tools
|
||||
shell: bash
|
||||
run: |
|
||||
brew install libtool
|
||||
mkdir -p "$GITHUB_WORKSPACE/deps/build/x86_64"
|
||||
|
||||
- name: Build macOS x86_64 deps
|
||||
shell: bash
|
||||
run: |
|
||||
./build_release_macos.sh -dx -1 -a x86_64 -t 11.3
|
||||
|
||||
- name: Build macOS x86_64 app bundle
|
||||
shell: bash
|
||||
run: |
|
||||
./build_release_macos.sh -s -n -x -1 -a x86_64 -t 11.3
|
||||
|
||||
- name: Pack macOS x86_64 app bundle
|
||||
shell: bash
|
||||
run: |
|
||||
tar -czvf OrcaSlicer_Mac_bundle_x86_64_${{ github.sha }}.tar.gz -C build/x86_64 OrcaSlicer
|
||||
|
||||
- name: Upload macOS x86_64 app bundle
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: OrcaSlicer_Mac_bundle_x86_64_${{ github.sha }}
|
||||
path: ${{ github.workspace }}/OrcaSlicer_Mac_bundle_x86_64_${{ github.sha }}.tar.gz
|
||||
if-no-files-found: error
|
||||
|
||||
build_macos_universal:
|
||||
name: Build macOS universal
|
||||
runs-on: macos-15
|
||||
needs:
|
||||
- build_macos_arm64
|
||||
- build_macos_x86_64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: 'false'
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: "~4.3.0"
|
||||
useLocalCache: true
|
||||
useCloudCache: true
|
||||
|
||||
- name: Download macOS app bundles
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: OrcaSlicer_Mac_bundle_*_${{ github.sha }}
|
||||
path: ${{ github.workspace }}/mac_bundles
|
||||
|
||||
- name: Extract macOS app bundles
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p build/arm64 build/x86_64
|
||||
arm_bundle=$(find "$GITHUB_WORKSPACE/mac_bundles/OrcaSlicer_Mac_bundle_arm64_${{ github.sha }}" -name '*.tar.gz' -print -quit)
|
||||
x86_bundle=$(find "$GITHUB_WORKSPACE/mac_bundles/OrcaSlicer_Mac_bundle_x86_64_${{ github.sha }}" -name '*.tar.gz' -print -quit)
|
||||
tar -xzvf "$arm_bundle" -C "$GITHUB_WORKSPACE/build/arm64"
|
||||
tar -xzvf "$x86_bundle" -C "$GITHUB_WORKSPACE/build/x86_64"
|
||||
|
||||
- name: Build universal mac app bundle
|
||||
shell: bash
|
||||
run: |
|
||||
./build_release_macos.sh -u -x -1 -a universal -t 11.3
|
||||
|
||||
- name: Create DMG without runtime validation
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "$GITHUB_WORKSPACE/build/universal/OrcaSlicer_dmg"
|
||||
rm -rf "$GITHUB_WORKSPACE/build/universal/OrcaSlicer_dmg"/*
|
||||
cp -R "$GITHUB_WORKSPACE/build/universal/OrcaSlicer/OrcaSlicer.app" "$GITHUB_WORKSPACE/build/universal/OrcaSlicer_dmg/"
|
||||
ln -sfn /Applications "$GITHUB_WORKSPACE/build/universal/OrcaSlicer_dmg/Applications"
|
||||
ver=$(grep 'set(SoftFever_VERSION' version.inc | cut -d '"' -f2)
|
||||
hdiutil create -volname "OrcaSlicer" -srcfolder "$GITHUB_WORKSPACE/build/universal/OrcaSlicer_dmg" -ov -format UDZO "OrcaSlicer_Mac_universal_V${ver}.dmg"
|
||||
|
||||
- name: Explain skipped hosted runtime validation
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Hosted macOS runners do not support nested virtualization, so bundled Lima runtime validation is intentionally skipped here."
|
||||
|
||||
- name: Upload macOS universal DMG
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: OrcaSlicer_Mac_universal_${{ github.sha }}
|
||||
path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_V*.dmg
|
||||
if-no-files-found: error
|
||||
|
|
@ -834,6 +834,10 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||
${CMAKE_PREFIX_PATH}/bin/occt/TKXDESTEP.dll
|
||||
${CMAKE_PREFIX_PATH}/bin/occt/TKXSBase.dll
|
||||
${CMAKE_PREFIX_PATH}/bin/freetype.dll
|
||||
${CMAKE_PREFIX_PATH}/bin/avcodec-61.dll
|
||||
${CMAKE_PREFIX_PATH}/bin/swresample-5.dll
|
||||
${CMAKE_PREFIX_PATH}/bin/swscale-8.dll
|
||||
${CMAKE_PREFIX_PATH}/bin/avutil-59.dll
|
||||
DESTINATION ${_out_dir})
|
||||
|
||||
set(${output_dlls}
|
||||
|
|
@ -869,6 +873,10 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||
${_out_dir}/TKXSBase.dll
|
||||
|
||||
${_out_dir}/freetype.dll
|
||||
${_out_dir}/avcodec-61.dll
|
||||
${_out_dir}/swresample-5.dll
|
||||
${_out_dir}/swscale-8.dll
|
||||
${_out_dir}/avutil-59.dll
|
||||
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ if [ -z "$CMAKE_IGNORE_PREFIX_PATH" ]; then
|
|||
export CMAKE_IGNORE_PREFIX_PATH="/opt/local:/usr/local:/opt/homebrew"
|
||||
fi
|
||||
|
||||
CMAKE_VERSION=$(cmake --version | head -1 | sed 's/[^0-9]*\([0-9]*\).*//')
|
||||
CMAKE_VERSION=$(cmake --version | head -1 | sed -E 's/[^0-9]*([0-9]+).*/\1/')
|
||||
if [ "$CMAKE_VERSION" -ge 4 ] 2>/dev/null; then
|
||||
export CMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
export CMAKE_POLICY_COMPAT="-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
|
||||
|
|
@ -123,6 +123,7 @@ PROJECT_BUILD_DIR="$PROJECT_DIR/build/$ARCH"
|
|||
DEPS_DIR="$PROJECT_DIR/deps"
|
||||
HOST_RUNTIME_DIR="$PROJECT_DIR/tools/pjarczak_bambu_linux_host/runtime/linux-x86_64"
|
||||
HOST_WRAPPER="$PROJECT_DIR/tools/pjarczak_bambu_linux_host/pjarczak-bambu-linux-host-wrapper"
|
||||
MAC_RUNTIME_HELPERS_DIR="$PROJECT_DIR/tools/pjarczak_bambu_runtime/macos"
|
||||
|
||||
export BUILD_DIR_CONFIG_SUBDIR="/$BUILD_CONFIG"
|
||||
|
||||
|
|
@ -154,6 +155,21 @@ copy_linux_bridge_runtime_to_app() {
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$MAC_RUNTIME_HELPERS_DIR/pjarczak_install_macos_runtime.sh" ]; then
|
||||
echo "Missing mac runtime installer: $MAC_RUNTIME_HELPERS_DIR/pjarczak_install_macos_runtime.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$MAC_RUNTIME_HELPERS_DIR/pjarczak_verify_macos_runtime.sh" ]; then
|
||||
echo "Missing mac runtime verifier: $MAC_RUNTIME_HELPERS_DIR/pjarczak_verify_macos_runtime.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$MAC_RUNTIME_HELPERS_DIR/pjarczak_lima_instance.txt" ]; then
|
||||
echo "Missing Lima instance file: $MAC_RUNTIME_HELPERS_DIR/pjarczak_lima_instance.txt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$bridge_dylib" ]; then
|
||||
echo "Missing installed bridge dylib: $bridge_dylib"
|
||||
exit 1
|
||||
|
|
@ -162,9 +178,17 @@ copy_linux_bridge_runtime_to_app() {
|
|||
cp -f "$bridge_dylib" "$macos_dir/"
|
||||
find "$HOST_RUNTIME_DIR" -maxdepth 1 -type f -exec cp -f {} "$macos_dir/" \;
|
||||
cp -f "$HOST_WRAPPER" "$macos_dir/"
|
||||
cp -f "$MAC_RUNTIME_HELPERS_DIR/pjarczak_install_macos_runtime.sh" "$macos_dir/install_runtime_macos.sh"
|
||||
cp -f "$MAC_RUNTIME_HELPERS_DIR/pjarczak_verify_macos_runtime.sh" "$macos_dir/verify_runtime_macos.sh"
|
||||
cp -f "$MAC_RUNTIME_HELPERS_DIR/pjarczak_lima_instance.txt" "$macos_dir/"
|
||||
if [ -f "$MAC_RUNTIME_HELPERS_DIR/README_runtime_bridge.txt" ]; then
|
||||
cp -f "$MAC_RUNTIME_HELPERS_DIR/README_runtime_bridge.txt" "$macos_dir/"
|
||||
fi
|
||||
|
||||
chmod +x "$macos_dir/pjarczak_bambu_linux_host"
|
||||
chmod +x "$macos_dir/pjarczak-bambu-linux-host-wrapper"
|
||||
chmod +x "$macos_dir/install_runtime_macos.sh"
|
||||
chmod +x "$macos_dir/verify_runtime_macos.sh"
|
||||
}
|
||||
|
||||
build_deps() {
|
||||
|
|
|
|||
7
deps/CMakeLists.txt
vendored
7
deps/CMakeLists.txt
vendored
|
|
@ -382,6 +382,12 @@ if(NOT FREETYPE_FOUND)
|
|||
set(FREETYPE_PKG "dep_FREETYPE")
|
||||
endif()
|
||||
|
||||
set(FFMPEG_PKG "")
|
||||
if (MSVC)
|
||||
include(FFMPEG/FFMPEG.cmake)
|
||||
set(FFMPEG_PKG "dep_FFMPEG")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-parse --is-inside-work-tree
|
||||
RESULT_VARIABLE REV_PARSE_RESULT
|
||||
|
|
@ -415,6 +421,7 @@ set(_dep_list
|
|||
dep_GLFW
|
||||
dep_OCCT
|
||||
${FREETYPE_PKG}
|
||||
${FFMPEG_PKG}
|
||||
${PNG_PKG}
|
||||
${ZLIB_PKG}
|
||||
${EXPAT_PKG}
|
||||
|
|
|
|||
14
deps/FFMPEG/FFMPEG.cmake
vendored
Normal file
14
deps/FFMPEG/FFMPEG.cmake
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
set(_dstdir ${DESTDIR}/usr/local)
|
||||
set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG")
|
||||
|
||||
ExternalProject_Add(dep_FFMPEG
|
||||
URL https://github.com/bambulab/ffmpeg_prebuilts/releases/download/7.0.2/7.0.2_msvc.zip
|
||||
URL_HASH SHA256=DF44AE6B97CE84C720695AE7F151B4A9654915D1841C68F10D62A1189E0E7181
|
||||
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/bin" "${_dstdir}/bin"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/lib" "${_dstdir}/lib"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/include" "${_dstdir}/include"
|
||||
)
|
||||
|
|
@ -680,21 +680,22 @@ if (APPLE)
|
|||
GUI/GUI_UtilsMac.mm
|
||||
GUI/wxMediaCtrl2.mm
|
||||
GUI/wxMediaCtrl2.h
|
||||
GUI/wxMediaCtrl3.h
|
||||
)
|
||||
FIND_LIBRARY(DISKARBITRATION_LIBRARY DiskArbitration)
|
||||
else ()
|
||||
list(APPEND SLIC3R_GUI_SOURCES
|
||||
GUI/AVVideoDecoder.cpp
|
||||
GUI/AVVideoDecoder.hpp
|
||||
GUI/wxMediaCtrl2.cpp
|
||||
GUI/wxMediaCtrl2.h
|
||||
GUI/wxMediaCtrl3.cpp
|
||||
GUI/wxMediaCtrl3.h
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
list(APPEND SLIC3R_GUI_SOURCES
|
||||
GUI/AVVideoDecoder.cpp
|
||||
GUI/AVVideoDecoder.hpp
|
||||
GUI/wxMediaCtrl3.cpp
|
||||
GUI/wxMediaCtrl3.h
|
||||
GUI/Printer/gstbambusrc.c
|
||||
)
|
||||
endif ()
|
||||
|
|
@ -748,7 +749,13 @@ target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo mini
|
|||
|
||||
|
||||
if (MSVC)
|
||||
target_link_libraries(libslic3r_gui Setupapi.lib)
|
||||
find_library(FFMPEG_AVCODEC_LIB NAMES avcodec avcodec-61 PATHS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES lib NO_DEFAULT_PATH)
|
||||
find_library(FFMPEG_AVUTIL_LIB NAMES avutil avutil-59 PATHS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES lib NO_DEFAULT_PATH)
|
||||
find_library(FFMPEG_SWSCALE_LIB NAMES swscale swscale-8 PATHS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES lib NO_DEFAULT_PATH)
|
||||
if (NOT FFMPEG_AVCODEC_LIB OR NOT FFMPEG_AVUTIL_LIB OR NOT FFMPEG_SWSCALE_LIB)
|
||||
message(FATAL_ERROR "Missing FFmpeg import libs for Windows build. Expected avcodec/avutil/swscale under ${CMAKE_PREFIX_PATH}/lib")
|
||||
endif ()
|
||||
target_link_libraries(libslic3r_gui Setupapi.lib ${FFMPEG_AVCODEC_LIB} ${FFMPEG_AVUTIL_LIB} ${FFMPEG_SWSCALE_LIB})
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server)
|
||||
FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl)
|
||||
|
|
|
|||
|
|
@ -247,6 +247,8 @@ std::string VersionInfo::convert_short_version(std::string full_version)
|
|||
|
||||
static void pjarczak_verify_or_install_windows_bridge_runtime(const boost::filesystem::path& plugin_folder,
|
||||
const boost::filesystem::path& plugin_cache_dir);
|
||||
static void pjarczak_verify_or_install_macos_bridge_runtime(const boost::filesystem::path& plugin_folder,
|
||||
const boost::filesystem::path& plugin_cache_dir);
|
||||
static long pjarczak_run_hidden_windows_command(const wxString& command, wxArrayString* stdout_lines, wxArrayString* stderr_lines);
|
||||
static void pjarczak_log_command_output(const char* tag, long exit_code, const wxArrayString& stdout_lines, const wxArrayString& stderr_lines);
|
||||
|
||||
|
|
@ -2976,13 +2978,15 @@ bool GUI_App::on_init_inner()
|
|||
}
|
||||
} */
|
||||
copy_network_if_available();
|
||||
#ifdef WIN32
|
||||
if (Slic3r::PJarczakLinuxBridge::enabled()) {
|
||||
const boost::filesystem::path plugin_folder = boost::filesystem::path(data_dir()) / "plugins";
|
||||
const boost::filesystem::path plugin_cache_dir = boost::filesystem::path(data_dir()) / "ota" / "plugins";
|
||||
#ifdef WIN32
|
||||
pjarczak_verify_or_install_windows_bridge_runtime(plugin_folder, plugin_cache_dir);
|
||||
}
|
||||
#elif defined(__APPLE__) || defined(__WXMAC__)
|
||||
pjarczak_verify_or_install_macos_bridge_runtime(plugin_folder, plugin_cache_dir);
|
||||
#endif
|
||||
}
|
||||
on_init_network();
|
||||
|
||||
if (m_agent && m_agent->is_user_login()) {
|
||||
|
|
@ -3180,6 +3184,19 @@ static wxString pjarczak_quote_windows_arg(const wxString& value)
|
|||
return wxString::Format("\"%s\"", escaped);
|
||||
}
|
||||
|
||||
static wxString pjarczak_quote_posix_arg(const wxString& value)
|
||||
{
|
||||
wxString out("'");
|
||||
for (wxUniChar ch : value) {
|
||||
if (ch == '\'')
|
||||
out += "'\\''";
|
||||
else
|
||||
out += ch;
|
||||
}
|
||||
out += "'";
|
||||
return out;
|
||||
}
|
||||
|
||||
static long pjarczak_run_hidden_windows_command(const wxString& command, wxArrayString* stdout_lines, wxArrayString* stderr_lines)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
|
@ -3199,6 +3216,25 @@ static long pjarczak_run_hidden_windows_command(const wxString& command, wxArray
|
|||
#endif
|
||||
}
|
||||
|
||||
static long pjarczak_run_hidden_posix_command(const wxString& command, wxArrayString* stdout_lines, wxArrayString* stderr_lines)
|
||||
{
|
||||
#if defined(__WXMAC__) || defined(__APPLE__) || defined(__WXGTK__)
|
||||
wxArrayString local_stdout;
|
||||
wxArrayString local_stderr;
|
||||
long exit_code = wxExecute(command, local_stdout, local_stderr, wxEXEC_SYNC);
|
||||
if (stdout_lines)
|
||||
*stdout_lines = local_stdout;
|
||||
if (stderr_lines)
|
||||
*stderr_lines = local_stderr;
|
||||
return exit_code;
|
||||
#else
|
||||
(void)command;
|
||||
(void)stdout_lines;
|
||||
(void)stderr_lines;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pjarczak_log_command_output(const char* tag, long exit_code, const wxArrayString& stdout_lines, const wxArrayString& stderr_lines)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << tag << ": exit_code=" << exit_code;
|
||||
|
|
@ -3259,6 +3295,66 @@ static void pjarczak_verify_or_install_windows_bridge_runtime(const boost::files
|
|||
#endif
|
||||
}
|
||||
|
||||
static void pjarczak_verify_or_install_macos_bridge_runtime(const boost::filesystem::path& plugin_folder,
|
||||
const boost::filesystem::path& plugin_cache_dir)
|
||||
{
|
||||
#if !(defined(__WXMAC__) || defined(__APPLE__))
|
||||
(void)plugin_folder;
|
||||
(void)plugin_cache_dir;
|
||||
#else
|
||||
if (!Slic3r::PJarczakLinuxBridge::enabled())
|
||||
return;
|
||||
|
||||
const auto verify_script = plugin_folder / Slic3r::PJarczakLinuxBridge::mac_runtime_verify_script_file_name();
|
||||
const auto install_script = plugin_folder / Slic3r::PJarczakLinuxBridge::mac_runtime_install_script_file_name();
|
||||
if (!boost::filesystem::exists(verify_script) || !boost::filesystem::exists(install_script)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "[pjarczak_runtime_setup] missing macOS verify/install script in " << plugin_folder.string();
|
||||
return;
|
||||
}
|
||||
|
||||
const wxString plugin_dir_wx = from_u8(plugin_folder.string());
|
||||
const wxString cache_dir_wx = from_u8(plugin_cache_dir.string());
|
||||
const wxString verify_cmd = wxString::Format(
|
||||
"/bin/bash %s -PackageDir %s -PluginDir %s -PluginCacheDir %s -AllowMissingLinuxPlugin",
|
||||
pjarczak_quote_posix_arg(from_u8(verify_script.string())),
|
||||
pjarczak_quote_posix_arg(plugin_dir_wx),
|
||||
pjarczak_quote_posix_arg(plugin_dir_wx),
|
||||
pjarczak_quote_posix_arg(cache_dir_wx));
|
||||
|
||||
wxArrayString verify_out;
|
||||
wxArrayString verify_err;
|
||||
long verify_code = pjarczak_run_hidden_posix_command(verify_cmd, &verify_out, &verify_err);
|
||||
pjarczak_log_command_output("[pjarczak_runtime_verify_macos]", verify_code, verify_out, verify_err);
|
||||
if (verify_code == 0)
|
||||
return;
|
||||
|
||||
wxMessageDialog prompt(
|
||||
nullptr,
|
||||
_L("The macOS Linux bridge runtime is not ready. OrcaSlicer can install or repair the bundled Lima runtime now."),
|
||||
_L("OrcaSlicer Linux Bridge"),
|
||||
wxYES_NO | wxICON_QUESTION | wxCENTRE);
|
||||
if (prompt.ShowModal() != wxID_YES)
|
||||
return;
|
||||
|
||||
const wxString install_cmd = wxString::Format(
|
||||
"/bin/bash %s -PackageDir %s -PluginDir %s -PluginCacheDir %s -ReplaceExisting",
|
||||
pjarczak_quote_posix_arg(from_u8(install_script.string())),
|
||||
pjarczak_quote_posix_arg(plugin_dir_wx),
|
||||
pjarczak_quote_posix_arg(plugin_dir_wx),
|
||||
pjarczak_quote_posix_arg(cache_dir_wx));
|
||||
|
||||
wxArrayString install_out;
|
||||
wxArrayString install_err;
|
||||
long install_code = pjarczak_run_hidden_posix_command(install_cmd, &install_out, &install_err);
|
||||
pjarczak_log_command_output("[pjarczak_runtime_install_macos]", install_code, install_out, install_err);
|
||||
|
||||
verify_out.clear();
|
||||
verify_err.clear();
|
||||
verify_code = pjarczak_run_hidden_posix_command(verify_cmd, &verify_out, &verify_err);
|
||||
pjarczak_log_command_output("[pjarczak_runtime_verify_after_install_macos]", verify_code, verify_out, verify_err);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool pjarczak_bridge_payload_ready(const boost::filesystem::path& plugin_folder, std::string* reason)
|
||||
{
|
||||
if (!Slic3r::PJarczakLinuxBridge::enabled()) {
|
||||
|
|
@ -3271,6 +3367,22 @@ bool pjarczak_bridge_payload_ready(const boost::filesystem::path& plugin_folder,
|
|||
return boost::filesystem::exists(candidate) && !boost::filesystem::is_directory(candidate);
|
||||
};
|
||||
|
||||
#if defined(__WXMAC__) || defined(__APPLE__)
|
||||
const std::string required_files[] = {
|
||||
Slic3r::PJarczakLinuxBridge::bridge_network_current_dir_name(),
|
||||
Slic3r::PJarczakLinuxBridge::host_executable_file_name(),
|
||||
std::string("pjarczak_bambu_linux_host_abi1"),
|
||||
std::string("pjarczak_bambu_linux_host_abi0"),
|
||||
Slic3r::PJarczakLinuxBridge::mac_host_wrapper_file_name(),
|
||||
Slic3r::PJarczakLinuxBridge::mac_runtime_install_script_file_name(),
|
||||
Slic3r::PJarczakLinuxBridge::mac_runtime_verify_script_file_name(),
|
||||
Slic3r::PJarczakLinuxBridge::mac_lima_instance_file_name(),
|
||||
Slic3r::PJarczakLinuxBridge::linux_network_library_name(),
|
||||
Slic3r::PJarczakLinuxBridge::linux_source_library_name(),
|
||||
std::string("ca-certificates.crt"),
|
||||
std::string("slicer_base64.cer")
|
||||
};
|
||||
#else
|
||||
const std::string required_files[] = {
|
||||
Slic3r::PJarczakLinuxBridge::bridge_network_current_dir_name(),
|
||||
Slic3r::PJarczakLinuxBridge::host_executable_file_name(),
|
||||
|
|
@ -3285,6 +3397,7 @@ bool pjarczak_bridge_payload_ready(const boost::filesystem::path& plugin_folder,
|
|||
std::string("ca-certificates.crt"),
|
||||
std::string("slicer_base64.cer")
|
||||
};
|
||||
#endif
|
||||
|
||||
for (const std::string& file_name : required_files) {
|
||||
if (!has_file(file_name)) {
|
||||
|
|
@ -3292,7 +3405,7 @@ bool pjarczak_bridge_payload_ready(const boost::filesystem::path& plugin_folder,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if !(defined(__WXMAC__) || defined(__APPLE__))
|
||||
if (!has_file(Slic3r::PJarczakLinuxBridge::windows_wsl_import_script_file_name()) &&
|
||||
!has_file("pjarczak-install-wsl-runtime.ps1")) {
|
||||
pjarczak_set_reason(reason, "missing required runtime file: " + Slic3r::PJarczakLinuxBridge::windows_wsl_import_script_file_name());
|
||||
|
|
@ -3304,6 +3417,7 @@ bool pjarczak_bridge_payload_ready(const boost::filesystem::path& plugin_folder,
|
|||
pjarczak_set_reason(reason, "missing required runtime file: " + Slic3r::PJarczakLinuxBridge::windows_wsl_bootstrap_script_file_name());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (const std::string& file_name : {
|
||||
Slic3r::PJarczakLinuxBridge::linux_network_library_name(),
|
||||
|
|
|
|||
|
|
@ -8,13 +8,8 @@
|
|||
#ifndef MediaPlayCtrl_h
|
||||
#define MediaPlayCtrl_h
|
||||
|
||||
#if defined(__linux__) && !defined(__APPLE__)
|
||||
#include "wxMediaCtrl3.h"
|
||||
using BBLMediaCtrl = wxMediaCtrl3;
|
||||
#else
|
||||
#include "wxMediaCtrl2.h"
|
||||
using BBLMediaCtrl = wxMediaCtrl2;
|
||||
#endif
|
||||
|
||||
#include <wx/panel.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ ZUserLogin::ZUserLogin() : wxDialog((wxWindow *) (wxGetApp().mainframe), wxID_AN
|
|||
CentreOnParent();
|
||||
}
|
||||
else {
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) || defined(__APPLE__) || defined(__WXMAC__)
|
||||
if (Slic3r::PJarczakLinuxBridge::enabled()) {
|
||||
m_external_browser_mode = true;
|
||||
SetTitle(_L("Login"));
|
||||
|
|
@ -187,7 +187,7 @@ ZUserLogin::ZUserLogin() : wxDialog((wxWindow *) (wxGetApp().mainframe), wxID_AN
|
|||
int MaxY = (screenheight - pSize.y) > 0 ? (screenheight - pSize.y) / 2 : 0;
|
||||
wxPoint tmpPT((screenwidth - pSize.x) / 2, MaxY);
|
||||
Move(tmpPT);
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) || defined(__APPLE__) || defined(__WXMAC__)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ bool ZUserLogin::run() {
|
|||
m_timer = new wxTimer(this, NETWORK_OFFLINE_TIMER_ID);
|
||||
m_timer->Start(m_external_browser_mode ? 30000 : 8000);
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) || defined(__APPLE__) || defined(__WXMAC__)
|
||||
if (m_external_browser_mode) {
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (agent) {
|
||||
|
|
|
|||
|
|
@ -95,15 +95,47 @@ if (UNIX AND NOT APPLE AND EXISTS "${PJARCZAK_LINUX_HOST_DIR}/main.cpp" AND EXIS
|
|||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set(PJARCZAK_MAC_WRAPPER_SCRIPT_SOURCE ${CMAKE_SOURCE_DIR}/tools/pjarczak_bambu_macos_linux_wrapper/pjarczak_bambu_macos_linux_wrapper.sh)
|
||||
set(PJARCZAK_MAC_WRAPPER_SCRIPT_SOURCE ${CMAKE_SOURCE_DIR}/tools/pjarczak_bambu_linux_host/pjarczak-bambu-linux-host-wrapper)
|
||||
set(PJARCZAK_MAC_INSTALLER_SOURCE ${CMAKE_SOURCE_DIR}/tools/pjarczak_bambu_runtime/macos/pjarczak_install_macos_runtime.sh)
|
||||
set(PJARCZAK_MAC_VERIFY_SOURCE ${CMAKE_SOURCE_DIR}/tools/pjarczak_bambu_runtime/macos/pjarczak_verify_macos_runtime.sh)
|
||||
set(PJARCZAK_MAC_INSTANCE_SOURCE ${CMAKE_SOURCE_DIR}/tools/pjarczak_bambu_runtime/macos/pjarczak_lima_instance.txt)
|
||||
set(PJARCZAK_MAC_README_SOURCE ${CMAKE_SOURCE_DIR}/tools/pjarczak_bambu_runtime/macos/README_runtime_bridge.txt)
|
||||
add_custom_command(TARGET pjarczak_bambu_networking_bridge POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${PJARCZAK_MAC_WRAPPER_SCRIPT_SOURCE}
|
||||
$<TARGET_FILE_DIR:pjarczak_bambu_networking_bridge>/pjarczak_bambu_macos_linux_wrapper.sh
|
||||
$<TARGET_FILE_DIR:pjarczak_bambu_networking_bridge>/pjarczak-bambu-linux-host-wrapper
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${PJARCZAK_MAC_INSTALLER_SOURCE}
|
||||
$<TARGET_FILE_DIR:pjarczak_bambu_networking_bridge>/install_runtime_macos.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${PJARCZAK_MAC_VERIFY_SOURCE}
|
||||
$<TARGET_FILE_DIR:pjarczak_bambu_networking_bridge>/verify_runtime_macos.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${PJARCZAK_MAC_INSTANCE_SOURCE}
|
||||
$<TARGET_FILE_DIR:pjarczak_bambu_networking_bridge>/pjarczak_lima_instance.txt
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${PJARCZAK_MAC_README_SOURCE}
|
||||
$<TARGET_FILE_DIR:pjarczak_bambu_networking_bridge>/README_runtime_bridge.txt
|
||||
)
|
||||
install(FILES ${PJARCZAK_MAC_WRAPPER_SCRIPT_SOURCE}
|
||||
DESTINATION "."
|
||||
RENAME pjarczak_bambu_macos_linux_wrapper.sh
|
||||
RENAME pjarczak-bambu-linux-host-wrapper
|
||||
)
|
||||
install(FILES ${PJARCZAK_MAC_INSTALLER_SOURCE}
|
||||
DESTINATION "."
|
||||
RENAME install_runtime_macos.sh
|
||||
)
|
||||
install(FILES ${PJARCZAK_MAC_VERIFY_SOURCE}
|
||||
DESTINATION "."
|
||||
RENAME verify_runtime_macos.sh
|
||||
)
|
||||
install(FILES ${PJARCZAK_MAC_INSTANCE_SOURCE}
|
||||
DESTINATION "."
|
||||
RENAME pjarczak_lima_instance.txt
|
||||
)
|
||||
install(FILES ${PJARCZAK_MAC_README_SOURCE}
|
||||
DESTINATION "."
|
||||
RENAME README_runtime_bridge.txt
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,9 @@ std::uint16_t read_u16_le(const unsigned char* p)
|
|||
|
||||
bool expected_machine_matches(std::uint16_t machine)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
#if defined(__APPLE__)
|
||||
return machine == EM_X86_64 || machine == EM_AARCH64;
|
||||
#elif defined(__x86_64__) || defined(_M_X64)
|
||||
return machine == EM_X86_64;
|
||||
#elif defined(__aarch64__)
|
||||
return machine == EM_AARCH64;
|
||||
|
|
@ -204,6 +206,21 @@ std::string mac_host_wrapper_file_name()
|
|||
return "pjarczak-bambu-linux-host-wrapper";
|
||||
}
|
||||
|
||||
std::string mac_lima_instance_file_name()
|
||||
{
|
||||
return "pjarczak_lima_instance.txt";
|
||||
}
|
||||
|
||||
std::string mac_runtime_install_script_file_name()
|
||||
{
|
||||
return "install_runtime_macos.sh";
|
||||
}
|
||||
|
||||
std::string mac_runtime_verify_script_file_name()
|
||||
{
|
||||
return "verify_runtime_macos.sh";
|
||||
}
|
||||
|
||||
std::string windows_wsl_distro_file_name()
|
||||
{
|
||||
return "pjarczak_wsl_distro.txt";
|
||||
|
|
@ -256,6 +273,9 @@ bool is_overlay_runtime_filename(const std::string& file_name)
|
|||
file_name == "pjarczak_bambu_linux_host_abi1" ||
|
||||
file_name == "pjarczak_bambu_linux_host_abi0" ||
|
||||
file_name == mac_host_wrapper_file_name() ||
|
||||
file_name == mac_lima_instance_file_name() ||
|
||||
file_name == mac_runtime_install_script_file_name() ||
|
||||
file_name == mac_runtime_verify_script_file_name() ||
|
||||
file_name == windows_wsl_distro_file_name() ||
|
||||
file_name == windows_wsl_import_script_file_name() ||
|
||||
file_name == windows_wsl_validate_script_file_name() ||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ std::string linux_network_library_name();
|
|||
std::string linux_source_library_name();
|
||||
std::string host_executable_file_name();
|
||||
std::string mac_host_wrapper_file_name();
|
||||
std::string mac_lima_instance_file_name();
|
||||
std::string mac_runtime_install_script_file_name();
|
||||
std::string mac_runtime_verify_script_file_name();
|
||||
std::string windows_wsl_distro_file_name();
|
||||
std::string windows_wsl_import_script_file_name();
|
||||
std::string windows_wsl_validate_script_file_name();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
#include "PJarczakLinuxSoBridgeLauncher.hpp"
|
||||
#include "PJarczakLinuxBridgeConfig.hpp"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <dlfcn.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r::PJarczakLinuxBridge {
|
||||
|
|
@ -18,6 +21,144 @@ std::filesystem::path module_dir()
|
|||
return std::filesystem::path(info.dli_fname).parent_path();
|
||||
}
|
||||
|
||||
std::string trim_ascii(std::string value)
|
||||
{
|
||||
auto is_space = [](unsigned char ch) { return std::isspace(ch) != 0; };
|
||||
while (!value.empty() && is_space(static_cast<unsigned char>(value.front())))
|
||||
value.erase(value.begin());
|
||||
while (!value.empty() && is_space(static_cast<unsigned char>(value.back())))
|
||||
value.pop_back();
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string read_text_file_trimmed(const std::filesystem::path& path)
|
||||
{
|
||||
std::ifstream in(path, std::ios::binary);
|
||||
if (!in)
|
||||
return {};
|
||||
|
||||
std::string value((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
||||
if (value.size() >= 3 &&
|
||||
static_cast<unsigned char>(value[0]) == 0xEFu &&
|
||||
static_cast<unsigned char>(value[1]) == 0xBBu &&
|
||||
static_cast<unsigned char>(value[2]) == 0xBFu)
|
||||
value.erase(0, 3);
|
||||
|
||||
return trim_ascii(value);
|
||||
}
|
||||
|
||||
std::string required_env(const char* name)
|
||||
{
|
||||
const char* value = std::getenv(name);
|
||||
return (value && *value) ? trim_ascii(std::string(value)) : std::string();
|
||||
}
|
||||
|
||||
std::string shell_quote(const std::string& value)
|
||||
{
|
||||
std::string out;
|
||||
out.reserve(value.size() + 2);
|
||||
out.push_back('\'');
|
||||
for (char ch : value) {
|
||||
if (ch == '\'')
|
||||
out += "'\\''";
|
||||
else
|
||||
out.push_back(ch);
|
||||
}
|
||||
out.push_back('\'');
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string run_and_capture(const std::string& command, int* exit_code = nullptr)
|
||||
{
|
||||
std::string output;
|
||||
FILE* pipe = popen(command.c_str(), "r");
|
||||
if (!pipe) {
|
||||
if (exit_code)
|
||||
*exit_code = -1;
|
||||
return {};
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
while (fgets(buffer, sizeof(buffer), pipe) != nullptr)
|
||||
output += buffer;
|
||||
|
||||
const int rc = pclose(pipe);
|
||||
if (exit_code)
|
||||
*exit_code = rc;
|
||||
return trim_ascii(output);
|
||||
}
|
||||
|
||||
std::string configured_instance_name(const std::filesystem::path& plugin_dir)
|
||||
{
|
||||
const auto env_value = required_env("PJARCZAK_MAC_LIMA_INSTANCE");
|
||||
if (!env_value.empty())
|
||||
return env_value;
|
||||
return read_text_file_trimmed(plugin_dir / mac_lima_instance_file_name());
|
||||
}
|
||||
|
||||
std::string first_missing_runtime_file(const std::filesystem::path& plugin_dir)
|
||||
{
|
||||
const std::string required_files[] = {
|
||||
host_executable_file_name(),
|
||||
std::string("pjarczak_bambu_linux_host_abi1"),
|
||||
std::string("pjarczak_bambu_linux_host_abi0"),
|
||||
mac_host_wrapper_file_name(),
|
||||
mac_runtime_install_script_file_name(),
|
||||
mac_runtime_verify_script_file_name(),
|
||||
mac_lima_instance_file_name(),
|
||||
linux_network_library_name(),
|
||||
linux_source_library_name(),
|
||||
std::string("ca-certificates.crt"),
|
||||
std::string("slicer_base64.cer")
|
||||
};
|
||||
|
||||
for (const std::string& name : required_files) {
|
||||
if (!std::filesystem::exists(plugin_dir / std::filesystem::path(name)))
|
||||
return name;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool probe_runtime_ready(const std::filesystem::path& plugin_dir, std::string* reason)
|
||||
{
|
||||
const auto verify_script = plugin_dir / mac_runtime_verify_script_file_name();
|
||||
if (!std::filesystem::exists(verify_script)) {
|
||||
if (reason)
|
||||
*reason = "mac runtime verify script missing";
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string command =
|
||||
std::string("/bin/bash ") + shell_quote(verify_script.string()) +
|
||||
" -PackageDir " + shell_quote(plugin_dir.string()) +
|
||||
" -PluginDir " + shell_quote(plugin_dir.string());
|
||||
|
||||
int rc = -1;
|
||||
const std::string output = run_and_capture(command + " 2>&1", &rc);
|
||||
if (rc == 0) {
|
||||
if (reason)
|
||||
reason->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (reason)
|
||||
*reason = output.empty() ? std::string("macOS Lima runtime is not ready") : output;
|
||||
return false;
|
||||
}
|
||||
|
||||
LaunchSpec error_launch_spec(const std::string& message)
|
||||
{
|
||||
LaunchSpec spec;
|
||||
spec.description = "mac bridge preflight error";
|
||||
spec.argv = {
|
||||
"/bin/sh",
|
||||
"-lc",
|
||||
"printf '%s\\n' " + shell_quote(message) + " 1>&2; exit 127"
|
||||
};
|
||||
return spec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string host_executable_name()
|
||||
|
|
@ -35,33 +176,52 @@ std::string launch_preflight_error()
|
|||
const std::filesystem::path plugin_dir = module_dir();
|
||||
if (plugin_dir.empty())
|
||||
return "bridge launcher could not resolve plugin directory";
|
||||
if (!std::filesystem::exists(plugin_dir / host_executable_file_name()))
|
||||
return "linux host executable missing in plugin directory";
|
||||
const char* runner = std::getenv("PJARCZAK_MAC_LINUX_GUEST_RUNNER");
|
||||
if (!runner || !*runner)
|
||||
return "PJARCZAK_MAC_LINUX_GUEST_RUNNER is not set";
|
||||
|
||||
const auto missing_file = first_missing_runtime_file(plugin_dir);
|
||||
if (!missing_file.empty())
|
||||
return "required macOS runtime file missing: " + missing_file;
|
||||
|
||||
const auto instance = configured_instance_name(plugin_dir);
|
||||
if (instance.empty())
|
||||
return "PJARCZAK_MAC_LIMA_INSTANCE is not set and pjarczak_lima_instance.txt is missing or empty";
|
||||
|
||||
std::string reason;
|
||||
if (!probe_runtime_ready(plugin_dir, &reason))
|
||||
return reason.empty() ? std::string("macOS Lima runtime is not ready") : reason;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
LaunchSpec build_default_launch_spec()
|
||||
{
|
||||
const std::filesystem::path plugin_dir = module_dir();
|
||||
if (plugin_dir.empty())
|
||||
return error_launch_spec("bridge launcher could not resolve plugin directory");
|
||||
|
||||
const char* wrapper_env = std::getenv("PJARCZAK_BAMBU_HOST_WRAPPER");
|
||||
const std::filesystem::path wrapper_path = (wrapper_env && *wrapper_env)
|
||||
? std::filesystem::path(wrapper_env)
|
||||
: (plugin_dir / mac_host_wrapper_file_name());
|
||||
const auto missing_file = first_missing_runtime_file(plugin_dir);
|
||||
if (!missing_file.empty())
|
||||
return error_launch_spec("required macOS runtime file missing: " + missing_file);
|
||||
|
||||
const auto instance = configured_instance_name(plugin_dir);
|
||||
if (instance.empty())
|
||||
return error_launch_spec("PJARCZAK_MAC_LIMA_INSTANCE is not set and pjarczak_lima_instance.txt is missing or empty");
|
||||
|
||||
std::string reason;
|
||||
if (!probe_runtime_ready(plugin_dir, &reason))
|
||||
return error_launch_spec(reason.empty() ? std::string("macOS Lima runtime is not ready") : reason);
|
||||
|
||||
const std::filesystem::path wrapper_path = plugin_dir / mac_host_wrapper_file_name();
|
||||
const std::filesystem::path host_path = plugin_dir / host_executable_file_name();
|
||||
|
||||
LaunchSpec spec;
|
||||
spec.description = "mac via external linux guest wrapper";
|
||||
spec.description = "macOS via Lima linux guest";
|
||||
spec.argv = {wrapper_path.string(), host_path.string()};
|
||||
spec.env = {
|
||||
{"PJARCZAK_BAMBU_PLUGIN_DIR", plugin_dir.string()},
|
||||
{"PJARCZAK_BAMBU_NETWORK_SO", (plugin_dir / linux_network_library_name()).string()},
|
||||
{"PJARCZAK_BAMBU_SOURCE_SO", (plugin_dir / linux_source_library_name()).string()},
|
||||
{"PJARCZAK_BAMBU_REQUIRE_LINUX_GUEST", "1"}
|
||||
{"PJARCZAK_BAMBU_REQUIRE_LINUX_GUEST", "1"},
|
||||
{"PJARCZAK_MAC_LIMA_INSTANCE", instance}
|
||||
};
|
||||
return spec;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,62 @@ if [ -z "$HOST_PATH" ]; then
|
|||
exit 127
|
||||
fi
|
||||
|
||||
RUNNER="${PJARCZAK_MAC_LINUX_GUEST_RUNNER:-}"
|
||||
if [ -z "$RUNNER" ]; then
|
||||
echo "PJARCZAK_MAC_LINUX_GUEST_RUNNER not set" >&2
|
||||
PLUGIN_DIR="${PJARCZAK_BAMBU_PLUGIN_DIR:-}"
|
||||
if [ -z "$PLUGIN_DIR" ]; then
|
||||
PLUGIN_DIR=$(cd "$(dirname "$HOST_PATH")" && pwd)
|
||||
fi
|
||||
|
||||
trim_file() {
|
||||
path="$1"
|
||||
if [ ! -f "$path" ]; then
|
||||
return 1
|
||||
fi
|
||||
LC_ALL=C tr -d '\r' < "$path" | head -n 1 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
|
||||
}
|
||||
|
||||
INSTANCE="${PJARCZAK_MAC_LIMA_INSTANCE:-}"
|
||||
if [ -z "$INSTANCE" ]; then
|
||||
INSTANCE=$(trim_file "$PLUGIN_DIR/pjarczak_lima_instance.txt" || true)
|
||||
fi
|
||||
if [ -z "$INSTANCE" ]; then
|
||||
INSTANCE="orcaslicer-bambu-network"
|
||||
fi
|
||||
|
||||
find_limactl() {
|
||||
if [ -n "${PJARCZAK_LIMACTL:-}" ] && [ -x "${PJARCZAK_LIMACTL}" ]; then
|
||||
printf '%s\n' "$PJARCZAK_LIMACTL"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v limactl >/dev/null 2>&1; then
|
||||
command -v limactl
|
||||
return 0
|
||||
fi
|
||||
|
||||
for candidate in \
|
||||
"$HOME/Library/Application Support/OrcaSlicer/macos-bridge/lima/bin/limactl" \
|
||||
"/opt/homebrew/bin/limactl" \
|
||||
"/usr/local/bin/limactl"
|
||||
do
|
||||
if [ -x "$candidate" ]; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
LIMACTL=$(find_limactl || true)
|
||||
if [ -z "$LIMACTL" ]; then
|
||||
echo "limactl not found" >&2
|
||||
exit 127
|
||||
fi
|
||||
|
||||
exec "$RUNNER" "$HOST_PATH"
|
||||
exec "$LIMACTL" shell "$INSTANCE" -- /usr/bin/env \
|
||||
PJARCZAK_BAMBU_PLUGIN_DIR="$PLUGIN_DIR" \
|
||||
PJARCZAK_BAMBU_NETWORK_SO="$PLUGIN_DIR/libbambu_networking.so" \
|
||||
PJARCZAK_BAMBU_SOURCE_SO="$PLUGIN_DIR/libBambuSource.so" \
|
||||
PJARCZAK_BAMBU_LIVE555_SO="$PLUGIN_DIR/liblive555.so" \
|
||||
PJARCZAK_EXPECTED_BAMBU_NETWORK_VERSION="${PJARCZAK_EXPECTED_BAMBU_NETWORK_VERSION:-}" \
|
||||
"$HOST_PATH"
|
||||
|
|
|
|||
177
tools/pjarczak_bambu_runtime/macos/pjarczak_install_macos_runtime.sh
Executable file
177
tools/pjarczak_bambu_runtime/macos/pjarczak_install_macos_runtime.sh
Executable file
|
|
@ -0,0 +1,177 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
PACKAGE_DIR=""
|
||||
PLUGIN_DIR=""
|
||||
PLUGIN_CACHE_DIR=""
|
||||
REPLACE_EXISTING=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-PackageDir)
|
||||
PACKAGE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-PluginDir)
|
||||
PLUGIN_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-PluginCacheDir)
|
||||
PLUGIN_CACHE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-ReplaceExisting)
|
||||
REPLACE_EXISTING=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "unknown argument: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$PLUGIN_DIR" ]]; then
|
||||
PLUGIN_DIR="$PACKAGE_DIR"
|
||||
fi
|
||||
if [[ -z "$PLUGIN_DIR" ]]; then
|
||||
echo "PluginDir is required" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
APP_SUPPORT_DIR="$HOME/Library/Application Support/OrcaSlicer/macos-bridge"
|
||||
LOCAL_LIMA_ROOT="$APP_SUPPORT_DIR/lima"
|
||||
LOCAL_LIMA_BIN="$LOCAL_LIMA_ROOT/bin"
|
||||
mkdir -p "$APP_SUPPORT_DIR" "$LOCAL_LIMA_ROOT"
|
||||
|
||||
trim_file() {
|
||||
local path="$1"
|
||||
if [[ ! -f "$path" ]]; then
|
||||
return 1
|
||||
fi
|
||||
LC_ALL=C tr -d '\r' < "$path" | head -n 1 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
|
||||
}
|
||||
|
||||
find_limactl() {
|
||||
if [[ -n "${PJARCZAK_LIMACTL:-}" && -x "${PJARCZAK_LIMACTL}" ]]; then
|
||||
printf '%s\n' "$PJARCZAK_LIMACTL"
|
||||
return 0
|
||||
fi
|
||||
if command -v limactl >/dev/null 2>&1; then
|
||||
command -v limactl
|
||||
return 0
|
||||
fi
|
||||
if [[ -x "$LOCAL_LIMA_BIN/limactl" ]]; then
|
||||
printf '%s\n' "$LOCAL_LIMA_BIN/limactl"
|
||||
return 0
|
||||
fi
|
||||
for candidate in /opt/homebrew/bin/limactl /usr/local/bin/limactl; do
|
||||
if [[ -x "$candidate" ]]; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
install_lima_binary_locally() {
|
||||
local version
|
||||
version=$(curl -fsSL https://api.github.com/repos/lima-vm/lima/releases/latest | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n 1)
|
||||
if [[ -z "$version" ]]; then
|
||||
echo "failed to resolve latest Lima version from GitHub API" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local host_arch
|
||||
host_arch=$(uname -m)
|
||||
case "$host_arch" in
|
||||
arm64|aarch64)
|
||||
host_arch=arm64
|
||||
;;
|
||||
x86_64|amd64)
|
||||
host_arch=x86_64
|
||||
;;
|
||||
*)
|
||||
echo "unsupported macOS architecture for Lima: $host_arch" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local version_no_v="${version#v}"
|
||||
local base_url="https://github.com/lima-vm/lima/releases/download/${version}"
|
||||
local main_archive="lima-${version_no_v}-Darwin-${host_arch}.tar.gz"
|
||||
local guest_archive="lima-additional-guestagents-${version_no_v}-Darwin-${host_arch}.tar.gz"
|
||||
local tmpdir
|
||||
tmpdir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmpdir"' RETURN
|
||||
|
||||
curl -fL "$base_url/$main_archive" -o "$tmpdir/$main_archive"
|
||||
tar -xzf "$tmpdir/$main_archive" -C "$LOCAL_LIMA_ROOT"
|
||||
|
||||
if curl -fL "$base_url/$guest_archive" -o "$tmpdir/$guest_archive"; then
|
||||
tar -xzf "$tmpdir/$guest_archive" -C "$LOCAL_LIMA_ROOT"
|
||||
fi
|
||||
|
||||
[[ -x "$LOCAL_LIMA_BIN/limactl" ]]
|
||||
}
|
||||
|
||||
ensure_lima_installed() {
|
||||
LIMACTL=$(find_limactl || true)
|
||||
if [[ -n "$LIMACTL" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v brew >/dev/null 2>&1; then
|
||||
brew install lima
|
||||
LIMACTL=$(find_limactl || true)
|
||||
if [[ -n "$LIMACTL" ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
install_lima_binary_locally
|
||||
LIMACTL=$(find_limactl || true)
|
||||
[[ -n "$LIMACTL" ]]
|
||||
}
|
||||
|
||||
maybe_install_rosetta() {
|
||||
if [[ "$(uname -m)" != "arm64" ]]; then
|
||||
return 0
|
||||
fi
|
||||
if pgrep -q oahd >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
/usr/sbin/softwareupdate --install-rosetta --agree-to-license >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
INSTANCE="${PJARCZAK_MAC_LIMA_INSTANCE:-}"
|
||||
if [[ -z "$INSTANCE" ]]; then
|
||||
INSTANCE=$(trim_file "$PLUGIN_DIR/pjarczak_lima_instance.txt" || true)
|
||||
fi
|
||||
if [[ -z "$INSTANCE" ]]; then
|
||||
INSTANCE="orcaslicer-bambu-network"
|
||||
fi
|
||||
|
||||
ensure_lima_installed
|
||||
maybe_install_rosetta
|
||||
|
||||
START_ARGS=(start "--name=${INSTANCE}" --mount-writable)
|
||||
MACOS_MAJOR=$(sw_vers -productVersion | awk -F. '{print $1}')
|
||||
if [[ "$MACOS_MAJOR" -ge 13 ]]; then
|
||||
START_ARGS+=(--vm-type=vz --network=vzNAT)
|
||||
if [[ "$(uname -m)" == "arm64" ]]; then
|
||||
START_ARGS+=(--rosetta)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$REPLACE_EXISTING" -eq 1 ]]; then
|
||||
"$LIMACTL" stop "$INSTANCE" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
if ! "$LIMACTL" shell "$INSTANCE" -- /usr/bin/env true >/dev/null 2>&1; then
|
||||
"$LIMACTL" "${START_ARGS[@]}" template:default
|
||||
fi
|
||||
|
||||
"$LIMACTL" start-at-login "$INSTANCE" --enabled >/dev/null 2>&1 || true
|
||||
"$LIMACTL" shell "$INSTANCE" -- /usr/bin/env true >/dev/null
|
||||
printf 'runtime installed\n'
|
||||
|
|
@ -0,0 +1 @@
|
|||
orcaslicer-bambu-network
|
||||
116
tools/pjarczak_bambu_runtime/macos/pjarczak_verify_macos_runtime.sh
Executable file
116
tools/pjarczak_bambu_runtime/macos/pjarczak_verify_macos_runtime.sh
Executable file
|
|
@ -0,0 +1,116 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
PACKAGE_DIR=""
|
||||
PLUGIN_DIR=""
|
||||
PLUGIN_CACHE_DIR=""
|
||||
ALLOW_MISSING_LINUX_PLUGIN=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-PackageDir)
|
||||
PACKAGE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-PluginDir)
|
||||
PLUGIN_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-PluginCacheDir)
|
||||
PLUGIN_CACHE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-AllowMissingLinuxPlugin)
|
||||
ALLOW_MISSING_LINUX_PLUGIN=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "unknown argument: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$PLUGIN_DIR" ]]; then
|
||||
PLUGIN_DIR="$PACKAGE_DIR"
|
||||
fi
|
||||
if [[ -z "$PLUGIN_DIR" ]]; then
|
||||
echo "PluginDir is required" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
trim_file() {
|
||||
local path="$1"
|
||||
if [[ ! -f "$path" ]]; then
|
||||
return 1
|
||||
fi
|
||||
LC_ALL=C tr -d '\r' < "$path" | head -n 1 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
|
||||
}
|
||||
|
||||
find_limactl() {
|
||||
if [[ -n "${PJARCZAK_LIMACTL:-}" && -x "${PJARCZAK_LIMACTL}" ]]; then
|
||||
printf '%s\n' "$PJARCZAK_LIMACTL"
|
||||
return 0
|
||||
fi
|
||||
if command -v limactl >/dev/null 2>&1; then
|
||||
command -v limactl
|
||||
return 0
|
||||
fi
|
||||
local local_bin="$HOME/Library/Application Support/OrcaSlicer/macos-bridge/lima/bin/limactl"
|
||||
if [[ -x "$local_bin" ]]; then
|
||||
printf '%s\n' "$local_bin"
|
||||
return 0
|
||||
fi
|
||||
for candidate in /opt/homebrew/bin/limactl /usr/local/bin/limactl; do
|
||||
if [[ -x "$candidate" ]]; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
require_file() {
|
||||
local path="$1"
|
||||
local label="$2"
|
||||
if [[ ! -f "$path" ]]; then
|
||||
echo "missing required file: $label" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "$ALLOW_MISSING_LINUX_PLUGIN" -eq 0 ]]; then
|
||||
require_file "$PLUGIN_DIR/libbambu_networking.so" "libbambu_networking.so"
|
||||
require_file "$PLUGIN_DIR/libBambuSource.so" "libBambuSource.so"
|
||||
fi
|
||||
require_file "$PLUGIN_DIR/pjarczak_bambu_linux_host" "pjarczak_bambu_linux_host"
|
||||
require_file "$PLUGIN_DIR/pjarczak_bambu_linux_host_abi1" "pjarczak_bambu_linux_host_abi1"
|
||||
require_file "$PLUGIN_DIR/pjarczak_bambu_linux_host_abi0" "pjarczak_bambu_linux_host_abi0"
|
||||
require_file "$PLUGIN_DIR/pjarczak-bambu-linux-host-wrapper" "pjarczak-bambu-linux-host-wrapper"
|
||||
require_file "$PLUGIN_DIR/install_runtime_macos.sh" "install_runtime_macos.sh"
|
||||
require_file "$PLUGIN_DIR/verify_runtime_macos.sh" "verify_runtime_macos.sh"
|
||||
require_file "$PLUGIN_DIR/pjarczak_lima_instance.txt" "pjarczak_lima_instance.txt"
|
||||
require_file "$PLUGIN_DIR/ca-certificates.crt" "ca-certificates.crt"
|
||||
require_file "$PLUGIN_DIR/slicer_base64.cer" "slicer_base64.cer"
|
||||
|
||||
LIMACTL=$(find_limactl || true)
|
||||
if [[ -z "$LIMACTL" ]]; then
|
||||
echo "limactl not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INSTANCE="${PJARCZAK_MAC_LIMA_INSTANCE:-}"
|
||||
if [[ -z "$INSTANCE" ]]; then
|
||||
INSTANCE=$(trim_file "$PLUGIN_DIR/pjarczak_lima_instance.txt" || true)
|
||||
fi
|
||||
if [[ -z "$INSTANCE" ]]; then
|
||||
echo "Lima instance name is not configured" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! "$LIMACTL" shell "$INSTANCE" -- /usr/bin/env true >/dev/null 2>&1; then
|
||||
echo "Lima instance '$INSTANCE' is not ready" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'runtime ok\n'
|
||||
Loading…
Add table
Reference in a new issue