# -*- coding: utf-8 -*- """Verify zip package contents for the two project packages (shared-layer layout). Checks: 1. zip top-level layout: / + Drivers/ + Shared/ (must be siblings) 2. uvprojx ..\\..\\Drivers / ..\\..\\Shared references resolve inside the zip (simulates the receiver unzipping the archive anywhere and opening Keil) 3. no junk build artifacts (.o/.d/.crf/...) """ import os import posixpath import re import sys import zipfile import xml.etree.ElementTree as ET EXCLUDE_EXT = ('.o', '.d', '.crf', '.axf', '.lst', '.dep', '.htm', '.map', '.bak', '.uvguix') ok = True for z, proj in [('bootloader_package.zip', 'Bootloader'), ('app_package.zip', 'App')]: names = zipfile.ZipFile(z).namelist() print('===== %s (%d files) =====' % (z, len(names))) # 1) 顶层布局 tops = sorted(set(n.split('/')[0] for n in names)) print('top dirs:', tops) expect = {proj, 'Drivers', 'Shared'} if not expect.issubset(tops): print(' [FAIL] 缺少共享层目录: %s' % (expect - set(tops))) ok = False # 2) uvprojx 的 ..\\..\\ 引用在 zip 内可解析 uv = [n for n in names if n.endswith('.uvprojx')] if not uv: print(' [FAIL] 无 uvprojx') ok = False continue data = zipfile.ZipFile(z).read(uv[0]).decode('utf-8', errors='ignore') tree = ET.fromstring(data) base = os.path.dirname(uv[0]) # 工程内 MDK-ARM 目录在 zip 中的路径 missing_f = [] for fp in tree.iter('FilePath'): v = (fp.text or '').strip() if not v: continue # zip 条目用 '/', uvprojx 用 '\' —— 统一为 posix 形式比较 full = posixpath.normpath(posixpath.join(base, v.replace('\\', '/'))) if full not in names: missing_f.append(v) missing_i = [] for ip in tree.iter('IncludePath'): for seg in (ip.text or '').split(';'): seg = seg.strip() if not seg: continue # IncludePath 是目录:zip 无目录条目,用「目录下有文件条目」判断存在 d = posixpath.normpath(posixpath.join(base, seg.replace('\\', '/'))) if not any(n.startswith(d + '/') for n in names): missing_i.append(seg) print('uvprojx: %s' % uv[0]) print(' FilePath 缺失: %d, IncludePath 缺失: %d' % (len(missing_f), len(missing_i))) for m in (missing_f + missing_i)[:8]: print(' MISSING: %s' % m) ok = False # 3) 中间产物 bad = [n for n in names if n.lower().endswith(EXCLUDE_EXT)] print('junk files:', len(bad)) if bad: ok = False print('has startup:', any(n.lower().endswith('startup_py32f040xx.s') for n in names)) print('has RTE:', any('/RTE/' in n for n in names)) print('\n%s' % ('=== 全部通过 ✓ 接收方解压即编译 ===' if ok else '=== 存在问题 ✗ ===')) sys.exit(0 if ok else 1)