@@ -25,9 +25,13 @@ mapfile -t cmake_args < <(cmake::common_args)
2525
2626mapfile -t feature_list < <( bazelisk --batch query \
2727 --noshow_progress --noshow_loading_progress \
28- ' kind(cc_library, //:all) except filter("experimental|mocks", kind(cc_library, //:all))' |
28+ ' kind(cc_library, //:all)
29+ except filter("experimental|mocks", kind(cc_library, //:all))' |
2930 sed -e ' s;//:;;' )
3031enabled=" $( printf " ;%s" " ${feature_list[@]} " ) "
32+ # These two are not libraries that require enabling.
33+ enabled=" ${enabled/ ;common/ } "
34+ enabled=" ${enabled/ ;grpc_utils/ } "
3135enabled=" ${enabled: 1} "
3236
3337INSTALL_PREFIX=/var/tmp/google-cloud-cpp
@@ -43,30 +47,37 @@ cmake "${cmake_args[@]}" \
4347 -DGOOGLE_CLOUD_CPP_ENABLE=" ${enabled} " \
4448 -DCMAKE_CXX_FLAGS=" -Og -Wno-maybe-uninitialized"
4549cmake --build cmake-out
46- cmake --install cmake-out
50+ cmake --install cmake-out > /dev/null
4751
48- # Uses `abi-dumper` to dump the ABI for the given library, which should be
49- # installed at the given prefix. This function will be called from a subshell,
50- # so it cannot use other variables or functions (including io::log*).
51- function dump_abi() {
52+ # Uses `abi-dumper` to dump the ABI for the given library, which should
53+ # be installed at the given @p prefix, and `abi-compliance-checker` to
54+ # produce a report comparing the old and new dumps. The (compressed) new
55+ # dump is left in the @p project_root tree.
56+ #
57+ # This function will be called from a subshell, so it cannot use other
58+ # variables or functions (including io::log*).
59+ function check_abi() {
5260 local library=" $1 "
5361 local prefix=" $2 "
54- local public_headers=" ${prefix} /include/google/cloud/${library# google_cloud_cpp_} "
55- if [[ " ${library} " == " google_cloud_cpp_common" || " ${library} " == " google_cloud_cpp_grpc_utils" ]]; then
56- # These two are special
62+ local project_root=" $3 "
63+
64+ local shortlib=" ${library# google_cloud_cpp_} "
65+ local public_headers=" ${prefix} /include/google/cloud/${shortlib} "
66+ # These two are special
67+ if [[ " ${shortlib} " == " common" || " ${shortlib} " == " grpc_utils" ]]; then
5768 public_headers=" ${prefix} /include/google/cloud"
5869 fi
5970
60- echo " Dumping ${library} (may be slow)..."
6171 local version
6272 version=$( git rev-parse --short HEAD)
73+ local actual_dump_file=" ${library} .actual.abi.dump"
6374 local -a dump_options=(
6475 # The source .so file
6576 " ${prefix} /lib64/lib${library} .so"
6677 # Use the git version as the library version number for reporting purposes
6778 -lver " ${version} "
6879 # The dump destination
69- -o " cmake-out/${library} .actual.abi.dump "
80+ -o " cmake-out/${actual_dump_file} "
7081 # Where to find the headers
7182 -include-paths " ${prefix} /include"
7283 -include-paths " /usr/local/include"
@@ -81,57 +92,65 @@ function dump_abi() {
8192 # Use the system's debuginfo
8293 -search-debuginfo /usr
8394 )
84- abi-dumper " ${dump_options[@]} "
85- }
86- export -f dump_abi # enables this function to be called from a subshell
87-
88- mapfile -t libraries < <( printf " google_cloud_cpp_%s\n" " ${feature_list[@]} " )
89-
90- # Run the dump_abi function for each library in parallel since its slow.
91- echo " ${libraries[@]} " | xargs -P " $( nproc) " -n 1 \
92- bash -c " dump_abi \$ 0 ${INSTALL_PREFIX} "
93-
94- # A count of the number of libraries that fail the api compliance check.
95- # This will become the script's exit code.
96- errors=0
95+ abi-dumper " ${dump_options[@]} " > /dev/null 2>&1 |
96+ grep -v " ERROR: missed type id" || true
9797
98- for lib in " ${libraries[@]} " ; do
99- io::log_h2 " Checking ${lib} "
100- actual_dump_file=" ${lib} .actual.abi.dump"
101- expected_dump_file=" ${lib} .expected.abi.dump"
102- expected_dump_path=" ${PROJECT_ROOT} /ci/abi-dumps/${expected_dump_file} .gz"
98+ local project_dir=" ${project_root} /ci/abi-dumps"
99+ local expected_dump_file=" ${library} .expected.abi.dump"
100+ local expected_dump_path=" ${project_dir} /${expected_dump_file} .gz"
103101 if [[ -r " ${expected_dump_path} " ]]; then
104102 zcat " ${expected_dump_path} " > " cmake-out/${expected_dump_file} "
105- report=" cmake-out/compat_reports/${lib } /src_compat_report.html"
103+ report=" cmake-out/compat_reports/${library } /src_compat_report.html"
106104 compliance_flags=(
107105 # Put the output report in a separate directory for each library
108106 -report-path " ${report} "
109107 # We only want a source-level report. We make no ABI guarantees, such
110108 # as data structure sizes or virtual table ordering
111109 -src
112- # We ignore all symbols in internal namespaces, because these are not part
113- # of our public API. We do this by specifying a regex that matches against
114- # the mangled symbol names. For example, 8 is the number of characters in
115- # the string "internal", and it should again be followed by some other
116- # number indicating the length of the symbol within the "internal"
117- # namespace. See: https://en.wikipedia.org/wiki/Name_mangling
110+ # We ignore all symbols in internal namespaces, because these are not
111+ # part of our public API. We do this by specifying a regex that matches
112+ # against the mangled symbol names. For example, 8 is the number of
113+ # characters in the string "internal", and it should again be followed
114+ # by some other number indicating the length of the symbol within the
115+ # "internal" namespace. See: https://en.wikipedia.org/wiki/Name_mangling
118116 -skip-internal-symbols " (8internal|_internal)\d"
119117 # The library to compare
120- -l " ${lib } "
118+ -l " ${library } "
121119 # Compared the saved baseline vs. the dump for the current version
122120 -old " cmake-out/${expected_dump_file} "
123121 -new " cmake-out/${actual_dump_file} "
124122 )
125- if ! io::run abi-compliance-checker " ${compliance_flags[@]} " ; then
126- io::log_red " ABI Compliance error: ${lib} "
127- (( ++ errors))
128- io::log " Report file: ${report} "
129- w3m -dump " ${report} "
130- fi
123+ abi-compliance-checker " ${compliance_flags[@]} " > /dev/null || true
131124 fi
125+
132126 # Replaces the (old) expected dump file with the (new) actual one.
133127 gzip -n " cmake-out/${actual_dump_file} "
134128 mv -f " cmake-out/${actual_dump_file} .gz" " ${expected_dump_path} "
129+ }
130+ export -f check_abi # enables this function to be called from a subshell
131+
132+ mapfile -t libraries < <( printf " google_cloud_cpp_%s\n" " ${feature_list[@]} " )
133+
134+ # Run the check_abi function for each library in parallel since its slow.
135+ echo " ${libraries[@]} " | xargs -P " $( nproc) " -n 1 \
136+ bash -c " TIMEFORMAT=\"\$ {0#google_cloud_cpp_} completed in %0lR\" ;
137+ time check_abi \$ {0} ${INSTALL_PREFIX} ${PROJECT_ROOT} "
138+
139+ # A count of the number of libraries that fail the api compliance check.
140+ # This will become the script's exit code.
141+ errors=0
142+
143+ for library in " ${libraries[@]} " ; do
144+ report=" cmake-out/compat_reports/${library} /src_compat_report.html"
145+ if grep --silent " <td class='compatible'>100%</td>" " ${report} " ; then
146+ io::log_green " ABI Compliance OK: ${library} "
147+ else
148+ io::log_red " ABI Compliance error: ${library} "
149+ io::log " Report file: ${report} "
150+ w3m -dump " ${report} "
151+ (( ++ errors))
152+ fi
135153done
154+
136155echo
137156exit " ${errors} "
0 commit comments