Skip to content

Commit 09d4388

Browse files
committed
Update build_binary.py
1 parent 5a0d43f commit 09d4388

File tree

1 file changed

+88
-66
lines changed

1 file changed

+88
-66
lines changed

iotdb-core/ainode/build_binary.py

Lines changed: 88 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,69 @@
2121
PyInstaller build script (Python version)
2222
"""
2323

24+
import hashlib
2425
import os
2526
import shutil
2627
import subprocess
2728
import sys
2829
from pathlib import Path
2930

3031

32+
def get_venv_base_dir():
33+
"""
34+
Get the base directory for virtual environments outside the project.
35+
36+
Returns:
37+
Path: Base directory path
38+
- Linux/macOS: ~/.cache/iotdb-ainode-build/
39+
- Windows: %LOCALAPPDATA%\\iotdb-ainode-build\\
40+
"""
41+
if sys.platform == "win32":
42+
localappdata = os.environ.get("LOCALAPPDATA") or os.environ.get("APPDATA", os.path.expanduser("~"))
43+
base_dir = Path(localappdata) / "iotdb-ainode-build"
44+
else:
45+
base_dir = Path.home() / ".cache" / "iotdb-ainode-build"
46+
47+
return base_dir
48+
49+
50+
def get_project_venv_name(project_dir):
51+
"""
52+
Generate a unique virtual environment name based on the project directory path.
53+
54+
Uses MD5 hash of the absolute path to ensure uniqueness across different
55+
project locations while keeping the name readable.
56+
57+
Returns:
58+
str: Virtual environment name in format <project-name>-<hash>
59+
"""
60+
project_path = str(project_dir.absolute())
61+
path_hash = hashlib.md5(project_path.encode()).hexdigest()[:8]
62+
project_name = project_dir.name
63+
return f"{project_name}-{path_hash}"
64+
65+
3166
def setup_venv():
32-
"""Create virtual environment if it doesn't exist"""
67+
"""
68+
Create virtual environment outside the project directory.
69+
70+
The virtual environment is created in a platform-specific location:
71+
- Linux/macOS: ~/.cache/iotdb-ainode-build/<project-name>-<hash>/
72+
- Windows: %LOCALAPPDATA%\\iotdb-ainode-build\\<project-name>-<hash>\\
73+
74+
Returns:
75+
Path: Path to the virtual environment directory
76+
"""
3377
script_dir = Path(__file__).parent
34-
venv_dir = script_dir / ".venv"
35-
78+
venv_base_dir = get_venv_base_dir()
79+
venv_name = get_project_venv_name(script_dir)
80+
venv_dir = venv_base_dir / venv_name
81+
3682
if venv_dir.exists():
3783
print(f"Virtual environment already exists at: {venv_dir}")
3884
return venv_dir
39-
85+
86+
venv_base_dir.mkdir(parents=True, exist_ok=True)
4087
print(f"Creating virtual environment at: {venv_dir}")
4188
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
4289
print("Virtual environment created successfully")
@@ -52,12 +99,7 @@ def get_venv_python(venv_dir):
5299

53100

