devlab-fpga 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devlab-fpga
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: FPGA development helper for installing OSS CAD Suite and running build/flash flows.
5
5
  Author-email: Mrju10 <name@email.com>
6
6
  License: MIT
@@ -64,6 +64,24 @@ YosysHQ. The installer selects the correct asset for:
64
64
  The default install location is `~/.devlab`. Set `DEVLAB_HOME` to use a
65
65
  different directory.
66
66
 
67
+ On Windows, OSS CAD Suite may be distributed as a 7-Zip self-extracting `.exe`
68
+ archive. `devlab install` extracts it automatically into `~/.devlab/toolchains`
69
+ without opening an installer:
70
+
71
+ ```powershell
72
+ devlab install
73
+ ```
74
+
75
+ The installed tree keeps the official OSS CAD Suite layout:
76
+
77
+ ```text
78
+ ~/.devlab/toolchains/oss-cad-suite-2026-07-06-windows-x64/
79
+ oss-cad-suite/
80
+ bin/
81
+ environment.bat
82
+ environment.ps1
83
+ ```
84
+
67
85
  ## OSS CAD Suite Source
68
86
 
69
87
  Default release:
@@ -40,6 +40,24 @@ YosysHQ. The installer selects the correct asset for:
40
40
  The default install location is `~/.devlab`. Set `DEVLAB_HOME` to use a
41
41
  different directory.
42
42
 
43
+ On Windows, OSS CAD Suite may be distributed as a 7-Zip self-extracting `.exe`
44
+ archive. `devlab install` extracts it automatically into `~/.devlab/toolchains`
45
+ without opening an installer:
46
+
47
+ ```powershell
48
+ devlab install
49
+ ```
50
+
51
+ The installed tree keeps the official OSS CAD Suite layout:
52
+
53
+ ```text
54
+ ~/.devlab/toolchains/oss-cad-suite-2026-07-06-windows-x64/
55
+ oss-cad-suite/
56
+ bin/
57
+ environment.bat
58
+ environment.ps1
59
+ ```
60
+
43
61
  ## OSS CAD Suite Source
44
62
 
45
63
  Default release:
@@ -2,5 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.1.0"
6
-
5
+ __version__ = "0.1.2"
@@ -24,8 +24,13 @@ def build_parser() -> argparse.ArgumentParser:
24
24
  description="Install FPGA toolchains and run local FPGA build flows.",
25
25
  )
26
26
  parser.add_argument("--version", action="version", version=f"devlab {__version__}")
27
+ parser.add_argument(
28
+ "--run-installer",
29
+ action="store_true",
30
+ help="Deprecated compatibility flag. Windows install is automatic.",
31
+ )
27
32
 
28
- commands = parser.add_subparsers(dest="command", required=True)
33
+ commands = parser.add_subparsers(dest="command")
29
34
 
30
35
  doctor_parser = commands.add_parser("doctor", help="Check local FPGA tools.")
