Skip to content

Commit 27dd05f

Browse files
committed
feat(build): create isolated virtual environment for building and streamline pyprophet installation process
1 parent ef06509 commit 27dd05f

File tree

1 file changed

+27
-90
lines changed

1 file changed

+27
-90
lines changed

scripts/build/build_linux.sh

Lines changed: 27 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,18 @@ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
4444
find . -type f -name "*.pyc" -delete 2>/dev/null || true
4545
find . -type f -name "*.pyo" -delete 2>/dev/null || true
4646

47-
# Install/upgrade build dependencies
48-
$PYTHON -m pip install --upgrade pip setuptools wheel cython numpy pyinstaller
47+
# Create a clean virtual environment for building
48+
echo "Creating clean virtual environment for building..."
49+
VENV_DIR=$(mktemp -d)/pyprophet_build_venv
50+
$PYTHON -m venv "$VENV_DIR"
51+
source "$VENV_DIR/bin/activate"
52+
53+
# Install build dependencies in venv
54+
pip install --upgrade pip setuptools wheel cython numpy pyinstaller
4955

5056
# Parse and install runtime dependencies from pyproject.toml
5157
echo "Installing runtime dependencies..."
52-
$PYTHON << 'PYEOF'
58+
python << 'PYEOF'
5359
import tomllib
5460
import subprocess
5561
import sys
@@ -71,89 +77,26 @@ for dep in deps:
7177
continue
7278
PYEOF
7379

74-
# Uninstall any existing pyprophet installation
75-
echo "Uninstalling any existing pyprophet..."
76-
$PYTHON -m pip uninstall -y pyprophet 2>/dev/null || true
77-
78-
# Move pyprophet source directory OUT of the way completely
79-
echo "Temporarily hiding pyprophet source directory..."
80-
TEMP_BACKUP_DIR=$(mktemp -d)
81-
if [ -d "pyprophet" ]; then
82-
mv pyprophet "${TEMP_BACKUP_DIR}/pyprophet_src"
83-
fi
84-
if [ -d "packaging" ]; then
85-
mv packaging "${TEMP_BACKUP_DIR}/packaging_src"
86-
fi
87-
88-
# Build pyprophet wheel in a completely isolated temp directory
89-
echo "Building pyprophet wheel in isolated directory..."
90-
WHEEL_BUILD_DIR=$(mktemp -d)
91-
92-
# Copy ONLY the files needed for building (not the entire tree)
93-
cp "${ORIGINAL_DIR}/pyproject.toml" "${WHEEL_BUILD_DIR}/"
94-
cp "${ORIGINAL_DIR}/setup.py" "${WHEEL_BUILD_DIR}/"
95-
cp "${ORIGINAL_DIR}/README.md" "${WHEEL_BUILD_DIR}/" 2>/dev/null || true
96-
cp "${ORIGINAL_DIR}/LICENSE" "${WHEEL_BUILD_DIR}/" 2>/dev/null || true
97-
98-
# Copy source files
99-
cp -r "${TEMP_BACKUP_DIR}/pyprophet_src" "${WHEEL_BUILD_DIR}/pyprophet"
100-
101-
cd "${WHEEL_BUILD_DIR}"
102-
103-
# Build wheel
104-
$PYTHON -m pip wheel --no-deps --wheel-dir /tmp/pyprophet_wheels .
105-
106-
# Return to original directory
107-
cd "${ORIGINAL_DIR}"
108-
109-
# Clean up wheel build directory
110-
rm -rf "${WHEEL_BUILD_DIR}"
111-
112-
# Install pyprophet from wheel (now pyprophet source is hidden, so it MUST go to site-packages)
113-
echo "Installing pyprophet from wheel to site-packages..."
114-
$PYTHON -m pip install --no-deps --no-cache-dir /tmp/pyprophet_wheels/pyprophet-*.whl
115-
116-
# Restore the source directories
117-
echo "Restoring source directories..."
118-
if [ -d "${TEMP_BACKUP_DIR}/pyprophet_src" ]; then
119-
mv "${TEMP_BACKUP_DIR}/pyprophet_src" pyprophet
120-
fi
121-
if [ -d "${TEMP_BACKUP_DIR}/packaging_src" ]; then
122-
mv "${TEMP_BACKUP_DIR}/packaging_src" packaging
123-
fi
124-
rm -rf "${TEMP_BACKUP_DIR}"
80+
# Build and install pyprophet directly in the venv (no wheel intermediate step)
81+
echo "Building and installing pyprophet in venv..."
82+
pip install --no-deps -e .
12583

