Skip to content

Commit 674e9e6

Browse files
committed
Make installer interactive with auto-configuration
Add wrapper install.sh for one-line piped installation Interactive install-interactive.sh prompts for PATH setup and activation Add color output and installation verification Update branding to Nullsafe
1 parent 5c723b2 commit 674e9e6

File tree

5 files changed

+345
-133
lines changed

5 files changed

+345
-133
lines changed

.github/workflows/deploy-playground.yml

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,37 @@ jobs:
2424

2525
- name: Download latest WASM files from release
2626
run: |
27-
LATEST_RELEASE=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases | \
28-
jq -r '[.[] | select(.tag_name | startswith("playground-v"))] | first | .tag_name')
27+
LATEST_RELEASE=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.tag_name')
2928
30-
echo "Latest playground release: $LATEST_RELEASE"
29+
echo "Latest release: $LATEST_RELEASE"
3130
32-
if [ -z "$LATEST_RELEASE" ]; then
33-
echo "No playground release found"
31+
if [ -z "$LATEST_RELEASE" ] || [ "$LATEST_RELEASE" = "null" ]; then
32+
echo "No release found"
3433
exit 1
3534
fi
3635
3736
mkdir -p /tmp/wasm-files
3837
cd /tmp/wasm-files
39-
curl -L -o clang.wasm "https://github.com/${{ github.repository }}/releases/download/${LATEST_RELEASE}/clang-nullsafe.wasm"
40-
curl -L -o clang.js "https://github.com/${{ github.repository }}/releases/download/${LATEST_RELEASE}/clang-nullsafe.js"
4138
42-
echo "Downloaded files:"
39+
# Download the tar.gz file
40+
curl -L -o clang-nullsafe-wasm.tar.gz "https://github.com/${{ github.repository }}/releases/download/${LATEST_RELEASE}/clang-nullsafe-wasm.tar.gz"
41+
42+
# Extract the tar.gz
43+
tar -xzf clang-nullsafe-wasm.tar.gz
44+
45+
# The tar.gz contains: clang-nullsafe.wasm, clang-nullsafe.js, and their .gz versions
46+
# Rename to the expected names (clang.wasm and clang.js)
47+
if [ -f clang-nullsafe.wasm ]; then
48+
mv clang-nullsafe.wasm clang.wasm
49+
fi
50+
if [ -f clang-nullsafe.js ]; then
51+
mv clang-nullsafe.js clang.js
52+
fi
53+
54+
# Clean up
55+
rm -f *.gz *.tar
56+
57+
echo "Extracted files:"
4358
ls -lh
4459
4560
- name: Deploy to gh-pages

.github/workflows/release-clang.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
6161
**Quick install (Linux/macOS):**
6262
```bash
63-
curl -fsSL https://raw.githubusercontent.com/cs01/llvm-project/null-safe-c-dev/install.sh | sh
63+
curl -fsSL https://raw.githubusercontent.com/cs01/llvm-project/null-safe-c-dev/install.sh | bash
6464
```
6565
6666
**Manual install:**

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ xcode-select --install # If not already installed
4545
### Quick Install
4646

4747
```bash
48-
curl -fsSL https://raw.githubusercontent.com/cs01/llvm-project/null-safe-c-dev/install.sh | sh
48+
curl -fsSL https://raw.githubusercontent.com/cs01/llvm-project/null-safe-c-dev/install.sh | bash
4949
```
5050