31
36
  doctor_parser.add_argument(
@@ -40,7 +45,7 @@ def build_parser() -> argparse.ArgumentParser:
40
45
  install_parser.add_argument(
41
46
  "--run-installer",
42
47
  action="store_true",
43
- help="On Windows, execute the downloaded OSS CAD Suite installer.",
48
+ help="Deprecated compatibility flag. Windows install is automatic.",
44
49
  )
45
50
  install_parser.set_defaults(func=_install)
46
51
 
@@ -105,6 +110,11 @@ def main(argv: list[str] | None = None) -> int:
105
110
  parser = build_parser()
106
111
  args = parser.parse_args(argv)
107
112
  try:
113
+ if args.command is None:
114
+ if args.run_installer:
115
+ args.force = False
116
+ return _install(args)
117
+ parser.error("the following arguments are required: command")
108
118
  return args.func(args)
109
119
  except DevlabError as exc:
110
120
  parser.exit(2, f"devlab: error: {exc}\n")
@@ -9,6 +9,7 @@ import sys
9
9
  import tarfile
10
10
  import tempfile
11
11
  import urllib.request
12
+ import zipfile
12
13
  from dataclasses import dataclass
13
14
  from pathlib import Path
14
15
 
@@ -104,13 +105,18 @@ def archive_path(asset: ToolchainAsset | None = None, home: Path | None = None)
104
105
 
105
106
  def bin_dir(path: Path | None = None) -> Path:
106
107
  path = path or install_path()
107
- return path / "bin"
108
+ return path / "oss-cad-suite" / "bin"
109
+
110
+
111
+ def bin_dirs(path: Path | None = None) -> list[Path]:
112
+ path = path or install_path()
113
+ return [path / "oss-cad-suite" / "bin", path / "bin"]
108
114
 
109
115
 
110
116
  def env_with_toolchain(path: Path | None = None) -> dict[str, str]:
111
117
  env = os.environ.copy()
112
- binary_dir = str(bin_dir(path))
113
- env["PATH"] = binary_dir + os.pathsep + env.get("PATH", "")
118
+ binary_dirs = os.pathsep.join(str(candidate) for candidate in bin_dirs(path))
119
+ env["PATH"] = binary_dirs + os.pathsep + env.get("PATH", "")
114
120
  return env
115
121
 
116
122
 
@@ -120,9 +126,9 @@ def find_executable(name: str, path: Path | None = None) -> str | None:
120
126
  suffixes = [".exe", ".bat", ".cmd", ""]
121
127
 
122
128
  candidates: list[str] = []
123
- binary_dir = bin_dir(path)
124
- for suffix in suffixes:
125
- candidates.append(str(binary_dir / f"{name}{suffix}"))
129
+ for binary_dir in bin_dirs(path):
130
+ for suffix in suffixes:
131
+ candidates.append(str(binary_dir / f"{name}{suffix}"))
126
132
 
127
133
  for candidate in candidates:
128
134
  if Path(candidate).exists():
@@ -179,45 +185,75 @@ def install_oss_cad_suite(
179
185
  asset = select_asset()
180
186
  destination = install_path(asset, home)
181
187
 
182
- if destination.exists() and not force:
188
+ if destination.exists() and find_executable("yosys", destination) and not force:
183
189
  return destination
184
190
 
185
191
  archive = download_asset(asset, archive_path(asset, home), force=force)
186
192
 
187
193
  if asset.name.endswith(".exe"):
188
- if not run_windows_installer:
194
+ _extract_windows_sfx(archive, destination, force=force)
195
+ if not find_executable("yosys", destination):
189
196
  raise DevlabError(
190
- "Windows uses the OSS CAD Suite .exe installer. "
191
- f"The file was downloaded to {archive}. Re-run with "
192
- "--run-installer to execute it."
197
+ "The Windows OSS CAD Suite archive was extracted, "
198
+ "but yosys was not found in "
199
+ f"{destination}\\oss-cad-suite\\bin or {destination}\\bin. "
200
+ "Check the extracted files, then run `devlab doctor`."
193
201
  )
194
- subprocess.check_call([str(archive)])
202
+ return destination
203
+
204
+ if asset.name.endswith(".zip"):
205
+ _extract_zip(archive, destination, force=force)
195
206
  return destination
196
207
 
197
208
  _extract_tarball(archive, destination, force=force)
198
- _mark_executables(bin_dir(destination))
209
+ for binary_dir in bin_dirs(destination):
210
+ _mark_executables(binary_dir)
199
211
  return destination
200
212
 
201
213
 
202
- def _extract_tarball(archive: Path, destination: Path, force: bool) -> None:
214
+ def _move_extracted_tree(source: Path, destination: Path, force: bool) -> None:
203
215
  destination.parent.mkdir(parents=True, exist_ok=True)
204
216
  if destination.exists():
205
- if not force:
217
+ if not force and find_executable("yosys", destination):
206
218
  raise DevlabError(f"Install destination already exists: {destination}")
207
219
  shutil.rmtree(destination)
208
220
 
221
+ destination.mkdir(parents=True)
222
+ for child in source.iterdir():
223
+ shutil.move(str(child), destination / child.name)
224
+
225
+
226
+ def _extract_windows_sfx(archive: Path, destination: Path, force: bool) -> None:
227
+ destination.parent.mkdir(parents=True, exist_ok=True)
228
+ with tempfile.TemporaryDirectory(
229
+ prefix="devlab-oss-cad-suite-", dir=destination.parent
230
+ ) as tmp:
231
+ tmp_path = Path(tmp)
232
+ try:
233
+ subprocess.check_call([str(archive), f"-o{tmp_path}", "-y"], cwd=tmp_path)
234
+ except subprocess.CalledProcessError as exc:
235
+ raise DevlabError(
236
+ f"Could not extract Windows OSS CAD Suite archive: {exc}"
237
+ ) from exc
238
+ _move_extracted_tree(tmp_path, destination, force=force)
239
+
240
+
241
+ def _extract_zip(archive: Path, destination: Path, force: bool) -> None:
242
+ with tempfile.TemporaryDirectory(prefix="devlab-oss-cad-suite-") as tmp:
243
+ tmp_path = Path(tmp)
244
+ with zipfile.ZipFile(archive) as zip_file:
245
+ _safe_extract_zip(zip_file, tmp_path)
246
+
247
+ _move_extracted_tree(tmp_path, destination, force=force)
248
+
249
+
250
+ def _extract_tarball(archive: Path, destination: Path, force: bool) -> None:
209
251
  with tempfile.TemporaryDirectory(prefix="devlab-oss-cad-suite-") as tmp:
210
252
  tmp_path = Path(tmp)
211
253
  with tarfile.open(archive, "r:gz") as tar:
212
254
  _safe_extract(tar, tmp_path)
213
255
 
214
- children = [child for child in tmp_path.iterdir()]
215
- if len(children) == 1 and children[0].is_dir():
216
- shutil.move(str(children[0]), destination)
217
- else:
218
- destination.mkdir(parents=True)
219
- for child in children:
220
- shutil.move(str(child), destination / child.name)
256
+ _move_extracted_tree(tmp_path, destination, force=force)
221
257
 
222
258
 
223
259
  def _safe_extract(tar: tarfile.TarFile, destination: Path) -> None:
@@ -232,6 +268,15 @@ def _safe_extract(tar: tarfile.TarFile, destination: Path) -> None:
232
268
  tar.extractall(destination)
233
269
 
234
270
 
271
+ def _safe_extract_zip(zip_file: zipfile.ZipFile, destination: Path) -> None:
272
+ destination = destination.resolve()
273
+ for member in zip_file.infolist():
274
+ target = (destination / member.filename).resolve()
275
+ if destination != target and destination not in target.parents:
276
+ raise DevlabError(f"Unsafe path in archive: {member.filename}")
277
+ zip_file.extractall(destination)
278
+
279
+
235
280
  def _mark_executables(path: Path) -> None:
236
281
  if not path.exists():
237
282
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devlab-fpga
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: FPGA development helper for installing OSS CAD Suite and running build/flash flows.
5
5
  Author-email: Mrju10 <name@email.com>
6
6
  License: MIT
@@ -64,6 +64,24 @@ YosysHQ. The installer selects the correct asset for:
64
64
  The default install location is `~/.devlab`. Set `DEVLAB_HOME` to use a
65
65
  different directory.
66
66
 
67
+ On Windows, OSS CAD Suite may be distributed as a 7-Zip self-extracting `.exe`
68
+ archive. `devlab install` extracts it automatically into `~/.devlab/toolchains`
69
+ without opening an installer:
70
+
71
+ ```powershell
72
+ devlab install
73
+ ```
74
+
75
+ The installed tree keeps the official OSS CAD Suite layout:
76
+
77
+ ```text
78
+ ~/.devlab/toolchains/oss-cad-suite-2026-07-06-windows-x64/
79
+ oss-cad-suite/
80
+ bin/
81
+ environment.bat
82
+ environment.ps1
83
+ ```
84
+
67
85
  ## OSS CAD Suite Source
68
86
 
69
87
  Default release:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "devlab-fpga"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "FPGA development helper for installing OSS CAD Suite and running build/flash flows."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
File without changes
File without changes
File without changes
File without changes