mlc-doxygen-bin 1.17.0__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.
- mlc_doxygen_bin-1.17.0/MANIFEST.in +7 -0
- mlc_doxygen_bin-1.17.0/PKG-INFO +110 -0
- mlc_doxygen_bin-1.17.0/README.md +93 -0
- mlc_doxygen_bin-1.17.0/pyproject.toml +69 -0
- mlc_doxygen_bin-1.17.0/scripts/cibuildwheel_run.sh +20 -0
- mlc_doxygen_bin-1.17.0/scripts/copy_wheel.py +19 -0
- mlc_doxygen_bin-1.17.0/scripts/install_manylinux_build_tools.sh +50 -0
- mlc_doxygen_bin-1.17.0/scripts/prepare_doxygen_v1_17_0.py +326 -0
- mlc_doxygen_bin-1.17.0/scripts/smoke_test_mlc_doxygen_bin.py +71 -0
- mlc_doxygen_bin-1.17.0/scripts/wheel_macos_v1_17_0.sh +131 -0
- mlc_doxygen_bin-1.17.0/scripts/wheel_manylinux_2_28_v1_17_0.sh +60 -0
- mlc_doxygen_bin-1.17.0/scripts/wheel_windows_v1_17_0.ps1 +52 -0
- mlc_doxygen_bin-1.17.0/setup.cfg +4 -0
- mlc_doxygen_bin-1.17.0/setup.py +27 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin/__init__.py +42 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin/__main__.py +7 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin/_version.py +2 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin/cli.py +11 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin/py.typed +1 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin.egg-info/PKG-INFO +110 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin.egg-info/SOURCES.txt +23 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin.egg-info/dependency_links.txt +1 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin.egg-info/entry_points.txt +2 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin.egg-info/not-zip-safe +1 -0
- mlc_doxygen_bin-1.17.0/src/mlc_doxygen_bin.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mlc-doxygen-bin
|
|
3
|
+
Version: 1.17.0
|
|
4
|
+
Summary: Prebuilt Doxygen 1.17.0 command-line executable
|
|
5
|
+
Author-email: MLC AI <mlc.ai.dev@gmail.com>
|
|
6
|
+
License-Expression: GPL-2.0-only
|
|
7
|
+
Project-URL: Doxygen, https://github.com/doxygen/doxygen
|
|
8
|
+
Project-URL: Repository, https://github.com/mlc-ai/package
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Documentation
|
|
14
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# mlc-doxygen-bin
|
|
19
|
+
|
|
20
|
+
`mlc-doxygen-bin` builds platform wheels containing the Doxygen 1.17.0 command-line
|
|
21
|
+
executable. It is intended for Python-driven build systems that want a pinned
|
|
22
|
+
Doxygen binary without relying on a system package manager.
|
|
23
|
+
|
|
24
|
+
The wheel installs a `doxygen` console script that delegates to the executable
|
|
25
|
+
stored inside the Python package.
|
|
26
|
+
|
|
27
|
+
## Build Wheels
|
|
28
|
+
|
|
29
|
+
For Doxygen 1.17.0 on macOS:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
scripts/wheel_macos_v1_17_0.sh
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For Doxygen 1.17.0 on manylinux_2_28:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
scripts/wheel_manylinux_2_28_v1_17_0.sh
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For Doxygen 1.17.0 on Windows:
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
scripts\wheel_windows_v1_17_0.ps1
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The scripts run `cibuildwheel==3.3.1` through `uv`. During CIBW's
|
|
48
|
+
`before-build` phase, `scripts/prepare_doxygen_v1_17_0.py` downloads the pinned
|
|
49
|
+
upstream source archive, verifies its SHA-256 digest, builds the CLI executable,
|
|
50
|
+
and copies the install tree into `src/mlc_doxygen_bin`.
|
|
51
|
+
|
|
52
|
+
Build artifacts are written to `wheelhouse/`.
|
|
53
|
+
|
|
54
|
+
## Platform And Architecture
|
|
55
|
+
|
|
56
|
+
The Linux and macOS scripts default to the host architecture. Override the
|
|
57
|
+
target architecture with:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
MLC_DOXYGEN_BIN_ARCH=aarch64 scripts/wheel_manylinux_2_28_v1_17_0.sh
|
|
61
|
+
MLC_DOXYGEN_BIN_ARCH=arm64 scripts/wheel_macos_v1_17_0.sh
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Supported values are:
|
|
65
|
+
|
|
66
|
+
- Linux: `x86_64`, `aarch64`
|
|
67
|
+
- macOS: `arm64`, `x86_64`
|
|
68
|
+
- Windows: `AMD64`
|
|
69
|
+
|
|
70
|
+
## Build Dependencies
|
|
71
|
+
|
|
72
|
+
The build needs CMake, Ninja, Python, Flex, Bison, and a C++ compiler. The
|
|
73
|
+
manylinux script installs Bison from the manylinux distribution and builds a
|
|
74
|
+
pinned Flex 2.6.4 into `/usr/local`, because AlmaLinux 8's Flex 2.6.1 can fail
|
|
75
|
+
while generating Doxygen's large scanners.
|
|
76
|
+
|
|
77
|
+
On macOS, use Homebrew Flex and Bison if the Apple-provided versions are too
|
|
78
|
+
old:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
brew install flex bison
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The macOS script automatically prepends Homebrew's `flex` and `bison`
|
|
85
|
+
directories to `PATH` when Homebrew is available.
|
|
86
|
+
|
|
87
|
+
On Windows, install Visual Studio Build Tools and `winflexbison3`.
|
|
88
|
+
|
|
89
|
+
## Runtime Scope
|
|
90
|
+
|
|
91
|
+
This package intentionally builds only the Doxygen CLI executable. It does not
|
|
92
|
+
bundle `doxywizard`, `doxyindexer`, `doxysearch.cgi`, libclang, Graphviz,
|
|
93
|
+
LaTeX, Ghostscript, or PlantUML. Those tools remain external runtime
|
|
94
|
+
dependencies for Doxygen features that need them.
|
|
95
|
+
|
|
96
|
+
## Usage
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
python -m pip install mlc-doxygen-bin==1.17.0
|
|
100
|
+
doxygen --version
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Programmatic path lookup is also available:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import mlc_doxygen_bin
|
|
107
|
+
|
|
108
|
+
print(mlc_doxygen_bin.get_executable_path())
|
|
109
|
+
print(mlc_doxygen_bin.metadata())
|
|
110
|
+
```
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# mlc-doxygen-bin
|
|
2
|
+
|
|
3
|
+
`mlc-doxygen-bin` builds platform wheels containing the Doxygen 1.17.0 command-line
|
|
4
|
+
executable. It is intended for Python-driven build systems that want a pinned
|
|
5
|
+
Doxygen binary without relying on a system package manager.
|
|
6
|
+
|
|
7
|
+
The wheel installs a `doxygen` console script that delegates to the executable
|
|
8
|
+
stored inside the Python package.
|
|
9
|
+
|
|
10
|
+
## Build Wheels
|
|
11
|
+
|
|
12
|
+
For Doxygen 1.17.0 on macOS:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
scripts/wheel_macos_v1_17_0.sh
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
For Doxygen 1.17.0 on manylinux_2_28:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
scripts/wheel_manylinux_2_28_v1_17_0.sh
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For Doxygen 1.17.0 on Windows:
|
|
25
|
+
|
|
26
|
+
```powershell
|
|
27
|
+
scripts\wheel_windows_v1_17_0.ps1
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The scripts run `cibuildwheel==3.3.1` through `uv`. During CIBW's
|
|
31
|
+
`before-build` phase, `scripts/prepare_doxygen_v1_17_0.py` downloads the pinned
|
|
32
|
+
upstream source archive, verifies its SHA-256 digest, builds the CLI executable,
|
|
33
|
+
and copies the install tree into `src/mlc_doxygen_bin`.
|
|
34
|
+
|
|
35
|
+
Build artifacts are written to `wheelhouse/`.
|
|
36
|
+
|
|
37
|
+
## Platform And Architecture
|
|
38
|
+
|
|
39
|
+
The Linux and macOS scripts default to the host architecture. Override the
|
|
40
|
+
target architecture with:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
MLC_DOXYGEN_BIN_ARCH=aarch64 scripts/wheel_manylinux_2_28_v1_17_0.sh
|
|
44
|
+
MLC_DOXYGEN_BIN_ARCH=arm64 scripts/wheel_macos_v1_17_0.sh
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Supported values are:
|
|
48
|
+
|
|
49
|
+
- Linux: `x86_64`, `aarch64`
|
|
50
|
+
- macOS: `arm64`, `x86_64`
|
|
51
|
+
- Windows: `AMD64`
|
|
52
|
+
|
|
53
|
+
## Build Dependencies
|
|
54
|
+
|
|
55
|
+
The build needs CMake, Ninja, Python, Flex, Bison, and a C++ compiler. The
|
|
56
|
+
manylinux script installs Bison from the manylinux distribution and builds a
|
|
57
|
+
pinned Flex 2.6.4 into `/usr/local`, because AlmaLinux 8's Flex 2.6.1 can fail
|
|
58
|
+
while generating Doxygen's large scanners.
|
|
59
|
+
|
|
60
|
+
On macOS, use Homebrew Flex and Bison if the Apple-provided versions are too
|
|
61
|
+
old:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
brew install flex bison
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The macOS script automatically prepends Homebrew's `flex` and `bison`
|
|
68
|
+
directories to `PATH` when Homebrew is available.
|
|
69
|
+
|
|
70
|
+
On Windows, install Visual Studio Build Tools and `winflexbison3`.
|
|
71
|
+
|
|
72
|
+
## Runtime Scope
|
|
73
|
+
|
|
74
|
+
This package intentionally builds only the Doxygen CLI executable. It does not
|
|
75
|
+
bundle `doxywizard`, `doxyindexer`, `doxysearch.cgi`, libclang, Graphviz,
|
|
76
|
+
LaTeX, Ghostscript, or PlantUML. Those tools remain external runtime
|
|
77
|
+
dependencies for Doxygen features that need them.
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python -m pip install mlc-doxygen-bin==1.17.0
|
|
83
|
+
doxygen --version
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Programmatic path lookup is also available:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
import mlc_doxygen_bin
|
|
90
|
+
|
|
91
|
+
print(mlc_doxygen_bin.get_executable_path())
|
|
92
|
+
print(mlc_doxygen_bin.metadata())
|
|
93
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=77",
|
|
4
|
+
"wheel>=0.43",
|
|
5
|
+
]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "mlc-doxygen-bin"
|
|
10
|
+
version = "1.17.0"
|
|
11
|
+
description = "Prebuilt Doxygen 1.17.0 command-line executable"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.8"
|
|
14
|
+
license = "GPL-2.0-only"
|
|
15
|
+
authors = [{ name = "MLC AI", email = "mlc.ai.dev@gmail.com" }]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Documentation",
|
|
22
|
+
"Topic :: Software Development :: Documentation",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Doxygen = "https://github.com/doxygen/doxygen"
|
|
27
|
+
Repository = "https://github.com/mlc-ai/package"
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
doxygen = "mlc_doxygen_bin.cli:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
package-dir = { "" = "src" }
|
|
34
|
+
include-package-data = true
|
|
35
|
+
zip-safe = false
|
|
36
|
+
|
|
37
|
+
[tool.setuptools.packages.find]
|
|
38
|
+
where = ["src"]
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.package-data]
|
|
41
|
+
mlc_doxygen_bin = [
|
|
42
|
+
"py.typed",
|
|
43
|
+
"*.json",
|
|
44
|
+
"bin/*",
|
|
45
|
+
"licenses/*",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[tool.cibuildwheel]
|
|
49
|
+
# CIBW_BUILD selects the Python used to run the build. setup.py overrides the
|
|
50
|
+
# output wheel tag to py3-none because this package exposes a native executable,
|
|
51
|
+
# not a CPython ABI extension.
|
|
52
|
+
build = "cp311-*"
|
|
53
|
+
build-frontend = "build"
|
|
54
|
+
build-verbosity = 1
|
|
55
|
+
skip = "*-musllinux_*"
|
|
56
|
+
before-build = "python -m pip install cmake ninja && python scripts/prepare_doxygen_v1_17_0.py"
|
|
57
|
+
test-command = "python {project}/scripts/smoke_test_mlc_doxygen_bin.py"
|
|
58
|
+
|
|
59
|
+
[tool.cibuildwheel.linux]
|
|
60
|
+
manylinux-x86_64-image = "manylinux_2_28"
|
|
61
|
+
manylinux-aarch64-image = "manylinux_2_28"
|
|
62
|
+
before-all = "bash scripts/install_manylinux_build_tools.sh"
|
|
63
|
+
repair-wheel-command = "python scripts/copy_wheel.py {wheel} {dest_dir}"
|
|
64
|
+
|
|
65
|
+
[tool.cibuildwheel.macos]
|
|
66
|
+
repair-wheel-command = "python scripts/copy_wheel.py {wheel} {dest_dir}"
|
|
67
|
+
|
|
68
|
+
[tool.cibuildwheel.windows]
|
|
69
|
+
repair-wheel-command = "python scripts/copy_wheel.py {wheel} {dest_dir}"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ "$#" -lt 1 || "$#" -gt 3 ]]; then
|
|
5
|
+
echo "usage: cibuildwheel_run.sh <platform> [output-dir] [package-dir]" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
platform="$1"
|
|
10
|
+
output_dir="${2:-wheelhouse}"
|
|
11
|
+
package_dir="${3:-.}"
|
|
12
|
+
|
|
13
|
+
: "${UV:=uv}"
|
|
14
|
+
if ! command -v "${UV}" >/dev/null 2>&1; then
|
|
15
|
+
echo "uv executable not found: ${UV}" >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
"${UV}" tool run --isolated --from "cibuildwheel==3.3.1" \
|
|
20
|
+
cibuildwheel --platform "${platform}" --output-dir "${output_dir}" "${package_dir}"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import shutil
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main() -> None:
|
|
10
|
+
if len(sys.argv) != 3:
|
|
11
|
+
raise SystemExit("usage: copy_wheel.py <wheel> <dest-dir>")
|
|
12
|
+
wheel = Path(sys.argv[1]).resolve()
|
|
13
|
+
dest_dir = Path(sys.argv[2]).resolve()
|
|
14
|
+
dest_dir.mkdir(parents=True, exist_ok=True)
|
|
15
|
+
shutil.copy2(wheel, dest_dir / wheel.name)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
main()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
flex_version="2.6.4"
|
|
5
|
+
flex_url="https://github.com/westes/flex/releases/download/v${flex_version}/flex-${flex_version}.tar.gz"
|
|
6
|
+
flex_sha256="e87aae032bf07c26f85ac0ed3250998c37621d95f8bd748b31f15b33c45ee995"
|
|
7
|
+
|
|
8
|
+
: "${MLC_DOXYGEN_BIN_TOOLS_PREFIX:=/usr/local}"
|
|
9
|
+
|
|
10
|
+
if command -v yum >/dev/null 2>&1; then
|
|
11
|
+
yum install -y bison m4 make gcc gcc-c++ curl tar gzip
|
|
12
|
+
elif command -v dnf >/dev/null 2>&1; then
|
|
13
|
+
dnf install -y bison m4 make gcc gcc-c++ curl tar gzip
|
|
14
|
+
else
|
|
15
|
+
echo "Neither yum nor dnf is available; cannot install manylinux build tools" >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
if [[ -x "${MLC_DOXYGEN_BIN_TOOLS_PREFIX}/bin/flex" ]]; then
|
|
20
|
+
installed_version="$("${MLC_DOXYGEN_BIN_TOOLS_PREFIX}/bin/flex" --version | sed -n '1s/.* \([0-9][0-9.]*\).*/\1/p')"
|
|
21
|
+
if [[ "${installed_version}" == "${flex_version}" ]]; then
|
|
22
|
+
"${MLC_DOXYGEN_BIN_TOOLS_PREFIX}/bin/flex" --version
|
|
23
|
+
bison --version | sed -n '1p'
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
work_dir="$(mktemp -d)"
|
|
29
|
+
cleanup() {
|
|
30
|
+
rm -rf "${work_dir}"
|
|
31
|
+
}
|
|
32
|
+
trap cleanup EXIT
|
|
33
|
+
|
|
34
|
+
cd "${work_dir}"
|
|
35
|
+
curl -fsSL --connect-timeout 10 --retry 5 -o "flex-${flex_version}.tar.gz" "${flex_url}"
|
|
36
|
+
echo "${flex_sha256} flex-${flex_version}.tar.gz" | sha256sum -c -
|
|
37
|
+
tar -xzf "flex-${flex_version}.tar.gz"
|
|
38
|
+
cd "flex-${flex_version}"
|
|
39
|
+
|
|
40
|
+
# Flex 2.6.4 detects reallocarray on manylinux_2_28, but GCC 14 builds fail
|
|
41
|
+
# unless glibc exposes its declaration. Keep the feature macro explicit instead
|
|
42
|
+
# of suppressing implicit-function-declaration diagnostics.
|
|
43
|
+
export CFLAGS="${CFLAGS:-} -D_GNU_SOURCE"
|
|
44
|
+
|
|
45
|
+
./configure --prefix="${MLC_DOXYGEN_BIN_TOOLS_PREFIX}" --disable-shared --enable-static
|
|
46
|
+
make -j"$(nproc)"
|
|
47
|
+
make install
|
|
48
|
+
|
|
49
|
+
"${MLC_DOXYGEN_BIN_TOOLS_PREFIX}/bin/flex" --version
|
|
50
|
+
bison --version | sed -n '1p'
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import hashlib
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import platform
|
|
8
|
+
import shlex
|
|
9
|
+
import shutil
|
|
10
|
+
import subprocess
|
|
11
|
+
import sys
|
|
12
|
+
import tarfile
|
|
13
|
+
import urllib.request
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
DOXYGEN_VERSION = "1.17.0"
|
|
17
|
+
DOXYGEN_TAG = "Release_1_17_0"
|
|
18
|
+
DOXYGEN_ARCHIVE_URL = (
|
|
19
|
+
"https://github.com/doxygen/doxygen/releases/download/"
|
|
20
|
+
f"{DOXYGEN_TAG}/doxygen-{DOXYGEN_VERSION}.src.tar.gz"
|
|
21
|
+
)
|
|
22
|
+
DOXYGEN_ARCHIVE_SHA256 = "fa4c3dd78785abc11ccc992bc9c01e7a8c3120fe14b8a8dfd7cefa7014530814"
|
|
23
|
+
|
|
24
|
+
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
25
|
+
DEFAULT_PACKAGE_DIR = PROJECT_ROOT / "src" / "mlc_doxygen_bin"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def run(cmd: list[str | Path], *, cwd: Path | None = None) -> None:
|
|
29
|
+
printable = " ".join(shlex.quote(str(part)) for part in cmd)
|
|
30
|
+
print(f"+ {printable}", flush=True)
|
|
31
|
+
subprocess.run([str(part) for part in cmd], cwd=cwd, check=True)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def sha256(path: Path) -> str:
|
|
35
|
+
digest = hashlib.sha256()
|
|
36
|
+
with path.open("rb") as source:
|
|
37
|
+
for chunk in iter(lambda: source.read(1024 * 1024), b""):
|
|
38
|
+
digest.update(chunk)
|
|
39
|
+
return digest.hexdigest()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def verify_archive(path: Path) -> bool:
|
|
43
|
+
if not path.is_file():
|
|
44
|
+
return False
|
|
45
|
+
actual = sha256(path)
|
|
46
|
+
if actual == DOXYGEN_ARCHIVE_SHA256:
|
|
47
|
+
return True
|
|
48
|
+
print(f"Discarding {path}: expected {DOXYGEN_ARCHIVE_SHA256}, got {actual}", flush=True)
|
|
49
|
+
path.unlink()
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def download_source_archive(work_root: Path) -> Path:
|
|
54
|
+
archive = work_root / f"doxygen-{DOXYGEN_VERSION}.src.tar.gz"
|
|
55
|
+
if verify_archive(archive):
|
|
56
|
+
return archive
|
|
57
|
+
|
|
58
|
+
tmp = archive.with_suffix(".tmp")
|
|
59
|
+
tmp.unlink(missing_ok=True)
|
|
60
|
+
print(f"Downloading Doxygen {DOXYGEN_VERSION} source from {DOXYGEN_ARCHIVE_URL}", flush=True)
|
|
61
|
+
with urllib.request.urlopen(DOXYGEN_ARCHIVE_URL, timeout=60) as response, tmp.open("wb") as dest:
|
|
62
|
+
shutil.copyfileobj(response, dest)
|
|
63
|
+
actual = sha256(tmp)
|
|
64
|
+
if actual != DOXYGEN_ARCHIVE_SHA256:
|
|
65
|
+
tmp.unlink(missing_ok=True)
|
|
66
|
+
raise RuntimeError(
|
|
67
|
+
"Doxygen source archive SHA-256 mismatch: "
|
|
68
|
+
f"expected {DOXYGEN_ARCHIVE_SHA256}, got {actual}"
|
|
69
|
+
)
|
|
70
|
+
tmp.replace(archive)
|
|
71
|
+
return archive
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def safe_extract(archive: Path, source_root: Path) -> Path:
|
|
75
|
+
source_dir = source_root / f"doxygen-{DOXYGEN_VERSION}"
|
|
76
|
+
if (source_dir / "CMakeLists.txt").is_file():
|
|
77
|
+
return source_dir
|
|
78
|
+
|
|
79
|
+
extract_dir = source_root / "_extract"
|
|
80
|
+
if extract_dir.exists():
|
|
81
|
+
shutil.rmtree(extract_dir)
|
|
82
|
+
extract_dir.mkdir(parents=True, exist_ok=True)
|
|
83
|
+
|
|
84
|
+
base = extract_dir.resolve()
|
|
85
|
+
with tarfile.open(archive, "r:gz") as tar:
|
|
86
|
+
members = tar.getmembers()
|
|
87
|
+
for member in members:
|
|
88
|
+
target = (extract_dir / member.name).resolve()
|
|
89
|
+
if target != base and base not in target.parents:
|
|
90
|
+
raise RuntimeError(f"Refusing to extract path outside destination: {member.name}")
|
|
91
|
+
extract_kwargs = {"filter": "data"} if hasattr(tarfile, "data_filter") else {}
|
|
92
|
+
tar.extractall(extract_dir, **extract_kwargs)
|
|
93
|
+
|
|
94
|
+
roots = [path for path in extract_dir.iterdir() if path.is_dir()]
|
|
95
|
+
if len(roots) != 1:
|
|
96
|
+
raise RuntimeError(f"Expected one root directory in {archive}, found {roots}")
|
|
97
|
+
|
|
98
|
+
if source_dir.exists():
|
|
99
|
+
shutil.rmtree(source_dir)
|
|
100
|
+
shutil.move(str(roots[0]), source_dir)
|
|
101
|
+
shutil.rmtree(extract_dir)
|
|
102
|
+
return source_dir
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def get_source_tree(work_root: Path) -> Path:
|
|
106
|
+
source_override = os.environ.get("MLC_DOXYGEN_BIN_SOURCE_DIR")
|
|
107
|
+
if source_override:
|
|
108
|
+
source_dir = Path(source_override).resolve()
|
|
109
|
+
if not (source_dir / "CMakeLists.txt").is_file():
|
|
110
|
+
raise RuntimeError(f"MLC_DOXYGEN_BIN_SOURCE_DIR is not a Doxygen source tree: {source_dir}")
|
|
111
|
+
return source_dir
|
|
112
|
+
|
|
113
|
+
archive = download_source_archive(work_root)
|
|
114
|
+
return safe_extract(archive, work_root / "src")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def find_program(env_name: str, candidates: tuple[str, ...]) -> str | None:
|
|
118
|
+
configured = os.environ.get(env_name)
|
|
119
|
+
if configured:
|
|
120
|
+
return configured
|
|
121
|
+
if platform.system() == "Darwin":
|
|
122
|
+
brew = shutil.which("brew")
|
|
123
|
+
if brew:
|
|
124
|
+
for candidate in candidates:
|
|
125
|
+
result = subprocess.run(
|
|
126
|
+
[brew, "--prefix", "--installed", candidate],
|
|
127
|
+
check=False,
|
|
128
|
+
text=True,
|
|
129
|
+
stdout=subprocess.PIPE,
|
|
130
|
+
stderr=subprocess.DEVNULL,
|
|
131
|
+
)
|
|
132
|
+
if result.returncode == 0:
|
|
133
|
+
path = Path(result.stdout.strip()) / "bin" / candidate
|
|
134
|
+
if path.is_file():
|
|
135
|
+
return str(path)
|
|
136
|
+
for candidate in candidates:
|
|
137
|
+
resolved = shutil.which(candidate)
|
|
138
|
+
if resolved:
|
|
139
|
+
return resolved
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def cmake_configure_command(source_dir: Path, build_dir: Path, stage_dir: Path) -> list[str | Path]:
|
|
144
|
+
build_type = os.environ.get("MLC_DOXYGEN_BIN_BUILD_TYPE", "Release")
|
|
145
|
+
cmd: list[str | Path] = [
|
|
146
|
+
"cmake",
|
|
147
|
+
"-S",
|
|
148
|
+
source_dir,
|
|
149
|
+
"-B",
|
|
150
|
+
build_dir,
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
generator = os.environ.get("MLC_DOXYGEN_BIN_CMAKE_GENERATOR")
|
|
154
|
+
if generator:
|
|
155
|
+
cmd.extend(["-G", generator])
|
|
156
|
+
elif platform.system() != "Windows" and shutil.which("ninja"):
|
|
157
|
+
cmd.extend(["-G", "Ninja"])
|
|
158
|
+
|
|
159
|
+
cmd.extend(
|
|
160
|
+
[
|
|
161
|
+
f"-DCMAKE_BUILD_TYPE={build_type}",
|
|
162
|
+
f"-DCMAKE_INSTALL_PREFIX={stage_dir}",
|
|
163
|
+
"-Dbuild_wizard=OFF",
|
|
164
|
+
"-Dbuild_app=OFF",
|
|
165
|
+
"-Dbuild_parse=OFF",
|
|
166
|
+
"-Dbuild_search=OFF",
|
|
167
|
+
"-Dbuild_doc=OFF",
|
|
168
|
+
"-Dbuild_doc_chm=OFF",
|
|
169
|
+
"-Duse_libclang=OFF",
|
|
170
|
+
"-Duse_sys_spdlog=OFF",
|
|
171
|
+
"-Duse_sys_fmt=OFF",
|
|
172
|
+
"-Duse_sys_sqlite3=OFF",
|
|
173
|
+
]
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
flex = find_program("FLEX_EXECUTABLE", ("flex", "win_flex", "win_flex.exe"))
|
|
177
|
+
if flex:
|
|
178
|
+
cmd.append(f"-DFLEX_EXECUTABLE={flex}")
|
|
179
|
+
bison = find_program("BISON_EXECUTABLE", ("bison", "win_bison", "win_bison.exe"))
|
|
180
|
+
if bison:
|
|
181
|
+
cmd.append(f"-DBISON_EXECUTABLE={bison}")
|
|
182
|
+
|
|
183
|
+
if platform.system() == "Darwin":
|
|
184
|
+
deployment_target = os.environ.get("MACOSX_DEPLOYMENT_TARGET")
|
|
185
|
+
if deployment_target:
|
|
186
|
+
cmd.append(f"-DMACOS_VERSION_MIN={deployment_target}")
|
|
187
|
+
cmd.append(f"-DCMAKE_OSX_DEPLOYMENT_TARGET={deployment_target}")
|
|
188
|
+
|
|
189
|
+
if platform.system() == "Windows":
|
|
190
|
+
cmd.append("-Dwin_static=ON")
|
|
191
|
+
|
|
192
|
+
extra_args = os.environ.get("MLC_DOXYGEN_BIN_EXTRA_CMAKE_ARGS")
|
|
193
|
+
if extra_args:
|
|
194
|
+
cmd.extend(shlex.split(extra_args))
|
|
195
|
+
|
|
196
|
+
return cmd
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def executable_name() -> str:
|
|
200
|
+
return "doxygen.exe" if platform.system() == "Windows" else "doxygen"
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def validate_stage(stage_dir: Path) -> Path:
|
|
204
|
+
executable = stage_dir / "bin" / executable_name()
|
|
205
|
+
if not executable.is_file():
|
|
206
|
+
raise RuntimeError(f"Doxygen install tree is missing executable: {executable}")
|
|
207
|
+
return executable
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def clean_package_outputs(package_dir: Path) -> None:
|
|
211
|
+
for name in ("bin", "licenses"):
|
|
212
|
+
shutil.rmtree(package_dir / name, ignore_errors=True)
|
|
213
|
+
for name in ("doxygen.json",):
|
|
214
|
+
(package_dir / name).unlink(missing_ok=True)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def copy_runtime(stage_dir: Path, package_dir: Path) -> Path:
|
|
218
|
+
source_bin = stage_dir / "bin"
|
|
219
|
+
dest_bin = package_dir / "bin"
|
|
220
|
+
shutil.copytree(source_bin, dest_bin)
|
|
221
|
+
executable = dest_bin / executable_name()
|
|
222
|
+
if platform.system() != "Windows":
|
|
223
|
+
executable.chmod(executable.stat().st_mode | 0o755)
|
|
224
|
+
return executable
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def rel(package_dir: Path, path: Path) -> str:
|
|
228
|
+
return path.relative_to(package_dir).as_posix()
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def write_version_file(package_dir: Path) -> None:
|
|
232
|
+
(package_dir / "_version.py").write_text(
|
|
233
|
+
(
|
|
234
|
+
f'__version__ = "{DOXYGEN_VERSION}"\n'
|
|
235
|
+
f'DOXYGEN_TAG = "{DOXYGEN_TAG}"\n'
|
|
236
|
+
),
|
|
237
|
+
encoding="utf-8",
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def write_license(package_dir: Path, source_dir: Path) -> str:
|
|
242
|
+
licenses_dir = package_dir / "licenses"
|
|
243
|
+
licenses_dir.mkdir(parents=True, exist_ok=True)
|
|
244
|
+
source_license = source_dir / "LICENSE"
|
|
245
|
+
dest = licenses_dir / "LICENSE-Doxygen.txt"
|
|
246
|
+
if source_license.is_file():
|
|
247
|
+
shutil.copy2(source_license, dest)
|
|
248
|
+
else:
|
|
249
|
+
dest.write_text("See https://github.com/doxygen/doxygen/blob/master/LICENSE\n", encoding="utf-8")
|
|
250
|
+
return rel(package_dir, dest)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def write_metadata(package_dir: Path, executable: Path, source_dir: Path, license_path: str) -> None:
|
|
254
|
+
metadata = {
|
|
255
|
+
"name": "doxygen",
|
|
256
|
+
"doxygen_version": DOXYGEN_VERSION,
|
|
257
|
+
"doxygen_tag": DOXYGEN_TAG,
|
|
258
|
+
"source_repository": "https://github.com/doxygen/doxygen",
|
|
259
|
+
"source_archive_url": DOXYGEN_ARCHIVE_URL,
|
|
260
|
+
"source_archive_sha256": DOXYGEN_ARCHIVE_SHA256,
|
|
261
|
+
"source_dir": str(source_dir),
|
|
262
|
+
"package_version": DOXYGEN_VERSION,
|
|
263
|
+
"executable": rel(package_dir, executable),
|
|
264
|
+
"license": license_path,
|
|
265
|
+
"features": {
|
|
266
|
+
"cli": True,
|
|
267
|
+
"doxywizard": False,
|
|
268
|
+
"search_tools": False,
|
|
269
|
+
"libclang": False,
|
|
270
|
+
},
|
|
271
|
+
"platform": platform.platform(),
|
|
272
|
+
"python": sys.version.split()[0],
|
|
273
|
+
}
|
|
274
|
+
(package_dir / "doxygen.json").write_text(
|
|
275
|
+
json.dumps(metadata, indent=2, sort_keys=True) + "\n",
|
|
276
|
+
encoding="utf-8",
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def build_and_install(source_dir: Path, work_root: Path) -> Path:
|
|
281
|
+
build_dir = work_root / "build"
|
|
282
|
+
stage_dir = work_root / "stage"
|
|
283
|
+
if build_dir.exists():
|
|
284
|
+
shutil.rmtree(build_dir)
|
|
285
|
+
if stage_dir.exists():
|
|
286
|
+
shutil.rmtree(stage_dir)
|
|
287
|
+
|
|
288
|
+
run(cmake_configure_command(source_dir, build_dir, stage_dir))
|
|
289
|
+
|
|
290
|
+
build_type = os.environ.get("MLC_DOXYGEN_BIN_BUILD_TYPE", "Release")
|
|
291
|
+
build_cmd: list[str | Path] = [
|
|
292
|
+
"cmake",
|
|
293
|
+
"--build",
|
|
294
|
+
build_dir,
|
|
295
|
+
"--config",
|
|
296
|
+
build_type,
|
|
297
|
+
"--target",
|
|
298
|
+
"install",
|
|
299
|
+
]
|
|
300
|
+
parallel = os.environ.get("CMAKE_BUILD_PARALLEL_LEVEL")
|
|
301
|
+
if parallel:
|
|
302
|
+
build_cmd.extend(["--parallel", parallel])
|
|
303
|
+
run(build_cmd)
|
|
304
|
+
validate_stage(stage_dir)
|
|
305
|
+
return stage_dir
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def main() -> None:
|
|
309
|
+
package_dir = Path(os.environ.get("MLC_DOXYGEN_BIN_PACKAGE_DIR", DEFAULT_PACKAGE_DIR)).resolve()
|
|
310
|
+
build_root = Path(
|
|
311
|
+
os.environ.get("MLC_DOXYGEN_BIN_BUILD_ROOT", PROJECT_ROOT / "build" / "doxygen-v1.17.0")
|
|
312
|
+
).resolve()
|
|
313
|
+
package_dir.mkdir(parents=True, exist_ok=True)
|
|
314
|
+
build_root.mkdir(parents=True, exist_ok=True)
|
|
315
|
+
|
|
316
|
+
source_dir = get_source_tree(build_root)
|
|
317
|
+
clean_package_outputs(package_dir)
|
|
318
|
+
stage_dir = build_and_install(source_dir, build_root)
|
|
319
|
+
executable = copy_runtime(stage_dir, package_dir)
|
|
320
|
+
license_path = write_license(package_dir, source_dir)
|
|
321
|
+
write_version_file(package_dir)
|
|
322
|
+
write_metadata(package_dir, executable, source_dir, license_path)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
if __name__ == "__main__":
|
|
326
|
+
main()
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import tempfile
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import mlc_doxygen_bin
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def run(cmd: list[str], *, cwd: Path | None = None) -> subprocess.CompletedProcess[str]:
|
|
13
|
+
print("+ " + " ".join(cmd), flush=True)
|
|
14
|
+
return subprocess.run(cmd, cwd=cwd, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def write_minimal_project(root: Path) -> Path:
|
|
18
|
+
source = root / "src"
|
|
19
|
+
output = root / "docs"
|
|
20
|
+
source.mkdir()
|
|
21
|
+
(source / "main.cpp").write_text(
|
|
22
|
+
"""
|
|
23
|
+
/// Adds two integers.
|
|
24
|
+
int add(int left, int right) {
|
|
25
|
+
return left + right;
|
|
26
|
+
}
|
|
27
|
+
""".lstrip(),
|
|
28
|
+
encoding="utf-8",
|
|
29
|
+
)
|
|
30
|
+
doxyfile = root / "Doxyfile"
|
|
31
|
+
doxyfile.write_text(
|
|
32
|
+
f"""
|
|
33
|
+
PROJECT_NAME = smoke
|
|
34
|
+
OUTPUT_DIRECTORY = {output}
|
|
35
|
+
INPUT = {source}
|
|
36
|
+
QUIET = YES
|
|
37
|
+
WARN_AS_ERROR = YES
|
|
38
|
+
GENERATE_HTML = YES
|
|
39
|
+
GENERATE_LATEX = NO
|
|
40
|
+
HAVE_DOT = NO
|
|
41
|
+
""".lstrip(),
|
|
42
|
+
encoding="utf-8",
|
|
43
|
+
)
|
|
44
|
+
return doxyfile
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def main() -> None:
|
|
48
|
+
executable = mlc_doxygen_bin.get_executable_path()
|
|
49
|
+
direct = run([executable, "--version"])
|
|
50
|
+
wrapped = run([sys.executable, "-m", "mlc_doxygen_bin", "--version"])
|
|
51
|
+
expected = mlc_doxygen_bin.__version__
|
|
52
|
+
if direct.stdout.strip() != expected:
|
|
53
|
+
raise RuntimeError(f"Expected direct Doxygen version {expected}, got {direct.stdout.strip()!r}")
|
|
54
|
+
if wrapped.stdout.strip() != expected:
|
|
55
|
+
raise RuntimeError(f"Expected wrapped Doxygen version {expected}, got {wrapped.stdout.strip()!r}")
|
|
56
|
+
|
|
57
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
58
|
+
root = Path(tmp)
|
|
59
|
+
doxyfile = write_minimal_project(root)
|
|
60
|
+
run([sys.executable, "-m", "mlc_doxygen_bin", str(doxyfile)], cwd=root)
|
|
61
|
+
index = root / "docs" / "html" / "index.html"
|
|
62
|
+
if not index.is_file():
|
|
63
|
+
raise RuntimeError(f"Doxygen did not generate expected HTML index: {index}")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
try:
|
|
68
|
+
main()
|
|
69
|
+
except Exception as err:
|
|
70
|
+
print(f"smoke test failed: {err}", file=sys.stderr)
|
|
71
|
+
raise
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
cd "${project_dir}"
|
|
6
|
+
|
|
7
|
+
if [[ "$(uname -s)" != "Darwin" ]]; then
|
|
8
|
+
echo "wheel_macos_v1_17_0.sh must run on macOS" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
detect_python_org_version() {
|
|
13
|
+
pkgutil --pkgs \
|
|
14
|
+
| sed -n 's/^org\.python\.Python\.PythonFramework-\([0-9][0-9.]*\)$/\1/p' \
|
|
15
|
+
| sort -t. -k1,1n -k2,2n \
|
|
16
|
+
| tail -n 1
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
prepend_homebrew_tool() {
|
|
20
|
+
local formula="$1"
|
|
21
|
+
if command -v brew >/dev/null 2>&1; then
|
|
22
|
+
local prefix
|
|
23
|
+
if prefix="$(brew --prefix --installed "${formula}" 2>/dev/null)" && [[ -d "${prefix}/bin" ]]; then
|
|
24
|
+
PATH="${prefix}/bin:${PATH}"
|
|
25
|
+
fi
|
|
26
|
+
fi
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
prepend_homebrew_tool flex
|
|
30
|
+
prepend_homebrew_tool bison
|
|
31
|
+
export PATH
|
|
32
|
+
|
|
33
|
+
host_arch="$(uname -m)"
|
|
34
|
+
: "${MLC_DOXYGEN_BIN_ARCH:=${host_arch}}"
|
|
35
|
+
case "${MLC_DOXYGEN_BIN_ARCH}" in
|
|
36
|
+
arm64|x86_64) ;;
|
|
37
|
+
*)
|
|
38
|
+
echo "Unsupported macOS architecture: ${MLC_DOXYGEN_BIN_ARCH}" >&2
|
|
39
|
+
exit 1
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
42
|
+
|
|
43
|
+
for tool in flex bison; do
|
|
44
|
+
if ! command -v "${tool}" >/dev/null 2>&1; then
|
|
45
|
+
echo "${tool} is required to build Doxygen. Install it with: brew install flex bison" >&2
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
done
|
|
49
|
+
flex_executable="$(command -v flex)"
|
|
50
|
+
bison_executable="$(command -v bison)"
|
|
51
|
+
|
|
52
|
+
check_tool_version() {
|
|
53
|
+
local tool="$1"
|
|
54
|
+
local executable="$2"
|
|
55
|
+
local minimum="$3"
|
|
56
|
+
local actual
|
|
57
|
+
actual="$("${executable}" --version | sed -n '1s/.* \([0-9][0-9.]*\).*/\1/p')"
|
|
58
|
+
if [[ -z "${actual}" ]]; then
|
|
59
|
+
echo "Could not determine ${tool} version" >&2
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
python3 - "${tool}" "${actual}" "${minimum}" <<'PY'
|
|
63
|
+
import re
|
|
64
|
+
import sys
|
|
65
|
+
|
|
66
|
+
tool, actual, minimum = sys.argv[1:]
|
|
67
|
+
|
|
68
|
+
def parts(version):
|
|
69
|
+
return tuple(int(part) for part in re.findall(r"\d+", version))
|
|
70
|
+
|
|
71
|
+
if parts(actual) < parts(minimum):
|
|
72
|
+
raise SystemExit(
|
|
73
|
+
f"{tool} {minimum} or newer is required to build Doxygen; found {actual}. "
|
|
74
|
+
"Install Homebrew flex and bison with: brew install flex bison"
|
|
75
|
+
)
|
|
76
|
+
PY
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
check_tool_version flex "${flex_executable}" 2.5.37
|
|
80
|
+
check_tool_version bison "${bison_executable}" 2.7
|
|
81
|
+
|
|
82
|
+
if command -v sysctl >/dev/null 2>&1; then
|
|
83
|
+
cpu_count="$(sysctl -n hw.ncpu)"
|
|
84
|
+
else
|
|
85
|
+
cpu_count="2"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
: "${MACOSX_DEPLOYMENT_TARGET:=13.0}"
|
|
89
|
+
: "${CMAKE_BUILD_PARALLEL_LEVEL:=${cpu_count}}"
|
|
90
|
+
|
|
91
|
+
platform_suffix="${MACOSX_DEPLOYMENT_TARGET//./_}_${MLC_DOXYGEN_BIN_ARCH}"
|
|
92
|
+
: "${MLC_DOXYGEN_BIN_PLAT_NAME:=macosx_${platform_suffix}}"
|
|
93
|
+
|
|
94
|
+
if [[ -z "${CIBW_BUILD:-}" ]]; then
|
|
95
|
+
python_org_version="$(detect_python_org_version)"
|
|
96
|
+
if [[ -z "${python_org_version}" ]]; then
|
|
97
|
+
cat >&2 <<'EOF'
|
|
98
|
+
No python.org CPython installation was found.
|
|
99
|
+
|
|
100
|
+
cibuildwheel on local macOS will not install CPython for you. Install one of
|
|
101
|
+
the official python.org packages, then rerun this script. The wheel produced by
|
|
102
|
+
this package is tagged py3-none, so the local build interpreter version only
|
|
103
|
+
needs to be supported by cibuildwheel.
|
|
104
|
+
EOF
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
python_tag="cp${python_org_version//./}"
|
|
108
|
+
export CIBW_BUILD="${python_tag}-macosx_${MLC_DOXYGEN_BIN_ARCH}"
|
|
109
|
+
fi
|
|
110
|
+
export CIBW_ARCHS_MACOS="${CIBW_ARCHS_MACOS:-${MLC_DOXYGEN_BIN_ARCH}}"
|
|
111
|
+
export CIBW_BUILD_VERBOSITY="${CIBW_BUILD_VERBOSITY:-1}"
|
|
112
|
+
export CIBW_ENVIRONMENT="${CIBW_ENVIRONMENT:-MLC_DOXYGEN_BIN_PLAT_NAME='${MLC_DOXYGEN_BIN_PLAT_NAME}' MACOSX_DEPLOYMENT_TARGET='${MACOSX_DEPLOYMENT_TARGET}' CMAKE_BUILD_PARALLEL_LEVEL='${CMAKE_BUILD_PARALLEL_LEVEL}' FLEX_EXECUTABLE='${flex_executable}' BISON_EXECUTABLE='${bison_executable}'}"
|
|
113
|
+
|
|
114
|
+
scripts/cibuildwheel_run.sh macos wheelhouse .
|
|
115
|
+
|
|
116
|
+
shopt -s nullglob
|
|
117
|
+
wheels=(wheelhouse/*-py3-none-"${MLC_DOXYGEN_BIN_PLAT_NAME}".whl)
|
|
118
|
+
if [[ "${#wheels[@]}" -eq 0 ]]; then
|
|
119
|
+
echo "No ${MLC_DOXYGEN_BIN_PLAT_NAME} wheels found in wheelhouse" >&2
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
for wheel in "${wheels[@]}"; do
|
|
123
|
+
filename="$(basename "${wheel}")"
|
|
124
|
+
case "${filename}" in
|
|
125
|
+
*-py3-none-*) ;;
|
|
126
|
+
*)
|
|
127
|
+
echo "Expected Python-agnostic py3-none wheel tag, got ${filename}" >&2
|
|
128
|
+
exit 1
|
|
129
|
+
;;
|
|
130
|
+
esac
|
|
131
|
+
done
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
cd "${project_dir}"
|
|
6
|
+
|
|
7
|
+
if [[ "$(uname -s)" != "Linux" ]]; then
|
|
8
|
+
echo "wheel_manylinux_2_28_v1_17_0.sh must run on Linux with Docker available" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
host_arch="$(uname -m)"
|
|
13
|
+
if [[ "${host_arch}" == "arm64" ]]; then
|
|
14
|
+
host_arch="aarch64"
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
: "${MLC_DOXYGEN_BIN_ARCH:=${host_arch}}"
|
|
18
|
+
case "${MLC_DOXYGEN_BIN_ARCH}" in
|
|
19
|
+
x86_64|aarch64) ;;
|
|
20
|
+
*)
|
|
21
|
+
echo "Unsupported manylinux architecture: ${MLC_DOXYGEN_BIN_ARCH}" >&2
|
|
22
|
+
exit 1
|
|
23
|
+
;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
26
|
+
if command -v nproc >/dev/null 2>&1; then
|
|
27
|
+
cpu_count="$(nproc)"
|
|
28
|
+
else
|
|
29
|
+
cpu_count="2"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
: "${CMAKE_BUILD_PARALLEL_LEVEL:=${cpu_count}}"
|
|
33
|
+
: "${MLC_DOXYGEN_BIN_PLAT_NAME:=manylinux_2_28_${MLC_DOXYGEN_BIN_ARCH}}"
|
|
34
|
+
: "${MLC_DOXYGEN_BIN_TOOLS_PREFIX:=/usr/local}"
|
|
35
|
+
|
|
36
|
+
export CIBW_BUILD="${CIBW_BUILD:-cp311-manylinux_${MLC_DOXYGEN_BIN_ARCH}}"
|
|
37
|
+
export CIBW_ARCHS_LINUX="${CIBW_ARCHS_LINUX:-${MLC_DOXYGEN_BIN_ARCH}}"
|
|
38
|
+
export CIBW_MANYLINUX_X86_64_IMAGE="${CIBW_MANYLINUX_X86_64_IMAGE:-manylinux_2_28}"
|
|
39
|
+
export CIBW_MANYLINUX_AARCH64_IMAGE="${CIBW_MANYLINUX_AARCH64_IMAGE:-manylinux_2_28}"
|
|
40
|
+
export CIBW_BUILD_VERBOSITY="${CIBW_BUILD_VERBOSITY:-1}"
|
|
41
|
+
export CIBW_ENVIRONMENT="${CIBW_ENVIRONMENT:-MLC_DOXYGEN_BIN_PLAT_NAME='${MLC_DOXYGEN_BIN_PLAT_NAME}' CMAKE_BUILD_PARALLEL_LEVEL='${CMAKE_BUILD_PARALLEL_LEVEL}' MLC_DOXYGEN_BIN_TOOLS_PREFIX='${MLC_DOXYGEN_BIN_TOOLS_PREFIX}' FLEX_EXECUTABLE='${MLC_DOXYGEN_BIN_TOOLS_PREFIX}/bin/flex' BISON_EXECUTABLE='/usr/bin/bison'}"
|
|
42
|
+
|
|
43
|
+
scripts/cibuildwheel_run.sh linux wheelhouse .
|
|
44
|
+
|
|
45
|
+
shopt -s nullglob
|
|
46
|
+
wheels=(wheelhouse/*-py3-none-"${MLC_DOXYGEN_BIN_PLAT_NAME}".whl)
|
|
47
|
+
if [[ "${#wheels[@]}" -eq 0 ]]; then
|
|
48
|
+
echo "No ${MLC_DOXYGEN_BIN_PLAT_NAME} wheels found in wheelhouse" >&2
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
for wheel in "${wheels[@]}"; do
|
|
52
|
+
filename="$(basename "${wheel}")"
|
|
53
|
+
case "${filename}" in
|
|
54
|
+
*-py3-none-*) ;;
|
|
55
|
+
*)
|
|
56
|
+
echo "Expected Python-agnostic py3-none wheel tag, got ${filename}" >&2
|
|
57
|
+
exit 1
|
|
58
|
+
;;
|
|
59
|
+
esac
|
|
60
|
+
done
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
$ErrorActionPreference = "Stop"
|
|
2
|
+
|
|
3
|
+
$ProjectDir = Split-Path -Parent $PSScriptRoot
|
|
4
|
+
Set-Location $ProjectDir
|
|
5
|
+
|
|
6
|
+
if (-not $env:MLC_DOXYGEN_BIN_ARCH) {
|
|
7
|
+
$env:MLC_DOXYGEN_BIN_ARCH = "AMD64"
|
|
8
|
+
}
|
|
9
|
+
if ($env:MLC_DOXYGEN_BIN_ARCH -ne "AMD64") {
|
|
10
|
+
throw "Unsupported Windows architecture: $env:MLC_DOXYGEN_BIN_ARCH"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
|
14
|
+
throw "uv executable not found"
|
|
15
|
+
}
|
|
16
|
+
if (-not (Get-Command win_flex -ErrorAction SilentlyContinue) -and -not (Get-Command flex -ErrorAction SilentlyContinue)) {
|
|
17
|
+
throw "winflexbison3 is required to build Doxygen. Install it with: choco install winflexbison3"
|
|
18
|
+
}
|
|
19
|
+
if (-not (Get-Command win_bison -ErrorAction SilentlyContinue) -and -not (Get-Command bison -ErrorAction SilentlyContinue)) {
|
|
20
|
+
throw "winflexbison3 is required to build Doxygen. Install it with: choco install winflexbison3"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (-not $env:CMAKE_BUILD_PARALLEL_LEVEL) {
|
|
24
|
+
$env:CMAKE_BUILD_PARALLEL_LEVEL = [string]$env:NUMBER_OF_PROCESSORS
|
|
25
|
+
}
|
|
26
|
+
if (-not $env:MLC_DOXYGEN_BIN_PLAT_NAME) {
|
|
27
|
+
$env:MLC_DOXYGEN_BIN_PLAT_NAME = "win_amd64"
|
|
28
|
+
}
|
|
29
|
+
if (-not $env:CIBW_BUILD) {
|
|
30
|
+
$env:CIBW_BUILD = "cp311-win_amd64"
|
|
31
|
+
}
|
|
32
|
+
if (-not $env:CIBW_ARCHS_WINDOWS) {
|
|
33
|
+
$env:CIBW_ARCHS_WINDOWS = "AMD64"
|
|
34
|
+
}
|
|
35
|
+
if (-not $env:CIBW_BUILD_VERBOSITY) {
|
|
36
|
+
$env:CIBW_BUILD_VERBOSITY = "1"
|
|
37
|
+
}
|
|
38
|
+
if (-not $env:CIBW_ENVIRONMENT) {
|
|
39
|
+
$env:CIBW_ENVIRONMENT = "MLC_DOXYGEN_BIN_PLAT_NAME='$env:MLC_DOXYGEN_BIN_PLAT_NAME' CMAKE_BUILD_PARALLEL_LEVEL='$env:CMAKE_BUILD_PARALLEL_LEVEL'"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
uv tool run --isolated --from "cibuildwheel==3.3.1" cibuildwheel --platform windows --output-dir wheelhouse .
|
|
43
|
+
|
|
44
|
+
$Wheels = Get-ChildItem -Path wheelhouse -Filter "*-py3-none-$env:MLC_DOXYGEN_BIN_PLAT_NAME.whl"
|
|
45
|
+
if ($Wheels.Count -eq 0) {
|
|
46
|
+
throw "No $env:MLC_DOXYGEN_BIN_PLAT_NAME wheels found in wheelhouse"
|
|
47
|
+
}
|
|
48
|
+
foreach ($Wheel in $Wheels) {
|
|
49
|
+
if ($Wheel.Name -notlike "*-py3-none-*") {
|
|
50
|
+
throw "Expected Python-agnostic py3-none wheel tag, got $($Wheel.Name)"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from setuptools import setup
|
|
6
|
+
from setuptools.command.bdist_wheel import bdist_wheel as _bdist_wheel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class bdist_wheel(_bdist_wheel):
|
|
10
|
+
def finalize_options(self) -> None:
|
|
11
|
+
super().finalize_options()
|
|
12
|
+
self.root_is_pure = False
|
|
13
|
+
plat_name = os.environ.get("MLC_DOXYGEN_BIN_PLAT_NAME")
|
|
14
|
+
if plat_name:
|
|
15
|
+
self.plat_name = plat_name
|
|
16
|
+
self.plat_name_supplied = True
|
|
17
|
+
|
|
18
|
+
def get_tag(self) -> tuple[str, str, str]:
|
|
19
|
+
_python, _abi, plat = super().get_tag()
|
|
20
|
+
return "py3", "none", plat
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
setup(
|
|
24
|
+
cmdclass={
|
|
25
|
+
"bdist_wheel": bdist_wheel,
|
|
26
|
+
},
|
|
27
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import platform
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from ._version import DOXYGEN_TAG, __version__
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"__version__",
|
|
12
|
+
"DOXYGEN_TAG",
|
|
13
|
+
"get_bin_dir",
|
|
14
|
+
"get_executable_path",
|
|
15
|
+
"metadata",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _package_dir() -> Path:
|
|
20
|
+
return Path(__file__).resolve().parent
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_bin_dir() -> str:
|
|
24
|
+
path = _package_dir() / "bin"
|
|
25
|
+
if not path.is_dir():
|
|
26
|
+
raise FileNotFoundError(f"Doxygen bin directory is missing: {path}")
|
|
27
|
+
return str(path)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_executable_path() -> str:
|
|
31
|
+
name = "doxygen.exe" if platform.system() == "Windows" else "doxygen"
|
|
32
|
+
path = Path(get_bin_dir()) / name
|
|
33
|
+
if not path.is_file():
|
|
34
|
+
raise FileNotFoundError(f"Doxygen executable is missing: {path}")
|
|
35
|
+
return str(path)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def metadata() -> dict[str, Any]:
|
|
39
|
+
path = _package_dir() / "doxygen.json"
|
|
40
|
+
if not path.is_file():
|
|
41
|
+
return {}
|
|
42
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mlc-doxygen-bin
|
|
3
|
+
Version: 1.17.0
|
|
4
|
+
Summary: Prebuilt Doxygen 1.17.0 command-line executable
|
|
5
|
+
Author-email: MLC AI <mlc.ai.dev@gmail.com>
|
|
6
|
+
License-Expression: GPL-2.0-only
|
|
7
|
+
Project-URL: Doxygen, https://github.com/doxygen/doxygen
|
|
8
|
+
Project-URL: Repository, https://github.com/mlc-ai/package
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Documentation
|
|
14
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# mlc-doxygen-bin
|
|
19
|
+
|
|
20
|
+
`mlc-doxygen-bin` builds platform wheels containing the Doxygen 1.17.0 command-line
|
|
21
|
+
executable. It is intended for Python-driven build systems that want a pinned
|
|
22
|
+
Doxygen binary without relying on a system package manager.
|
|
23
|
+
|
|
24
|
+
The wheel installs a `doxygen` console script that delegates to the executable
|
|
25
|
+
stored inside the Python package.
|
|
26
|
+
|
|
27
|
+
## Build Wheels
|
|
28
|
+
|
|
29
|
+
For Doxygen 1.17.0 on macOS:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
scripts/wheel_macos_v1_17_0.sh
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For Doxygen 1.17.0 on manylinux_2_28:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
scripts/wheel_manylinux_2_28_v1_17_0.sh
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For Doxygen 1.17.0 on Windows:
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
scripts\wheel_windows_v1_17_0.ps1
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The scripts run `cibuildwheel==3.3.1` through `uv`. During CIBW's
|
|
48
|
+
`before-build` phase, `scripts/prepare_doxygen_v1_17_0.py` downloads the pinned
|
|
49
|
+
upstream source archive, verifies its SHA-256 digest, builds the CLI executable,
|
|
50
|
+
and copies the install tree into `src/mlc_doxygen_bin`.
|
|
51
|
+
|
|
52
|
+
Build artifacts are written to `wheelhouse/`.
|
|
53
|
+
|
|
54
|
+
## Platform And Architecture
|
|
55
|
+
|
|
56
|
+
The Linux and macOS scripts default to the host architecture. Override the
|
|
57
|
+
target architecture with:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
MLC_DOXYGEN_BIN_ARCH=aarch64 scripts/wheel_manylinux_2_28_v1_17_0.sh
|
|
61
|
+
MLC_DOXYGEN_BIN_ARCH=arm64 scripts/wheel_macos_v1_17_0.sh
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Supported values are:
|
|
65
|
+
|
|
66
|
+
- Linux: `x86_64`, `aarch64`
|
|
67
|
+
- macOS: `arm64`, `x86_64`
|
|
68
|
+
- Windows: `AMD64`
|
|
69
|
+
|
|
70
|
+
## Build Dependencies
|
|
71
|
+
|
|
72
|
+
The build needs CMake, Ninja, Python, Flex, Bison, and a C++ compiler. The
|
|
73
|
+
manylinux script installs Bison from the manylinux distribution and builds a
|
|
74
|
+
pinned Flex 2.6.4 into `/usr/local`, because AlmaLinux 8's Flex 2.6.1 can fail
|
|
75
|
+
while generating Doxygen's large scanners.
|
|
76
|
+
|
|
77
|
+
On macOS, use Homebrew Flex and Bison if the Apple-provided versions are too
|
|
78
|
+
old:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
brew install flex bison
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The macOS script automatically prepends Homebrew's `flex` and `bison`
|
|
85
|
+
directories to `PATH` when Homebrew is available.
|
|
86
|
+
|
|
87
|
+
On Windows, install Visual Studio Build Tools and `winflexbison3`.
|
|
88
|
+
|
|
89
|
+
## Runtime Scope
|
|
90
|
+
|
|
91
|
+
This package intentionally builds only the Doxygen CLI executable. It does not
|
|
92
|
+
bundle `doxywizard`, `doxyindexer`, `doxysearch.cgi`, libclang, Graphviz,
|
|
93
|
+
LaTeX, Ghostscript, or PlantUML. Those tools remain external runtime
|
|
94
|
+
dependencies for Doxygen features that need them.
|
|
95
|
+
|
|
96
|
+
## Usage
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
python -m pip install mlc-doxygen-bin==1.17.0
|
|
100
|
+
doxygen --version
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Programmatic path lookup is also available:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import mlc_doxygen_bin
|
|
107
|
+
|
|
108
|
+
print(mlc_doxygen_bin.get_executable_path())
|
|
109
|
+
print(mlc_doxygen_bin.metadata())
|
|
110
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
scripts/cibuildwheel_run.sh
|
|
6
|
+
scripts/copy_wheel.py
|
|
7
|
+
scripts/install_manylinux_build_tools.sh
|
|
8
|
+
scripts/prepare_doxygen_v1_17_0.py
|
|
9
|
+
scripts/smoke_test_mlc_doxygen_bin.py
|
|
10
|
+
scripts/wheel_macos_v1_17_0.sh
|
|
11
|
+
scripts/wheel_manylinux_2_28_v1_17_0.sh
|
|
12
|
+
scripts/wheel_windows_v1_17_0.ps1
|
|
13
|
+
src/mlc_doxygen_bin/__init__.py
|
|
14
|
+
src/mlc_doxygen_bin/__main__.py
|
|
15
|
+
src/mlc_doxygen_bin/_version.py
|
|
16
|
+
src/mlc_doxygen_bin/cli.py
|
|
17
|
+
src/mlc_doxygen_bin/py.typed
|
|
18
|
+
src/mlc_doxygen_bin.egg-info/PKG-INFO
|
|
19
|
+
src/mlc_doxygen_bin.egg-info/SOURCES.txt
|
|
20
|
+
src/mlc_doxygen_bin.egg-info/dependency_links.txt
|
|
21
|
+
src/mlc_doxygen_bin.egg-info/entry_points.txt
|
|
22
|
+
src/mlc_doxygen_bin.egg-info/not-zip-safe
|
|
23
|
+
src/mlc_doxygen_bin.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mlc_doxygen_bin
|