-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·241 lines (227 loc) · 10.2 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·241 lines (227 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env bash
#
# RedControl installer — checks dependencies (incl. umr), sets up the launcher,
# and gets you from a fresh clone to a working app. Safe: it asks before it
# installs anything and never runs silent sudo.
#
set -u
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# ---- pretty output ----------------------------------------------------------
if [ -t 1 ]; then B=$'\e[1m'; G=$'\e[32m'; Y=$'\e[33m'; R=$'\e[31m'; C=$'\e[36m'; N=$'\e[0m'
else B=""; G=""; Y=""; R=""; C=""; N=""; fi
say() { printf "%s\n" "$*"; }
ok() { printf "%s✓%s %s\n" "$G" "$N" "$*"; }
warn() { printf "%s!%s %s\n" "$Y" "$N" "$*"; }
err() { printf "%s✗%s %s\n" "$R" "$N" "$*"; }
head() { printf "\n%s%s%s\n" "$B$C" "$*" "$N"; }
ask() { local a; read -r -p "$1 [y/N] " a; [[ "$a" =~ ^[Yy]$ ]]; }
head "RedControl installer"
say "Folder: $HERE"
# ---- distro detection -------------------------------------------------------
DISTRO="unknown"; PM=""
if [ -r /etc/os-release ]; then . /etc/os-release; DISTRO="${ID:-unknown}"; fi
case "$DISTRO" in
arch|cachyos|endeavouros|manjaro) PM="pacman" ;;
debian|ubuntu|pop|linuxmint|elementary) PM="apt" ;;
fedora|rhel|centos|nobara) PM="dnf" ;;
esac
say "Detected: ${DISTRO} (${PM:-no known package manager})"
# ---- 1. Python + Tkinter ----------------------------------------------------
head "1. Python & Tkinter"
if command -v python3 >/dev/null 2>&1; then ok "python3: $(python3 --version 2>&1)"
else err "python3 not found — install Python 3 first."; exit 1; fi
have_tk() { python3 -c "import tkinter" 2>/dev/null; }
if have_tk; then ok "tkinter present"
else
warn "tkinter (python3-tk) is missing — the GUI needs it."
case "$PM" in
pacman) TK_PKG="tk" ;;
apt) TK_PKG="python3-tk" ;;
dnf) TK_PKG="python3-tkinter" ;;
*) TK_PKG="" ;;
esac
if [ -n "$TK_PKG" ] && ask "Install $TK_PKG now?"; then
case "$PM" in
pacman) sudo pacman -S --needed "$TK_PKG" ;;
apt) sudo apt update && sudo apt install -y "$TK_PKG" ;;
dnf) sudo dnf install -y "$TK_PKG" ;;
esac
else
case "$PM" in
pacman) say " Install with: sudo pacman -S tk" ;;
apt) say " Install with: sudo apt install python3-tk" ;;
dnf) say " Install with: sudo dnf install python3-tkinter" ;;
*) say " Install your distro's python3-tk / tk package." ;;
esac
fi
if have_tk; then ok "tkinter present"
else err "tkinter still missing — RedControl cannot start without it."; fi
fi
# ---- 2. umr (the core dependency) -------------------------------------------
head "2. umr (User Mode Register debugger — required)"
if command -v umr >/dev/null 2>&1; then
ok "umr found: $(command -v umr)"
else
warn "umr is NOT installed. RedControl cannot talk to the GPU without it."
case "$PM" in
pacman)
if command -v yay >/dev/null 2>&1 || command -v paru >/dev/null 2>&1; then
AUR=$(command -v yay || command -v paru)
if ask "Install umr from the AUR with $(basename "$AUR")?"; then
"$AUR" -S --needed umr-git && ok "umr installed" || err "AUR install failed — see manual steps below."
fi
else
warn "No AUR helper (yay/paru) found."
say " Install one, then: yay -S umr-git (or build from source, below)"
fi
;;
apt|dnf)
say "umr isn't in most $PM repos, so it's built from source (a few minutes)."
say "RedControl only needs umr's register CLI, so the build skips the GUI and"
say "LLVM disassembler (-DUMR_NO_GUI=ON -DUMR_NO_LLVM=ON) — far fewer dependencies."
if ask "Install build tools and compile umr now?"; then
deps_ok=1
if [ "$PM" = apt ]; then
sudo apt update \
&& sudo apt install -y git cmake build-essential pkg-config \
libpciaccess-dev libdrm-dev libncurses-dev \
|| deps_ok=0
else
sudo dnf install -y git cmake gcc gcc-c++ make pkgconf-pkg-config \
libpciaccess-devel libdrm-devel ncurses-devel \
|| deps_ok=0
fi
if [ "$deps_ok" -eq 0 ]; then
err "Package install failed — fix the errors above and re-run this script."
else
tmp="$(mktemp -d)"
if git clone --depth 1 https://gitlab.freedesktop.org/tomstdenis/umr "$tmp/umr" \
&& cmake -S "$tmp/umr" -B "$tmp/umr/build" -DUMR_NO_GUI=ON -DUMR_NO_LLVM=ON \
&& make -C "$tmp/umr/build" -j"$(nproc)" \
&& sudo make -C "$tmp/umr/build" install; then
ok "umr installed"
else
err "umr build failed — see the error above, or try the manual steps below."
fi
rm -rf "$tmp"
fi
fi
;;
*)
warn "Unknown distro — build umr from source (see below)."
;;
esac
if ! command -v umr >/dev/null 2>&1; then
say ""
say "${B}Manual umr install (minimal build — all RedControl needs):${N}"
say " # Debian/Ubuntu/Mint:"
say " sudo apt install git cmake build-essential pkg-config libpciaccess-dev libdrm-dev libncurses-dev"
say " # Fedora:"
say " sudo dnf install git cmake gcc gcc-c++ make pkgconf-pkg-config libpciaccess-devel libdrm-devel ncurses-devel"
say " # Arch (or just: yay -S umr-git):"
say " sudo pacman -S --needed git base-devel cmake libpciaccess libdrm ncurses"
say " # then:"
say " git clone https://gitlab.freedesktop.org/tomstdenis/umr"
say " cd umr && cmake -S . -B build -DUMR_NO_GUI=ON -DUMR_NO_LLVM=ON && make -C build -j && sudo make -C build install"
fi
fi
# ---- 3. Privileged helper + polkit policy -----------------------------------
head "3. Privileged helper"
say "RedControl runs as your normal user. GPU register access goes through a"
say "small root helper, authorised by polkit — no sudoers rule is installed."
if [ ! -f "$HERE/redcontrol-helper" ]; then
err "redcontrol-helper is missing from $HERE — cannot continue."
elif ask "Install redcontrol-helper and its polkit policy?"; then
helper_ok=1
sudo install -d -m 0755 /usr/libexec || helper_ok=0
sudo install -m 0755 -o root -g root "$HERE/redcontrol-helper" \
/usr/libexec/redcontrol-helper || helper_ok=0
sudo install -d -m 0755 /usr/share/polkit-1/actions || helper_ok=0
sudo install -m 0644 -o root -g root "$HERE/org.redcontrol.helper.policy" \
/usr/share/polkit-1/actions/org.redcontrol.helper.policy || helper_ok=0
if [ "$helper_ok" -eq 1 ]; then
ok "helper installed to /usr/libexec/redcontrol-helper"
if ! command -v pkexec >/dev/null 2>&1; then
warn "pkexec not found — install polkit, or RedControl falls back to sudo."
fi
else
err "helper install failed — RedControl will not be able to reach the GPU."
fi
fi
# Older versions wrote a passwordless sudo rule that also allowed find, cat and
# mount as root — enough for any local program to obtain a root shell. It is no
# longer used, so remove it.
# /etc/sudoers.d is not readable by a normal user, so probe the rule the way
# sudo would rather than testing for the file.
if sudo -n /usr/bin/true 2>/dev/null; then
warn "An insecure passwordless sudo rule from an earlier version is installed."
if ask "Remove /etc/sudoers.d/umr-passwordless now?"; then
sudo rm -f /etc/sudoers.d/umr-passwordless && ok "removed" || err "removal failed"
sudo -k
fi
fi
# ---- 4. Optional niceties ---------------------------------------------------
head "4. Optional extras (nicer names, tray icon)"
if ask "Install optional Python extras (pystray, pillow) for the tray icon?"; then
# Newer distros (PEP 668, e.g. Ubuntu 24.04 / Mint 22) refuse plain pip installs;
# --break-system-packages with --user only touches ~/.local, so it's a safe fallback.
if python3 -m pip install --user --upgrade pystray pillow 2>/dev/null \
|| python3 -m pip install --user --upgrade --break-system-packages pystray pillow; then
ok "extras installed"
else
warn "pip install failed — the app still runs without the tray."
fi
fi
# ---- 5. Desktop launcher + icon ---------------------------------------------
head "5. Menu launcher"
APPS="$HOME/.local/share/applications"; ICONS="$HOME/.local/share/icons"
mkdir -p "$APPS" "$ICONS"
chmod +x "$HERE/redcontrol.py" 2>/dev/null
# The launcher hardcodes this directory. Installing from a temporary or
# throwaway location produces a menu entry that silently stops working the
# moment the folder is moved or cleaned up.
case "$HERE" in
/tmp/*|/var/tmp/*|*/Downloads/*|*/Desktop/*)
warn "Installing from $HERE"
say " The menu entry points at this folder. If you move or delete it the"
say " shortcut will stop working — re-run ./install.sh from the new path."
;;
esac
ICON_LINE="Icon=video-display"
if [ -f "$HERE/redcontrol-icon.png" ]; then
cp "$HERE/redcontrol-icon.png" "$ICONS/redcontrol.png" && ICON_LINE="Icon=$ICONS/redcontrol.png"
fi
cat > "$APPS/redcontrol.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=RedControl
Comment=AMD display pipeline control (dithering, depth, DisplayPort signal)
Exec=python3 "$HERE/redcontrol.py"
Path=$HERE
$ICON_LINE
Terminal=false
StartupNotify=false
Categories=System;Settings;Utility;
Keywords=display;dither;dithering;flicker;amd;gpu;depth;bpc;displayport;hdmi;
EOF
chmod +x "$APPS/redcontrol.desktop" 2>/dev/null
update-desktop-database "$APPS" >/dev/null 2>&1
if command -v desktop-file-validate >/dev/null 2>&1; then
if ! desktop-file-validate "$APPS/redcontrol.desktop" 2>/dev/null; then
warn "The launcher did not validate cleanly (see messages above)."
fi
fi
if ! python3 -c "import tkinter" 2>/dev/null; then
warn "tkinter is missing, so the menu entry will not open anything."
fi
ok "Launcher installed — search 'RedControl' in your app menu."
say " If it does not start, run it from a terminal to see why:"
say " cd \"$HERE\" && python3 redcontrol.py"
# ---- done -------------------------------------------------------------------
head "Done"
if command -v umr >/dev/null 2>&1; then ok "All set."; else warn "Install umr (above) before RedControl can control the GPU."; fi
say "Run now with: python3 \"$HERE/redcontrol.py\""
if ask "Launch RedControl now?"; then
if have_tk; then setsid python3 "$HERE/redcontrol.py" >/dev/null 2>&1 &
else err "Cannot launch — tkinter is not installed (see step 1)."; fi
fi