codeanalyzer-java 2.3.7__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.
- codeanalyzer_java-2.3.7/.gitignore +11 -0
- codeanalyzer_java-2.3.7/PKG-INFO +85 -0
- codeanalyzer_java-2.3.7/README.md +66 -0
- codeanalyzer_java-2.3.7/codeanalyzer_java/__init__.py +15 -0
- codeanalyzer_java-2.3.7/codeanalyzer_java/__main__.py +86 -0
- codeanalyzer_java-2.3.7/hatch_build.py +167 -0
- codeanalyzer_java-2.3.7/pyproject.toml +56 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codeanalyzer-java
|
|
3
|
+
Version: 2.3.7
|
|
4
|
+
Summary: Static analysis for Java, shipped as a self-contained native binary (no JVM required).
|
|
5
|
+
Project-URL: Homepage, https://github.com/codellm-devkit/codeanalyzer-java
|
|
6
|
+
Project-URL: Issues, https://github.com/codellm-devkit/codeanalyzer-java/issues
|
|
7
|
+
Project-URL: Source, https://github.com/codellm-devkit/codeanalyzer-java
|
|
8
|
+
Author-email: Rahul Krishna <i.m.ralk@gmail.com>
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
Keywords: call-graph,codeanalyzer,java,javaparser,static-analysis,wala
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Java
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
Native WALA implementation of source code analysis tool for Enterprise Java Applications.
|
|
23
|
+
|
|
24
|
+
## 1. Installing `codeanalyzer`
|
|
25
|
+
|
|
26
|
+
`codeanalyzer` ships as a self-contained, JVM-free native binary. No JDK, no
|
|
27
|
+
GraalVM, and no build step are required — just install from PyPI:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install codeanalyzer-java
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This installs the `codajv` command, which runs the bundled native binary
|
|
34
|
+
(`pip install` automatically selects the wheel matching your OS/architecture).
|
|
35
|
+
|
|
36
|
+
## 2. Using `codeanalyzer`
|
|
37
|
+
|
|
38
|
+
```help
|
|
39
|
+
Usage: codajv [-hvV] [--no-build] [-a=<analysisLevel>] [-b=<build>]
|
|
40
|
+
[-i=<input>] [-o=<output>] [-s=<sourceAnalysis>]
|
|
41
|
+
Convert java binary into a comprehensive system dependency graph.
|
|
42
|
+
-i, --input=<input> Path to the project root directory.
|
|
43
|
+
-s, --source-analysis=<sourceAnalysis>
|
|
44
|
+
Analyze a single string of java source code instead
|
|
45
|
+
the project.
|
|
46
|
+
-o, --output=<output> Destination directory to save the output graphs. By
|
|
47
|
+
default, the SDG formatted as a JSON will be
|
|
48
|
+
printed to the console.
|
|
49
|
+
-b, --build-cmd=<build> Custom build command. Defaults to auto build.
|
|
50
|
+
--no-build Do not build your application. Use this option if
|
|
51
|
+
you have already built your application.
|
|
52
|
+
-a, --analysis-level=<analysisLevel>
|
|
53
|
+
Level of analysis to perform. Options: 1 (for just
|
|
54
|
+
symbol table) or 2 (for call graph). Default: 1
|
|
55
|
+
-v, --verbose Print logs to console.
|
|
56
|
+
-h, --help Show this help message and exit.
|
|
57
|
+
-V, --version Print version information and exit.
|
|
58
|
+
-t, --target-files For each file user wants to perform source analysis on top of existing analysis.json
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
For example, to analyze a project and print the system dependency graph to the
|
|
63
|
+
console:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
codajv -i /path/to/java/project
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Pass `-o <dir>` to save the output as JSON. Explore the other flags above to
|
|
70
|
+
control the analysis level and build behavior.
|
|
71
|
+
|
|
72
|
+
## LICENSE
|
|
73
|
+
|
|
74
|
+
```LICENSE
|
|
75
|
+
Copyright IBM Corporation 2023, 2024
|
|
76
|
+
|
|
77
|
+
Licensed under the Apache Public License 2.0, Version 2.0 (the "License");
|
|
78
|
+
you may not use this file except in compliance with the License.
|
|
79
|
+
|
|
80
|
+
Unless required by applicable law or agreed to in writing, software
|
|
81
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
82
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
83
|
+
See the License for the specific language governing permissions and
|
|
84
|
+
limitations under the License.
|
|
85
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
Native WALA implementation of source code analysis tool for Enterprise Java Applications.
|
|
4
|
+
|
|
5
|
+
## 1. Installing `codeanalyzer`
|
|
6
|
+
|
|
7
|
+
`codeanalyzer` ships as a self-contained, JVM-free native binary. No JDK, no
|
|
8
|
+
GraalVM, and no build step are required — just install from PyPI:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install codeanalyzer-java
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This installs the `codajv` command, which runs the bundled native binary
|
|
15
|
+
(`pip install` automatically selects the wheel matching your OS/architecture).
|
|
16
|
+
|
|
17
|
+
## 2. Using `codeanalyzer`
|
|
18
|
+
|
|
19
|
+
```help
|
|
20
|
+
Usage: codajv [-hvV] [--no-build] [-a=<analysisLevel>] [-b=<build>]
|
|
21
|
+
[-i=<input>] [-o=<output>] [-s=<sourceAnalysis>]
|
|
22
|
+
Convert java binary into a comprehensive system dependency graph.
|
|
23
|
+
-i, --input=<input> Path to the project root directory.
|
|
24
|
+
-s, --source-analysis=<sourceAnalysis>
|
|
25
|
+
Analyze a single string of java source code instead
|
|
26
|
+
the project.
|
|
27
|
+
-o, --output=<output> Destination directory to save the output graphs. By
|
|
28
|
+
default, the SDG formatted as a JSON will be
|
|
29
|
+
printed to the console.
|
|
30
|
+
-b, --build-cmd=<build> Custom build command. Defaults to auto build.
|
|
31
|
+
--no-build Do not build your application. Use this option if
|
|
32
|
+
you have already built your application.
|
|
33
|
+
-a, --analysis-level=<analysisLevel>
|
|
34
|
+
Level of analysis to perform. Options: 1 (for just
|
|
35
|
+
symbol table) or 2 (for call graph). Default: 1
|
|
36
|
+
-v, --verbose Print logs to console.
|
|
37
|
+
-h, --help Show this help message and exit.
|
|
38
|
+
-V, --version Print version information and exit.
|
|
39
|
+
-t, --target-files For each file user wants to perform source analysis on top of existing analysis.json
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
For example, to analyze a project and print the system dependency graph to the
|
|
44
|
+
console:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
codajv -i /path/to/java/project
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Pass `-o <dir>` to save the output as JSON. Explore the other flags above to
|
|
51
|
+
control the analysis level and build behavior.
|
|
52
|
+
|
|
53
|
+
## LICENSE
|
|
54
|
+
|
|
55
|
+
```LICENSE
|
|
56
|
+
Copyright IBM Corporation 2023, 2024
|
|
57
|
+
|
|
58
|
+
Licensed under the Apache Public License 2.0, Version 2.0 (the "License");
|
|
59
|
+
you may not use this file except in compliance with the License.
|
|
60
|
+
|
|
61
|
+
Unless required by applicable law or agreed to in writing, software
|
|
62
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
63
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
64
|
+
See the License for the specific language governing permissions and
|
|
65
|
+
limitations under the License.
|
|
66
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Python wrapper that ships and runs the codeanalyzer native binary."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
__version__ = version("codeanalyzer-java")
|
|
10
|
+
except PackageNotFoundError: # running from a source checkout
|
|
11
|
+
__version__ = "0.0.0"
|
|
12
|
+
except Exception: # pragma: no cover - importlib.metadata always present on 3.9+
|
|
13
|
+
__version__ = "0.0.0"
|
|
14
|
+
|
|
15
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Console entry point (``codajv``) for the bundled codeanalyzer native binary.
|
|
2
|
+
|
|
3
|
+
The wheel ships a prebuilt, JVM-free GraalVM native image together with the JDK
|
|
4
|
+
``.jmod`` files it needs at runtime: both WALA's primordial scope (analysis
|
|
5
|
+
level 2) and the JavaParser bytecode symbol solver read the jmods straight off
|
|
6
|
+
disk, so they cannot be baked into the image. This module locates those bundled
|
|
7
|
+
assets, points ``CODEANALYZER_JMODS_DIR`` at the bundled jmods, and hands off to
|
|
8
|
+
the native binary.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
_PKG_DIR = Path(__file__).resolve().parent
|
|
18
|
+
_VENDOR = _PKG_DIR / "_vendor"
|
|
19
|
+
# pypi/codeanalyzer_java/ -> pypi/ -> repo root (dev/source-checkout fallback).
|
|
20
|
+
_REPO_ROOT = _PKG_DIR.parent.parent
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _find_binary() -> Path | None:
|
|
24
|
+
candidates: list[Path] = []
|
|
25
|
+
override = os.environ.get("CODEANALYZER_NATIVE_BINARY")
|
|
26
|
+
if override:
|
|
27
|
+
candidates.append(Path(override))
|
|
28
|
+
candidates += [
|
|
29
|
+
_VENDOR / "bin" / "codeanalyzer",
|
|
30
|
+
_VENDOR / "bin" / "codeanalyzer.exe",
|
|
31
|
+
_REPO_ROOT / "build" / "native" / "nativeCompile" / "codeanalyzer",
|
|
32
|
+
_REPO_ROOT / "build" / "native" / "nativeCompile" / "codeanalyzer.exe",
|
|
33
|
+
]
|
|
34
|
+
return next((c for c in candidates if c.is_file()), None)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _find_jmods() -> Path | None:
|
|
38
|
+
bundled = _VENDOR / "jmods"
|
|
39
|
+
if bundled.is_dir() and any(bundled.glob("*.jmod")):
|
|
40
|
+
return bundled
|
|
41
|
+
override = os.environ.get("CODEANALYZER_JMODS_DIR")
|
|
42
|
+
if override and Path(override).is_dir():
|
|
43
|
+
return Path(override)
|
|
44
|
+
java_home = os.environ.get("JAVA_HOME")
|
|
45
|
+
if java_home:
|
|
46
|
+
jmods = Path(java_home) / "jmods"
|
|
47
|
+
if jmods.is_dir():
|
|
48
|
+
return jmods
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def main() -> int:
|
|
53
|
+
binary = _find_binary()
|
|
54
|
+
if binary is None:
|
|
55
|
+
sys.stderr.write(
|
|
56
|
+
"codajv: could not find a codeanalyzer native binary.\n"
|
|
57
|
+
"This usually means the installed wheel does not match your "
|
|
58
|
+
"platform/architecture, or you are running from a source checkout "
|
|
59
|
+
"without a built binary (run `./gradlew nativeCompile`).\n"
|
|
60
|
+
)
|
|
61
|
+
return 1
|
|
62
|
+
|
|
63
|
+
env = dict(os.environ)
|
|
64
|
+
jmods = _find_jmods()
|
|
65
|
+
if jmods is not None:
|
|
66
|
+
env["CODEANALYZER_JMODS_DIR"] = str(jmods)
|
|
67
|
+
|
|
68
|
+
# Wheel installation does not reliably preserve the executable bit.
|
|
69
|
+
try:
|
|
70
|
+
os.chmod(binary, binary.stat().st_mode | 0o111)
|
|
71
|
+
except OSError:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
argv = [str(binary), *sys.argv[1:]]
|
|
75
|
+
if os.name == "posix":
|
|
76
|
+
# Replace this process so signals and the exit code pass through cleanly.
|
|
77
|
+
os.execve(str(binary), argv, env)
|
|
78
|
+
return 127 # unreachable when execve succeeds
|
|
79
|
+
|
|
80
|
+
import subprocess
|
|
81
|
+
|
|
82
|
+
return subprocess.run(argv, env=env).returncode
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Local hatchling plugins for the codeanalyzer-java wheel.
|
|
2
|
+
|
|
3
|
+
Two concerns live here:
|
|
4
|
+
|
|
5
|
+
1. **Version lockstep.** The wheel version is read from the Java project's
|
|
6
|
+
``gradle.properties`` so the Python package and the native binary it ships
|
|
7
|
+
can never drift apart.
|
|
8
|
+
|
|
9
|
+
2. **Impure, platform-tagged wheels.** The wheel carries a prebuilt native
|
|
10
|
+
binary plus the JDK ``.jmod`` files it needs at runtime. The build hook
|
|
11
|
+
force-includes those assets, marks the wheel non-purelib, and stamps a
|
|
12
|
+
concrete ``py3-none-<platform>`` tag so pip resolves the correct artifact
|
|
13
|
+
per OS/arch instead of a universal ``py3-none-any`` wheel.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import sysconfig
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
23
|
+
from hatchling.metadata.plugin.interface import MetadataHookInterface
|
|
24
|
+
|
|
25
|
+
_BINARY_NAMES = ("codeanalyzer", "codeanalyzer.exe")
|
|
26
|
+
|
|
27
|
+
# Bundling every JDK jmod (~104 MB) pushes the wheel over PyPI's default 100 MB
|
|
28
|
+
# per-file limit, and the native binary does not compress further (~23.5 MB),
|
|
29
|
+
# leaving room for ~80 MB of jmods. We therefore drop only the largest modules
|
|
30
|
+
# that static type resolution never needs, keeping 79 of 83 (~90 MB wheel):
|
|
31
|
+
# - jdk.localedata locale resource *data*, not API types
|
|
32
|
+
# - jdk.compiler com.sun.tools.javac.* internals (annotation-
|
|
33
|
+
# processor sources are the only mild compromise)
|
|
34
|
+
# - jdk.internal.vm.compiler Graal compiler internals, never referenced
|
|
35
|
+
# - jdk.hotspot.agent Serviceability Agent internals, never referenced
|
|
36
|
+
# Set CODEANALYZER_BUNDLE_ALL_JMODS=1 to bundle all 83 (needs a PyPI size bump).
|
|
37
|
+
_EXCLUDED_JMODS = frozenset(
|
|
38
|
+
{
|
|
39
|
+
"jdk.localedata.jmod",
|
|
40
|
+
"jdk.compiler.jmod",
|
|
41
|
+
"jdk.internal.vm.compiler.jmod",
|
|
42
|
+
"jdk.hotspot.agent.jmod",
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _bundle_all_jmods() -> bool:
|
|
48
|
+
return os.environ.get("CODEANALYZER_BUNDLE_ALL_JMODS", "").lower() in {"1", "true", "yes"}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _select_jmods(jmod_files: list[Path]) -> list[Path]:
|
|
52
|
+
if _bundle_all_jmods():
|
|
53
|
+
return jmod_files
|
|
54
|
+
return [jmod for jmod in jmod_files if jmod.name not in _EXCLUDED_JMODS]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def read_gradle_version(repo_root: Path) -> str:
|
|
58
|
+
"""Return the ``version=`` value from ``<repo_root>/gradle.properties``."""
|
|
59
|
+
gradle_properties = repo_root / "gradle.properties"
|
|
60
|
+
for line in gradle_properties.read_text(encoding="utf-8").splitlines():
|
|
61
|
+
line = line.strip()
|
|
62
|
+
if line.startswith("version="):
|
|
63
|
+
return line.split("=", 1)[1].strip()
|
|
64
|
+
raise RuntimeError(f"no 'version=' entry found in {gradle_properties}")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _wheel_platform_tag() -> str:
|
|
68
|
+
"""Concrete wheel tag for the current platform, e.g. ``py3-none-linux_x86_64``.
|
|
69
|
+
|
|
70
|
+
CI sets ``CODEANALYZER_WHEEL_PLATFORM`` to stamp the exact target tag per
|
|
71
|
+
build leg (e.g. ``manylinux_2_28_x86_64``, ``musllinux_1_2_aarch64``,
|
|
72
|
+
``macosx_11_0_arm64``, ``win_amd64``). The Linux legs build inside the
|
|
73
|
+
matching manylinux container (or a static musl binary), so the tag is
|
|
74
|
+
correct by construction and no ``auditwheel repair`` pass is needed. When
|
|
75
|
+
the override is unset, the tag falls back to the build host's platform.
|
|
76
|
+
"""
|
|
77
|
+
override = os.environ.get("CODEANALYZER_WHEEL_PLATFORM")
|
|
78
|
+
if override:
|
|
79
|
+
platform = override
|
|
80
|
+
else:
|
|
81
|
+
platform = sysconfig.get_platform()
|
|
82
|
+
platform = platform.replace("-", "_").replace(".", "_")
|
|
83
|
+
return f"py3-none-{platform}"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _resolve_binary(repo_root: Path) -> Path:
|
|
87
|
+
override = os.environ.get("CODEANALYZER_NATIVE_BINARY")
|
|
88
|
+
if override:
|
|
89
|
+
candidate = Path(override)
|
|
90
|
+
if candidate.is_file():
|
|
91
|
+
return candidate
|
|
92
|
+
raise RuntimeError(
|
|
93
|
+
f"CODEANALYZER_NATIVE_BINARY is set to '{override}' but no file exists there."
|
|
94
|
+
)
|
|
95
|
+
native_dir = repo_root / "build" / "native" / "nativeCompile"
|
|
96
|
+
for name in _BINARY_NAMES:
|
|
97
|
+
candidate = native_dir / name
|
|
98
|
+
if candidate.is_file():
|
|
99
|
+
return candidate
|
|
100
|
+
raise RuntimeError(
|
|
101
|
+
"no prebuilt codeanalyzer native binary found for this platform/arch.\n"
|
|
102
|
+
f"Looked for {_BINARY_NAMES} under {native_dir}.\n"
|
|
103
|
+
"Build it first with `./gradlew nativeCompile`, or point "
|
|
104
|
+
"CODEANALYZER_NATIVE_BINARY at an existing binary. "
|
|
105
|
+
"codeanalyzer-java ships only prebuilt wheels; there is no from-source "
|
|
106
|
+
"build path for unsupported platforms."
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _resolve_jmods() -> Path:
|
|
111
|
+
override = os.environ.get("CODEANALYZER_JMODS_DIR")
|
|
112
|
+
if override:
|
|
113
|
+
candidate = Path(override)
|
|
114
|
+
if candidate.is_dir():
|
|
115
|
+
return candidate
|
|
116
|
+
raise RuntimeError(
|
|
117
|
+
f"CODEANALYZER_JMODS_DIR is set to '{override}' but it is not a directory."
|
|
118
|
+
)
|
|
119
|
+
java_home = os.environ.get("JAVA_HOME")
|
|
120
|
+
if java_home:
|
|
121
|
+
candidate = Path(java_home) / "jmods"
|
|
122
|
+
if candidate.is_dir():
|
|
123
|
+
return candidate
|
|
124
|
+
raise RuntimeError(
|
|
125
|
+
"could not locate JDK .jmod files to bundle. Set CODEANALYZER_JMODS_DIR "
|
|
126
|
+
"to a directory of .jmod files, or JAVA_HOME to a JDK that has a jmods/ "
|
|
127
|
+
"directory (a JDK 9+ image, not a JRE)."
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class CustomMetadataHook(MetadataHookInterface):
|
|
132
|
+
"""Inject the version read from gradle.properties."""
|
|
133
|
+
|
|
134
|
+
def update(self, metadata: dict) -> None:
|
|
135
|
+
metadata["version"] = read_gradle_version(Path(self.root).parent)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class CustomBuildHook(BuildHookInterface):
|
|
139
|
+
"""Bundle the native binary + jmods and force an impure platform wheel."""
|
|
140
|
+
|
|
141
|
+
def initialize(self, version: str, build_data: dict) -> None:
|
|
142
|
+
if self.target_name != "wheel":
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
repo_root = Path(self.root).parent
|
|
146
|
+
binary = _resolve_binary(repo_root)
|
|
147
|
+
jmods_dir = _resolve_jmods()
|
|
148
|
+
jmod_files = sorted(jmods_dir.glob("*.jmod"))
|
|
149
|
+
if not jmod_files:
|
|
150
|
+
raise RuntimeError(f"no .jmod files found in {jmods_dir}")
|
|
151
|
+
selected = _select_jmods(jmod_files)
|
|
152
|
+
if not selected:
|
|
153
|
+
raise RuntimeError(f"jmod selection is empty (from {jmods_dir})")
|
|
154
|
+
|
|
155
|
+
force_include = build_data["force_include"]
|
|
156
|
+
force_include[str(binary)] = f"codeanalyzer_java/_vendor/bin/{binary.name}"
|
|
157
|
+
for jmod in selected:
|
|
158
|
+
force_include[str(jmod)] = f"codeanalyzer_java/_vendor/jmods/{jmod.name}"
|
|
159
|
+
|
|
160
|
+
build_data["pure_python"] = False
|
|
161
|
+
build_data["infer_tag"] = False
|
|
162
|
+
build_data["tag"] = _wheel_platform_tag()
|
|
163
|
+
|
|
164
|
+
self.app.display_info(
|
|
165
|
+
f"codeanalyzer-java: bundling {binary.name} + {len(selected)}/"
|
|
166
|
+
f"{len(jmod_files)} jmods as {build_data['tag']}"
|
|
167
|
+
)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "codeanalyzer-java"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Static analysis for Java, shipped as a self-contained native binary (no JVM required)."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
authors = [{ name = "Rahul Krishna", email = "i.m.ralk@gmail.com" }]
|
|
13
|
+
keywords = ["java", "static-analysis", "wala", "javaparser", "call-graph", "codeanalyzer"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Programming Language :: Java",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Software Development :: Libraries",
|
|
20
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://github.com/codellm-devkit/codeanalyzer-java"
|
|
25
|
+
Issues = "https://github.com/codellm-devkit/codeanalyzer-java/issues"
|
|
26
|
+
Source = "https://github.com/codellm-devkit/codeanalyzer-java"
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
codajv = "codeanalyzer_java.__main__:main"
|
|
30
|
+
|
|
31
|
+
# Version is read from ../gradle.properties by CustomMetadataHook so the wheel
|
|
32
|
+
# stays in lockstep with the native binary.
|
|
33
|
+
[tool.hatch.metadata.hooks.custom]
|
|
34
|
+
path = "hatch_build.py"
|
|
35
|
+
|
|
36
|
+
# Bundles the native binary + jmods and forces an impure, platform-tagged wheel.
|
|
37
|
+
[tool.hatch.build.targets.wheel.hooks.custom]
|
|
38
|
+
path = "hatch_build.py"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["codeanalyzer_java"]
|
|
42
|
+
# The native binary and jmods are injected at build time via force_include in
|
|
43
|
+
# hatch_build.py; nothing under _vendor/ is tracked in source control.
|
|
44
|
+
exclude = ["codeanalyzer_java/_vendor"]
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.sdist]
|
|
47
|
+
# The sdist carries only the wrapper sources. Building a wheel from it requires
|
|
48
|
+
# a prebuilt native binary (CODEANALYZER_NATIVE_BINARY) and jmods; without them
|
|
49
|
+
# the build hook fails with a clear message rather than silently shipping a
|
|
50
|
+
# binary-less, non-functional wheel.
|
|
51
|
+
include = [
|
|
52
|
+
"codeanalyzer_java",
|
|
53
|
+
"hatch_build.py",
|
|
54
|
+
"pyproject.toml",
|
|
55
|
+
"README.md",
|
|
56
|
+
]
|