build_v8.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import zipfile, os, subprocess, glob, sys, shutil
  2. BASE = os.path.dirname(os.path.abspath(__file__))
  3. SRC = os.path.join(BASE, "src", "main", "java")
  4. RES = os.path.join(BASE, "src", "main", "resources")
  5. OUT = os.path.join(BASE, "build_tmp_classes")
  6. LIB = os.path.join(BASE, "lib")
  7. JAVAC = r"D:\Program Files\Java\jdk-17\bin\javac.exe"
  8. LOMBOK = r"C:\Users\BXD-XTYW\.m2\repository\org\projectlombok\lombok\1.18.32\lombok-1.18.32.jar"
  9. SRC_JAR = os.path.join(BASE, "target", "resource-platform-v7.jar")
  10. DST_JAR = os.path.join(BASE, "target", "resource-platform-v8.jar")
  11. # 1) 准备依赖 classpath: 从 fat jar 抽取 BOOT-INF/lib 到 lib/(若缺失), 并放入 lombok
  12. os.makedirs(LIB, exist_ok=True)
  13. if not glob.glob(os.path.join(LIB, "*.jar")):
  14. with zipfile.ZipFile(SRC_JAR) as z:
  15. for name in z.namelist():
  16. if name.startswith("BOOT-INF/lib/") and name.endswith(".jar"):
  17. out = os.path.join(LIB, os.path.basename(name))
  18. with open(out, "wb") as f:
  19. f.write(z.read(name))
  20. if not os.path.exists(os.path.join(LIB, "lombok-1.18.32.jar")):
  21. shutil.copy(LOMBOK, os.path.join(LIB, "lombok-1.18.32.jar"))
  22. dep_jars = sorted(glob.glob(os.path.join(LIB, "*.jar")))
  23. cp = ";".join(dep_jars)
  24. print("classpath entries:", len(dep_jars))
  25. # 2) 编译全部源码
  26. sources = []
  27. for root, _, files in os.walk(SRC):
  28. for f in files:
  29. if f.endswith(".java"):
  30. sources.append(os.path.join(root, f))
  31. print("source files:", len(sources))
  32. os.makedirs(OUT, exist_ok=True)
  33. cmd = [JAVAC, "-parameters", "-encoding", "UTF-8", "-cp", cp, "-d", OUT] + sources
  34. r = subprocess.run(cmd, capture_output=True)
  35. print("javac returncode:", r.returncode)
  36. if r.returncode != 0:
  37. err = (r.stderr or b"").decode("utf-8", "replace")
  38. print("=== STDERR (first 50 lines) ===")
  39. print("\n".join(err.splitlines()[:50]))
  40. sys.exit(1)
  41. print("compiled classes:", len(glob.glob(os.path.join(OUT, "**", "*.class"), recursive=True)))
  42. # 3) 重打包: 以 v7 为基底, 替换最新编译的 class, 并注入 src/main/resources 中的资源(xml等)
  43. with zipfile.ZipFile(SRC_JAR) as zin:
  44. infos = zin.infolist()
  45. def local_for(entry_name):
  46. if entry_name.startswith("BOOT-INF/classes/") and entry_name.endswith(".class"):
  47. rel = entry_name[len("BOOT-INF/classes/"):]
  48. local = os.path.join(OUT, rel)
  49. if os.path.isfile(local):
  50. return local
  51. return None
  52. if entry_name.startswith("BOOT-INF/classes/"):
  53. rel = entry_name[len("BOOT-INF/classes/"):]
  54. local = os.path.join(RES, rel)
  55. if os.path.isfile(local):
  56. return local
  57. return None
  58. manifest_name = "META-INF/MANIFEST.MF"
  59. all_names = set(zin.namelist())
  60. extra_resources = []
  61. for root, _, files in os.walk(RES):
  62. for f in files:
  63. full = os.path.join(root, f)
  64. rel = os.path.relpath(full, RES).replace("\\", "/")
  65. entry = "BOOT-INF/classes/" + rel
  66. if entry not in all_names:
  67. extra_resources.append((entry, full))
  68. # 源码中新增的类, 在基底 jar 里原本不存在, 需补打到新 jar
  69. extra_classes = []
  70. for root, _, files in os.walk(OUT):
  71. for f in files:
  72. if f.endswith(".class"):
  73. full = os.path.join(root, f)
  74. rel = os.path.relpath(full, OUT).replace("\\", "/")
  75. entry = "BOOT-INF/classes/" + rel
  76. if entry not in all_names:
  77. extra_classes.append((entry, full))
  78. with zipfile.ZipFile(DST_JAR, "w", compression=zipfile.ZIP_DEFLATED) as zout:
  79. mi = next(i for i in infos if i.filename == manifest_name)
  80. zout.writestr(mi, zin.read(manifest_name))
  81. for i in infos:
  82. if i.filename == manifest_name:
  83. continue
  84. local = local_for(i.filename)
  85. if local:
  86. with open(local, "rb") as lf:
  87. data = lf.read()
  88. zi = zipfile.ZipInfo(i.filename)
  89. zi.external_attr = i.external_attr
  90. zi.date_time = i.date_time
  91. zout.writestr(zi, data)
  92. else:
  93. zout.writestr(i, zin.read(i.filename))
  94. for entry, full in extra_resources:
  95. with open(full, "rb") as lf:
  96. data = lf.read()
  97. zout.writestr(zipfile.ZipInfo(entry), data)
  98. for entry, full in extra_classes:
  99. with open(full, "rb") as lf:
  100. data = lf.read()
  101. zout.writestr(zipfile.ZipInfo(entry), data)
  102. print("built:", DST_JAR, "exists:", os.path.exists(DST_JAR))
  103. zm = zipfile.ZipFile(DST_JAR)
  104. print("manifest first:", zm.namelist()[0] == manifest_name)
  105. # 校验关键新类已打入
  106. for cls in ["ResourceRenewal.class", "ResourceRenewalMapper.class",
  107. "ProcurementCostVO.class", "ResourceRenewalServiceImpl.class"]:
  108. name = "BOOT-INF/classes/com/example/resourceplatform/" + (
  109. "entity/" if "Renewal.class" in cls and "Mapper" not in cls and "Service" not in cls
  110. else "mapper/" if "Mapper" in cls
  111. else "dto/" if "VO" in cls
  112. else "service/impl/")
  113. entry = name + cls
  114. print("contains", entry, ":", entry in zm.namelist())