mirror of
git://sourceware.org/git/libabigail.git
synced 2025-02-15 04:56:54 +00:00
Make abi{pkg}diff filter out changes about private types
This is to address the following enhancement requests: #19588 - Add a --headers-dir1 and --headers-dir2 option to abidiff #19948 - Add --devel-pkg1 and --devel-pkg2 options to abipkgdiff When the user specifies where to find header files for two binaries (or packages) being compared, this patch generates a type suppression specification that filters out change reports about types that are defined in files that are not in the set of header files specified. The type suppression specification also suppresses change reports about changed/added/removed virtual member functions which enclosing class type matches the type suppression specification. There is a corner case that the patch handles too, and that is exhibited by the accompanying test case for abidiff. There can be a class defined by DWARF as having no source location and as being a pure declaration. This can be a class declaration that has inline virtual members only, and one or several non-defined virtual methods too. When that declaration is included in a source file, GCC generates debug info that describes that class as being a declaration-only class with no source declaration. This patch considers such a class as being non defined; you know, like a true opaque type. So it's considered being not defined in any public header file. Changes to this kind of class are thus filtered out. * include/abg-comp-filter.h: Update copyright year. * src/abg-comp-filter.cc (has_virtual_mem_fn_change): Make this static function become exported. (has_virtual_mem_fn_change): Declare new function. * include/abg-suppression.h (suppression_base::{get,set}_is_artificial): Declare new accessors. (type_suppression::get_source_locations_to_keep): Return an unordered set of strings, not a vector. Add a non-const overload. (type_suppression::set_source_locations_to_keep): Set an unordered set of strings, not a vector. * src/abg-suppression.cc (suppression_base::priv::is_artificial_): New data member. (suppression_base::priv::priv): Initialize the new data member. (suppression_base::{get,set}_is_artificial): Define new accessors. (type_suppression::priv::source_locations_to_keep_): Change the vector of strings representing source file names into unordered set of string. (type_suppression::get_source_locations_to_keep): Return an unordered set of strings, not a vector. Define a non-const overload. (type_suppression::set_source_locations_to_keep): Set an unordered set of strings, not a vector. (type_suppression::suppresses_diff): Make this suppress virtual member function diffs if the enclosing type of the changed virtual member is suppressed by the current type_suppression. (read_type_suppression): Adjust to use the fact that the source locations are not stored in an unordered set, not in a vector anymore. Otherwise, using a vector here make things too slow. (type_suppression::suppresses_type): Likewise. Also, If the type we are looking at has no location because it's a true opaque type and if the current suppression is an artificial suppression that is meant to suppress change reports about non-public types, then suppress the type. * include/abg-tools-utils.h (gen_suppr_spec_from_headers): Declare new public function. * src/abg-tools-utils.cc (PRIVATE_TYPES_SUPPR_SPEC_NAME): Define a new constant variable. (handle_fts_entry): Define new static function. (gen_suppr_spec_from_headers): Define new public function. * src/abg-comparison.cc (corpus_diff::priv::apply_suppressions_to_added_removed_fns_vars): If a type suppression suppresses a given class C, make it change added/removed virtual functions whose enclosing type is C. * tools/abidiff.cc (options::{headers_dir1, headers_dir2}): New data members. (display_usage): Add help strings for --headers-dir1 and --headers-dir2. (parse_command_line): Parse the new --headers-dir1 and --headers-dir2 options. (set_diff_context_from_opts): Generate suppression specifications to filter out changes on private types, if --headers-dir1 or --headers-dir2 is given. * tools/abipkgdiff.cc (options::{devel_package1, devel_package2}): New data members. (typedef package_sptr): New typedef. (enum package::kind): New enum. (package::kind_): New data member. This replaces ... (package::is_debug_info_): ... this data member. (package::{devel_package_, private_types_suppressions_}): New data members. (package::package): Adjust. (package::get_kind): Define new member function. This replaces ... (package::is_debug_info): ... this member function overload. (package::set_kind): Define new member functin. It replaces ... (package::is_debug_info): ... this member function overload. (package::{devel_package, private_types_suppressions}): Define new accessors. (package::erase_extraction_directies): Erase the sub-directory where development packages are extracted to. (compare_args::private_types_suppr{1,2}): New data members. (compare_args::compare_args): Adjust. (display_usage): Add help strings for --devel-pkg1/--devel-pkg2. (compare): Make the overload that compares elf files take private types suppressions. Add the private types suppressions to the diff context. (pthread_routine_compare): Adjust the call to compare. (maybe_create_private_types_suppressions): Define new static function. (pthread_routine_extract_pkg_and_map_its_content): If a devel package was specified for the main package then extract it in parallel with the other package extraction. When the extraction is done, create private types suppressions by visiting the directories that contain the header files. (compare): In the overload that compares packages by scheduling comparison of individual elf files that are in the packages, pass in the private type suppressions too. (parse_command_line): Parse the new --devel-pkg{1,2} command line options. (main): Associate the devel package to the main package, if the --devel-pkg{1,2}. * doc/manuals/abidiff.rst: Add documentation about the new --headers-dir1 and --headers-dir2 options. * doc/manuals/abipkgdiff.rst: Likewise, add documentation about the new --devel-pkg1 and --devel-pkg2 libraries. * tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt: New test reference output. * tests/data/test-diff-pkg/tbb-devel-4.1-9.20130314.fc22.x86_64.rpm: New test input package. * tests/data/test-diff-pkg/tbb-devel-4.3-3.20141204.fc23.x86_64.rpm: Likewise. * tests/test-diff-pkg.cc b/tests/test-diff-pkg.cc (InOutSpec::{first,second}_in_devel_package_path): New data members. (in_out_specs): Adjust. Also, add a new entry describing the new test inputs above. (test_task::perform): When the new test entry contains devel packages, pass them to abipkgdiff using the --devel1 and --devel2 options. * tests/data/test-diff-suppr/test30-include-dir-v0/test30-pub-lib-v0.h: A new test input source code. * tests/data/test-diff-suppr/test30-include-dir-v1/test30-pub-lib-v1.h: Likewise. * tests/data/test-diff-suppr/test30-priv-lib-v0.cc: Likewise. * tests/data/test-diff-suppr/test30-priv-lib-v0.h: Likewise. * tests/data/test-diff-suppr/test30-priv-lib-v1.cc: Likewise. * tests/data/test-diff-suppr/test30-priv-lib-v1.h: Likewise. * tests/data/test-diff-suppr/test30-pub-lib-v0.cc: Likewise. * tests/data/test-diff-suppr/test30-pub-lib-v0.so: Add new test binary input. * tests/data/test-diff-suppr/test30-pub-lib-v1.cc: Add new test input source code. * tests/data/test-diff-suppr/test30-pub-lib-v1.so: Add new test binary input. * tests/data/test-diff-suppr/test30-report-0.txt: Add new test reference output. * tests/data/test-diff-suppr/test30-report-1.txt: Add new test reference output. * tests/test-diff-suppr.cc (InOutSpec::headers_dir{1,2}): New data members. (InOutSpec::abidiff_options): Renamed the bidiff_options data member into this. (in_out_specs): Adjust. Also, added the new test input above to this. (main): Adjust to invoke abidiff with the new --hd1 and --hd2 options if the input specs for the tests has the new InOutSpec::headers_dir{1,2} data member set. Renamed bidiff into abidiff. * tests/data/Makefile.am: Add the new test inputs to the source distribution. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
3f1d7c3976
commit
e19bf5627a
@ -57,6 +57,18 @@ Options
|
||||
to find the split debug information for the
|
||||
*second-shared-library* file.
|
||||
|
||||
* ``--headers-dir1 | --hd1`` <headers-directory-path-1>
|
||||
|
||||
Specifies where to find the public headers of the first shared
|
||||
library that the tool has to consider. The tool will thus filter
|
||||
out ABI changes on types that are not defined in public headers.
|
||||
|
||||
* ``--headers-dir2 | --hd2`` <headers-directory-path-1>
|
||||
|
||||
Specifies where to find the public headers of the second shared
|
||||
library that the tool has to consider. The tool will thus filter
|
||||
out ABI changes on types that are not defined in public headers.
|
||||
|
||||
* ``--stat``
|
||||
|
||||
Rather than displaying the detailed ABI differences between
|
||||
|
@ -15,12 +15,6 @@ function and variable sub-types, the two input packages must be
|
||||
accompanied with their debug information packages that contain debug
|
||||
information in `DWARF`_ format.
|
||||
|
||||
.. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
.. _RPM: https://en.wikipedia.org/wiki/RPM_Package_Manager
|
||||
.. _Deb: https://en.wikipedia.org/wiki/Deb_%28file_format%29
|
||||
.. _tar: https://en.wikipedia.org/wiki/Tar_%28computing%29
|
||||
.. _DWARF: http://www.dwarfstd.org
|
||||
|
||||
|
||||
.. _abipkgdiff_invocation_label:
|
||||
|
||||
@ -31,6 +25,9 @@ Invocation
|
||||
|
||||
abipkgdiff [option] <package1> <package2>
|
||||
|
||||
``package1`` and ``package2`` are the packages that contain the
|
||||
binaries to be compared.
|
||||
|
||||
.. _abipkgdiff_options_label:
|
||||
|
||||
Options
|
||||
@ -56,6 +53,26 @@ Options
|
||||
into a separate file, tells ``abipkgdiff`` where to find that
|
||||
separate debug information package.
|
||||
|
||||
* ``--devel-pkg1 | --devel1`` <path>
|
||||
|
||||
Specifies where to find the `Development Package`_ associated with
|
||||
the first package to be compared. That `Development Package`_ at
|
||||
``path`` should at least contain header files in which public
|
||||
types exposed by the libraries (of the first package to be
|
||||
compared) are defined. When this option is provided, the tool
|
||||
filters out reports about ABI changes to types that are *NOT*
|
||||
defined in these header files.
|
||||
|
||||
* ``--devel-pkg2 | --devel2`` <path>
|
||||
|
||||
Specifies where to find the `Development Package`_ associated with
|
||||
the second package to be compared. That `Development Package`_ at
|
||||
``path`` should at least contains header files in which public
|
||||
types exposed by the libraries (of the second package to be
|
||||
compared) are defined. When this option is provided, the tool
|
||||
filters out reports about ABI changes to types that are *NOT*
|
||||
defined in these header files.
|
||||
|
||||
* ``--dso-only``
|
||||
|
||||
Compare ELF files that are shared libraries, only. Do not compare
|
||||
@ -145,3 +162,10 @@ tool encountered an error.
|
||||
In the later case, the value of the exit code is the same as for the
|
||||
:ref:`abidiff tool <abidiff_return_value_label>`.
|
||||
|
||||
|
||||
.. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
.. _RPM: https://en.wikipedia.org/wiki/RPM_Package_Manager
|
||||
.. _Deb: https://en.wikipedia.org/wiki/Deb_%28file_format%29
|
||||
.. _tar: https://en.wikipedia.org/wiki/Tar_%28computing%29
|
||||
.. _DWARF: http://www.dwarfstd.org
|
||||
.. _Development Package: https://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging/Guidelines#Devel_Packages
|
||||
|
@ -1,6 +1,6 @@
|
||||
// -*- Mode: C++ -*-
|
||||
//
|
||||
// Copyright (C) 2013-2015 Red Hat, Inc.
|
||||
// Copyright (C) 2013-2016 Red Hat, Inc.
|
||||
//
|
||||
// This file is part of the GNU Application Binary Interface Generic
|
||||
// Analysis and Instrumentation Library (libabigail). This library is
|
||||
@ -42,6 +42,9 @@ namespace filtering
|
||||
bool
|
||||
has_harmless_name_change(decl_base_sptr f, decl_base_sptr s);
|
||||
|
||||
bool
|
||||
has_virtual_mem_fn_change(const function_decl_diff* diff);
|
||||
|
||||
class filter_base;
|
||||
/// Convenience typedef for a shared pointer to filter_base
|
||||
typedef shared_ptr<filter_base> filter_base_sptr;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#ifndef __ABG_SUPPRESSION_H__
|
||||
#define __ABG_SUPPRESSION_H__
|
||||
|
||||
#include <tr1/unordered_set>
|
||||
#include "abg-ini.h"
|
||||
#include "abg-comparison.h"
|
||||
|
||||
@ -42,6 +43,7 @@ namespace suppr
|
||||
{
|
||||
|
||||
using namespace abigail::comparison;
|
||||
using std::tr1::unordered_set;
|
||||
|
||||
/// Base type of the suppression specifications types.
|
||||
///
|
||||
@ -66,6 +68,12 @@ public:
|
||||
const string& file_name_regex_str,
|
||||
const string& file_name_not_regex_str);
|
||||
|
||||
bool
|
||||
get_is_artificial() const;
|
||||
|
||||
void
|
||||
set_is_artificial(bool);
|
||||
|
||||
const string
|
||||
get_label() const;
|
||||
|
||||
@ -230,11 +238,14 @@ public:
|
||||
insertion_ranges&
|
||||
get_data_member_insertion_ranges();
|
||||
|
||||
const vector<string>&
|
||||
const unordered_set<string>&
|
||||
get_source_locations_to_keep() const;
|
||||
|
||||
unordered_set<string>&
|
||||
get_source_locations_to_keep();
|
||||
|
||||
void
|
||||
set_source_locations_to_keep(const vector<string>&);
|
||||
set_source_locations_to_keep(const unordered_set<string>&);
|
||||
|
||||
const string&
|
||||
get_source_location_to_keep_regex_str() const;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
#include <iostream>
|
||||
#include <abg-suppression.h>
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
@ -54,6 +55,8 @@ bool check_file(const string& path, ostream& out, const string& prog_name = "");
|
||||
bool string_ends_with(const string&, const string&);
|
||||
bool string_is_ascii(const string&);
|
||||
bool string_is_ascii_identifier(const string&);
|
||||
suppr::type_suppression_sptr
|
||||
gen_suppr_spec_from_headers(const string& hdrs_root_dir);
|
||||
|
||||
class temp_file;
|
||||
|
||||
@ -192,5 +195,7 @@ file_type guess_file_type(const string& file_path);
|
||||
std::tr1::shared_ptr<char>
|
||||
make_path_absolute(const char*p);
|
||||
|
||||
extern const char* PRIVATE_TYPES_SUPPR_SPEC_NAME;
|
||||
|
||||
}// end namespace tools_utils
|
||||
}//end namespace abigail
|
||||
|
@ -600,7 +600,7 @@ has_virtual_mem_fn_change(const class_diff* diff)
|
||||
///
|
||||
/// @return true iff the function_decl_diff node contains changes
|
||||
/// involving virtual member functions.
|
||||
static bool
|
||||
bool
|
||||
has_virtual_mem_fn_change(const function_decl_diff* diff)
|
||||
{
|
||||
if (!diff)
|
||||
|
@ -10345,6 +10345,40 @@ corpus_diff::priv::apply_suppressions_to_added_removed_fns_vars()
|
||||
ctxt))
|
||||
suppressed_deleted_unrefed_fn_syms_[e->first] = e->second;
|
||||
}
|
||||
// Added/Delete virtual member functions changes that might be
|
||||
// suppressed by a type_suppression that matches the enclosing
|
||||
// class of the virtual member function.
|
||||
else if (type_suppression_sptr type_suppr = is_type_suppression(*i))
|
||||
{
|
||||
// Added virtual functions
|
||||
for (string_function_ptr_map::const_iterator e = added_fns_.begin();
|
||||
e != added_fns_.end();
|
||||
++e)
|
||||
if (is_member_function(e->second)
|
||||
&& get_member_function_is_virtual(e->second))
|
||||
{
|
||||
function_decl *f = e->second;
|
||||
class_decl_sptr c =
|
||||
is_method_type(f->get_type())->get_class_type();
|
||||
assert(c);
|
||||
if (type_suppr->suppresses_type(c, ctxt))
|
||||
suppressed_added_fns_[e->first] = e->second;
|
||||
}
|
||||
// Deleted virtual functions
|
||||
for (string_function_ptr_map::const_iterator e = deleted_fns_.begin();
|
||||
e != deleted_fns_.end();
|
||||
++e)
|
||||
if (is_member_function(e->second)
|
||||
&& get_member_function_is_virtual(e->second))
|
||||
{
|
||||
function_decl *f = e->second;
|
||||
class_decl_sptr c =
|
||||
is_method_type(f->get_type())->get_class_type();
|
||||
assert(c);
|
||||
if (type_suppr->suppresses_type(c, ctxt))
|
||||
suppressed_deleted_fns_[e->first] = e->second;
|
||||
}
|
||||
}
|
||||
// Added/Deleted variables
|
||||
else if (variable_suppression_sptr var_suppr =
|
||||
is_variable_suppression(*i))
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "abg-suppression.h"
|
||||
#include "abg-ini.h"
|
||||
#include "abg-sptr-utils.h"
|
||||
#include "abg-comp-filter.h"
|
||||
#include "abg-tools-utils.h"
|
||||
|
||||
namespace abigail
|
||||
@ -43,6 +44,7 @@ using std::tr1::dynamic_pointer_cast;
|
||||
/// The private data of @ref suppression_base.
|
||||
class suppression_base::priv
|
||||
{
|
||||
bool is_artificial_;
|
||||
string label_;
|
||||
string file_name_regex_str_;
|
||||
mutable sptr_utils::regex_t_sptr file_name_regex_;
|
||||
@ -55,16 +57,19 @@ class suppression_base::priv
|
||||
|
||||
public:
|
||||
priv()
|
||||
: is_artificial_()
|
||||
{}
|
||||
|
||||
priv(const string& label)
|
||||
: label_(label)
|
||||
: is_artificial_(),
|
||||
label_(label)
|
||||
{}
|
||||
|
||||
priv(const string& label,
|
||||
const string& file_name_regex_str,
|
||||
const string& file_name_not_regex_str)
|
||||
: label_(label),
|
||||
: is_artificial_(),
|
||||
label_(label),
|
||||
file_name_regex_str_(file_name_regex_str),
|
||||
file_name_not_regex_str_(file_name_not_regex_str)
|
||||
{}
|
||||
@ -190,6 +195,26 @@ suppression_base::suppression_base(const string& label,
|
||||
{
|
||||
}
|
||||
|
||||
/// Test is the suppression specification is artificial.
|
||||
///
|
||||
/// Artificial means that the suppression was automatically generated
|
||||
/// by libabigail, rather than being constructed from a suppression
|
||||
/// file provided by the user.
|
||||
///
|
||||
/// @return TRUE iff the suppression specification is artificial.
|
||||
bool
|
||||
suppression_base::get_is_artificial() const
|
||||
{return priv_->is_artificial_;}
|
||||
|
||||
/// Set a flag saying if the suppression specification is artificial
|
||||
/// or not.
|
||||
///
|
||||
/// Artificial means that the suppression was automatically generated
|
||||
/// by libabigail, rather than being constructed from a suppression
|
||||
/// file provided by the user.
|
||||
void
|
||||
suppression_base::set_is_artificial(bool f)
|
||||
{priv_->is_artificial_ = f;}
|
||||
|
||||
/// Getter for the label associated to this suppression specification.
|
||||
///
|
||||
@ -484,7 +509,7 @@ class type_suppression::priv
|
||||
bool consider_reach_kind_;
|
||||
type_suppression::reach_kind reach_kind_;
|
||||
type_suppression::insertion_ranges insertion_ranges_;
|
||||
vector<string> source_locations_to_keep_;
|
||||
unordered_set<string> source_locations_to_keep_;
|
||||
string source_location_to_keep_regex_str_;
|
||||
mutable sptr_utils::regex_t_sptr source_location_to_keep_regex_;
|
||||
|
||||
@ -739,13 +764,22 @@ type_suppression::insertion_ranges&
|
||||
type_suppression::get_data_member_insertion_ranges()
|
||||
{return priv_->insertion_ranges_;}
|
||||
|
||||
/// Getter for the array of source location paths of types that should
|
||||
/// *NOT* be suppressed.
|
||||
///
|
||||
/// @return the set of source locations of types that should *NOT* be
|
||||
/// supressed.
|
||||
const unordered_set<string>&
|
||||
type_suppression::get_source_locations_to_keep() const
|
||||
{return priv_->source_locations_to_keep_;}
|
||||
|
||||
/// Getter for the array of source location paths of types that should
|
||||
/// *NOT* be suppressed.
|
||||
///
|
||||
/// @return the array of source locations of types that should *NOT*
|
||||
/// be supressed.
|
||||
const vector<string>&
|
||||
type_suppression::get_source_locations_to_keep() const
|
||||
unordered_set<string>&
|
||||
type_suppression::get_source_locations_to_keep()
|
||||
{return priv_->source_locations_to_keep_;}
|
||||
|
||||
/// Setter for the array of source location paths of types that should
|
||||
@ -753,7 +787,8 @@ type_suppression::get_source_locations_to_keep() const
|
||||
///
|
||||
/// @param l the new array.
|
||||
void
|
||||
type_suppression::set_source_locations_to_keep(const vector<string>& l)
|
||||
type_suppression::set_source_locations_to_keep
|
||||
(const unordered_set<string>& l)
|
||||
{priv_->source_locations_to_keep_ = l;}
|
||||
|
||||
/// Getter of the regular expression string that designates the source
|
||||
@ -784,7 +819,34 @@ type_suppression::suppresses_diff(const diff* diff) const
|
||||
{
|
||||
const type_diff_base* d = is_type_diff(diff);
|
||||
if (!d)
|
||||
return false;
|
||||
{
|
||||
// So the diff we are looking at is not a type diff. However,
|
||||
// there are cases where a type suppression can suppress changes
|
||||
// on functions.
|
||||
|
||||
// Typically, if a virtual member function's virtual index (its
|
||||
// index in the vtable of a class) changes and if the current
|
||||
// type suppression is meant to suppress change reports about
|
||||
// the enclosing class of the virtual member function, then this
|
||||
// type suppression should suppress reports about that function
|
||||
// change.
|
||||
const function_decl_diff* d = is_function_decl_diff(diff);
|
||||
if (d)
|
||||
{
|
||||
// Let's see if 'd' carries a virtual member function
|
||||
// change.
|
||||
if (comparison::filtering::has_virtual_mem_fn_change(d))
|
||||
{
|
||||
function_decl_sptr f = d->first_function_decl();
|
||||
class_decl_sptr fc =
|
||||
is_method_type(f->get_type())->get_class_type();
|
||||
assert(fc);
|
||||
if (suppresses_type(fc, diff->context()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the suppression should consider the way the diff node has been
|
||||
// reached, then do it now.
|
||||
@ -995,6 +1057,17 @@ type_suppression::suppresses_type(const type_base_sptr& type,
|
||||
if (decl_base_sptr d = get_type_declaration(type))
|
||||
{
|
||||
location loc = d->get_location();
|
||||
if (!loc)
|
||||
{
|
||||
if (class_decl_sptr c = is_class_type(d))
|
||||
if (c->get_is_declaration_only()
|
||||
&& c->get_definition_of_declaration())
|
||||
{
|
||||
c = c->get_definition_of_declaration();
|
||||
loc = c->get_location();
|
||||
}
|
||||
}
|
||||
|
||||
if (loc)
|
||||
{
|
||||
translation_unit* tu = get_translation_unit(d);
|
||||
@ -1011,15 +1084,12 @@ type_suppression::suppresses_type(const type_base_sptr& type,
|
||||
return false;
|
||||
|
||||
tools_utils::base_name(loc_path, loc_path_base);
|
||||
for (vector<string>::const_iterator s =
|
||||
get_source_locations_to_keep().begin();
|
||||
s != get_source_locations_to_keep().end();
|
||||
++s)
|
||||
{
|
||||
if (tools_utils::string_ends_with(*s, loc_path)
|
||||
|| tools_utils::string_ends_with(*s, loc_path_base))
|
||||
return false;
|
||||
}
|
||||
if (get_source_locations_to_keep().find(loc_path_base)
|
||||
!= get_source_locations_to_keep().end())
|
||||
return false;
|
||||
if (get_source_locations_to_keep().find(loc_path)
|
||||
!= get_source_locations_to_keep().end())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1034,6 +1104,29 @@ type_suppression::suppresses_type(const type_base_sptr& type,
|
||||
}
|
||||
else
|
||||
{
|
||||
// So the type had no source location.
|
||||
//
|
||||
// In the case where this type suppression was automatically
|
||||
// generated to suppress types not defined in public
|
||||
// headers, then this might mean that the type is not
|
||||
// defined in the public headers. Otherwise, why does it
|
||||
// not have a source location?
|
||||
if (get_is_artificial())
|
||||
{
|
||||
if (class_decl_sptr cl = is_class_type(d))
|
||||
{
|
||||
if (cl->get_is_declaration_only())
|
||||
// We tried hard above to get the definition of
|
||||
// the declaration. If we reach this place, it
|
||||
// means the class has no definition at this point.
|
||||
assert(!cl->get_definition_of_declaration());
|
||||
if (get_label() == tools_utils::PRIVATE_TYPES_SUPPR_SPEC_NAME)
|
||||
// So this looks like what really amounts to an
|
||||
// opaque type. So it's not defined in the public
|
||||
// headers. So we want to filter it out.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!get_source_locations_to_keep().empty()
|
||||
|| priv_->get_source_location_to_keep_regex())
|
||||
// The user provided a "source_location_not_regexp" or
|
||||
@ -1485,17 +1578,23 @@ read_type_suppression(const ini::config::section& section)
|
||||
|
||||
ini::property_sptr srcloc_not_in_prop =
|
||||
section.find_property("source_location_not_in");
|
||||
vector<string> srcloc_not_in;
|
||||
unordered_set<string> srcloc_not_in;
|
||||
if (srcloc_not_in_prop)
|
||||
{
|
||||
if (ini::simple_property_sptr p = is_simple_property(srcloc_not_in_prop))
|
||||
srcloc_not_in.push_back(p->get_value()->as_string());
|
||||
srcloc_not_in.insert(p->get_value()->as_string());
|
||||
else
|
||||
{
|
||||
ini::list_property_sptr list_property =
|
||||
is_list_property(srcloc_not_in_prop);
|
||||
if (list_property)
|
||||
srcloc_not_in = list_property->get_value()->get_content();
|
||||
{
|
||||
vector<string>::const_iterator i;
|
||||
for (i = list_property->get_value()->get_content().begin();
|
||||
i != list_property->get_value()->get_content().end();
|
||||
++i)
|
||||
srcloc_not_in.insert(*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <fts.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctype.h>
|
||||
@ -40,6 +41,8 @@ using std::string;
|
||||
namespace abigail
|
||||
{
|
||||
|
||||
using namespace abigail::suppr;
|
||||
|
||||
/// @brief Namespace for a set of utility function used by tools based
|
||||
/// on libabigail.
|
||||
namespace tools_utils
|
||||
@ -772,6 +775,77 @@ make_path_absolute(const char*p)
|
||||
return result;
|
||||
}
|
||||
|
||||
/// The name of the artificial private type suppression specification
|
||||
/// that is auto-generated by libabigail to suppress change reports
|
||||
/// about types that are not defined in public headers.
|
||||
const char* PRIVATE_TYPES_SUPPR_SPEC_NAME =
|
||||
"Artificial private types suppression specification";
|
||||
|
||||
/// This is a sub-routine of gen_suppr_spec_from_headers.
|
||||
///
|
||||
/// @param entry if this file represents a regular (or symlink) file,
|
||||
/// then its file name is going to be added to the vector returned by
|
||||
/// type_suppression::get_source_locations_to_keep().
|
||||
///
|
||||
/// @param if @p entry represents a file, then its file name is going
|
||||
/// to be added to the vector returned by the method
|
||||
/// type_suppression::get_source_locations_to_keep of this instance.
|
||||
/// If this smart pointer is nil then a new instance @ref
|
||||
/// type_suppression is created and this variable is made to point to
|
||||
/// it.
|
||||
static void
|
||||
handle_fts_entry(const FTSENT *entry,
|
||||
type_suppression_sptr& suppr)
|
||||
{
|
||||
if (entry == NULL
|
||||
|| (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
|
||||
|| entry->fts_info == FTS_ERR
|
||||
|| entry->fts_info == FTS_NS)
|
||||
return;
|
||||
|
||||
string fname = entry->fts_name;
|
||||
if (!fname.empty())
|
||||
{
|
||||
if (string_ends_with(fname, ".h")
|
||||
|| string_ends_with(fname, ".hpp")
|
||||
|| string_ends_with(fname, ".hxx"))
|
||||
{
|
||||
if (!suppr)
|
||||
suppr.reset(new type_suppression(PRIVATE_TYPES_SUPPR_SPEC_NAME,
|
||||
/*type_name_regexp=*/"",
|
||||
/*type_name=*/""));
|
||||
suppr->set_is_artificial(true);
|
||||
suppr->get_source_locations_to_keep().insert(fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a type suppression specification that suppresses ABI
|
||||
/// changes for types defines in source files that are *NOT* in a give
|
||||
/// header root dir.
|
||||
///
|
||||
/// @param headers_root_dir ABI changes in types defined in files
|
||||
/// *NOT* found in this directory tree are going be suppressed.
|
||||
///
|
||||
/// @return the resulting type suppression generated, if any file was
|
||||
/// found in the directory tree @p headers_root_dir.
|
||||
type_suppression_sptr
|
||||
gen_suppr_spec_from_headers(const string& headers_root_dir)
|
||||
{
|
||||
char* paths[] = {const_cast<char*>(headers_root_dir.c_str()), 0};
|
||||
type_suppression_sptr result;
|
||||
|
||||
FTS *file_hierarchy = fts_open(paths, FTS_LOGICAL|FTS_NOCHDIR, NULL);
|
||||
if (!file_hierarchy)
|
||||
return result;
|
||||
|
||||
FTSENT *entry;
|
||||
while ((entry = fts_read(file_hierarchy)))
|
||||
handle_fts_entry(entry, result);
|
||||
fts_close(file_hierarchy);
|
||||
return result;
|
||||
}
|
||||
|
||||
}//end namespace tools_utils
|
||||
|
||||
using abigail::ir::function_decl;
|
||||
|
@ -928,6 +928,18 @@ test-diff-suppr/test29-suppr-5.txt \
|
||||
test-diff-suppr/test29-suppr-6.txt \
|
||||
test-diff-suppr/test29-suppr-7.txt \
|
||||
test-diff-suppr/test29-suppr-8.txt \
|
||||
test-diff-suppr/test30-include-dir-v0/test30-pub-lib-v0.h \
|
||||
test-diff-suppr/test30-include-dir-v1/test30-pub-lib-v1.h \
|
||||
test-diff-suppr/test30-priv-lib-v0.cc \
|
||||
test-diff-suppr/test30-priv-lib-v0.h \
|
||||
test-diff-suppr/test30-priv-lib-v1.cc \
|
||||
test-diff-suppr/test30-priv-lib-v1.h \
|
||||
test-diff-suppr/test30-pub-lib-v0.cc \
|
||||
test-diff-suppr/test30-pub-lib-v0.so \
|
||||
test-diff-suppr/test30-pub-lib-v1.cc \
|
||||
test-diff-suppr/test30-pub-lib-v1.so \
|
||||
test-diff-suppr/test30-report-0.txt \
|
||||
test-diff-suppr/test30-report-1.txt \
|
||||
\
|
||||
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
|
||||
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \
|
||||
@ -1125,7 +1137,10 @@ test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64.rpm \
|
||||
test-diff-pkg/tbb-4.3-3.20141204.fc23.x86_64.rpm \
|
||||
test-diff-pkg/tbb-debuginfo-4.1-9.20130314.fc22.x86_64.rpm \
|
||||
test-diff-pkg/tbb-debuginfo-4.3-3.20141204.fc23.x86_64.rpm \
|
||||
test-diff-pkg/tbb-devel-4.1-9.20130314.fc22.x86_64.rpm \
|
||||
test-diff-pkg/tbb-devel-4.3-3.20141204.fc23.x86_64.rpm \
|
||||
test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt \
|
||||
test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt \
|
||||
test-diff-pkg/libICE-debuginfo-1.0.6-1.el6.x86_64.rpm \
|
||||
test-diff-pkg/libICE-debuginfo-1.0.9-2.el7.x86_64.rpm \
|
||||
test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm \
|
||||
@ -1140,3 +1155,4 @@ test-diff-pkg/tarpkg-1-dir1.tar.gz \
|
||||
test-diff-pkg/tarpkg-1-dir2.tar.gz \
|
||||
test-diff-pkg/tarpkg-1-report-0.txt
|
||||
|
||||
|
||||
|
@ -0,0 +1,160 @@
|
||||
================ changes of 'libtbb.so.2'===============
|
||||
Functions changes summary: 0 Removed, 7 Changed (17 filtered out), 17 Added functions
|
||||
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
|
||||
Function symbols changes summary: 0 Removed, 0 Added function symbol not referenced by debug info
|
||||
Variable symbols changes summary: 3 Removed, 0 Added variable symbols not referenced by debug info
|
||||
|
||||
17 Added functions:
|
||||
|
||||
'method int tbb::interface7::internal::task_arena_base::internal_current_slot()' {_ZN3tbb10interface78internal15task_arena_base21internal_current_slotEv}
|
||||
'method void tbb::interface7::internal::task_arena_base::internal_enqueue(tbb::task&, intptr_t)' {_ZNK3tbb10interface78internal15task_arena_base16internal_enqueueERNS_4taskEl}
|
||||
'method void tbb::interface7::internal::task_arena_base::internal_execute(tbb::interface7::internal::delegate_base&)' {_ZNK3tbb10interface78internal15task_arena_base16internal_executeERNS1_13delegate_baseE}
|
||||
'method void tbb::interface7::internal::task_arena_base::internal_initialize()' {_ZN3tbb10interface78internal15task_arena_base19internal_initializeEv}
|
||||
'method void tbb::interface7::internal::task_arena_base::internal_terminate()' {_ZN3tbb10interface78internal15task_arena_base18internal_terminateEv}
|
||||
'method void tbb::interface7::internal::task_arena_base::internal_wait()' {_ZNK3tbb10interface78internal15task_arena_base13internal_waitEv}
|
||||
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_acquire_reader(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&, bool)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex23internal_acquire_readerERNS2_11scoped_lockEb}
|
||||
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_acquire_writer(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&, bool)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex23internal_acquire_writerERNS2_11scoped_lockEb}
|
||||
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_construct()' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex18internal_constructEv}
|
||||
'method bool tbb::interface8::internal::x86_rtm_rw_mutex::internal_downgrade(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex18internal_downgradeERNS2_11scoped_lockE}
|
||||
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_release(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex16internal_releaseERNS2_11scoped_lockE}
|
||||
'method bool tbb::interface8::internal::x86_rtm_rw_mutex::internal_try_acquire_writer(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex27internal_try_acquire_writerERNS2_11scoped_lockE}
|
||||
'method bool tbb::interface8::internal::x86_rtm_rw_mutex::internal_upgrade(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex16internal_upgradeERNS2_11scoped_lockE}
|
||||
'method void tbb::internal::concurrent_queue_base_v8::internal_push_move()' {_ZN3tbb8internal24concurrent_queue_base_v818internal_push_moveEPKv}
|
||||
'method bool tbb::internal::concurrent_queue_base_v8::internal_push_move_if_not_full()' {_ZN3tbb8internal24concurrent_queue_base_v830internal_push_move_if_not_fullEPKv}
|
||||
'method void tbb::internal::concurrent_queue_base_v8::move_content(tbb::internal::concurrent_queue_base_v8&)' {_ZN3tbb8internal24concurrent_queue_base_v812move_contentERS1_}
|
||||
'method void tbb::task_group_context::capture_fp_settings()' {_ZN3tbb18task_group_context19capture_fp_settingsEv}
|
||||
|
||||
7 functions with some indirect sub-type change:
|
||||
|
||||
[C]'function void tbb::internal::throw_exception_v4(tbb::internal::exception_id)' at tbb_misc.cpp:119:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'enum tbb::internal::exception_id' has sub-type changes:
|
||||
1 enumerator insertion:
|
||||
'tbb::internal::exception_id::eid_bad_tagged_msg_cast' value '20'
|
||||
|
||||
1 enumerator change:
|
||||
'tbb::internal::exception_id::eid_max' from value '20' to '21'
|
||||
|
||||
|
||||
[C]'method void tbb::mutex::scoped_lock::internal_acquire(tbb::mutex&)' at mutex.h:129:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'tbb::mutex&' has sub-type changes:
|
||||
in referenced type 'class tbb::mutex' at mutex.h:40:1:
|
||||
1 base class insertion:
|
||||
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
|
||||
|
||||
[C]'method void tbb::pipeline::run(std::size_t, tbb::task_group_context&)' at pipeline.cpp:633:1 has some indirect sub-type changes:
|
||||
parameter 2 of type 'tbb::task_group_context&' has sub-type changes:
|
||||
in referenced type 'class tbb::task_group_context' at task.h:302:1:
|
||||
1 data member insertion:
|
||||
'tbb::internal::cpu_ctl_env_space tbb::task_group_context::my_cpu_ctl_env', at offset 896 (in bits) at task.h:380:1
|
||||
1 data member changes (2 filtered):
|
||||
type of 'char tbb::task_group_context::_leading_padding[80]' changed:
|
||||
type name changed from 'char[80]' to 'char[72]'
|
||||
array type size changed from 640 to 576 bits:
|
||||
array type subrange 1 changed length from 80 to 72
|
||||
|
||||
|
||||
[C]'method void tbb::queuing_mutex::scoped_lock::acquire(tbb::queuing_mutex&)' at queuing_mutex.h:84:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'tbb::queuing_mutex&' has sub-type changes:
|
||||
in referenced type 'class tbb::queuing_mutex' at queuing_mutex.h:45:1:
|
||||
1 base class insertion:
|
||||
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
|
||||
no data member change (1 filtered);
|
||||
|
||||
[C]'method void tbb::queuing_rw_mutex::scoped_lock::acquire(tbb::queuing_rw_mutex&, bool)' at queuing_rw_mutex.h:95:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'tbb::queuing_rw_mutex&' has sub-type changes:
|
||||
in referenced type 'class tbb::queuing_rw_mutex' at queuing_rw_mutex.h:47:1:
|
||||
1 base class insertion:
|
||||
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
|
||||
no data member change (1 filtered);
|
||||
|
||||
[C]'method void tbb::recursive_mutex::scoped_lock::internal_acquire(tbb::recursive_mutex&)' at recursive_mutex.h:139:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'tbb::recursive_mutex&' has sub-type changes:
|
||||
in referenced type 'class tbb::recursive_mutex' at recursive_mutex.h:39:1:
|
||||
1 base class insertion:
|
||||
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
|
||||
|
||||
[C]'method void tbb::spin_mutex::scoped_lock::internal_acquire(tbb::spin_mutex&)' at spin_mutex.h:66:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'tbb::spin_mutex&' has sub-type changes:
|
||||
in referenced type 'class tbb::spin_mutex' at spin_mutex.h:40:1:
|
||||
1 base class insertion:
|
||||
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
|
||||
|
||||
|
||||
3 Removed variable symbols not referenced by debug info:
|
||||
|
||||
_ZTVN3rml16versioned_objectE
|
||||
_ZTVN3rml6clientE
|
||||
_ZTVN3rml6serverE
|
||||
|
||||
================ end of changes of 'libtbb.so.2'===============
|
||||
|
||||
================ changes of 'libtbbmalloc.so.2'===============
|
||||
Functions changes summary: 9 Removed, 0 Changed, 0 Added functions
|
||||
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
|
||||
Function symbols changes summary: 0 Removed, 27 Added function symbols not referenced by debug info
|
||||
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info
|
||||
|
||||
9 Removed functions:
|
||||
|
||||
'function void* rml::internal::__TBB_internal_calloc(size_t, size_t)' {__TBB_internal_calloc}
|
||||
'function void rml::internal::__TBB_internal_free(void*)' {__TBB_internal_free}
|
||||
'function void* rml::internal::__TBB_internal_malloc(size_t)' {__TBB_internal_malloc}
|
||||
'function int rml::internal::__TBB_internal_posix_memalign(void**, size_t, size_t)' {__TBB_internal_posix_memalign}
|
||||
'function void* rml::internal::__TBB_internal_realloc(void*, size_t)' {__TBB_internal_realloc}
|
||||
'function void* safer_scalable_aligned_realloc(void*, size_t, size_t, void*)' {safer_scalable_aligned_realloc}
|
||||
'function void safer_scalable_free(void*, void (void*)*)' {safer_scalable_free}
|
||||
'function size_t safer_scalable_msize(void*, typedef size_t (void*)*)' {safer_scalable_msize}
|
||||
'function void* safer_scalable_realloc(void*, size_t, void*)' {safer_scalable_realloc}
|
||||
|
||||
|
||||
27 Added function symbols not referenced by debug info:
|
||||
|
||||
_Z10BitScanRevm
|
||||
_Z10FencedLoadRVKl
|
||||
_Z11FencedStoreRVll
|
||||
_Z15AtomicIncrementRVl
|
||||
_Z15SpinWaitWhileEqRVKll
|
||||
_Z16AtomicFetchStorePVvm
|
||||
_Z21AtomicCompareExchangeRVlll
|
||||
_Z8AtomicOrPVvm
|
||||
_Z8do_yieldv
|
||||
_Z9AtomicAddRVll
|
||||
_Z9AtomicAndPVvm
|
||||
_ZN11MallocMutex11scoped_lockC1ERS_
|
||||
_ZN11MallocMutex11scoped_lockC1ERS_bPb, aliases _ZN11MallocMutex11scoped_lockC2ERS_bPb
|
||||
_ZN11MallocMutex11scoped_lockC2ERS_, aliases _ZN11MallocMutex11scoped_lockC1ERS_
|
||||
_ZN11MallocMutex11scoped_lockC2ERS_bPb
|
||||
_ZN11MallocMutex11scoped_lockD1Ev, aliases _ZN11MallocMutex11scoped_lockD2Ev
|
||||
_ZN11MallocMutex11scoped_lockD2Ev
|
||||
_ZN11MallocMutexC1Ev, aliases _ZN11MallocMutexC2Ev
|
||||
_ZN11MallocMutexC2Ev
|
||||
_ZdlPvS_
|
||||
_ZnwmPv
|
||||
__TBB_malloc_safer_aligned_msize
|
||||
__TBB_malloc_safer_aligned_realloc
|
||||
__TBB_malloc_safer_free
|
||||
__TBB_malloc_safer_msize
|
||||
__TBB_malloc_safer_realloc
|
||||
scalable_allocation_command
|
||||
|
||||
================ end of changes of 'libtbbmalloc.so.2'===============
|
||||
|
||||
================ changes of 'libtbbmalloc_proxy.so.2'===============
|
||||
Functions changes summary: 1 Removed, 0 Changed, 5 Added functions
|
||||
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
|
||||
|
||||
1 Removed function:
|
||||
|
||||
'function bool __TBB_internal_find_original_malloc(int, const char**, void**)' {__TBB_internal_find_original_malloc}
|
||||
|
||||
5 Added functions:
|
||||
|
||||
'function void __libc_free(void*)' {__libc_free}
|
||||
'function void* __libc_realloc(void*, size_t)' {__libc_realloc}
|
||||
'function void* calloc(size_t, size_t)' {__libc_calloc, aliases calloc}
|
||||
'function size_t malloc_usable_size(void*)' {malloc_usable_size}
|
||||
'function void* valloc(size_t)' {__libc_valloc, aliases valloc}
|
||||
|
||||
|
||||
================ end of changes of 'libtbbmalloc_proxy.so.2'===============
|
||||
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,9 @@
|
||||
class S
|
||||
{
|
||||
class priv_type;
|
||||
priv_type* priv;
|
||||
|
||||
friend int public_function(S*);
|
||||
};
|
||||
|
||||
int public_function(S*);
|
@ -0,0 +1,9 @@
|
||||
class S
|
||||
{
|
||||
class priv_type;
|
||||
priv_type* priv;
|
||||
|
||||
friend int public_function(S*);
|
||||
};
|
||||
|
||||
int public_function(S*);
|
4
tests/data/test-diff-suppr/test30-priv-lib-v0.cc
Normal file
4
tests/data/test-diff-suppr/test30-priv-lib-v0.cc
Normal file
@ -0,0 +1,4 @@
|
||||
// Compile this with:
|
||||
// g++ -g -Wall -shared -fPIC -o test30-priv-lib-v0.so test30-priv-lib-v0.cc
|
||||
|
||||
#include "test30-priv-lib-v0.h"
|
18
tests/data/test-diff-suppr/test30-priv-lib-v0.h
Normal file
18
tests/data/test-diff-suppr/test30-priv-lib-v0.h
Normal file
@ -0,0 +1,18 @@
|
||||
// This is a class that, when #included in a .cc file will generate a
|
||||
// dwarf representation that is declaration-only class because the all
|
||||
// of the methods of the class are inline virtual methods but one.
|
||||
// And the one virtual method that is not inline is not defined. So
|
||||
// the .cc file that is going to define that method is going to see
|
||||
// the class as being defined, and that file will also have the
|
||||
// definition of the vtable.
|
||||
class non_defined_class
|
||||
{
|
||||
public:
|
||||
virtual int virtual_func_to_be_removed(){return 0;}
|
||||
non_defined_class(){};
|
||||
virtual ~non_defined_class(){}
|
||||
virtual int virtual_func0(){return 0;}
|
||||
virtual int virtual_func1();
|
||||
};
|
||||
|
||||
int private_function(non_defined_class *);
|
23
tests/data/test-diff-suppr/test30-priv-lib-v1.cc
Normal file
23
tests/data/test-diff-suppr/test30-priv-lib-v1.cc
Normal file
@ -0,0 +1,23 @@
|
||||
// Compile this with:
|
||||
// g++ -g -Wall -shared -fPIC -o test30-priv-lib-v1.so test30-priv-lib-v1.cc
|
||||
|
||||
#include "test30-priv-lib-v1.h"
|
||||
|
||||
class opaque_class
|
||||
{
|
||||
public:
|
||||
virtual int inserted_member();
|
||||
virtual int member0();
|
||||
};
|
||||
|
||||
int
|
||||
opaque_class::member0()
|
||||
{return 0;}
|
||||
|
||||
int
|
||||
opaque_class::inserted_member()
|
||||
{return 0;}
|
||||
|
||||
int
|
||||
private_function(opaque_class *o)
|
||||
{return o->member0() + o->inserted_member();}
|
18
tests/data/test-diff-suppr/test30-priv-lib-v1.h
Normal file
18
tests/data/test-diff-suppr/test30-priv-lib-v1.h
Normal file
@ -0,0 +1,18 @@
|
||||
// This is a class that, when #included in a .cc file will generate a
|
||||
// dwarf representation that is declaration-only class because the all
|
||||
// of the methods of the class are inline virtual methods but one.
|
||||
// And the one virtual method that is not inline is not defined. So
|
||||
// the .cc file that is going to define that method is going to see
|
||||
// the class as being defined, and that file will also have the
|
||||
// definition of the vtable.
|
||||
class non_defined_class
|
||||
{
|
||||
public:
|
||||
non_defined_class(){};
|
||||
virtual ~non_defined_class(){}
|
||||
virtual int virtual_func_inserted(){return 0;};
|
||||
virtual int virtual_func1();
|
||||
virtual int virtual_func0(){return 0;}
|
||||
};
|
||||
|
||||
int private_function(non_defined_class *);
|
22
tests/data/test-diff-suppr/test30-pub-lib-v0.cc
Normal file
22
tests/data/test-diff-suppr/test30-pub-lib-v0.cc
Normal file
@ -0,0 +1,22 @@
|
||||
// Compile this with:
|
||||
// g++ -g -Wall -shared -fPIC -o test30-pub-lib-v0.so test30-pub-lib-v0.cc
|
||||
|
||||
#include "test30-include-dir-v0/test30-pub-lib-v0.h"
|
||||
#include "test30-priv-lib-v0.h"
|
||||
|
||||
int
|
||||
private_function(non_defined_class*)
|
||||
{
|
||||
non_defined_class o;
|
||||
return o.virtual_func0() + o.virtual_func_to_be_removed();
|
||||
}
|
||||
|
||||
class S::priv_type
|
||||
{
|
||||
public:
|
||||
non_defined_class* member0;
|
||||
};
|
||||
|
||||
int
|
||||
public_function(S* s)
|
||||
{return private_function(s->priv->member0);}
|
BIN
tests/data/test-diff-suppr/test30-pub-lib-v0.so
Executable file
BIN
tests/data/test-diff-suppr/test30-pub-lib-v0.so
Executable file
Binary file not shown.
23
tests/data/test-diff-suppr/test30-pub-lib-v1.cc
Normal file
23
tests/data/test-diff-suppr/test30-pub-lib-v1.cc
Normal file
@ -0,0 +1,23 @@
|
||||
// Compile this with:
|
||||
// g++ -g -Wall -shared -fPIC -o test30-pub-lib-v1.so test30-pub-lib-v1.cc
|
||||
|
||||
#include "test30-include-dir-v1/test30-pub-lib-v1.h"
|
||||
#include "test30-priv-lib-v1.h"
|
||||
|
||||
int
|
||||
private_function(non_defined_class *)
|
||||
{
|
||||
non_defined_class o;
|
||||
return o.virtual_func0() + o.virtual_func_inserted();
|
||||
}
|
||||
|
||||
class S::priv_type
|
||||
{
|
||||
public:
|
||||
non_defined_class* member0;
|
||||
int member1;
|
||||
};
|
||||
|
||||
int
|
||||
public_function(S* s)
|
||||
{return private_function(s->priv->member0) + s->priv->member1;}
|
BIN
tests/data/test-diff-suppr/test30-pub-lib-v1.so
Executable file
BIN
tests/data/test-diff-suppr/test30-pub-lib-v1.so
Executable file
Binary file not shown.
32
tests/data/test-diff-suppr/test30-report-0.txt
Normal file
32
tests/data/test-diff-suppr/test30-report-0.txt
Normal file
@ -0,0 +1,32 @@
|
||||
Functions changes summary: 1 Removed, 2 Changed, 1 Added functions
|
||||
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
|
||||
|
||||
1 Removed function:
|
||||
|
||||
'method virtual int non_defined_class::virtual_func_to_be_removed()' {_ZN17non_defined_class26virtual_func_to_be_removedEv}
|
||||
note that this removes an entry from the vtable of class non_defined_class
|
||||
|
||||
1 Added function:
|
||||
|
||||
'method virtual int non_defined_class::virtual_func_inserted()' {_ZN17non_defined_class21virtual_func_insertedEv}
|
||||
note that this adds a new entry to the vtable of class non_defined_class
|
||||
|
||||
2 functions with some indirect sub-type change:
|
||||
|
||||
[C]'method virtual int non_defined_class::virtual_func0()' at test30-priv-lib-v1.h:15:1 has some indirect sub-type changes:
|
||||
the vtable offset of method virtual int non_defined_class::virtual_func0() changed from 3 to 4
|
||||
note that this is an ABI incompatible change to the vtable of class non_defined_class
|
||||
|
||||
[C]'function int public_function(S*)' at test30-pub-lib-v1.cc:22:1 has some indirect sub-type changes:
|
||||
parameter 1 of type 'S*' has sub-type changes:
|
||||
in pointed to type 'class S' at test30-pub-lib-v1.h:1:1:
|
||||
1 data member change:
|
||||
type of 'S::priv_type* S::priv' changed:
|
||||
in pointed to type 'class S::priv_type' at test30-pub-lib-v1.cc:14:1:
|
||||
type size changed from 64 to 128 bits
|
||||
1 data member insertion:
|
||||
'int S::priv_type::member1', at offset 64 (in bits) at test30-pub-lib-v1.cc:18:1
|
||||
|
||||
|
||||
|
||||
|
3
tests/data/test-diff-suppr/test30-report-1.txt
Normal file
3
tests/data/test-diff-suppr/test30-report-1.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Functions changes summary: 0 Removed (1 filtered out), 0 Changed (2 filtered out), 0 Added function (1 filtered out)
|
||||
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
|
||||
|
@ -55,6 +55,8 @@ struct InOutSpec
|
||||
const char* suppression_path;
|
||||
const char* first_in_debug_package_path;
|
||||
const char* second_in_debug_package_path;
|
||||
const char* first_in_devel_package_path;
|
||||
const char* second_in_devel_package_path;
|
||||
const char* ref_report_path;
|
||||
const char* out_report_path;
|
||||
};// end struct InOutSpec
|
||||
@ -69,6 +71,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dirpkg-0-report-0.txt",
|
||||
"output/test-diff-pkg/dirpkg-0-report-0.txt"
|
||||
},
|
||||
@ -80,6 +84,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dirpkg-1-report-0.txt",
|
||||
"output/test-diff-pkg/dirpkg-1-report-0.txt"
|
||||
},
|
||||
@ -92,6 +98,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dirpkg-1-report-1.txt",
|
||||
"output/test-diff-pkg/dirpkg-1-report-1.txt"
|
||||
},
|
||||
@ -104,6 +112,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dirpkg-2-report-0.txt",
|
||||
"output/test-diff-pkg/dirpkg-2-report-0.txt"
|
||||
},
|
||||
@ -117,6 +127,8 @@ static InOutSpec in_out_specs[] =
|
||||
"data/test-diff-pkg/dirpkg-3.suppr",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dirpkg-3-report-0.txt",
|
||||
"output/test-diff-pkg/dirpkg-3-report-0.txt"
|
||||
},
|
||||
@ -131,6 +143,8 @@ static InOutSpec in_out_specs[] =
|
||||
"data/test-diff-pkg/dirpkg-3.suppr",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dirpkg-3-report-1.txt",
|
||||
"output/test-diff-pkg/dirpkg-3-report-1.txt"
|
||||
},
|
||||
@ -141,6 +155,8 @@ static InOutSpec in_out_specs[] =
|
||||
"data/test-diff-pkg/dirpkg-3.suppr",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dirpkg-3-report-2.txt",
|
||||
"output/test-diff-pkg/dirpkg-3-report-2.txt"
|
||||
},
|
||||
@ -151,6 +167,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/symlink-dir-test1-report0.txt ",
|
||||
"output/test-diff-pkg/symlink-dir-test1-report0.txt "
|
||||
},
|
||||
@ -162,6 +180,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/tarpkg-0-report-0.txt",
|
||||
"output/test-diff-pkg/tarpkg-0-report-0.txt"
|
||||
},
|
||||
@ -172,6 +192,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/tarpkg-0-report-0.txt",
|
||||
"output/test-diff-pkg/tarpkg-0-report-01.txt"
|
||||
},
|
||||
@ -182,6 +204,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/tarpkg-0-report-0.txt",
|
||||
"output/test-diff-pkg/tarpkg-0-report-02.txt"
|
||||
},
|
||||
@ -192,6 +216,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/tarpkg-0-report-0.txt",
|
||||
"output/test-diff-pkg/tarpkg-0-report-03.txt"
|
||||
},
|
||||
@ -202,6 +228,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/tarpkg-1-report-0.txt",
|
||||
"output/test-diff-pkg/tarpkg-1-report-0.txt"
|
||||
},
|
||||
@ -216,55 +244,65 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-0.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-0.txt"
|
||||
},
|
||||
// Two RPM packages with 2nd package debuginfo missing
|
||||
{
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-1.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-1.txt"
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-1.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-1.txt"
|
||||
},
|
||||
|
||||
// Two RPM packages with first package debuginfo missing
|
||||
{
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
|
||||
"data/test-diff-pkg/test-rpm-report-2.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-2.txt"
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-2.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-2.txt"
|
||||
},
|
||||
|
||||
// Two RPM packages with missing debuginfo
|
||||
{
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-3.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-3.txt"
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-3.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-3.txt"
|
||||
},
|
||||
|
||||
// Two RPM packages with no ABI change
|
||||
{
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/test-rpm-report-4.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-4.txt"
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
|
||||
"--no-show-locs",
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-4.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-4.txt"
|
||||
},
|
||||
// Two RPM packages with debuginfo available and we don't want to
|
||||
// see added symbols.
|
||||
@ -275,6 +313,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
|
||||
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/test-rpm-report-5.txt",
|
||||
"output/test-diff-pkg/test-rpm-report-5.txt"
|
||||
},
|
||||
@ -285,17 +325,22 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"data/test-diff-pkg/qemu-kvm-rhev-debuginfo-2.3.0-7.el7.ppc64.rpm",
|
||||
"data/test-diff-pkg/qemu-kvm-rhev-debuginfo-2.3.0-20.el7.ppc64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/qemu-img-rhev-2.3.0-7.el7.ppc64--qemu-img-rhev-2.3.0-20.el7.ppc64-report-0.txt",
|
||||
"output/test-diff-pkg/qemu-img-rhev-2.3.0-7.el7.ppc64--qemu-img-rhev-2.3.0-20.el7.ppc64-report-0.txt"
|
||||
},
|
||||
{"data/test-diff-pkg/empty-pkg-libvirt-0.9.11.3-1.el7.ppc64.rpm",
|
||||
"data/test-diff-pkg/empty-pkg-libvirt-1.2.17-13.el7_2.2.ppc64.rpm",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/empty-pkg-report-0.txt",
|
||||
"output/test-diff-pkg/empty-pkg-report-0.txt"
|
||||
{
|
||||
"data/test-diff-pkg/empty-pkg-libvirt-0.9.11.3-1.el7.ppc64.rpm",
|
||||
"data/test-diff-pkg/empty-pkg-libvirt-1.2.17-13.el7_2.2.ppc64.rpm",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/empty-pkg-report-0.txt",
|
||||
"output/test-diff-pkg/empty-pkg-report-0.txt"
|
||||
},
|
||||
{
|
||||
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64.rpm",
|
||||
@ -304,9 +349,23 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"data/test-diff-pkg/tbb-debuginfo-4.1-9.20130314.fc22.x86_64.rpm",
|
||||
"data/test-diff-pkg/tbb-debuginfo-4.3-3.20141204.fc23.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt",
|
||||
"output/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt"
|
||||
},
|
||||
{
|
||||
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64.rpm",
|
||||
"data/test-diff-pkg/tbb-4.3-3.20141204.fc23.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/tbb-debuginfo-4.1-9.20130314.fc22.x86_64.rpm",
|
||||
"data/test-diff-pkg/tbb-debuginfo-4.3-3.20141204.fc23.x86_64.rpm",
|
||||
"data/test-diff-pkg/tbb-devel-4.1-9.20130314.fc22.x86_64.rpm",
|
||||
"data/test-diff-pkg/tbb-devel-4.3-3.20141204.fc23.x86_64.rpm",
|
||||
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt",
|
||||
"output/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt"
|
||||
},
|
||||
{
|
||||
"data/test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm",
|
||||
"data/test-diff-pkg/libICE-1.0.9-2.el7.x86_64.rpm",
|
||||
@ -314,6 +373,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"data/test-diff-pkg/libICE-debuginfo-1.0.6-1.el6.x86_64.rpm",
|
||||
"data/test-diff-pkg/libICE-debuginfo-1.0.9-2.el7.x86_64.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm--libICE-1.0.9-2.el7.x86_64.rpm-report-0.txt",
|
||||
"output/test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm--libICE-1.0.9-2.el7.x86_64.rpm-report-0.txt"
|
||||
},
|
||||
@ -324,6 +385,8 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"data/test-diff-pkg/gtk2-debuginfo-2.24.22-5.el7.i686.rpm",
|
||||
"data/test-diff-pkg/gtk2-debuginfo-2.24.28-8.el7.i686.rpm",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/gtk2-immodule-xim-2.24.22-5.el7.i686--gtk2-immodule-xim-2.24.28-8.el7.i686-report-0.txt",
|
||||
"output/test-diff-pkg/gtk2-immodule-xim-2.24.22-5.el7.i686--gtk2-immodule-xim-2.24.28-8.el7.i686-report-0.txt"
|
||||
},
|
||||
@ -338,12 +401,14 @@ static InOutSpec in_out_specs[] =
|
||||
"",
|
||||
"data/test-diff-pkg/libsigc++-2.0-0c2a-dbgsym_2.4.0-1_amd64.ddeb",
|
||||
"data/test-diff-pkg/libsigc++-2.0-0v5-dbgsym_2.4.1-1ubuntu2_amd64.ddeb",
|
||||
"",
|
||||
"",
|
||||
"data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt",
|
||||
"output/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt"
|
||||
},
|
||||
#endif // WITH_DEB
|
||||
// This should be the last entry.
|
||||
{0, 0, 0, 0, 0, 0, 0, 0}
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/// A task which launches abipkgdiff on the binaries passed to the
|
||||
@ -379,6 +444,7 @@ struct test_task : public abigail::workers::task
|
||||
prog_options,
|
||||
ref_abi_diff_report_path, out_abi_diff_report_path, cmd, abipkgdiff,
|
||||
first_in_debug_package_path, second_in_debug_package_path,
|
||||
first_in_devel_package_path, second_in_devel_package_path,
|
||||
suppression_path;
|
||||
|
||||
first_in_package_path =
|
||||
@ -402,6 +468,16 @@ struct test_task : public abigail::workers::task
|
||||
else
|
||||
second_in_debug_package_path.clear();
|
||||
|
||||
if (spec.first_in_devel_package_path
|
||||
&& strcmp(spec.first_in_devel_package_path, ""))
|
||||
first_in_devel_package_path =
|
||||
string(get_src_dir()) + "/tests/" + spec.first_in_devel_package_path;
|
||||
|
||||
if (spec.second_in_devel_package_path
|
||||
&& strcmp(spec.second_in_devel_package_path, ""))
|
||||
second_in_devel_package_path =
|
||||
string(get_src_dir()) + "/tests/" + spec.second_in_devel_package_path;
|
||||
|
||||
if (spec.suppression_path
|
||||
&& strcmp(spec.suppression_path, ""))
|
||||
suppression_path =
|
||||
@ -432,6 +508,12 @@ struct test_task : public abigail::workers::task
|
||||
if (!second_in_debug_package_path.empty())
|
||||
abipkgdiff += " --d2 " + second_in_debug_package_path;
|
||||
|
||||
if (!first_in_devel_package_path.empty())
|
||||
abipkgdiff += " --devel1 " + first_in_devel_package_path;
|
||||
|
||||
if (!second_in_devel_package_path.empty())
|
||||
abipkgdiff += " --devel2 " + second_in_devel_package_path;
|
||||
|
||||
if (!suppression_path.empty())
|
||||
abipkgdiff += " --suppressions " + suppression_path;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -55,6 +55,7 @@ using namespace abigail::dwarf_reader;
|
||||
using abigail::tools_utils::emit_prefix;
|
||||
using abigail::tools_utils::check_file;
|
||||
using abigail::tools_utils::guess_file_type;
|
||||
using abigail::tools_utils::gen_suppr_spec_from_headers;
|
||||
using abigail::tools_utils::abidiff_status;
|
||||
|
||||
struct options
|
||||
@ -70,6 +71,8 @@ struct options
|
||||
vector<string> drop_var_regex_patterns;
|
||||
vector<string> keep_fn_regex_patterns;
|
||||
vector<string> keep_var_regex_patterns;
|
||||
string headers_dir1;
|
||||
string headers_dir2;
|
||||
bool no_arch;
|
||||
bool show_stats_only;
|
||||
bool show_symtabs;
|
||||
@ -126,10 +129,12 @@ display_usage(const string& prog_name, ostream& out)
|
||||
emit_prefix(prog_name, out)
|
||||
<< "usage: " << prog_name << " [options] [<file1> <file2>]\n"
|
||||
<< " where options can be:\n"
|
||||
<< " --help|-h display this message\n "
|
||||
<< " --version|-v display program version information and exit\n"
|
||||
<< " --debug-info-dir1|--d1 <path> the root for the debug info of file1\n"
|
||||
<< " --debug-info-dir2|--d2 <path> the root for the debug info of file2\n"
|
||||
<< " --help|-h display this message\n "
|
||||
<< " --headers-dir1|--hd1 <path> the path headers of file1\n"
|
||||
<< " --headers-dir2|--hd2 <path> the path headers of file2\n"
|
||||
<< " --stat only display the diff stats\n"
|
||||
<< " --symtabs only display the symbol tables of the corpora\n"
|
||||
<< " --no-architecture do not take architecture in account\n"
|
||||
@ -228,6 +233,32 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
abigail::tools_utils::make_path_absolute(argv[j]);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--headers-dir1")
|
||||
|| !strcmp(argv[i], "--hd1"))
|
||||
{
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
{
|
||||
opts.missing_operand = true;
|
||||
opts.wrong_option = argv[i];
|
||||
return true;
|
||||
}
|
||||
opts.headers_dir1 = argv[j];
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--headers-dir2")
|
||||
|| !strcmp(argv[i], "--hd2"))
|
||||
{
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
{
|
||||
opts.missing_operand = true;
|
||||
opts.wrong_option = argv[i];
|
||||
return true;
|
||||
}
|
||||
opts.headers_dir2 = argv[j];
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--stat"))
|
||||
opts.show_stats_only = true;
|
||||
else if (!strcmp(argv[i], "--symtabs"))
|
||||
@ -495,6 +526,26 @@ set_diff_context_from_opts(diff_context_sptr ctxt,
|
||||
read_suppressions(*i, supprs);
|
||||
ctxt->add_suppressions(supprs);
|
||||
|
||||
if (!opts.headers_dir1.empty())
|
||||
{
|
||||
// Generate suppression specification to avoid showing ABI
|
||||
// changes on types that are not defined in public headers.
|
||||
suppression_sptr suppr =
|
||||
gen_suppr_spec_from_headers(opts.headers_dir1);
|
||||
if (suppr)
|
||||
ctxt->add_suppression(suppr);
|
||||
}
|
||||
|
||||
if (!opts.headers_dir2.empty())
|
||||
{
|
||||
// Generate suppression specification to avoid showing ABI
|
||||
// changes on types that are not defined in public headers.
|
||||
suppression_sptr suppr =
|
||||
gen_suppr_spec_from_headers(opts.headers_dir2);
|
||||
if (suppr)
|
||||
ctxt->add_suppression(suppr);
|
||||
}
|
||||
|
||||
ctxt->dump_diff_tree(opts.dump_diff_tree);
|
||||
}
|
||||
|
||||
|
@ -89,12 +89,16 @@ using std::map;
|
||||
using std::ostringstream;
|
||||
using std::tr1::shared_ptr;
|
||||
using abigail::tools_utils::maybe_get_symlink_target_file_path;
|
||||
using abigail::tools_utils::file_exists;
|
||||
using abigail::tools_utils::is_dir;
|
||||
using abigail::tools_utils::emit_prefix;
|
||||
using abigail::tools_utils::check_file;
|
||||
using abigail::tools_utils::guess_file_type;
|
||||
using abigail::tools_utils::string_ends_with;
|
||||
using abigail::tools_utils::file_type;
|
||||
using abigail::tools_utils::make_path_absolute;
|
||||
using abigail::tools_utils::base_name;
|
||||
using abigail::tools_utils::gen_suppr_spec_from_headers;
|
||||
using abigail::tools_utils::abidiff_status;
|
||||
using abigail::ir::corpus_sptr;
|
||||
using abigail::comparison::diff_context;
|
||||
@ -156,6 +160,8 @@ public:
|
||||
string package2;
|
||||
string debug_package1;
|
||||
string debug_package2;
|
||||
string devel_package1;
|
||||
string devel_package2;
|
||||
bool keep_tmp_files;
|
||||
bool compare_dso_only;
|
||||
bool show_linkage_names;
|
||||
@ -242,18 +248,43 @@ struct abi_diff
|
||||
}
|
||||
};
|
||||
|
||||
class package;
|
||||
|
||||
/// Convenience typedef for a shared pointer to a @ref package.
|
||||
typedef shared_ptr<package> package_sptr;
|
||||
|
||||
/// Abstracts a package.
|
||||
class package
|
||||
{
|
||||
public:
|
||||
|
||||
/// The kind of package we are looking at.
|
||||
enum kind
|
||||
{
|
||||
/// Main package. Contains binaries to ABI-compare.
|
||||
KIND_MAIN = 0,
|
||||
/// Devel package. Contains public headers files in which public
|
||||
/// types are defined.
|
||||
KIND_DEVEL,
|
||||
/// Debug info package. Contains the debug info for the binaries
|
||||
/// int he main packge.
|
||||
KIND_DEBUG_INFO,
|
||||
/// Source package. Contains the source of the binaries in the
|
||||
/// main package.
|
||||
KIND_SRC
|
||||
};
|
||||
|
||||
private:
|
||||
string path_;
|
||||
string extracted_dir_path_;
|
||||
abigail::tools_utils::file_type type_;
|
||||
bool is_debug_info_;
|
||||
kind kind_;
|
||||
map<string, elf_file_sptr> path_elf_file_sptr_map_;
|
||||
shared_ptr<package> debug_info_package_;
|
||||
package_sptr debug_info_package_;
|
||||
package_sptr devel_package_;
|
||||
suppressions_type private_types_suppressions_;
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor for the @ref package type.
|
||||
///
|
||||
/// @param path the path to the package.
|
||||
@ -261,12 +292,12 @@ public:
|
||||
/// @parm dir the temporary directory where to extract the content
|
||||
/// of the package.
|
||||
///
|
||||
/// @param is_debug_info true if the pacakge is a debug info package.
|
||||
/// @param pkg_kind the kind of package.
|
||||
package(const string& path,
|
||||
const string& dir,
|
||||
bool is_debug_info = false)
|
||||
kind pkg_kind = package::KIND_MAIN)
|
||||
: path_(path),
|
||||
is_debug_info_(is_debug_info)
|
||||
kind_(pkg_kind)
|
||||
{
|
||||
type_ = guess_file_type(path);
|
||||
if (type_ == abigail::tools_utils::FILE_TYPE_DIR)
|
||||
@ -327,19 +358,19 @@ public:
|
||||
void type(abigail::tools_utils::file_type t)
|
||||
{type_ = t;}
|
||||
|
||||
/// Test if the current package is a debug info package.
|
||||
/// Get the package kind
|
||||
///
|
||||
/// @return true iff the current package is a debug info package.
|
||||
bool
|
||||
is_debug_info() const
|
||||
{return is_debug_info_;}
|
||||
/// @return the package kind
|
||||
kind
|
||||
get_kind() const
|
||||
{return kind_;}
|
||||
|
||||
/// Set the flag that says if the current package is a debug info package.
|
||||
/// Set the package kind
|
||||
///
|
||||
/// @param f the new flag.
|
||||
/// @param k the package kind.
|
||||
void
|
||||
is_debug_info(bool f)
|
||||
{is_debug_info_ = f;}
|
||||
set_kind(kind k)
|
||||
{kind_ = k;}
|
||||
|
||||
/// Getter for the path <-> elf_file map.
|
||||
///
|
||||
@ -372,6 +403,38 @@ public:
|
||||
debug_info_package(const shared_ptr<package> p)
|
||||
{debug_info_package_ = p;}
|
||||
|
||||
/// Getter for the devel package associated to the current package.
|
||||
///
|
||||
/// @return the devel package associated to the current package.
|
||||
const package_sptr&
|
||||
devel_package() const
|
||||
{return devel_package_;}
|
||||
|
||||
/// Setter of the devel package associated to the current package.
|
||||
///
|
||||
/// @param p the new devel package associated to the current package.
|
||||
void
|
||||
devel_package(const package_sptr& p)
|
||||
{devel_package_ = p;}
|
||||
|
||||
/// Getter of the specifications to suppress change reports about
|
||||
/// private types.
|
||||
///
|
||||
/// @return the vector of specifications to suppress change reports
|
||||
/// about private types.
|
||||
const suppressions_type&
|
||||
private_types_suppressions() const
|
||||
{return private_types_suppressions_;}
|
||||
|
||||
/// Getter of the specifications to suppress change reports about
|
||||
/// private types.
|
||||
///
|
||||
/// @return the vector of specifications to suppress change reports
|
||||
/// about private types.
|
||||
suppressions_type&
|
||||
private_types_suppressions()
|
||||
{return private_types_suppressions_;}
|
||||
|
||||
/// Erase the content of the temporary extraction directory that has
|
||||
/// been populated by the @ref extract_package() function;
|
||||
void
|
||||
@ -409,6 +472,8 @@ public:
|
||||
erase_extraction_directory();
|
||||
if (debug_info_package())
|
||||
debug_info_package()->erase_extraction_directory();
|
||||
if (devel_package())
|
||||
devel_package()->erase_extraction_directory();
|
||||
}
|
||||
};
|
||||
|
||||
@ -424,9 +489,11 @@ struct package_descriptor
|
||||
struct compare_args
|
||||
{
|
||||
const elf_file elf1;
|
||||
const string& debug_dir1;
|
||||
const string& debug_dir1;
|
||||
const suppressions_type& private_types_suppr1;
|
||||
const elf_file elf2;
|
||||
const string& debug_dir2;
|
||||
const string& debug_dir2;
|
||||
const suppressions_type& private_types_suppr2;
|
||||
const options& opts;
|
||||
|
||||
/// Constructor for compare_args, which is used to pass
|
||||
@ -444,10 +511,15 @@ struct compare_args
|
||||
///
|
||||
/// @param opts the options the current program has been called with.
|
||||
compare_args(const elf_file &elf1, const string& debug_dir1,
|
||||
const suppressions_type& priv_types_suppr1,
|
||||
const elf_file &elf2, const string& debug_dir2,
|
||||
const suppressions_type& priv_types_suppr2,
|
||||
const options& opts)
|
||||
: elf1(elf1), debug_dir1(debug_dir1), elf2(elf2),
|
||||
debug_dir2(debug_dir2), opts(opts)
|
||||
: elf1(elf1), debug_dir1(debug_dir1),
|
||||
private_types_suppr1(priv_types_suppr1),
|
||||
elf2(elf2), debug_dir2(debug_dir2),
|
||||
private_types_suppr2(priv_types_suppr2),
|
||||
opts(opts)
|
||||
{}
|
||||
};
|
||||
/// A convenience typedef for arguments passed to the comparison workers.
|
||||
@ -507,10 +579,12 @@ display_usage(const string& prog_name, ostream& out)
|
||||
<< " where options can be:\n"
|
||||
<< " --debug-info-pkg1|--d1 <path> path of debug-info package of package1\n"
|
||||
<< " --debug-info-pkg2|--d2 <path> path of debug-info package of package2\n"
|
||||
<< " --devel-pkg1|--devel1 <path> path of devel package of pakage1\n"
|
||||
<< " --devel-pkg2|--devel2 <path> path of devel package of pakage1\n"
|
||||
<< " --suppressions|--suppr <path> specify supression specification path\n"
|
||||
<< " --keep-tmp-files don't erase created temporary files\n"
|
||||
<< " --dso-only compare shared libraries only\n"
|
||||
<< " --no-linkage-name do not display linkage names of "
|
||||
<< " --no-linkage-name do not display linkage names of "
|
||||
"added/removed/changed\n"
|
||||
<< " --redundant display redundant changes\n"
|
||||
<< " --no-show-locs do not show location information\n"
|
||||
@ -930,8 +1004,10 @@ set_diff_context_from_opts(diff_context_sptr ctxt,
|
||||
static abidiff_status
|
||||
compare(const elf_file& elf1,
|
||||
const string& debug_dir1,
|
||||
const suppressions_type& priv_types_supprs1,
|
||||
const elf_file& elf2,
|
||||
const string& debug_dir2,
|
||||
const suppressions_type& priv_types_supprs2,
|
||||
const options& opts,
|
||||
abigail::ir::environment_sptr &env,
|
||||
corpus_diff_sptr &diff,
|
||||
@ -968,6 +1044,20 @@ compare(const elf_file& elf1,
|
||||
return abigail::tools_utils::ABIDIFF_OK;
|
||||
}
|
||||
|
||||
// Add the first private type suppressions set to the set of
|
||||
// suppressions.
|
||||
for (suppressions_type::const_iterator i = priv_types_supprs1.begin();
|
||||
i != priv_types_supprs1.end();
|
||||
++i)
|
||||
supprs.push_back(*i);
|
||||
|
||||
// Add the second private type suppressions set to the set of
|
||||
// suppressions.
|
||||
for (suppressions_type::const_iterator i = priv_types_supprs2.begin();
|
||||
i != priv_types_supprs2.end();
|
||||
++i)
|
||||
supprs.push_back(*i);
|
||||
|
||||
if (verbose)
|
||||
emit_prefix("abipkgdiff", cerr)
|
||||
<< " Reading file "
|
||||
@ -1097,8 +1187,8 @@ pthread_routine_compare(vector<compare_args_sptr> *args)
|
||||
break;
|
||||
|
||||
abigail::ir::environment_sptr env(new abigail::ir::environment);
|
||||
status |= s = compare(a->elf1, a->debug_dir1,
|
||||
a->elf2, a->debug_dir2,
|
||||
status |= s = compare(a->elf1, a->debug_dir1, a->private_types_suppr1,
|
||||
a->elf2, a->debug_dir2, a->private_types_suppr2,
|
||||
a->opts, env, diff, ctxt);
|
||||
|
||||
const string key = a->elf1.path;
|
||||
@ -1211,6 +1301,55 @@ create_maps_of_package_content(package& package,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// If devel packages were associated to the main package we are
|
||||
/// looking at, use the names of the header files (extracted from the
|
||||
/// package) to generate suppression specification to filter out types
|
||||
/// that are not defined in those header files.
|
||||
///
|
||||
/// Filtering out types not defined in publi headers amounts to filter
|
||||
/// out types that are deemed private to the package we are looking
|
||||
/// at.
|
||||
///
|
||||
/// If the function succeeds, the generated private type suppressions
|
||||
/// are available by invoking the
|
||||
/// package::private_types_suppressions() accessor of the @p pkg
|
||||
/// parameter.
|
||||
///
|
||||
/// @param pkg the main package we are looking at.
|
||||
///
|
||||
/// @return true iff suppression specifications were generated for
|
||||
/// types private to the package.
|
||||
static bool
|
||||
maybe_create_private_types_suppressions(package& pkg)
|
||||
{
|
||||
if (!pkg.private_types_suppressions().empty())
|
||||
return false;
|
||||
|
||||
package_sptr devel_pkg = pkg.devel_package();
|
||||
if (!devel_pkg
|
||||
|| !file_exists(devel_pkg->extracted_dir_path())
|
||||
|| !is_dir(devel_pkg->extracted_dir_path()))
|
||||
return false;
|
||||
|
||||
string headers_path = devel_pkg->extracted_dir_path();
|
||||
if (devel_pkg->type() == abigail::tools_utils::FILE_TYPE_RPM
|
||||
||devel_pkg->type() == abigail::tools_utils::FILE_TYPE_DEB)
|
||||
// For RPM and DEB packages, header files are under the
|
||||
// /usr/include sub-directories.
|
||||
headers_path += "/usr/include";
|
||||
|
||||
if (!is_dir(headers_path))
|
||||
return false;
|
||||
|
||||
suppression_sptr suppr =
|
||||
gen_suppr_spec_from_headers(headers_path);
|
||||
|
||||
if (suppr)
|
||||
pkg.private_types_suppressions().push_back(suppr);
|
||||
|
||||
return suppr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pthread_join(pthread_t thr)
|
||||
{
|
||||
@ -1239,11 +1378,11 @@ pthread_join(pthread_t thr)
|
||||
static void
|
||||
pthread_routine_extract_pkg_and_map_its_content(package_descriptor *a)
|
||||
{
|
||||
pthread_t thr_pkg, thr_debug;
|
||||
pthread_t thr_pkg, thr_debug, thr_devel;
|
||||
package& package = a->pkg;
|
||||
const options& opts = a->opts;
|
||||
ftw_cb_type callback = a->callback;
|
||||
bool has_debug_info_pkg, result = true;
|
||||
bool has_debug_info_pkg, has_devel_pkg, result = true;
|
||||
|
||||
// The debug-info package usually takes longer to extract than the main
|
||||
// package plus that package's mapping for ELFs and optionally suppression
|
||||
@ -1268,6 +1407,29 @@ pthread_routine_extract_pkg_and_map_its_content(package_descriptor *a)
|
||||
}
|
||||
}
|
||||
|
||||
if ((has_devel_pkg = package.devel_package()))
|
||||
{
|
||||
// A devel package was provided for 'package'. Let's extract it
|
||||
// too.
|
||||
if (pthread_create(&thr_devel, /*attr=*/NULL,
|
||||
reinterpret_cast<void*(*)(void*)>
|
||||
(pthread_routine_extract_package),
|
||||
package.devel_package().get()))
|
||||
{
|
||||
result = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Wait for devel package extraction to complete if we're
|
||||
// not running in parallel.
|
||||
if (!opts.parallel)
|
||||
{
|
||||
result = pthread_join(thr_devel);
|
||||
if (!result)
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the package itself.
|
||||
if (pthread_create(&thr_pkg, /*attr=*/NULL,
|
||||
reinterpret_cast<void*(*)(void*)>(pthread_routine_extract_package),
|
||||
@ -1283,7 +1445,14 @@ pthread_routine_extract_pkg_and_map_its_content(package_descriptor *a)
|
||||
if (result)
|
||||
result = create_maps_of_package_content(package, opts, callback);
|
||||
|
||||
// Let's wait for both extractions to finish before we exit.
|
||||
// Wait for devel package extraction to finish
|
||||
if (has_devel_pkg && opts.parallel)
|
||||
result &= pthread_join(thr_devel);
|
||||
|
||||
maybe_create_private_types_suppressions(package);
|
||||
|
||||
// Let's wait for debug package extractions to finish before
|
||||
// we exit.
|
||||
if (has_debug_info_pkg && opts.parallel)
|
||||
result &= pthread_join(thr_debug);
|
||||
|
||||
@ -1430,9 +1599,15 @@ compare(package& first_package,
|
||||
|| iter->second->type == abigail::dwarf_reader::ELF_TYPE_EXEC
|
||||
|| iter->second->type == abigail::dwarf_reader::ELF_TYPE_PI_EXEC))
|
||||
{
|
||||
elf_pairs.push_back(compare_args_sptr(new compare_args(*it->second,
|
||||
debug_dir1, *iter->second,
|
||||
debug_dir2, opts)));
|
||||
elf_pairs.push_back
|
||||
(compare_args_sptr (new compare_args
|
||||
(*it->second,
|
||||
debug_dir1,
|
||||
first_package.private_types_suppressions(),
|
||||
*iter->second,
|
||||
debug_dir2,
|
||||
second_package.private_types_suppressions(),
|
||||
opts)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1652,6 +1827,34 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
abigail::tools_utils::make_path_absolute(argv[j]).get();
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--devel-pkg1")
|
||||
|| !strcmp(argv[i], "--devel1"))
|
||||
{
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
{
|
||||
opts.missing_operand = true;
|
||||
opts.wrong_option = argv[i];
|
||||
return true;
|
||||
}
|
||||
opts.devel_package1 =
|
||||
abigail::tools_utils::make_path_absolute(argv[j]).get();
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--devel-pkg2")
|
||||
|| !strcmp(argv[i], "--devel2"))
|
||||
{
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
{
|
||||
opts.missing_operand = true;
|
||||
opts.wrong_option = argv[i];
|
||||
return true;
|
||||
}
|
||||
opts.devel_package2 =
|
||||
abigail::tools_utils::make_path_absolute(argv[j]).get();
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--keep-tmp-files"))
|
||||
opts.keep_tmp_files = true;
|
||||
else if (!strcmp(argv[i], "--dso-only"))
|
||||
@ -1765,13 +1968,26 @@ main(int argc, char* argv[])
|
||||
first_package->debug_info_package
|
||||
(package_sptr(new package(opts.debug_package1,
|
||||
"debug_package1",
|
||||
/*is_debug_info=*/true)));
|
||||
/*pkg_kind=*/package::KIND_DEBUG_INFO)));
|
||||
|
||||
if (!opts.debug_package2.empty())
|
||||
second_package->debug_info_package
|
||||
(package_sptr(new package(opts.debug_package2,
|
||||
"debug_package2",
|
||||
/*is_debug_info=*/true)));
|
||||
/*pkg_kind=*/package::KIND_DEBUG_INFO)));
|
||||
|
||||
if (!opts.devel_package1.empty())
|
||||
first_package->devel_package
|
||||
(package_sptr(new package(opts.devel_package1,
|
||||
"devel_package1",
|
||||
/*pkg_kind=*/package::KIND_DEVEL)));
|
||||
;
|
||||
|
||||
if (!opts.devel_package2.empty())
|
||||
second_package->devel_package
|
||||
(package_sptr(new package(opts.devel_package2,
|
||||
"devel_package2",
|
||||
/*pkg_kind=*/package::KIND_DEVEL)));
|
||||
|
||||
switch (first_package->type())
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user