126-
# Verify installation is in site-packages, NOT source directory
84+
# Verify installation
12785
echo "Verifying pyprophet installation..."
128-
PYPROPHET_LOCATION=$($PYTHON -c "import pyprophet; print(pyprophet.__file__)")
86+
PYPROPHET_LOCATION=$(python -c "import pyprophet; print(pyprophet.__file__)")
12987
echo "PyProphet installed at: ${PYPROPHET_LOCATION}"
13088

131-
# Ensure it's in site-packages
132-
if [[ "$PYPROPHET_LOCATION" == *"/site-packages/"* ]]; then
133-
echo "✓ PyProphet correctly installed in site-packages"
134-
else
135-
echo "✗ ERROR: PyProphet is NOT in site-packages!"
136-
echo " Location: ${PYPROPHET_LOCATION}"
137-
exit 1
138-
fi
139-
140-
# Get the site-packages location where pyprophet was installed
141-
SITE_PACKAGES=$($PYTHON -c "import pyprophet, os; print(os.path.dirname(pyprophet.__file__))")
89+
# Get the site-packages location
90+
SITE_PACKAGES=$(python -c "import pyprophet, os; print(os.path.dirname(pyprophet.__file__))")
14291
echo "PyProphet package location: ${SITE_PACKAGES}"
14392

144-
# Verify numpy is installed correctly (not from source)
145-
echo "Verifying numpy installation..."
146-
NUMPY_LOCATION=$($PYTHON -c "import numpy; print(numpy.__file__)")
93+
# Verify numpy
94+
NUMPY_LOCATION=$(python -c "import numpy; print(numpy.__file__)")
14795
echo "NumPy installed at: ${NUMPY_LOCATION}"
148-
if [[ "$NUMPY_LOCATION" == *"/site-packages/"* ]]; then
149-
echo "✓ NumPy correctly installed in site-packages"
150-
else
151-
echo "✗ WARNING: NumPy may not be in site-packages!"
152-
fi
15396

154-
$PYTHON -c "import pandas; print('✓ Pandas imports successfully')"
97+
python -c "import pandas; print('✓ Pandas imports successfully')"
15598

156-
# Collect compiled extension binaries from the installed package
99+
# Collect compiled extension binaries
157100
ADD_BINARY_ARGS=()
158101
for so in "${SITE_PACKAGES}"/pyprophet/scoring/_optimized*.so; do
159102
if [ -f "$so" ]; then
@@ -170,20 +113,14 @@ BUILD_DIR=$(mktemp -d)
170113
echo "Using temporary build directory: ${BUILD_DIR}"
171114
cd "${BUILD_DIR}"
172115

173-
# Copy only the necessary files (NOT the entire source tree)
116+
# Copy only the necessary files
174117
cp "${ORIGINAL_DIR}/packaging/pyinstaller/run_pyprophet.py" .
175118
mkdir -p hooks
176119
cp "${ORIGINAL_DIR}/packaging/pyinstaller/hooks"/*.py hooks/ 2>/dev/null || true
177120

178-
# Verify we're in a clean directory with no source pollution
179-
echo "Build directory contents:"
180-
ls -la
181-
182-
# Run PyInstaller in onefile mode
121+
# Run PyInstaller in onefile mode (still in venv)
183122
echo "Running PyInstaller (onefile mode)..."
184-
echo "Current directory: $(pwd)"
185-
186-
$PYTHON -m PyInstaller \
123+
python -m PyInstaller \
187124
--clean \
188125
--noconfirm \
189126
--onefile \
@@ -224,10 +161,10 @@ mv dist/pyprophet "${ORIGINAL_DIR}/dist/pyprophet"
224161
# Return to original directory
225162
cd "${ORIGINAL_DIR}"
226163

227-
# Clean up temporary directories
228-
rm -rf "${BUILD_DIR}" /tmp/pyprophet_wheels
229-
230-
# NOTE: UPX compression is NOT applied on Linux because it breaks PyInstaller executables
164+
# Deactivate and clean up venv
165+
deactivate
166+
rm -rf "$(dirname "$VENV_DIR")"
167+
rm -rf "${BUILD_DIR}"
231168

232169
echo "============================================"
233170
echo "Build complete! Single executable at: dist/pyprophet"

0 commit comments

Comments
 (0)