]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/build_tools/amalgamate.py
2 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
4 # amalgamate.py creates an amalgamation from a unity build.
5 # It can be run with either Python 2 or 3.
6 # An amalgamation consists of a header that includes the contents of all public
7 # headers and a source file that includes the contents of all source files and
10 # This script works by starting with the unity build file and recursively expanding
11 # #include directives. If the #include is found in a public include directory,
12 # that header is expanded into the amalgamation header.
14 # A particular header is only expanded once, so this script will
15 # break if there are multiple inclusions of the same header that are expected to
16 # expand differently. Similarly, this type of code causes issues:
22 # #include "bar.h" // oops, doesn't get expanded
23 # // different code here
26 # The solution is to move the include out of the #ifdef.
28 from __future__
import print_function
35 include_re
= re
.compile('^[ \t]*#include[ \t]+"(.*)"[ \t]*$')
40 def find_header(name
, abs_path
, include_paths
):
41 samedir
= path
.join(path
.dirname(abs_path
), name
)
42 if path
.exists(samedir
):
44 for include_path
in include_paths
:
45 include_path
= path
.join(include_path
, name
)
46 if path
.exists(include_path
):
60 if include_path
in included
:
63 included
.add(include_path
)
64 with
open(include_path
) as f
:
65 print('#line 1 "{}"'.format(include_path
), file=source_out
)
67 f
, include_path
, source_out
, header_out
, include_paths
, public_include_paths
73 f
, abs_path
, source_out
, header_out
, include_paths
, public_include_paths
75 for (line
, text
) in enumerate(f
):
76 m
= include_re
.match(text
)
78 filename
= m
.groups()[0]
79 # first check private headers
80 include_path
= find_header(filename
, abs_path
, include_paths
)
82 if include_path
in excluded
:
83 source_out
.write(text
)
86 expanded
= expand_include(
96 # now try public headers
97 include_path
= find_header(filename
, abs_path
, public_include_paths
)
101 if include_path
in excluded
:
102 source_out
.write(text
)
110 public_include_paths
,
115 "unable to find {}, included in {} on line {}".format(
116 filename
, abs_path
, line
121 print('#line {} "{}"'.format(line
+ 1, abs_path
), file=source_out
)
122 elif text
!= "#pragma once\n":
123 source_out
.write(text
)
127 parser
= argparse
.ArgumentParser(
128 description
="Transform a unity build into an amalgamation"
130 parser
.add_argument("source", help="source file")
134 dest
="include_paths",
135 help="include paths for private headers",
140 dest
="public_include_paths",
141 help="include paths for public headers",
144 "-x", action
="append", dest
="excluded", help="excluded header files"
146 parser
.add_argument("-o", dest
="source_out", help="output C++ file", required
=True)
148 "-H", dest
="header_out", help="output C++ header file", required
=True
150 args
= parser
.parse_args()
152 include_paths
= list(map(path
.abspath
, args
.include_paths
or []))
153 public_include_paths
= list(map(path
.abspath
, args
.public_include_paths
or []))
154 excluded
.update(map(path
.abspath
, args
.excluded
or []))
155 filename
= args
.source
156 abs_path
= path
.abspath(filename
)
157 with
open(filename
) as f
, open(args
.source_out
, "w") as source_out
, open(
160 print('#line 1 "{}"'.format(filename
), file=source_out
)
161 print('#include "{}"'.format(header_out
.name
), file=source_out
)
163 f
, abs_path
, source_out
, header_out
, include_paths
, public_include_paths
167 if __name__
== "__main__":