File OrcaSlicer.spec of Package OrcaSlicer
#
# spec file for package OrcaSlicer
#
# Copyright (c) 2026 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%define __builder ninja
Name: OrcaSlicer
Version: 2.3.1
Release: 0
Summary: G-code generator for FDM 3D printers
License: AGPL-3.0-only
URL: https://github.com/SoftFever/OrcaSlicer
Source0: OrcaSlicer-%{version}.tar.gz
Source1: https://github.com/SoftFever/Orca-deps-libnoise/archive/refs/tags/1.0.tar.gz#/libnoise-1.0.tar.gz
# Build requirements (following SuperSlicer pattern)
BuildRequires: blosc-devel
BuildRequires: cereal-devel
BuildRequires: cgal-devel
BuildRequires: cmake
BuildRequires: dbus-1-devel
BuildRequires: eigen3-devel >= 3
BuildRequires: expat
BuildRequires: fdupes
BuildRequires: gcc-c++
BuildRequires: gettext-tools
BuildRequires: glew-devel
BuildRequires: gstreamer-devel
BuildRequires: gtest >= 1.7
BuildRequires: hicolor-icon-theme
BuildRequires: ilmbase-devel
BuildRequires: libbgcode-devel
BuildRequires: libboost_atomic-devel
BuildRequires: libboost_chrono-devel
BuildRequires: libboost_date_time-devel
BuildRequires: libboost_filesystem-devel
BuildRequires: libboost_iostreams-devel
BuildRequires: libboost_locale-devel
BuildRequires: libboost_log-devel
BuildRequires: libboost_nowide-devel
BuildRequires: libboost_program_options-devel
BuildRequires: libboost_regex-devel
BuildRequires: libboost_thread-devel
BuildRequires: libcurl-devel
BuildRequires: libexpat-devel
BuildRequires: libglfw-devel
BuildRequires: libjpeg8-devel
BuildRequires: libpng16-devel
BuildRequires: libsecret-devel
BuildRequires: libudev-devel
BuildRequires: memory-constraints
BuildRequires: nanosvg-devel
BuildRequires: ninja
BuildRequires: nlopt-devel
BuildRequires: opencv-devel
BuildRequires: openvdb-devel >= 7.1
BuildRequires: openssl-devel
BuildRequires: pkgconfig
BuildRequires: qhull_r-devel
BuildRequires: qhullcpp-devel-static
BuildRequires: tbb-devel
BuildRequires: update-desktop-files
BuildRequires: webkit2gtk3-devel
BuildRequires: wxGTK3-devel >= 3.2
BuildRequires: zlib-devel-static
BuildRequires: cmake(OpenCASCADE)
BuildRequires: pkgconfig(wayland-client)
BuildRequires: pkgconfig(wayland-egl)
%description
OrcaSlicer is an open-source slicer for FDM (Fused Deposition Modeling)
3D printers. It converts 3D models (STL, OBJ, AMF, 3MF, STEP) into G-code
instructions for 3D printers.
OrcaSlicer is a fork of Bambu Studio by Bambulab, which itself is based
on PrusaSlicer by Prusa Research. It supports many printer brands including
Bambu Lab, Prusa, Voron, Creality, and many more.
%prep
%autosetup -p1 -n %{name}-%{version}
# Extract and build libnoise
tar -xzf %{SOURCE1}
pushd Orca-deps-libnoise-1.0
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=%{_builddir}/%{name}-%{version}/libnoise-install \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
make %{?_smp_mflags}
make install
popd
%if 0%{?suse_version}
sed -i 's/+UNKNOWN/%{release}-%{?is_opensuse:open}SUSE-0%{?suse_version}/' version.inc
%endif
# ===== Boost fixes =====
# Use FindBoost module instead of BoostConfig.cmake
sed -i 's/cmake_policy(SET CMP0167 NEW)/cmake_policy(SET CMP0167 OLD)/' CMakeLists.txt
sed -i '/find_package(Boost/i set(Boost_NO_BOOST_CMAKE ON)' CMakeLists.txt
# Lower Boost version and remove system component
sed -i 's/find_package(Boost 1.83.0 REQUIRED COMPONENTS system filesystem/find_package(Boost 1.66.0 REQUIRED COMPONENTS filesystem/' CMakeLists.txt
# ===== OCCT library names (new OpenCASCADE) =====
sed -i 's/TKXDESTEP/TKDESTEP/' src/libslic3r/CMakeLists.txt
sed -i '/TKSTEP$/d' src/libslic3r/CMakeLists.txt
sed -i '/TKSTEP209/d' src/libslic3r/CMakeLists.txt
sed -i '/TKSTEPAttr/d' src/libslic3r/CMakeLists.txt
sed -i '/TKSTEPBase/d' src/libslic3r/CMakeLists.txt
sed -i '/TKXSBase/d' src/libslic3r/CMakeLists.txt
# ===== OpenCV library names =====
sed -i 's/opencv_world/opencv_imgproc opencv_core/' src/libslic3r/CMakeLists.txt
# ===== Qhull =====
sed -i "s|find_package(Qhull 7.2 REQUIRED)|find_package(Qhull 8.0.2 REQUIRED)|" src/CMakeLists.txt
sed -i 's#INTERFACE Qhull::qhullcpp#INTERFACE -lqhullcpp#' src/CMakeLists.txt
# ===== CGAL 6 API fixes =====
# AABB_traits -> AABB_traits_3
sed -i 's/CGAL::AABB_traits</CGAL::AABB_traits_3</g' src/libslic3r/CutSurface.cpp
# property_map returns std::optional in CGAL 6, not std::pair
sed -i 's/\.property_map<\([^>]*\)>(\([^)]*\))\.first/.property_map<\1>(\2).value()/g' src/libslic3r/CutSurface.cpp
# ===== Boost.Process removed in Boost 1.90+ - use popen() instead =====
# Remove boost/process.hpp include and namespace alias
sed -i '/#include <boost\/process.hpp>/d' src/libslic3r/GCode/PostProcessor.cpp
sed -i '/namespace process = boost::process;/d' src/libslic3r/GCode/PostProcessor.cpp
# Add sys/wait.h for WEXITSTATUS
sed -i '/#include <cstdlib>/a #include <sys/wait.h>' src/libslic3r/GCode/PostProcessor.cpp
# Replace process::ipstream and process::child with popen-based code
sed -i '/process::ipstream istd_err;/,/return child.exit_code();/c\
std::string full_cmd = std::string(shell) + " -c '\"'" + command + "'\"' 2>\&1";\
FILE* pipe = popen(full_cmd.c_str(), "r");\
if (!pipe) {\
std_err = "Failed to execute post-processing script: popen failed";\
return -1;\
}\
std_err.clear();\
char buffer[256];\
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {\
std_err.append(buffer);\
}\
int status = pclose(pipe);\
return WIFEXITED(status) ? WEXITSTATUS(status) : -1;' src/libslic3r/GCode/PostProcessor.cpp
# ===== Boost.Asio io_service -> io_context (deprecated in Boost 1.90) =====
sed -i 's/boost::asio::io_service/boost::asio::io_context/g' src/slic3r/GUI/HttpServer.hpp
sed -i 's/boost::asio::io_service/boost::asio::io_context/g' src/slic3r/Utils/Bonjour.hpp
sed -i 's/boost::asio::io_service/boost::asio::io_context/g' src/slic3r/Utils/Bonjour.cpp
# ===== Fix show_profile_info() call - missing bool argument =====
sed -i 's/show_profile_info(wxString::FromUTF8/show_profile_info(true, wxString::FromUTF8/g' src/slic3r/GUI/CalibrationWizardCaliPage.cpp
# ===== Fix wxString to bool implicit conversion (wxNO_UNSAFE_WXSTRING_CONV) =====
sed -i 's/if(m_create_type\.create_nozzle)/if(!m_create_type.create_nozzle.IsEmpty())/g' src/slic3r/GUI/CreatePresetsDialog.cpp
# ===== Fix boost::process removal in Boost 1.90 =====
# MediaPlayCtrl.cpp - disable stream service on Linux (requires boost::process)
# The start_stream_service function uses boost::process which was removed in Boost 1.90
# Wrap the boost::process code in Windows-only preprocessor guards
sed -i 's|#include <boost/process.hpp>|#ifdef __WXMSW__\n#include <boost/process.hpp>\n#endif|' src/slic3r/GUI/MediaPlayCtrl.cpp
# Add return false for non-Windows before boost::process::pipe usage (line ~756)
sed -i 's|boost::process::pipe intermediate;|#ifndef __WXMSW__\n // boost::process not available on Linux with Boost 1.90+\n return false;\n#else\n boost::process::pipe intermediate;|' src/slic3r/GUI/MediaPlayCtrl.cpp
# Close the #ifdef __WXMSW__ block after process_ffmpeg.detach()
sed -i 's|process_ffmpeg.detach();|process_ffmpeg.detach();\n#endif // __WXMSW__|' src/slic3r/GUI/MediaPlayCtrl.cpp
# ===== Fix wxArrayString constructor - can't take (int, std::string) =====
# DeviceManager.cpp line 5050: wxArrayString dev_id_list(1, dev_id_string);
# Change to: wxArrayString dev_id_list; dev_id_list.Add(dev_id_string);
sed -i 's/wxArrayString\s*dev_id_list(1,\s*dev_id_string);/wxArrayString dev_id_list; dev_id_list.Add(dev_id_string);/' src/slic3r/GUI/DeviceManager.cpp
# Plater.cpp:9396 - wxArrayString(1, target_path.string()) is invalid
# Replace with initializer list which works with wxArrayString
sed -i 's/wxArrayString(1, target_path\.string())/wxArrayString{wxString::FromUTF8(target_path.string())}/' src/slic3r/GUI/Plater.cpp
# PhysicalPrinterDialog.cpp:376 - ambiguous set_values call
# Explicitly use std::vector<std::string> to disambiguate
sed -i 's/choice->set_values({ m_config->opt_string("printhost_port") })/choice->set_values(std::vector<std::string>{ m_config->opt_string("printhost_port") })/' src/slic3r/GUI/PhysicalPrinterDialog.cpp
# ===== Fix wxList Node -> compatibility_iterator (wxWidgets 3.2) =====
# SendMultiMachinePage.cpp - wxList now uses compatibility_iterator instead of Node
sed -i 's/AmsRadioSelectorList::Node\*/AmsRadioSelectorList::compatibility_iterator /g' src/slic3r/GUI/SendMultiMachinePage.cpp
# ===== Fix Bonjour.cpp Boost.Asio API changes (Boost 1.90) =====
# 1. io_context->post() -> boost::asio::post(*io_context, ...)
sed -i 's|io_service->post(\(.*\));|boost::asio::post(*io_service, \1);|g' src/slic3r/Utils/Bonjour.cpp
# 2. asio::deadline_timer -> boost::asio::steady_timer
sed -i 's|asio::deadline_timer|boost::asio::steady_timer|g' src/slic3r/Utils/Bonjour.cpp
# 3. expires_from_now(boost::posix_time::seconds(...)) -> expires_after(std::chrono::seconds(...))
sed -i 's|expires_from_now(boost::posix_time::seconds(\([^)]*\)))|expires_after(std::chrono::seconds(\1))|g' src/slic3r/Utils/Bonjour.cpp
# 4. Add chrono header if not present
sed -i '/#include <boost\/asio\.hpp>/a #include <chrono>' src/slic3r/Utils/Bonjour.cpp
# ===== Fix Serial.hpp/cpp io_service -> io_context (Boost 1.90) =====
sed -i 's/boost::asio::io_service/boost::asio::io_context/g' src/slic3r/Utils/Serial.hpp
sed -i 's/asio::io_service/boost::asio::io_context/g' src/slic3r/Utils/Serial.cpp
# ===== Fix TCPConsole.cpp resolver_results API (Boost 1.90) =====
# endpoints->endpoint() is no longer valid, use endpoints.begin()->endpoint()
sed -i 's/endpoints->endpoint()/endpoints.begin()->endpoint()/g' src/slic3r/Utils/TCPConsole.cpp
# RemovableDriveManager.cpp - replace boost::process with POSIX popen()
# First replace the include
sed -i 's|#include <boost/process.hpp>|// boost::process removed in Boost 1.90 - using POSIX alternatives\n#include <cstdio>\n#include <sys/wait.h>|' src/slic3r/GUI/RemovableDriveManager.cpp
# Replace boost::process::ipstream with our popen setup
sed -i 's|boost::process::ipstream istd_err;|// Using POSIX popen() instead of boost::process\n\t\tstd::string cmd;|' src/slic3r/GUI/RemovableDriveManager.cpp
# Replace the boost::process::child( line - just remove it
sed -i 's|boost::process::child child(||' src/slic3r/GUI/RemovableDriveManager.cpp
# Replace diskutil line (macOS)
sed -i "s|boost::process::search_path(\"diskutil\"), \"eject\", correct_path.c_str(), (boost::process::std_out \& boost::process::std_err) > istd_err);|cmd = \"diskutil eject '\" + correct_path + \"' 2>\&1\";|" src/slic3r/GUI/RemovableDriveManager.cpp
# Replace umount line (Linux)
sed -i "s|boost::process::search_path(\"umount\"), correct_path.c_str(), (boost::process::std_out \& boost::process::std_err) > istd_err);|cmd = \"umount '\" + correct_path + \"' 2>\&1\";\n\t\tFILE* pipe = popen(cmd.c_str(), \"r\");\n\t\tif (pipe) { char buffer[256]; while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { BOOST_LOG_TRIVIAL(trace) << buffer; } }\n\t\tint ret = pipe ? pclose(pipe) : -1;|" src/slic3r/GUI/RemovableDriveManager.cpp
# Replace the while loop (child.running()) - make it empty
sed -i 's|while (child.running() && std::getline(istd_err, line))|while (false)|' src/slic3r/GUI/RemovableDriveManager.cpp
# Replace child.wait(ec); - no longer needed
sed -i 's|child.wait(ec);|// pclose already waited for completion|' src/slic3r/GUI/RemovableDriveManager.cpp
# Replace if (ec) check with ret == -1 check
sed -i 's|if (ec) {|if (ret == -1) {|' src/slic3r/GUI/RemovableDriveManager.cpp
# Replace child.exit_code() with WEXITSTATUS
sed -i 's|int err = child.exit_code();|int err = WIFEXITED(ret) ? WEXITSTATUS(ret) : -1;|' src/slic3r/GUI/RemovableDriveManager.cpp
# Fix the error message
sed -i 's|boost::process::child::wait() failed during Ejection|popen/pclose failed during Ejection|' src/slic3r/GUI/RemovableDriveManager.cpp
sed -i 's|ec.value()|ret|' src/slic3r/GUI/RemovableDriveManager.cpp
# ===== Add X11 library to OrcaSlicer target (needed for XInitThreads) =====
# Add find_package(X11) to MAIN CMakeLists.txt (not src/CMakeLists.txt) so target is available
sed -i '/find_package(GLEW REQUIRED)/a find_package(X11 REQUIRED)' CMakeLists.txt
# Link X11 to OrcaSlicer using the imported target
sed -i '/target_link_libraries(OrcaSlicer libslic3r_gui)/s/)$/ X11::X11)/' src/CMakeLists.txt
# ===== Add webkit2gtk-4.1 library (needed for WebView.cpp) =====
# pkg-config finds webkit2gtk-4.1 headers but library not linked
sed -i '/target_link_libraries(OrcaSlicer libslic3r_gui/s/)$/ webkit2gtk-4.1)/' src/CMakeLists.txt
%build
%limit_build -m 6144
# Add flags to suppress deprecated warnings from CGAL
export CXXFLAGS="${CXXFLAGS} -Wno-deprecated-declarations -Wno-error=deprecated-declarations -Wno-cpp -DCGAL_NO_DEPRECATION_WARNINGS"
%cmake -Wno-dev -DSLIC3R_FHS=1 \
-DSLIC3R_BUILD_TESTS=0 \
-DSLIC3R_GTK=3 \
-DOPENVDB_FIND_MODULE_PATH=%{_libdir}/cmake/OpenVDB \
-DLIBNOISE_INCLUDE_DIR=%{_builddir}/%{name}-%{version}/libnoise-install/include \
-DLIBNOISE_LIBRARY=%{_builddir}/%{name}-%{version}/libnoise-install/lib64/liblibnoise_static.a \
%ifarch i686 i586 i386
-DCMAKE_C_FLAGS:STRING="%{optflags} -mfpmath=sse -msse2" \
-DCMAKE_CXX_FLAGS:STRING="%{optflags} -mfpmath=sse -msse2"
%endif
%cmake_build
# Create i18n output directories before generating .mo files
for lang in ca cs de en es fr hu it ja ko lt nl pl pt_BR ru sv tr uk zh_CN zh_TW; do
mkdir -p resources/i18n/$lang
done
%cmake_build gettext_po_to_mo
%install
%cmake_install
%if 0%{?suse_version} > 1500
%suse_update_desktop_file -i %{name}
%else
%suse_update_desktop_file -i -r %{name} Graphics 3DGraphics
%endif
rm -rf %{buildroot}%{_includedir}
rm -rf %{buildroot}%{_prefix}/lib/cmake
# Remove localization source files
find %{buildroot}%{_datadir}/%{name}/i18n/ -name \*.po -delete 2>/dev/null || true
find %{buildroot}%{_datadir}/%{name}/i18n/ -name settings.ini -delete 2>/dev/null || true
# Remove LICENSE.txt installed to wrong location
rm -f %{buildroot}/usr/LICENSE.txt
# Handle locale files
find %{buildroot}%{_datadir}/%{name}/i18n -type f -o -type l 2>/dev/null | sed '
s:'"%{buildroot}"'::
s:\(.*/%{name}/i18n/\)\([^/_]\+\)\(.*\.mo$\):%%lang(\2) \1\2\3:
s:^\([^%].*\)::
s:%lang(C) ::
/^$/d
' > lang-files || touch lang-files
find %{buildroot}%{_datadir}/%{name}/i18n -type d 2>/dev/null | sed '
s:'"%{buildroot}"'::
s:\(.*\):%dir \1:
' >> lang-files || true
%fdupes %{buildroot}%{_datadir}
%files -f lang-files
%{_bindir}/orca-slicer
%dir %{_datadir}/%{name}/
%{_datadir}/%{name}/
%{_datadir}/icons/hicolor/*/apps/%{name}.png
%{_datadir}/applications/%{name}.desktop
%license LICENSE.txt
%doc README.md
%changelog