-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmake_binary.sh
More file actions
executable file
·155 lines (136 loc) · 5.27 KB
/
Copy pathmake_binary.sh
File metadata and controls
executable file
·155 lines (136 loc) · 5.27 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
#!/bin/bash
set -e
# Colors
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
# Default target (empty means build both archs)
TARGET=""
# Parse options
while getopts ":t:" opt; do
case ${opt} in
t) TARGET=${OPTARG} ;;
\?) echo -e "${RED}Invalid option: -$OPTARG${NC}" >&2; exit 1 ;;
:) echo -e "${RED}Option -$OPTARG requires an argument (x86_64 or arm64)${NC}" >&2; exit 1 ;;
esac
done
# Validate target if provided
if [[ -n "$TARGET" && "$TARGET" != "x86_64" && "$TARGET" != "arm64" ]]; then
echo -e "${RED}❌ Invalid target architecture: $TARGET (use x86_64 or arm64)${NC}"
exit 1
fi
# Paths
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)"
PROJECT_ROOT="$SCRIPT_DIR"
ENTITLEMENTS_FILE="$PROJECT_ROOT/entitlements.plist"
SPEC_FILE="$PROJECT_ROOT/pdfpost.spec"
CODESIGN_IDENTITY="Developer ID Application: SUMURI LLC (M2UAN8S5M3)"
# Venv paths
VENV_X86="$PROJECT_ROOT/.venv_x86"
VENV_ARM64="$PROJECT_ROOT/.venv"
# Step 0: If no target given, build both architectures sequentially
if [ -z "$TARGET" ]; then
rm -rf "$PROJECT_ROOT/build/" "$PROJECT_ROOT/dist/"
echo -e "${YELLOW}🧬 No -t specified. Building both x86_64 and arm64...${NC}"
"$0" -t x86_64
"$0" -t arm64
echo -e "${GREEN}✅ Binaries built:${NC}"
echo " - $PROJECT_ROOT/dist/x86_64/pdf_toc_builder_x86_64"
echo " - $PROJECT_ROOT/dist/arm64/pdf_toc_builder_arm64"
exit 0
fi
echo -e "${GREEN}🚀 Building pdfpost for architecture: $TARGET${NC}"
# Step 1: Ensure and activate appropriate venv
if [ "$TARGET" == "x86_64" ]; then
if [ ! -d "$VENV_X86" ]; then
echo -e "${YELLOW}🧪 Creating x86_64 venv under Rosetta...${NC}"
if command -v arch >/dev/null 2>&1; then
arch -x86_64 /usr/bin/python3 -m venv "$VENV_X86" || arch -x86_64 python3 -m venv "$VENV_X86"
else
echo -e "${RED}arch not found; cannot create x86_64 venv${NC}"; exit 1
fi
source "$VENV_X86/bin/activate"
python -m pip install --upgrade pip
pip install -r "$PROJECT_ROOT/requirements.txt" pyinstaller
deactivate
fi
source "$VENV_X86/bin/activate"
elif [ "$TARGET" == "arm64" ]; then
if [ ! -d "$VENV_ARM64" ]; then
echo -e "${YELLOW}🧪 Creating arm64 venv...${NC}"
/usr/bin/python3 -m venv "$VENV_ARM64" || python3 -m venv "$VENV_ARM64"
source "$VENV_ARM64/bin/activate"
python -m pip install --upgrade pip
pip install -r "$PROJECT_ROOT/requirements.txt" pyinstaller
deactivate
fi
source "$VENV_ARM64/bin/activate"
fi
PYINSTALLER_BIN="$(which pyinstaller)"
# Step 2: Create entitlements if missing
echo -e "${YELLOW}📄 Checking entitlements.plist...${NC}"
if [ ! -f "$ENTITLEMENTS_FILE" ]; then
echo -e "${YELLOW}Creating entitlements.plist...${NC}"
cat > "$ENTITLEMENTS_FILE" << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist ... >
<plist version="1.0"><dict>
<key>com.apple.security.cs.allow-jit</key><true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key><true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key><true/>
<key>com.apple.security.cs.disable-library-validation</key><true/>
<key>com.apple.security.cs.disable-executable-page-protection</key><true/>
<key>com.apple.security.files.user-selected.read-write</key><true/>
<key>com.apple.security.network.client</key><true/>
<key>com.apple.security.get-task-allow</key><true/>
</dict></plist>
EOF
fi
# Step 3: Modify spec file
echo -e "${YELLOW}🔧 Updating spec file...${NC}"
cp "$SPEC_FILE" "$SPEC_FILE.backup" 2>/dev/null || true
BINARY_NAME="pdf_toc_builder_$TARGET"
DIST_PATH="$PROJECT_ROOT/dist/$TARGET"
mkdir -p "$DIST_PATH"
cat > "$SPEC_FILE" << EOF
# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import collect_dynamic_libs, collect_data_files
fitz_bins = collect_dynamic_libs('fitz')
fitz_data = collect_data_files('fitz')
a = Analysis(
["$PROJECT_ROOT/pdfpost.py"],
pathex=["$PROJECT_ROOT"],
binaries=fitz_bins,
datas=fitz_data,
hiddenimports=["fitz", "pymupdf"],
hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz, a.scripts, a.binaries, a.datas, [],
name="${BINARY_NAME}", debug=False, bootloader_ignore_signals=False,
strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True,
disable_windowed_traceback=False, argv_emulation=False,
target_arch="${TARGET}",
codesign_identity="${CODESIGN_IDENTITY}",
entitlements_file="${ENTITLEMENTS_FILE}",
)
EOF
# Step 4: Verify codesigning identity
echo -e "${YELLOW}🔍 Verifying codesign identity...${NC}"
security find-identity -v -p codesigning | grep -q "$CODESIGN_IDENTITY" || {
echo -e "${RED}❌ Code signing identity not found${NC}"
exit 1
}
# Step 5: Build with PyInstaller
echo -e "${YELLOW}🔨 Building with PyInstaller...${NC}"
"$PYINSTALLER_BIN" --clean --log-level=INFO --distpath "$DIST_PATH" "$SPEC_FILE"
# Step 6: Post-build checks
BINARY_PATH="$DIST_PATH/$BINARY_NAME"
if [ -f "$BINARY_PATH" ]; then
echo -e "${GREEN}✅ Build successful: $BINARY_PATH${NC}"
codesign --verify --verbose "$BINARY_PATH"
codesign -dvvv "$BINARY_PATH" | grep "Hardened Runtime" >/dev/null && echo -e "${GREEN}✅ Hardened runtime enabled${NC}"
file "$BINARY_PATH"
else
echo -e "${RED}❌ Build failed!${NC}"
exit 1
fi