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