]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/build_tools/amalgamate.py
3 # amalgamate.py creates an amalgamation from a unity build.
4 # It can be run with either Python 2 or 3.
5 # An amalgamation consists of a header that includes the contents of all public
6 # headers and a source file that includes the contents of all source files and
9 # This script works by starting with the unity build file and recursively expanding
10 # #include directives. If the #include is found in a public include directory,
11 # that header is expanded into the amalgamation header.
13 # A particular header is only expanded once, so this script will
14 # break if there are multiple inclusions of the same header that are expected to
15 # expand differently. Similarly, this type of code causes issues:
21 # #include "bar.h" // oops, doesn't get expanded
22 # // different code here
25 # The solution is to move the include out of the #ifdef.
27 from __future__
import print_function
34 include_re
= re
.compile('^[ \t]*#include[ \t]+"(.*)"[ \t]*$')
38 def find_header(name
, abs_path
, include_paths
):
39 samedir
= path
.join(path
.dirname(abs_path
), name
)
40 if path
.exists(samedir
):
42 for include_path
in include_paths
:
43 include_path
= path
.join(include_path
, name
)
44 if path
.exists(include_path
):
48 def expand_include(include_path
, f
, abs_path
, source_out
, header_out
, include_paths
, public_include_paths
):
49 if include_path
in included
:
52 included
.add(include_path
)
53 with
open(include_path
) as f
:
54 print('#line 1 "{}"'.format(include_path
), file=source_out
)
55 process_file(f
, include_path
, source_out
, header_out
, include_paths
, public_include_paths
)
58 def process_file(f
, abs_path
, source_out
, header_out
, include_paths
, public_include_paths
):
59 for (line
, text
) in enumerate(f
):
60 m
= include_re
.match(text
)
62 filename
= m
.groups()[0]
63 # first check private headers
64 include_path
= find_header(filename
, abs_path
, include_paths
)
66 if include_path
in excluded
:
67 source_out
.write(text
)
70 expanded
= expand_include(include_path
, f
, abs_path
, source_out
, header_out
, include_paths
, public_include_paths
)
72 # now try public headers
73 include_path
= find_header(filename
, abs_path
, public_include_paths
)
77 if include_path
in excluded
:
78 source_out
.write(text
)
80 expand_include(include_path
, f
, abs_path
, header_out
, None, public_include_paths
, [])
82 sys
.exit("unable to find {}, included in {} on line {}".format(filename
, abs_path
, line
))
85 print('#line {} "{}"'.format(line
+1, abs_path
), file=source_out
)
86 elif text
!= "#pragma once\n":
87 source_out
.write(text
)
90 parser
= argparse
.ArgumentParser(description
="Transform a unity build into an amalgamation")
91 parser
.add_argument("source", help="source file")
92 parser
.add_argument("-I", action
="append", dest
="include_paths", help="include paths for private headers")
93 parser
.add_argument("-i", action
="append", dest
="public_include_paths", help="include paths for public headers")
94 parser
.add_argument("-x", action
="append", dest
="excluded", help="excluded header files")
95 parser
.add_argument("-o", dest
="source_out", help="output C++ file", required
=True)
96 parser
.add_argument("-H", dest
="header_out", help="output C++ header file", required
=True)
97 args
= parser
.parse_args()
99 include_paths
= list(map(path
.abspath
, args
.include_paths
or []))
100 public_include_paths
= list(map(path
.abspath
, args
.public_include_paths
or []))
101 excluded
.update(map(path
.abspath
, args
.excluded
or []))
102 filename
= args
.source
103 abs_path
= path
.abspath(filename
)
104 with
open(filename
) as f
, open(args
.source_out
, 'w') as source_out
, open(args
.header_out
, 'w') as header_out
:
105 print('#line 1 "{}"'.format(filename
), file=source_out
)
106 print('#include "{}"'.format(header_out
.name
), file=source_out
)
107 process_file(f
, abs_path
, source_out
, header_out
, include_paths
, public_include_paths
)
109 if __name__
== "__main__":