5151
Or download manually from [releases](https://github.com/cs01/llvm-project/releases).

install-interactive.sh

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
REPO="cs01/llvm-project"
6+
DEFAULT_INSTALL_DIR="$HOME/.local/null-safe-clang"
7+
8+
GREEN='\033[0;32m'
9+
NC='\033[0m'
10+
11+
prompt_yn() {
12+
local prompt="$1"
13+
local default="$2"
14+
local response
15+
16+
if ! [ -t 0 ] && ! [ -e /dev/tty ]; then
17+
echo "No TTY available, using default: $default"
18+
[ "$default" = "y" ] && return 0 || return 1
19+
fi
20+
21+
if [ "$default" = "y" ]; then
22+
prompt="$prompt [Y/n]: "
23+
else
24+
prompt="$prompt [y/N]: "
25+
fi
26+
27+
while true; do
28+
if [ -t 0 ]; then
29+
read -p "$prompt" response
30+
else
31+
printf "%s" "$prompt" > /dev/tty
32+
read response < /dev/tty
33+
fi
34+
response=${response:-$default}
35+
case "$response" in
36+
[Yy]|[Yy][Ee][Ss]) return 0 ;;
37+
[Nn]|[Nn][Oo]) return 1 ;;
38+
*) echo "Please answer yes or no." ;;
39+
esac
40+
done
41+
}
42+
43+
detect_shell_profile() {
44+
case "$SHELL" in
45+
*/zsh)
46+
echo "$HOME/.zshrc"
47+
;;
48+
*/bash)
49+
if [ -f "$HOME/.bashrc" ]; then
50+
echo "$HOME/.bashrc"
51+
elif [ -f "$HOME/.bash_profile" ]; then
52+
echo "$HOME/.bash_profile"
53+
else
54+
echo "$HOME/.profile"
55+
fi
56+
;;
57+
*)
58+
if [ -f "$HOME/.zshrc" ]; then
59+
echo "$HOME/.zshrc"
60+
elif [ -f "$HOME/.bashrc" ]; then
61+
echo "$HOME/.bashrc"
62+
elif [ -f "$HOME/.bash_profile" ]; then
63+
echo "$HOME/.bash_profile"
64+
else
65+
echo "$HOME/.profile"
66+
fi
67+
;;
68+
esac
69+
}
70+
71+
INSTALL_DIR="${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}"
72+
73+
echo ""
74+
printf "${GREEN}Welcome to Nullsafe Clang installer${NC}\n"
75+
echo ""
76+
77+
if [ -z "$SKIP_PROMPTS" ]; then
78+
echo "This will download and install Nullsafe Clang to:"
79+
echo " $INSTALL_DIR"
80+
echo ""
81+
82+
if ! prompt_yn "Proceed with installation?" "y"; then
83+
echo "Installation cancelled."
84+
exit 0
85+
fi
86+
echo ""
87+
fi
88+
89+
if [ -z "$VERSION" ]; then
90+
echo "Fetching latest release version..."
91+
VERSION=$(curl -s https://api.github.com/repos/$REPO/releases | \
92+
jq -r '[.[] | select(.tag_name | startswith("v")) | select(.prerelease == false)] | first | .tag_name')
93+
94+
if [ -z "$VERSION" ]; then
95+
echo "Failed to fetch latest version. Set VERSION manually:"
96+
echo " VERSION=v0.1.6 $0"
97+
exit 1
98+
fi
99+
echo "Latest version: $VERSION"
100+
fi
101+
102+
echo "Detecting platform..."
103+
OS=$(uname -s)
104+
ARCH=$(uname -m)
105+
106+
if [ "$OS" = "Linux" ] && [ "$ARCH" = "x86_64" ]; then
107+
RELEASE_FILE="clang-nullsafe-linux-x86_64.tar.gz"
108+
echo "Detected: Linux x86_64"
109+
elif [ "$OS" = "Darwin" ]; then
110+
RELEASE_FILE="clang-nullsafe-macos-universal.tar.gz"
111+
echo "Detected: macOS (Universal)"
112+
113+
if [ ! -f "/opt/homebrew/opt/zstd/lib/libzstd.1.dylib" ] && [ ! -f "/usr/local/opt/zstd/lib/libzstd.1.dylib" ]; then
114+
echo ""
115+
echo "Missing required dependency: zstd"
116+
echo ""
117+
118+
if command -v brew >/dev/null 2>&1; then
119+
if [ -z "$SKIP_PROMPTS" ] && prompt_yn "Install zstd via Homebrew now?" "y"; then
120+
echo "Installing zstd..."
121+
brew install zstd
122+
printf "${GREEN}zstd installed successfully${NC}\n"
123+
else
124+
echo "Please install zstd manually:"
125+
echo " brew install zstd"
126+
echo ""
127+
echo "Then run this installer again."
128+
exit 1
129+
fi
130+
else
131+
echo "Homebrew not found. Please install Homebrew first:"
132+
echo " https://brew.sh"
133+
echo ""
134+
echo "Then run this installer again."
135+
exit 1
136+
fi
137+
fi
138+
else
139+
echo "Unsupported platform: $OS $ARCH"
140+
echo ""
141+
echo "For WebAssembly/Playground, visit:"
142+
echo " https://cs01.github.io/llvm-project/"
143+
echo ""
144+
echo "Or download manually from:"
145+
echo " https://github.com/$REPO/releases/tag/$VERSION"
146+
exit 1
147+
fi
148+
149+
URL="https://github.com/$REPO/releases/download/$VERSION/$RELEASE_FILE"
150+
151+
echo "Downloading Nullsafe Clang $VERSION..."
152+
echo " $URL"
153+
154+
mkdir -p "$INSTALL_DIR"
155+
cd "$INSTALL_DIR"
156+
157+
if command -v curl >/dev/null 2>&1; then
158+
curl -L "$URL" | tar xz --strip-components=0
159+
elif command -v wget >/dev/null 2>&1; then
160+
wget -O - "$URL" | tar xz --strip-components=0
161+
else
162+
echo "Neither curl nor wget found. Please install one of them."
163+
exit 1
164+
fi
165+
166+
if [ "$OS" = "Darwin" ]; then
167+
echo "Removing macOS quarantine attribute..."
168+
xattr -dr com.apple.quarantine "$INSTALL_DIR/bin" 2>/dev/null || true
169+
170+
if ! command -v xcrun >/dev/null 2>&1; then
171+
echo ""
172+
echo "Xcode Command Line Tools not found"
173+
echo ""
174+
175+
if [ -z "$SKIP_PROMPTS" ] && prompt_yn "Install Xcode Command Line Tools now?" "y"; then
176+
echo "Opening Xcode Command Line Tools installer..."
177+
echo "Please complete the installation dialog, then press Enter to continue."
178+
xcode-select --install 2>/dev/null || true
179+
read -p "Press Enter after installation completes..."
180+
181+
if ! command -v xcrun >/dev/null 2>&1; then
182+
echo "Xcode Command Line Tools still not found."
183+
echo "Please ensure installation completed successfully."
184+
exit 1
185+
fi
186+
else
187+
echo "Please install Xcode Command Line Tools:"
188+
echo " xcode-select --install"
189+
echo ""
190+
echo "Then run this installer again."
191+
exit 1
192+
fi
193+
fi
194+
195+
SDK_PATH=$(xcrun --show-sdk-path 2>/dev/null || echo "")
196+
if [ -n "$SDK_PATH" ]; then
197+
echo "Configuring macOS SDK integration..."
198+
199+
mv "$INSTALL_DIR/bin/clang" "$INSTALL_DIR/bin/clang.real"
200+
mv "$INSTALL_DIR/bin/clang++" "$INSTALL_DIR/bin/clang++.real" 2>/dev/null || true
201+
202+
cat > "$INSTALL_DIR/bin/clang" << 'WRAPPER_EOF'
203+
#!/bin/bash
204+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
205+
SDK_PATH="$(xcrun --show-sdk-path 2>/dev/null || echo "")"
206+
if [ -n "$SDK_PATH" ]; then
207+
exec "$SCRIPT_DIR/clang.real" -isysroot "$SDK_PATH" "$@"
208+
else
209+
exec "$SCRIPT_DIR/clang.real" "$@"
210+
fi
211+
WRAPPER_EOF
212+
213+
cat > "$INSTALL_DIR/bin/clang++" << 'WRAPPER_EOF'
214+
#!/bin/bash
215+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
216+
SDK_PATH="$(xcrun --show-sdk-path 2>/dev/null || echo "")"
217+
if [ -n "$SDK_PATH" ]; then
218+
exec "$SCRIPT_DIR/clang++.real" -isysroot "$SDK_PATH" "$@"
219+
else
220+
exec "$SCRIPT_DIR/clang++.real" "$@"
221+
fi
222+
WRAPPER_EOF
223+
224+
chmod +x "$INSTALL_DIR/bin/clang" "$INSTALL_DIR/bin/clang++"
225+
fi
226+
fi
227+
228+
echo ""
229+
printf "${GREEN}Successfully installed to: $INSTALL_DIR${NC}\n"
230+
echo ""
231+
232+
SHELL_PROFILE=$(detect_shell_profile)
233+
PATH_EXPORT="export PATH=\"$INSTALL_DIR/bin:\$PATH\""
234+
235+
if [ -z "$SKIP_PROMPTS" ]; then
236+
echo "To use Nullsafe Clang, we need to add it to your PATH."
237+
echo "Detected shell profile: $SHELL_PROFILE"
238+
echo ""
239+
240+
if grep -q "$INSTALL_DIR/bin" "$SHELL_PROFILE" 2>/dev/null; then
241+
printf "${GREEN}PATH already configured in $SHELL_PROFILE${NC}\n"
242+
echo ""
243+
echo "If you just configured it, reload your shell:"
244+
echo " source $SHELL_PROFILE"
245+
else
246+
if prompt_yn "Add Nullsafe Clang to PATH in $SHELL_PROFILE?" "y"; then
247+
echo "" >> "$SHELL_PROFILE"
248+
echo "# Nullsafe Clang" >> "$SHELL_PROFILE"
249+
echo "$PATH_EXPORT" >> "$SHELL_PROFILE"
250+
printf "${GREEN}Added to $SHELL_PROFILE${NC}\n"
251+
echo ""
252+
253+
if prompt_yn "Activate it now in this shell?" "y"; then
254+
export PATH="$INSTALL_DIR/bin:$PATH"
255+
printf "${GREEN}Activated! You can now use 'clang' in this shell.${NC}\n"
256+
else
257+
echo "Reload your shell later to activate:"
258+
echo " source $SHELL_PROFILE"
259+
echo ""
260+
echo "Or open a new terminal window."
261+
fi
262+
else
263+
echo ""
264+
echo "Skipped PATH configuration. To add it manually, add this to $SHELL_PROFILE:"
265+
echo " $PATH_EXPORT"
266+
fi
267+
fi
268+
echo ""
269+
270+
if prompt_yn "Verify installation now?" "y"; then
271+
echo ""
272+
echo "Testing Nullsafe Clang..."
273+
274+
if command -v clang >/dev/null 2>&1 && clang --version 2>&1 | grep -q "cs01/llvm-project"; then
275+
PATH_ACTIVE=true
276+
else
277+
export PATH="$INSTALL_DIR/bin:$PATH"
278+
PATH_ACTIVE=false
279+
fi
280+
281+
if "$INSTALL_DIR/bin/clang" --version >/dev/null 2>&1; then
282+
echo ""
283+
"$INSTALL_DIR/bin/clang" --version | head -n 1
284+
echo ""
285+
printf "${GREEN}Installation verified successfully!${NC}\n"
286+
echo ""
287+
288+
if [ "$PATH_ACTIVE" = true ]; then
289+
echo "Try it now:"
290+
echo " echo 'void f(int* _Nullable p) { *p = 42; }' | clang -x c - -fsyntax-only"
291+
else
292+
echo "Try it now (using full path):"
293+
echo " echo 'void f(int* _Nullable p) { *p = 42; }' | $INSTALL_DIR/bin/clang -x c - -fsyntax-only"
294+
echo ""
295+
echo "Or reload your shell and use just 'clang'."
296+
fi
297+
else
298+
echo "Warning: clang --version failed"
299+
echo "There may be an issue with the installation."
300+
fi
301+
fi
302+
else
303+
echo "To use Nullsafe Clang, add this to $SHELL_PROFILE:"
304+
echo " $PATH_EXPORT"
305+
fi
306+
307+
echo ""
308+
echo "Try the interactive WebAssembly playground:"
309+
echo " https://cs01.github.io/llvm-project/"
310+
echo ""

0 commit comments

Comments
 (0)