Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / bin / find-mergedlib-can-be-private.py
blob7029592062a9dd3f77055d0cb6320cb3e76f7247
1 #!/usr/bin/python2
3 # Generate a custom linker script/map file for the --enabled-mergedlibs merged library
4 # which reduces the startup time and enables further optimisations with --enable-lto because 60% or more
5 # of the symbols become internal only.
8 import subprocess
9 import sys
10 import re
11 import multiprocessing
13 exported_symbols = set()
14 imported_symbols = set()
17 # Copied from solenv/gbuild/extensions/pre_MergedLibsList.mk
18 # TODO there has to be a way to run gmake and get it to dump this list for me
19 merged_libs = { \
20 "avmedia" \
21 ,"basctl" \
22 ,"basprov" \
23 ,"basegfx" \
24 ,"canvasfactory" \
25 ,"canvastools" \
26 ,"comphelper" \
27 ,"configmgr" \
28 ,"cppcanvas" \
29 ,"crashreport)" \
30 ,"dbtools" \
31 ,"deployment" \
32 ,"deploymentmisc" \
33 ,"desktopbe1)" \
34 ,"desktop_detector)" \
35 ,"drawinglayer" \
36 ,"editeng" \
37 ,"filterconfig" \
38 ,"fsstorage" \
39 ,"fwk" \
40 ,"helplinker)" \
41 ,"i18npool" \
42 ,"i18nutil" \
43 ,"lng" \
44 ,"localebe1" \
45 ,"msfilter" \
46 ,"mtfrenderer" \
47 ,"opencl" \
48 ,"package2" \
49 ,"sax" \
50 ,"sb" \
51 ,"simplecanvas" \
52 ,"sfx" \
53 ,"sofficeapp" \
54 ,"sot" \
55 ,"spl" \
56 ,"stringresource" \
57 ,"svl" \
58 ,"svt" \
59 ,"svx" \
60 ,"svxcore" \
61 ,"tk" \
62 ,"tl" \
63 ,"ucb1" \
64 ,"ucbhelper" \
65 ,"ucpexpand1" \
66 ,"ucpfile1" \
67 ,"unoxml" \
68 ,"utl" \
69 ,"uui" \
70 ,"vcl" \
71 ,"xmlscript" \
72 ,"xo" \
73 ,"xstor" }
75 # look for symbols exported by libmerged
76 subprocess_nm = subprocess.Popen("nm -D instdir/program/libmergedlo.so", stdout=subprocess.PIPE, shell=True)
77 with subprocess_nm.stdout as txt:
78 # We are looking for lines something like:
79 # 0000000000036ed0 T flash_component_getFactory
80 line_regex = re.compile(r'^[0-9a-fA-F]+ T ')
81 for line in txt:
82 line = line.strip()
83 if line_regex.match(line):
84 exported_symbols.add(line.split(" ")[2])
85 subprocess_nm.terminate()
87 # look for symbols imported from libmerged
88 subprocess_find = subprocess.Popen("(find instdir/program/ -type f; ls ./workdir/LinkTarget/CppunitTest/*.so) | xargs grep -l mergedlo",
89 stdout=subprocess.PIPE, shell=True)
90 with subprocess_find.stdout as txt:
91 for line in txt:
92 sharedlib = line.strip()
93 s = sharedlib[sharedlib.find("/lib") + 4 : len(sharedlib) - 3]
94 if s in merged_libs: continue
95 # look for imported symbols
96 subprocess_objdump = subprocess.Popen("objdump -T " + sharedlib, stdout=subprocess.PIPE, shell=True)
97 with subprocess_objdump.stdout as txt2:
98 # ignore some header bumpf
99 txt2.readline()
100 txt2.readline()
101 txt2.readline()
102 txt2.readline()
103 # We are looking for lines something like (noting that one of them uses spaces, and the other tabs)
104 # 0000000000000000 DF *UND* 0000000000000000 _ZN16FilterConfigItem10WriteInt32ERKN3rtl8OUStringEi
105 for line2 in txt2:
106 line2 = line2.strip()
107 if line2.find("*UND*") == -1: continue
108 tokens = line2.split(" ")
109 sym = tokens[len(tokens)-1].strip()
110 imported_symbols.add(sym)
111 subprocess_objdump.terminate()
112 subprocess_find.terminate()
114 intersec_symbols = exported_symbols.intersection(imported_symbols)
115 print("no symbols exported from libmerged = " + str(len(exported_symbols)))
116 print("no symbols that can be made internal = " + str(len(intersec_symbols)))
118 # Now look for classes where none of the class symbols are imported,
119 # i.e. we can mark the whole class as hidden
121 def extract_class(sym):
122 filtered_sym = subprocess.check_output(["c++filt", sym]).strip()
123 if filtered_sym.startswith("vtable for "):
124 classname = filtered_sym[11:]
125 return classname
126 if filtered_sym.startswith("non-virtual thunk to "):
127 filtered_sym = filtered_sym[21:]
128 elif filtered_sym.startswith("virtual thunk to "):
129 filtered_sym = filtered_sym[17:]
130 i = filtered_sym.find("(")
131 if i != -1:
132 i = filtered_sym.rfind("::", 0, i)
133 if i != -1:
134 classname = filtered_sym[:i]
135 return classname
136 return ""
138 pool = multiprocessing.Pool(multiprocessing.cpu_count())
139 classes_with_exported_symbols = set(pool.map(extract_class, list(exported_symbols)))
140 classes_with_imported_symbols = set(pool.map(extract_class, list(imported_symbols)))
142 # Some stuff is particular to Windows, so won't be found by a Linux analysis, so remove
143 # those classes.
144 can_be_private_classes = classes_with_exported_symbols - classes_with_imported_symbols;
145 can_be_private_classes.discard("SpinField")
147 with open("bin/find-mergedlib-can-be-private.classes.results", "wt") as f:
148 for sym in sorted(can_be_private_classes):
149 if sym.startswith("std::") or sym.startswith("void std::"): continue
150 f.write(sym + "\n")