import os,subprocess,time,statistics,glob,shutil
ROOT="/Users/oscar/.worktree/hot-reload/labs/hot-reload"
LD="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld"
DEPS=f"{ROOT}/target/debug/deps"
STD=[p for p in glob.glob(os.path.expanduser("~/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libstd-*.dylib"))][0]
TLIB=os.path.dirname(STD)
rlibs=[sorted(glob.glob(f"{DEPS}/libapi_common-*.rlib"))[-1], sorted(glob.glob(f"{DEPS}/libapi-*.rlib"))[-1]]
BASE="/private/var/folders/ft/fkt3bwqd01g7f54wvyz9wgjc0000gn/T/opencode/pipe/link"
os.makedirs(BASE,exist_ok=True)
def base(extra=[],objects=None):
    cmd=[LD,"-dylib","-arch","arm64","-platform_version","macos","11.0","0.0","-undefined","dynamic_lookup","-dead_strip","-no_function_starts","-x"]
    if objects is None:
        for r in rlibs: cmd+=["-force_load",r]
    else: cmd+=objects
    cmd+=["-o",f"{BASE}/out.dylib","-L",TLIB,f"-lstd-{os.path.basename(STD).split('-',1)[1].rsplit('.',1)[0]}","-rpath",TLIB]
    return cmd+extra
def timeit(cmd,n=8):
    xs=[]
    for _ in range(n):
        if os.path.exists(f"{BASE}/out.dylib"): os.remove(f"{BASE}/out.dylib")
        s=time.monotonic(); p=subprocess.run(cmd,stdout=subprocess.DEVNULL,stderr=subprocess.PIPE); xs.append((time.monotonic()-s)*1000)
        if p.returncode: print("FAIL",p.stderr.decode()[:300]); return
    return xs
print("current", [round(x,1) for x in timeit(base())])
print("no_dead_strip", [round(x,1) for x in timeit([c for c in base() if c!="-dead_strip"])])
print("no_x_nofs", [round(x,1) for x in timeit([c for c in base() if c not in ("-x","-no_function_starts")])])
# objects direct
OD=f"{BASE}/objs"; shutil.rmtree(OD,ignore_errors=True); os.makedirs(OD)
objs=[]
for i,r in enumerate(rlibs):
    d=f"{OD}/{i}"; os.makedirs(d)
    subprocess.run(["ar","x",r],cwd=d,capture_output=True)
    for f in sorted(os.listdir(d)):
        if f.endswith(".o"): objs.append(os.path.join(d,f))
print("objs_direct", [round(x,1) for x in timeit(base(objects=objs))])
print("objs_deadstrip_off", [round(x,1) for x in timeit([c for c in base(objects=objs) if c!="-dead_strip"])])