54101
def update_pip(venv_python):
55-
"""
56-
Update pip in virtual environment.
57-
58-
Note: subprocess.run() is synchronous and blocks until the subprocess completes.
59-
This ensures pip upgrade finishes before the script continues.
60-
"""
102+
"""Update pip in the virtual environment to the latest version."""
61103
print("Updating pip...")
62104
subprocess.run(
63105
[str(venv_python), "-m", "pip", "install", "--upgrade", "pip"], check=True
@@ -66,12 +108,7 @@ def update_pip(venv_python):
66108

67109

68110
def install_poetry(venv_python):
69-
"""
70-
Install poetry 2.1.2 in virtual environment.
71-
72-
Note: subprocess.run() is synchronous and blocks until the subprocess completes.
73-
This ensures poetry installation finishes before the script continues.
74-
"""
111+
"""Install poetry 2.1.2 in the virtual environment."""
75112
print("Installing poetry 2.1.2...")
76113
subprocess.run(
77114
[
@@ -87,46 +124,39 @@ def install_poetry(venv_python):
87124

88125

89126
def get_venv_env(venv_dir):
90-
"""Get environment variables for virtual environment activation"""
127+
"""
128+
Get environment variables configured for the virtual environment.
129+
130+
Sets VIRTUAL_ENV and prepends the venv's bin/Scripts directory to PATH
131+
so that tools installed in the venv take precedence.
132+
133+
Returns:
134+
dict: Environment variables dictionary
135+
"""
91136
env = os.environ.copy()
92-
venv_path = str(venv_dir.absolute())
93-
env["VIRTUAL_ENV"] = venv_path
94-
95-
# Add venv bin directory to PATH
96-
if sys.platform == "win32":
97-
venv_bin = str(venv_dir / "Scripts")
98-
else:
99-
venv_bin = str(venv_dir / "bin")
100-
101-
# Prepend venv bin to PATH to ensure venv tools take precedence
137+
env["VIRTUAL_ENV"] = str(venv_dir.absolute())
138+
139+
venv_bin = str(venv_dir / ("Scripts" if sys.platform == "win32" else "bin"))
102140
env["PATH"] = f"{venv_bin}{os.pathsep}{env.get('PATH', '')}"
103-
141+
104142
return env
105143

106144

107145
def install_dependencies(venv_python, venv_dir, script_dir):
108146
"""
109-
Install dependencies using poetry.
110-
111-
Note: subprocess.run() is synchronous and blocks until each command completes.
112-
This ensures each step (poetry lock, install) finishes before proceeding.
113-
114-
We configure poetry to use our .venv directory by:
115-
1. Configuring poetry to use in-project virtualenvs
116-
2. Setting poetry to use our .venv via poetry env use
117-
3. Running poetry lock and install which will use our .venv
147+
Install project dependencies using poetry.
148+
149+
Configures poetry to use the external virtual environment and installs
150+
all dependencies from pyproject.toml.
118151
"""
119152
print("Installing dependencies with poetry...")
120-
121-
# Get environment with VIRTUAL_ENV set
122153
venv_env = get_venv_env(venv_dir)
123154

124-
# Configure poetry to use in-project virtualenvs
125-
# This makes poetry create/use .venv in the project directory
126-
print("Configuring poetry to use in-project virtualenvs...")
155+
# Configure poetry to use external virtual environments
156+
print("Configuring poetry to use external virtual environments...")
127157
try:
128158
subprocess.run(
129-
["poetry", "config", "virtualenvs.in-project", "true"],
159+
["poetry", "config", "virtualenvs.in-project", "false"],
130160
cwd=str(script_dir),
131161
env=venv_env,
132162
check=True,
@@ -136,32 +166,26 @@ def install_dependencies(venv_python, venv_dir, script_dir):
136166
except Exception:
137167
pass # Configuration may already be set
138168

139-
# Configure poetry to use our existing virtual environment
140-
# This links poetry's management to our .venv directory
169+
# Link poetry to the existing virtual environment
141170
print(f"Configuring poetry to use virtual environment at: {venv_dir}")
142171
result = subprocess.run(
143172
["poetry", "env", "use", str(venv_python)],
144173
cwd=str(script_dir),
145174
env=venv_env,
146-
check=False, # Don't fail if venv is already configured
175+
check=False,
147176
capture_output=True,
148177
text=True,
149178
)
150179

151-
# Check output - if poetry tries to recreate venv, that's okay as it will use our path
152180
if result.stdout:
153-
output = result.stdout.strip()
154-
print(output)
181+
print(result.stdout.strip())
155182
if result.stderr:
156183
stderr = result.stderr.strip()
157-
# Ignore warnings about venv already existing or being created
158-
if (
159-
"already been activated" not in stderr.lower()
160-
and "already in use" not in stderr.lower()
161-
):
184+
# Only print non-benign errors
185+
if "already been activated" not in stderr.lower() and "already in use" not in stderr.lower():
162186
print(stderr)
163187

164-
# Run poetry lock
188+
# Update lock file and install dependencies
165189
print("Running poetry lock...")
166190
result = subprocess.run(
167191
["poetry", "lock"],
@@ -176,8 +200,6 @@ def install_dependencies(venv_python, venv_dir, script_dir):
176200
if result.stderr:
177201
print(result.stderr)
178202

179-
# Run poetry install
180-
# With VIRTUAL_ENV set and poetry env use configured, this should install into our .venv
181203
print("Running poetry install...")
182204
result = subprocess.run(
183205
["poetry", "install"],
@@ -218,23 +240,24 @@ def check_pyinstaller(venv_python):
218240

219241

220242
def build():
221-
"""Execute build process"""
243+
"""
244+
Execute the complete build process.
245+
246+
Steps:
247+
1. Setup virtual environment (outside project directory)
248+
2. Update pip and install poetry 2.1.2
249+
3. Install project dependencies
250+
4. Build executable using PyInstaller
251+
"""
222252
script_dir = Path(__file__).parent
223253

224-
# Setup virtual environment
225254
venv_dir = setup_venv()
226255
venv_python = get_venv_python(venv_dir)
227256

228-
# Update pip
229257
update_pip(venv_python)
230-
231-
# Install poetry 2.1.2
232258
install_poetry(venv_python)
233-
234-
# Install dependencies
235259
install_dependencies(venv_python, venv_dir, script_dir)
236260

237-
# Check PyInstaller
238261
if not check_pyinstaller(venv_python):
239262
sys.exit(1)
240263

@@ -243,7 +266,6 @@ def build():
243266
print("=" * 50)
244267
print()
245268

246-
# Execute build (incremental build - no cleanup for faster rebuilds)
247269
print("Starting build...")
248270
print()
249271

0 commit comments

Comments
 (0)