%bcond_with prebuilt Name: crossmacro Version: 1.5.1 Release: 1.dev.1046.g35955bf637a2817da48e1dd8c158277c56ccf751 Summary: Mouse and keyboard macro recorder and automation License: GPL-3.0-only URL: https://github.com/alper-han/CrossMacro Source0: %{name}-%{version}.tar.gz # Do not strip .NET single-file bundles during RPM post-processing. # Stripping can corrupt apphost bundles (observed on aarch64 builds). %global debug_package %{nil} %global _build_id_links none %global __strip /bin/true %global __debug_install_post %{nil} ExclusiveArch: x86_64 aarch64 AutoReqProv: no Requires: glibc, libstdc++, polkit, libXtst, zlib, libssl.so.3()(64bit), systemd-libs, libxkbcommon, libicu, fontconfig, libX11, libXcursor, libXrandr BuildRequires: checkpolicy, policycoreutils %if %{without prebuilt} BuildRequires: dotnet-sdk-aot-10.0 %endif Requires(post): systemd Requires(post): systemd-udev Requires(post): policycoreutils Requires(post): shadow-utils Requires(pre): shadow-utils Requires(preun): systemd Requires(postun): systemd Requires(postun): policycoreutils %description Mouse and keyboard macro recorder and automation for Linux, with Wayland/X11 support, a macro editor, hotkeys, scheduling, text expansion, screen recognition, and CLI control. %prep %setup -q %build %if %{without prebuilt} bash -eu -o pipefail <<'BUILD_SOURCE' source scripts/lib/platform.sh arch='%{_target_cpu}' rid="linux-$(to_dotnet_arch "$arch")" bash scripts/ci/publish-linux-artifacts.sh \ --rid "$rid" --arch "$arch" --version '%{version}' \ --ui-output "$PWD/publish" --daemon-output "$PWD/daemon" --skip-smoke BUILD_SOURCE %endif checkmodule -M -m -o crossmacro.mod scripts/packaging/rpm/crossmacro.te semodule_package -o crossmacro.pp -m crossmacro.mod %install mkdir -p %{buildroot}/usr/lib/%{name} mkdir -p %{buildroot}/usr/lib/%{name}/daemon mkdir -p %{buildroot}/usr/bin mkdir -p %{buildroot}/usr/share/applications # Icons handled in loop mkdir -p %{buildroot}/usr/lib/systemd/system mkdir -p %{buildroot}/usr/lib/udev/rules.d mkdir -p %{buildroot}/usr/share/icons/hicolor mkdir -p %{buildroot}/usr/share/selinux/packages/%{name} mkdir -p %{buildroot}/usr/share/polkit-1/actions mkdir -p %{buildroot}/usr/share/polkit-1/rules.d mkdir -p %{buildroot}/usr/share/man/man1 # Copy UI cp -r publish/* %{buildroot}/usr/lib/%{name}/ # Copy Daemon cp -r daemon/* %{buildroot}/usr/lib/%{name}/daemon/ # Copy Service (already has correct ExecStart path) cp scripts/daemon/crossmacro.service %{buildroot}/usr/lib/systemd/system/crossmacro.service install -m 0644 scripts/assets/99-crossmacro.rules %{buildroot}/usr/lib/udev/rules.d/99-crossmacro.rules install -m 0644 crossmacro.pp %{buildroot}/usr/share/selinux/packages/%{name}/crossmacro.pp install -m 0644 scripts/assets/io.github.alper_han.crossmacro.policy %{buildroot}/usr/share/polkit-1/actions/io.github.alper_han.crossmacro.policy install -m 0644 scripts/assets/50-crossmacro.rules %{buildroot}/usr/share/polkit-1/rules.d/50-crossmacro.rules # Install modules-load config mkdir -p %{buildroot}/usr/lib/modules-load.d install -m 0644 scripts/assets/crossmacro-modules.conf %{buildroot}/usr/lib/modules-load.d/crossmacro.conf ln -s /usr/lib/%{name}/CrossMacro.UI %{buildroot}/usr/bin/%{name} # Copy icons cp -r src/CrossMacro.UI/Assets/icons/* %{buildroot}/usr/share/icons/hicolor/ cp scripts/assets/CrossMacro.desktop %{buildroot}/usr/share/applications/CrossMacro.desktop sed -i 's/Exec=crossmacro/Exec=\/usr\/lib\/crossmacro\/CrossMacro.UI/g' %{buildroot}/usr/share/applications/CrossMacro.desktop install -m 0644 docs/man/crossmacro.1 %{buildroot}/usr/share/man/man1/crossmacro.1 install -D -m 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE install -D -m 0644 scripts/assets/io.github.alper_han.crossmacro.metainfo.xml \ %{buildroot}/usr/share/metainfo/io.github.alper_han.crossmacro.metainfo.xml grep -Fq 'io.github.alper_han.crossmacro.desktop' \ %{buildroot}/usr/share/metainfo/io.github.alper_han.crossmacro.metainfo.xml sed -i 's|io.github.alper_han.crossmacro.desktop|CrossMacro.desktop|' \ %{buildroot}/usr/share/metainfo/io.github.alper_han.crossmacro.metainfo.xml %pre # Create group and user if they don't exist getent group crossmacro >/dev/null || groupadd -r crossmacro getent group input >/dev/null || groupadd -r input getent group uinput >/dev/null || groupadd -r uinput getent passwd crossmacro >/dev/null || \ useradd -r -g crossmacro -G input,uinput -s /sbin/nologin \ -c "CrossMacro Input Daemon User" crossmacro usermod -g crossmacro crossmacro || : usermod -aG input crossmacro || : usermod -aG uinput crossmacro || : %post # Reload rules before loading uinput so the device node is created with the # packaged permissions on first load. udevadm control --reload-rules >/dev/null 2>&1 || : if command -v modprobe >/dev/null 2>&1; then modprobe uinput >/dev/null 2>&1 || : fi udevadm trigger >/dev/null 2>&1 || : udevadm settle >/dev/null 2>&1 || : selinux_enabled=0 if [ -x /usr/sbin/selinuxenabled ]; then /usr/sbin/selinuxenabled && selinux_enabled=1 || : elif command -v selinuxenabled >/dev/null 2>&1; then selinuxenabled && selinux_enabled=1 || : fi semodule_cmd="" if [ -x /usr/sbin/semodule ]; then semodule_cmd=/usr/sbin/semodule elif command -v semodule >/dev/null 2>&1; then semodule_cmd="$(command -v semodule)" fi policy_ready=1 if [ "$selinux_enabled" -eq 1 ]; then if [ -z "$semodule_cmd" ]; then echo "CrossMacro: SELinux is enabled but semodule was not found; service will not be started." >&2 policy_ready=0 elif "$semodule_cmd" -i /usr/share/selinux/packages/%{name}/crossmacro.pp; then if ! "$semodule_cmd" -l | awk '{print $1}' | grep -qx crossmacro; then echo "CrossMacro: SELinux policy verification failed; service will not be started." >&2 policy_ready=0 fi else echo "CrossMacro: failed to install SELinux policy; service will not be started." >&2 policy_ready=0 fi fi # systemd_post equivalent if [ $1 -eq 1 ] && [ "$policy_ready" -eq 1 ]; then systemctl daemon-reload >/dev/null 2>&1 || : systemctl enable crossmacro.service >/dev/null 2>&1 || : systemctl start crossmacro.service >/dev/null 2>&1 || : elif [ $1 -eq 1 ] && [ "$policy_ready" -ne 1 ]; then echo "CrossMacro: start skipped because the SELinux policy is not active yet." >&2 fi # Best effort: add invoking user to crossmacro group. # This works in common sudo/pkexec flows; if no user context is available, # keep the manual instruction as fallback. installer_user="" if [ -n "${SUDO_USER:-}" ] && [ "${SUDO_USER}" != "root" ]; then installer_user="${SUDO_USER}" elif [ -n "${PKEXEC_UID:-}" ] && [ "${PKEXEC_UID}" != "0" ]; then installer_user="$(getent passwd "${PKEXEC_UID}" | cut -d: -f1)" fi if [ -n "$installer_user" ] && getent passwd "$installer_user" >/dev/null 2>&1; then if gpasswd -a "$installer_user" crossmacro >/dev/null 2>&1; then echo "CrossMacro installed. Added '$installer_user' to 'crossmacro' group." echo "Re-login (or reboot) is required for group change to take effect." else echo "CrossMacro installed, but could not add '$installer_user' to 'crossmacro' group automatically." >&2 echo "Run: sudo gpasswd -a crossmacro" >&2 fi else echo "CrossMacro installed. To use the daemon, add yourself to the 'crossmacro' group:" echo "sudo gpasswd -a \$USER crossmacro" fi %preun # systemd_preun equivalent if [ $1 -eq 0 ]; then systemctl stop crossmacro.service >/dev/null 2>&1 || : systemctl disable crossmacro.service >/dev/null 2>&1 || : fi %postun # systemd_postun_with_restart equivalent if [ $1 -ge 1 ]; then systemctl try-restart crossmacro.service >/dev/null 2>&1 || : fi if [ $1 -eq 0 ]; then systemctl daemon-reload >/dev/null 2>&1 || : if [ -x /usr/sbin/semodule ]; then /usr/sbin/semodule -r crossmacro >/dev/null 2>&1 || : elif command -v semodule >/dev/null 2>&1; then semodule -r crossmacro >/dev/null 2>&1 || : fi fi %files %license %{_licensedir}/%{name}/LICENSE /usr/lib/%{name} /usr/bin/%{name} /usr/lib/systemd/system/crossmacro.service /usr/lib/udev/rules.d/99-crossmacro.rules /usr/share/applications/CrossMacro.desktop /usr/share/metainfo/io.github.alper_han.crossmacro.metainfo.xml /usr/share/icons/hicolor/*/apps/%{name}.png /usr/share/selinux/packages/%{name}/crossmacro.pp /usr/share/polkit-1/actions/io.github.alper_han.crossmacro.policy /usr/share/polkit-1/rules.d/50-crossmacro.rules /usr/lib/modules-load.d/crossmacro.conf /usr/share/man/man1/crossmacro.1*