summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongkyun Son <dongkyun.s@samsung.com>2020-06-04 16:34:36 +0900
committerDongkyun Son <dongkyun.s@samsung.com>2020-06-04 16:37:10 +0900
commit02a0a8167314243f1e07156d30ac6fe6e30684f0 (patch)
tree6b71052827a464fff5789276933bb4c3c9b0b05f
parent03561656104d77fb23ae89e56305e4bb8eb09c4a (diff)
downloadconfigure-dumper-accepted/tizen_base_tool.tar.gz
configure-dumper-accepted/tizen_base_tool.tar.bz2
configure-dumper-accepted/tizen_base_tool.zip
Change-Id: I91a9c9da6f03f65ebadcd138cea49637076999be Signed-off-by: Dongkyun Son <dongkyun.s@samsung.com>
-rw-r--r--README.txt42
-rwxr-xr-xdump_configure.pl569
-rwxr-xr-xdump_differ.pl167
-rwxr-xr-xmodules/CLOOGRules.pm21
-rw-r--r--modules/DumperCommon.pm8
-rwxr-xr-xmodules/GCCRules.pm44
-rwxr-xr-xmodules/GMPRules.pm18
-rwxr-xr-xmodules/ISLRules.pm23
-rwxr-xr-xmodules/MPCRules.pm25
-rwxr-xr-xmodules/MPFRRules.pm37
-rwxr-xr-xmodules/SpecialRules.pm253
-rw-r--r--packaging/autoconf-2.64.tar.gzbin0 -> 1714683 bytes
-rw-r--r--packaging/autoconf-2.69.tar.gzbin0 -> 1927468 bytes
-rw-r--r--packaging/configure-dumper-1.1-0/autoconf-2.64.tar.gzbin0 -> 1714683 bytes
-rw-r--r--packaging/configure-dumper-1.1-0/autoconf-2.69.tar.gzbin0 -> 1927468 bytes
-rw-r--r--packaging/configure-dumper-1.1-0/configure-dumper-1.1.tar.gzbin0 -> 3654718 bytes
-rw-r--r--packaging/configure-dumper-1.1-0/configure-dumper.manifest5
-rw-r--r--packaging/configure-dumper-1.1-0/configure-dumper.spec79
-rw-r--r--packaging/configure-dumper.manifest5
-rw-r--r--packaging/configure-dumper.spec78
-rwxr-xr-xpatch_configure.pl82
21 files changed, 1456 insertions, 0 deletions
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..dc8b9c7
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,42 @@
+Configure-dumper tool is intended to determine configure options and their values.
+
+Configure-dumper consists of three scripts.
+
+1. patch_configure.pl <source dir>
+It finds all ‘configure’ files in a source tree and inserts inside found files code that saves the
+dump of all used variables during configure run. It should be run before top-level configure.
+2. dump_configure.pl <src_dir> <build_dir> [--project name] [--project-version version]
+ [--out_db out.db] [--autoconf-path dir]
+It determines possible configure options by parsing output of ‘configure --help’ on each level of
+a source tree. Then it tries to get values of found options by parsing dump files and matching
+an option name with appropriate variable in a dump file. If option name or its default value
+cannot be found by simple matching, dump_configure.pl uses the exception rules manually written
+in modules/*Rules.pm files. Finally, it saves the results in sqlite3 data base. It should be run
+after ‘make’.
+The utility can detect the name of project automatically for GCC, binutils and glibc. For applying
+custom rules need setup the project-version parameter, otherwise will be use a default value (for
+gcc is 6.2.1).
+3. dump_differ.pl <db1> [db2] [out_dir] [--print-sections] [--use-alignment]
+ [--section=section{1,..N}]
+It extracts values of a configure options from a data base and prepares plain text files that can be
+easily compared with ‘vim’ or ‘vimdiff’ tools.
+out_dir - where to store out text files to be compared
+--print-sections - just print all sections of input data bases
+--use-alignment - inserts empty lines in cases where the same sections from db1 and db2 have differ
+ number of options/sections. In this case the result is shown in ‘vim’ instead of ‘vimdiff’.
+ It’s required additional plugin for ‘vim’, see below.
+--section=section{1,..N} - specify exact section to be checked. Can be applied multiple times.
+
+Usage.
+
+Steps for the options dumping:
+1. Make build directory:
+ # mkdir build ; cd build
+2. Modify configure scripts
+ # patch_configure.pl ../
+3. Launch configure script with necessary parameters
+ # ../configure --prefix=/opt/
+4. Make
+ # make
+5. Save data in data base
+ # dump_configure.pl ../ ./ --project gcc --project-version 6.2.1 --out_db gcc_build_01.db
diff --git a/dump_configure.pl b/dump_configure.pl
new file mode 100755
index 0000000..36bd37a
--- /dev/null
+++ b/dump_configure.pl
@@ -0,0 +1,569 @@
+#!/usr/bin/perl -w
+
+use DBI qw(:sql_types);
+use Getopt::Long;
+use File::Basename;
+use Cwd qw(abs_path);
+use File::Glob qw(:globally);
+use File::Spec::Functions qw(abs2rel catfile);
+use Data::Dumper;
+
+
+if ( -d dirname(abs_path(__FILE__))."/modules") {
+ use lib dirname(abs_path(__FILE__))."/modules";
+} else {
+ use lib qw(/etc/configure-dumper/modules);
+}
+use SpecialRules;
+use DumperCommon;
+
+use strict;
+
+# maps configure path to the set of its options.
+my %src_path2option;
+
+my %src_path2help;
+
+# the same as src_path2option, but for each option variable
+# there are alternatives by which we can determine option value.
+my %option2alternatives;
+
+# maps dump file path to the set of pairs: (option, value).
+my %build_path2option;
+# automatic variables from autoconf, for example:
+# autoconf -I glibc -I glibc/libidn -t 'AC_ARG_VAR:${|:::::|}%' glibc/libidn/configure.ac
+# the parsing rule <variable>=<value>
+my %build_path2variable;
+my $UNDEFINED_VALUE = '##########';
+
+my $out_db = "configure_opts.db";
+my $autoconf_path = '/usr/local';
+my $gcc_vers = '6.2.1';
+my $project_name;
+my $project_version = $gcc_vers;
+my $print_help;
+
+my $usage_help = "Usage: ".basename($0)." src_dir build_dir [--project name] [--project-version version] [--out_db out.db] [--autoconf-path dir]\n".
+ " src_dir - path to sources\n".
+ " build_dir - build directory\n".
+ " out_db - output database filename, by default $out_db\n".
+ " autoconf-path - base directory for autoconf tools searching, by default '$autoconf_path'\n";
+
+my $dump_fname = DumperCommon::dump_filename; # 'dump_vars.txt';
+my ($BEGIN_DUMP_STR, $END_DUMP_STR) = DumperCommon::dump_parsing_strings;
+
+GetOptions ("project" => \$project_name,
+ "project-version" => \$project_version,
+ "out_db=s" => \$out_db,
+ "autoconf-path=s" => \$autoconf_path,
+ "help" => \$print_help) or die "$usage_help";
+
+if ($print_help) {
+ print($usage_help);
+ exit;
+}
+
+my ($src_dir, $build_dir) = @ARGV;
+
+die "$usage_help" unless (defined $src_dir && defined $build_dir);
+die "Can't find source or build dir.\n" unless (-d $src_dir && -d $build_dir);
+
+# The project autodetection
+my %project_detect = (
+ 'GNU Compiler Collection' => 'gcc',
+ 'GNU development tools' => 'binutils',
+ 'GNU C Library' => 'glibc'
+);
+my $pr_error1 = "Can't detect the project. Please use the --project option.\n";
+open(my $fh_readme, '<', $src_dir."/README") or die "$pr_error1";
+my $fline = <$fh_readme>;
+close($fh_readme);
+foreach my $l_readme (keys %project_detect) {
+ if ( $fline =~ /$l_readme/ ) {
+ $project_name = $project_detect{$l_readme};
+ last;
+ }
+}
+die "$pr_error1" unless (defined $project_name);
+
+print "The $project_name project detected\n";
+#-------------------------------------------
+
+my %prefix2opp = (
+ 'disable' => 'enable',
+ 'enable' => 'disable',
+ 'with' => 'without',
+ 'without' => 'with'
+);
+
+my %ver2autoconf;
+my $default_autoconf_v = '2.69';
+my %autoconf2util;
+
+my $ignore = qr/
+ disable
+ |enable
+ |with
+ |without
+ |without-PACKAGE
+ |with-PACKAGE
+ |enable-FEATURE
+ |disable-FEATURE
+ |cache-file
+ |help/x;
+
+my $enable_opp = 1;
+my $alternatives_check = 1;
+my $ignore_neg_opts = 1;
+my $auto_variables_check = 1;
+
+my $transl_rules = SpecialRules::get_rules($project_name, $project_version);
+my $special_help = SpecialRules::get_help($project_name, $project_version);
+
+sub get_rdir {
+ my ($file, $dir) = @_;
+ my $rdir = dirname($file);
+ return abs2rel($rdir, $dir);
+}
+
+sub get_configure_fname {
+ my ($path) = @_;
+ die "The path is not defined" unless (defined $path);
+ my $conf_ac = catfile($path, 'configure.ac');
+ # Support different names of autoconf script
+ $conf_ac = catfile($path, 'configure.in') unless ( -f catfile($src_dir, $conf_ac) );
+ return unless ( -f catfile($src_dir, $conf_ac) );
+ return $conf_ac;
+}
+
+sub parse_opt_alternatives {
+ my ($path, $opts) = @_;
+ # my $conf_ac = get_configure_fname($path);
+ my $conf_ac = $autoconf2util{$path}{'conf_ac'};
+ die unless (defined $conf_ac);
+
+ # print("> ".catfile($src_dir, $path)."\n");
+ #my $autoconf = get_autoconf("$conf_ac", "-I $src_dir -I $src_dir/$path");
+ # my $autoconf = get_autoconf("$src_dir/$conf_ac", "-I $src_dir -I $src_dir/$path");
+ my $autoconf = $autoconf2util{$path}{'autoconf'};
+
+ foreach my $prefix ('with', 'enable') {
+ my $ucprefix = uc($prefix);
+ #my $cmd = "$autoconf -I $src_dir -I $src_dir/$path -t 'AC_ARG_$ucprefix:\${|:::::|}%' $conf_ac 2>/dev/null";
+ my $cmd = "$autoconf -I $src_dir/$path -t 'AC_ARG_$ucprefix:\${|:::::|}%' $src_dir/$conf_ac 2>/dev/null";
+ # print "> $cmd\n";
+ open(my $fh, '-|', "$cmd") or die "$!";
+ while (my $line = <$fh>) {
+ chomp $line;
+ my ($opt, $help, $ifenabled, $ifdisabled) = split(/\|:::::\|/, $line);
+ my $opt_name = $prefix.'_'.$opt;
+ $opt_name =~ s/-/_/g;
+ $option2alternatives{$path}{$opt_name} = ();
+ if (exists $opts->{$opt_name}) {
+ foreach my $arg ($ifenabled, $ifdisabled) {
+ next unless (defined $arg);
+ chomp($arg);
+ if ($arg =~ /^(\w+)=(([^\s]*)|(".*?")|('.*?'))$/i) {
+ $option2alternatives{$path}{$opt_name}{$1}++;
+ }
+ }
+ } else {
+ warn "WARNING: $conf_ac: $opt_name doesn't match to any configure option\n";
+ }
+ }
+ close($fh);
+ }
+}
+
+sub handle_exeptions {
+ # TODO: add for glibc, binutils
+ my ($line) = @_;
+ my $exc_1 = '--enable-serial-[{host,target,build}-]configure';
+ $line =~ s/\Q$exc_1\E/--enable-serial-configure/;
+ return $line;
+}
+
+sub connect_db {
+ my ($database) = @_;
+ my $driver = "SQLite";
+ my $dsn = "DBI:$driver:dbname=$database";
+ my $userid = "";
+ my $password = "";
+ my $dbh = DBI->connect($dsn, $userid, $password, { RaiseError => 1, PrintError => 0 })
+ or die $DBI::errstr;
+ return $dbh;
+}
+
+sub create_db_table {
+ my ($dbh) = @_;
+ my $sth = $dbh->prepare(q{
+ CREATE TABLE OPTIONS (
+ PATH TEXT NOT NULL,
+ NAME TEXT NOT NULL,
+ VALUE TEXT NOT NULL,
+ HELP TEXT
+ );});
+ $sth->execute() or die $sth->errstr;
+}
+
+sub insert_db_row {
+ my ($dbh, $path, $name, $val, $help) = @_;
+ my $sth = $dbh->prepare(q{
+ INSERT INTO OPTIONS(
+ PATH,NAME,VALUE,HELP)
+ VALUES (?, ?, ?, ?)
+ });
+ $sth->bind_param( 1, $path, SQL_VARCHAR);
+ $sth->bind_param( 2, $name, SQL_VARCHAR);
+ $sth->bind_param( 3, $val, SQL_VARCHAR);
+ $sth->bind_param( 4, $help, SQL_VARCHAR);
+ $sth->execute() or die $sth->errstr;
+}
+
+# For the given configure.ac returns path to autoconf
+# which is able to parse it.
+sub get_autoconf {
+ my ($conf_ac, $inc_dirs) = @_;
+ my $autoconf = $ver2autoconf{$default_autoconf_v};
+ my $cmd = "$autoconf $inc_dirs -t 'AC_PREREQ' $conf_ac >/dev/null 2>&1";
+ my $result = system($cmd);
+ # print("> Check '$cmd': $result ".($result == 0 ? "success" : "fail")."\n");
+
+ return $autoconf if ($result == 0);
+
+ foreach my $autoconf_v (reverse sort keys %ver2autoconf) {
+ next if ("$autoconf_v" eq "$default_autoconf_v");
+
+ $autoconf = $ver2autoconf{$autoconf_v};
+ $cmd = "$autoconf $inc_dirs -t 'AC_PREREQ' $conf_ac >/dev/null 2>&1";
+ $result = system($cmd);
+ # print("> Check '$cmd': $result ".($result == 0 ? "success" : "fail")."\n");
+ return $autoconf if ($result == 0);
+ }
+ die "Couldn't find right autoconf version for $conf_ac";
+}
+
+sub get_auto_variables {
+ my ($path) = @_;
+ unless (defined $path) {
+ warn "WARNING: undefined path\n";
+ return;
+ }
+ die unless (defined $autoconf2util{$path}{'conf_ac'} && defined $autoconf2util{$path}{'autoconf'});
+ my $conf_ac = $autoconf2util{$path}{'conf_ac'};
+ my $autoconf = $autoconf2util{$path}{'autoconf'};
+ my $cmd = "$autoconf -I $src_dir -I $src_dir/$path -t 'AC_ARG_VAR:\${|:::::|}%' $src_dir/$conf_ac 2>/dev/null";
+ # print("> $cmd\n");
+ open(my $fh, '-|', "$cmd") or die "$!";
+ while (my $line = <$fh>) {
+ chomp $line;
+ my ($opt, $help) = split(/\|:::::\|/, $line);
+ unless (defined $help) {
+ $help = '';
+ warn "WARNING: $path:$opt - help message is undefined (for variable)\n";
+ }
+ # print("$opt -> $help");
+ # $build_path2variable{$path}{$opt}{'value'} = $UNDEFINED_VALUE;
+ $build_path2variable{$path}{$opt}{'help'} = $help;
+ }
+ close($fh);
+}
+
+# find available 'autoconf' versions
+my @autoconf_dirs = <$autoconf_path/autoconf-2.*>;
+
+foreach my $autconf_dir (@autoconf_dirs) {
+ if ($autconf_dir =~ /autoconf-(\d\.\d\d)$/) {
+ $ver2autoconf{$1} = "$autconf_dir/bin/autoconf";
+ }
+}
+die "No autoconf-$default_autoconf_v" unless (exists $ver2autoconf{$default_autoconf_v});
+
+# parse 'configure --help' to get all available options.
+chomp(my @configures = `find $src_dir -name configure`) or die "$!";
+
+foreach my $conf (@configures) {
+ my $rdir = get_rdir($conf, $src_dir);
+ # Fill %autoconf2util
+ my $conf_ac = get_configure_fname($rdir);
+ if (defined $conf_ac) {
+ my $autoconf = get_autoconf("$src_dir/$conf_ac", "-I $src_dir -I $src_dir/$rdir");
+ $autoconf2util{$rdir}{'conf_ac'} = $conf_ac;
+ $autoconf2util{$rdir}{'autoconf'} = $autoconf;
+ } else {
+ warn "WARNING: configure undefined for path $rdir\n";
+ }
+
+ if ($auto_variables_check) {
+ get_auto_variables($rdir);
+ }
+
+ # No need try to execute, because it have a specific environment for launching
+ next unless -x $conf;
+ my $cmd = "CONFIGURE_DUMPER_OUT=\"/dev/null\" $conf --help";
+ open (my $fh, '-|', "$cmd") or die "$!";
+
+ my $help;
+ my $prev_opt;
+ my $getting_help = 0;
+ while (my $line = <$fh>) {
+ chomp $line;
+ $line = handle_exeptions($line);
+ if ($line =~ /^\s*(--(\w+(-\w+)*))/) {
+ my $opt_var = $2;
+ next if ($opt_var =~ /^$ignore$/);
+
+ if (defined $prev_opt) {
+ $help =~ s/\s+|\t/ /g;
+ $help =~ s/^\s+//g;
+ $src_path2help{$rdir}{$prev_opt} = $help;
+ }
+
+ $help = $line;
+ $getting_help = 1;
+ chomp $help;
+
+ $opt_var =~ s/-/_/g;
+ $prev_opt = $opt_var;
+ $src_path2option{$rdir}{$opt_var}++;
+ next unless $enable_opp;
+
+ foreach my $pref (keys %prefix2opp) {
+ if ($opt_var =~ /^($pref)_/) {
+ $opt_var =~ s/$pref/$prefix2opp{$pref}/;
+ $src_path2option{$rdir}{$opt_var}++;
+ last;
+ }
+ }
+ } elsif ($getting_help && $line =~ /^\s+[^\s]+/) {
+ chomp $line;
+ $help .= $line;
+ } else {
+ $getting_help = 0;
+ }
+ }
+ if (defined $prev_opt) {
+ $help =~ s/\s+|\t/ /g;
+ $help =~ s/^\s+//g;
+ $src_path2help{$rdir}{$prev_opt} = $help;
+ }
+ close($fh);
+
+ if ($alternatives_check) {
+ parse_opt_alternatives($rdir, \%{$src_path2option{$rdir}});
+ }
+}
+
+# generate help in terms of opposite options
+my %src_path2opphelp;
+foreach my $path (keys %src_path2help) {
+ foreach my $opt (keys %{$src_path2help{$path}}) {
+ foreach my $pref ('disable', 'without') {
+ if ($opt =~ /^$pref/) {
+ my $opp_opt = $opt;
+ $opp_opt =~ s/$pref/$prefix2opp{$pref}/;
+ next if (exists $src_path2help{$path}{$opp_opt});
+
+ my $help = $src_path2help{$path}{$opt};
+ $src_path2opphelp{$path}{$opp_opt} = "OPPOSITE: $help";
+ }
+ }
+ }
+}
+
+foreach my $path (keys %src_path2opphelp) {
+ foreach my $opp_opt (keys %{$src_path2opphelp{$path}}) {
+ $src_path2help{$path}{$opp_opt} = $src_path2opphelp{$path}{$opp_opt};
+ }
+}
+
+chomp(my @dumps = `find $build_dir -name $dump_fname`) or die "$!";
+
+# The dump file may content dump from several configures
+my @path_stack;
+my @paths;
+
+sub init_help_for_build {
+ my ($path, $dump_path) = @_;
+ die "Not defined path or dump_path\n" unless (defined $path && defined $dump_path);
+ # print("Init for $path\n");
+ foreach my $opt (sort keys %{$src_path2option{$path}}) {
+ unless (defined $build_path2option{$dump_path}{$opt}) {
+ $build_path2option{$dump_path}{$opt} = {
+ 'h' => $src_path2help{$path}{$opt}
+ };
+ }
+ }
+}
+
+foreach my $dump (@dumps) {
+ open(my $fh, '<', $dump) or die "Couldn't open $dump: $!";
+ my $line_num = 0;
+ my $path;
+
+ my $dump_path = get_rdir($dump, $build_dir);
+
+ while (my $line = <$fh>) {
+ $line_num++;
+ chomp $line;
+
+ if ($line =~ /^\# /) {
+ if ($line =~ /^\Q$BEGIN_DUMP_STR\E/) {
+ $line =~ s/^\Q$BEGIN_DUMP_STR\E //;
+ unless ($line =~ /\s/ || $line eq '') {
+ push(@path_stack, $path) if (defined $path);
+ $path = $line;
+ push(@paths, $path) unless (grep { $_ eq $path } @paths);
+ # print "SET $path ($dump:$line_num)\n";
+ init_help_for_build($path, $dump_path);
+ } else {
+ warn "WARNING: BEGIN_DUMP_STR found, but path is not defined ($dump:$line_num)\n";
+ }
+ } elsif ($line =~ /^\Q$END_DUMP_STR\E/) {
+ $line =~ s/^\Q$END_DUMP_STR\E //;
+ if (defined $line) {
+ warn "WARNING: END_DUMP_STR found, but path is not defined ($dump:$line_num)\n" if ($line =~ /\s/ || $line eq '');
+ warn "WARNING: END_DUMP_STR found, but paths are not equvivalent: dump read '$line', path '$path' ($dump:$line_num)\n" unless ($line eq $path);
+ }
+ my $path_pop = pop(@path_stack);
+ $path = $path_pop;
+ if (defined $path) {
+ # print "SET $path ($dump:$line_num)\n";
+ push(@paths, $path) unless (grep { $_ eq $path } @paths);
+ }
+ # print "UNSET \$path ($dump:$line_num)\n" unless (defined $path);
+ }
+ next;
+ }
+ unless (defined $path) {
+ print "Skip ($dump:$line_num)\n";
+ next;
+ }
+ my @check_opts;
+
+ # checking manual rules.
+ foreach my $opt (keys %{$transl_rules->{$path}}) {
+ my $man_opt_ = $transl_rules->{$path}->{$opt};
+ if ($man_opt_ =~ /^[+\-]?(\w*)$/) {
+ my $man_opt = $1;
+ next if ($man_opt =~ /^$/);
+
+ if ($line =~ /^$man_opt=(.*)/) {
+ $build_path2option{$dump_path}{$opt}->{'v'} = $1;
+ }
+ } else {
+ die "Wrong format of a translation rule: \'$man_opt_\'\n";
+ }
+ }
+
+ foreach my $opt (keys %{$src_path2option{$path}}) {
+ next if (exists $build_path2option{$dump_path}{$opt}->{'v'});
+
+ my $man_opt_ = $transl_rules->{$path}->{$opt};
+ next if ((defined $man_opt_) && ($man_opt_ =~ /^[+\-]?(\w+)$/));
+
+ if ($line =~ /^$opt=(.*)/) {
+ $build_path2option{$dump_path}{$opt}->{'v'} = $1;
+ } elsif ($alternatives_check) {
+ foreach my $alt_opt (keys %{$option2alternatives{$path}{$opt}}) {
+ if ($line =~ /^$alt_opt=(.*)/) {
+ $build_path2option{$dump_path}{$opt}->{'v'} = $1;
+ last;
+ }
+ }
+ }
+ }
+ next unless ($auto_variables_check);
+ foreach my $opt (keys %{$build_path2variable{$path}}) {
+ if ($line =~ /^$opt=(.*)/) {
+ if ( catfile($src_dir, $dump_path) eq catfile($src_dir, $path) ) {
+ # name of build subdirectory equvivalent name of source directory
+ if (defined $build_path2variable{$path}{$opt}{'value'}) {
+ warn "WARNING: $path -> $opt already defined ($dump:$line_num) = \"$build_path2variable{$path}{$opt}{'value'}\"\nread from file \"$line\"\n";
+ }
+ } else {
+ # add the build path - extend the option name
+ $opt .= "($dump_path)";
+ if (defined $build_path2variable{$path}{$opt}{'value'}) {
+ warn "WARNING: $path -> $opt already defined ($dump:$line_num) = \"$build_path2variable{$path}{$opt}{'value'}\"\nread from file \"$line\"\n";
+ }
+ }
+ # always use the last value
+ $build_path2variable{$path}{$opt}{'value'} = $1;
+ last;
+ }
+ }
+ }
+ close $fh;
+
+ # set up default values for all paths
+ foreach $path (@paths) {
+ foreach my $opt (keys %{$transl_rules->{$path}}) {
+ #next unless (exists $src_path2option{$path}{$opt});
+ next if (exists $build_path2option{$dump_path}{$opt}->{'v'});
+
+ my $man_opt_ = $transl_rules->{$path}->{$opt};
+ my $sign = '';
+ $sign = $1 if ($man_opt_ =~ /^([+\-])/);
+ my $default_val = undef;
+ if ($sign eq '+') {
+ $default_val = 'yes';
+ } elsif ($sign eq '-') {
+ $default_val = 'no';
+ }
+ if (defined $default_val) {
+ $build_path2option{$dump_path}{$opt}->{'v'} = $default_val;
+ }
+ }
+ }
+}
+
+unlink $out_db;
+my $dbh = connect_db($out_db);
+create_db_table($dbh);
+
+foreach my $path (sort keys %build_path2option) {
+ print "$path\n";
+ foreach my $opt (sort keys %{$build_path2option{$path}}) {
+ if ($ignore_neg_opts) {
+ next if ($opt =~ /(without|disable)/);
+ }
+ my $val = $build_path2option{$path}{$opt}->{'v'};
+ my $help = $build_path2option{$path}{$opt}->{'h'};
+ $val = $UNDEFINED_VALUE unless (defined $val);
+ unless (defined $help) {
+ $help = $special_help->{$path}->{$opt};
+ unless (defined $help) {
+ $help = '';
+ warn "WARNING: $path:$opt - help message is undefined\n";
+ }
+ }
+ chomp $help;
+ print "\t$opt:$val|:::|$help\n";
+ insert_db_row($dbh, $path, $opt, $val, $help);
+ }
+
+ next unless ($auto_variables_check);
+ foreach my $opt (sort keys %{$build_path2variable{$path}}) {
+ my $value = $build_path2variable{$path}{$opt}{'value'};
+ unless (defined $value) {
+ # print("$path -> $opt is undefined\n");
+ next;
+ }
+ my $help = $build_path2variable{$path}{$opt}{'help'};
+ unless (defined $help) {
+ if ($opt =~ /(.*)\(.*\)$/ ) {
+ # use help description for extended name of variable
+ my $lopt = $opt;
+ $lopt =~ s/(.*)\(.*\)$/$1/;
+ $help = $build_path2variable{$path}{$lopt}{'help'};
+ $help = '' unless (defined $help);
+ }
+ }
+ chomp $help;
+ print "\t$opt:$value|:::|$help\n";
+ insert_db_row($dbh, $path, $opt, $value, $help);
+ }
+}
+
+$dbh->disconnect();
diff --git a/dump_differ.pl b/dump_differ.pl
new file mode 100755
index 0000000..080ba25
--- /dev/null
+++ b/dump_differ.pl
@@ -0,0 +1,167 @@
+#!/usr/bin/perl -w
+
+use DBI;
+use Getopt::Long;
+use File::Path qw(make_path);
+use File::Basename;
+use File::Spec::Functions qw(catfile);
+use Data::Dumper;
+use File::Temp qw(tempfile);
+
+use strict;
+
+my @sections;
+my $print_sections = 0;
+my $usage_help = "usage: ".basename($0)." db1 [db2] [out_dir] [--print-sections] [--use-alignment] [--section=section{1,..N}]\n";
+my $opts1 = {};
+my $opts2 = {};
+my $use_alignment = 0;
+
+GetOptions ("section=s" => \@sections,
+ "print-sections" => \$print_sections,
+ "use-alignment" => \$use_alignment) or die "$usage_help";
+
+my ($db1, $db2, $out_dir) = @ARGV;
+
+die "$usage_help" unless (defined $db1 && -f $db1);
+die "$usage_help" unless ($print_sections
+ || ((defined $db2 && -f $db2) && (defined $out_dir)));
+
+sub connect_db {
+ my ($database) = @_;
+ my $driver = "SQLite";
+ my $dsn = "DBI:$driver:dbname=$database";
+ my $userid = "";
+ my $password = "";
+ my $dbh = DBI->connect($dsn, $userid, $password, { RaiseError => 1 })
+ or die $DBI::errstr;
+ return $dbh;
+}
+
+sub read_db {
+ my ($db, $opts) = @_;
+ my $dbh = connect_db($db);
+ my $stmt = qq(SELECT PATH,NAME,VALUE,HELP from OPTIONS;);
+ my $sth = $dbh->prepare($stmt);
+ my $rv = $sth->execute() or die $DBI::errstr;
+ if ($rv < 0){
+ print $DBI::errstr;
+ }
+ while (my @row = $sth->fetchrow_array()) {
+ my ($path, $opt, $value, $help) = @row;
+ $opts->{$path}->{$opt} = {
+ 'value' => $value,
+ 'help' => $help
+ }
+ }
+ $dbh->disconnect();
+}
+
+sub format_option {
+ my ($opt, $opt_name) = @_;
+ my $v = $opt->{'value'};
+ my $h = '';
+ $h = "|:::|".$opt->{'help'} if ($v =~ /#{10}/);
+ return " $opt_name=$v$h\n";
+}
+
+sub section2txt_view {
+ my ($opts_s1, $opts_s2) = @_;
+ my ($sview_1, $sview_2) = ('','');
+
+ my @handled_opts;
+ foreach my $opt (sort keys %$opts_s1) {
+ if (exists $opts_s2->{$opt}) {
+ my $fo = format_option($opts_s1->{$opt}, $opt);
+ $sview_1 .= "$fo";
+ $fo = format_option($opts_s2->{$opt}, $opt);
+ $sview_2 .= "$fo";
+ push (@handled_opts, $opt);
+ }
+ }
+ foreach (@handled_opts) {
+ delete $opts_s1->{$_};
+ delete $opts_s2->{$_};
+ }
+
+ foreach my $opt (sort keys %$opts_s1) {
+ my $fo = format_option($opts_s1->{$opt}, $opt);
+ $sview_1 .= "$fo";
+ $sview_2 .= "\n" if ($use_alignment);
+ }
+ foreach my $opt (sort keys %$opts_s2) {
+ my $fo = format_option($opts_s2->{$opt}, $opt);
+ $sview_2 .= "$fo";
+ $sview_1 .= "\n" if ($use_alignment);
+ }
+ return ($sview_1, $sview_2);
+}
+
+read_db($db1, $opts1);
+read_db($db2, $opts2) if (defined $db2);
+
+if ($print_sections) {
+ print "$db1 sections:\n";
+ print "\t$_\n" for (sort keys %$opts1);
+ if (defined $db2) {
+ print "\n\n$db2 sections:\n";
+ print "\t$_\n" for (sort keys %$opts2);
+ }
+ exit 0;
+}
+
+my ($view_1, $view_2) = ('','');
+unless (@sections) {
+ my %unique_sects;
+ my @keys1 = (sort keys %$opts1);
+ my @keys2 = (sort keys %$opts2);
+ $unique_sects{$_} = 1 for (keys %$opts1);
+ $unique_sects{$_} = 1 for (keys %$opts2);
+ @sections = (sort keys %unique_sects);
+}
+
+foreach my $sect (@sections) {
+ my ($sview_1, $sview_2) = ('','');
+ $view_1 .= "$sect\n";
+ $view_2 .= "$sect\n";
+ print "process section: $sect\n";
+
+ if ((exists $opts1->{$sect}) && (exists $opts2->{$sect})) {
+ ($sview_1, $sview_2) = section2txt_view($opts1->{$sect}, $opts2->{$sect});
+ } elsif (exists $opts1->{$sect}) {
+ ($sview_1, $sview_2) = section2txt_view($opts1->{$sect}, {});
+ } elsif (exists $opts2->{$sect}) {
+ ($sview_1, $sview_2) = section2txt_view({}, $opts2->{$sect});
+ }
+ $view_1 .= $sview_1;
+ $view_2 .= $sview_2;
+}
+
+unless (-d $out_dir) {
+ make_path($out_dir) or die "Couldn't create dir $!";
+}
+my $db1_name = basename($db1);
+my $db2_name = basename($db2);
+if ($db1_name eq $db2_name) {
+ $db1_name .= '.1';
+ $db2_name .= '.2';
+}
+$db1_name .= '.txt';
+$db2_name .= '.txt';
+
+my $fname_1 = catfile($out_dir, $db1_name);
+open (my $fh1, '>', $fname_1) or die "Couldn't open $fname_1: $!";
+print $fh1 $view_1 or die "$!";
+
+my $fname_2 = catfile($out_dir, $db2_name);
+open (my $fh2, '>', $fname_2) or die "Couldn't open $fname_2: $!";
+print $fh2 $view_2 or die "$!";
+
+if ($use_alignment) {
+ system("vim -O $fname_1 $fname_2");
+} else {
+ system("vimdiff $fname_1 $fname_2");
+}
+
+close $fh1;
+close $fh2;
diff --git a/modules/CLOOGRules.pm b/modules/CLOOGRules.pm
new file mode 100755
index 0000000..b71e83b
--- /dev/null
+++ b/modules/CLOOGRules.pm
@@ -0,0 +1,21 @@
+package CLOOGRules;
+
+use strict;
+
+my $rules = {
+ 'cloog-0.18.4' => {
+ 'enable_dependency_tracking' => '+',
+ 'enable_silent_rules' => '+'
+ },
+ 'cloog-0.18.1' => {
+ 'enable_dependency_tracking' => '+',
+ 'enable_silent_rules' => '+'
+ }
+};
+
+sub get_rules {
+ return $rules;
+}
+
+1;
+
diff --git a/modules/DumperCommon.pm b/modules/DumperCommon.pm
new file mode 100644
index 0000000..e8bd79b
--- /dev/null
+++ b/modules/DumperCommon.pm
@@ -0,0 +1,8 @@
+package DumperCommon;
+
+use strict;
+
+sub dump_filename { return 'dump_vars.txt'; }
+sub dump_parsing_strings { return ('# START DUMP FOR PATH', '# END DUMP'); }
+
+1;
diff --git a/modules/GCCRules.pm b/modules/GCCRules.pm
new file mode 100755
index 0000000..321bc14
--- /dev/null
+++ b/modules/GCCRules.pm
@@ -0,0 +1,44 @@
+package GCCRules;
+
+use strict;
+
+my $rules = {
+ '4.9.2' => {
+ '.' => {
+ 'with_cloog_include' => 'clooginc',
+ 'with_cloog_lib' => 'clooglibs'
+ }
+ },
+ '6.2.1' => {
+ '.' => {
+ 'enable_offload_targets' => 'enable_offload_targets'
+ },
+ 'gcc' => {
+ 'enable_fdpic' => 'enable_fdpic' #
+ }
+ }
+};
+
+my $help = {
+ '6.2.1' => {
+ '.' => {
+ 'enable_offload_targets' => q(Enable offloading to targets target1, ..., targetN.)
+ },
+ 'gcc' => {
+ 'enable_fdpic' => q(On SH Linux systems, generate ELF FDPIC code.)
+ }
+ }
+};
+
+sub get_rules {
+ my ($vers) = @_;
+ return $rules->{$vers};
+}
+
+sub get_help {
+ my ($vers) = @_;
+ return $help->{$vers};
+}
+
+1;
+
diff --git a/modules/GMPRules.pm b/modules/GMPRules.pm
new file mode 100755
index 0000000..eff92db
--- /dev/null
+++ b/modules/GMPRules.pm
@@ -0,0 +1,18 @@
+package GMPRules;
+
+use base 'Exporter';
+use strict;
+
+my $rules = {
+ 'gmp-6.1.1' => {
+ 'with_pic' => 'pic_mode',
+ 'enable_silent_rules' => '+'
+ }
+};
+
+sub get_rules {
+ return $rules;
+}
+
+1;
+
diff --git a/modules/ISLRules.pm b/modules/ISLRules.pm
new file mode 100755
index 0000000..864eea5
--- /dev/null
+++ b/modules/ISLRules.pm
@@ -0,0 +1,23 @@
+package ISLRules;
+
+use strict;
+
+my $rules = {
+ 'isl-0.17.1' => {
+ 'enable_dependency_tracking' => '+',
+ 'enable_silent_rules' => '+',
+ 'with_pic' => 'pic_mode'
+ },
+ 'isl-0.12.2' => {
+ 'enable_dependency_tracking' => '+',
+ 'enable_silent_rules' => '+',
+ 'with_pic' => 'pic_mode'
+ }
+};
+
+sub get_rules {
+ return $rules;
+}
+
+1;
+
diff --git a/modules/MPCRules.pm b/modules/MPCRules.pm
new file mode 100755
index 0000000..3c4cadc
--- /dev/null
+++ b/modules/MPCRules.pm
@@ -0,0 +1,25 @@
+package MPCRules;
+
+use strict;
+
+my $rules = {
+ 'mpc-1.0' => {
+ 'enable_dependency_tracking' => '+',
+ 'enable_logging' => '-',
+ 'enable_valgrind_tests' => '+'
+ },
+ 'mpc-1.0.3' => {
+ 'enable_dependency_tracking' => '+',
+ 'enable_logging' => '-',
+ 'enable_valgrind_tests' => '+',
+ 'with_pic' => 'pic_mode',
+ 'enable_silent_rules' => '+'
+ }
+};
+
+sub get_rules {
+ return $rules;
+}
+
+1;
+
diff --git a/modules/MPFRRules.pm b/modules/MPFRRules.pm
new file mode 100755
index 0000000..9e04f2f
--- /dev/null
+++ b/modules/MPFRRules.pm
@@ -0,0 +1,37 @@
+package MPFRRules;
+
+use strict;
+
+my $rules = {
+ 'mpfr-3.1.2' => {
+ 'enable_assert' => '-',
+ 'enable_decimal_float' => '-',
+ 'enable_dependency_tracking' => '+',
+ 'enable_gmp_internals' => '-',
+ 'enable_logging' => '-',
+ 'enable_tests_timeout' => '-',
+ 'enable_thread_safe' => '-',
+ 'enable_warnings' => '-',
+ 'with_mulhigh_size' => '-'
+ },
+ 'mpfr-3.1.5' => {
+ 'enable_assert' => '-',
+ 'enable_decimal_float' => '-',
+ 'enable_dependency_tracking' => '+',
+ 'enable_gmp_internals' => '-',
+ 'enable_logging' => '-',
+ 'enable_tests_timeout' => '-',
+ 'enable_thread_safe' => '-',
+ 'enable_warnings' => '-',
+ 'with_mulhigh_size' => '-',
+ 'enable_silent_rules' => '+',
+ 'with_pic' => 'pic_mode'
+ }
+};
+
+sub get_rules {
+ return $rules;
+}
+
+1;
+
diff --git a/modules/SpecialRules.pm b/modules/SpecialRules.pm
new file mode 100755
index 0000000..746b734
--- /dev/null
+++ b/modules/SpecialRules.pm
@@ -0,0 +1,253 @@
+package SpecialRules;
+
+use ISLRules;
+use MPCRules;
+use MPFRRules;
+use GMPRules;
+use CLOOGRules;
+use GCCRules;
+
+use strict;
+
+my $gcc_common_rules = {
+ 'libstdc++-v3' => {
+ 'with_cross_host' => '-',
+ 'with_newlib' => '-'
+ },
+ 'libsanitizer' => {
+ 'enable_dependency_tracking' => '+'
+ },
+ 'libgomp' => {
+ 'enable_dependency_tracking' => '+'
+ },
+ 'libatomic' => {
+ 'enable_dependency_tracking' => '+'
+ },
+ 'lto-plugin' => {
+ 'enable_dependency_tracking' => '+',
+ 'enable_largefile' => '+'
+ },
+ 'libiberty' => {
+ 'enable_largefile' => '+',
+ 'with_newlib' => '-'
+ },
+ 'libcpp' => {
+ 'enable_largefile' => '+'
+ },
+ 'libcc1' => {
+ 'enable_dependency_tracking' => '+'
+ },
+ 'gcc' => {
+ 'enable_tls' => 'gcc_cv_as_tls',
+ 'enable_fix_cortex_a53_835769' => '-',
+ 'enable_fix_cortex_a53_843419' => '-',
+ 'enable_gold' => '-',
+ 'enable_largefile' => '+',
+ 'enable_ld' => '+',
+ 'enable_leading_mingw64_underscores' => '-',
+ 'enable_secureplt' => '-',
+ 'enable_sjlj_exceptions' => '-',
+ 'enable_objc_gc' => '-enable_objc_gc',
+ 'with_local_prefix' => '-',
+ 'with_long_double_128' => '-gcc_cv_target_ldbl128',
+ 'with_plugin_ld' => 'ORIGINAL_PLUGIN_LD_FOR_TARGET',
+ 'with_gxx_include_dir' => '-',
+ 'enable_targets' => 'enable_targets', #
+ 'with_abi' => 'with_abi',
+ 'with_advance_toolchain' => 'with_advance_toolchain',
+ 'with_arch' => 'with_arch',
+ 'with_arch_32' => 'with_arch_32',
+ 'with_arch_64' => 'with_arch_64',
+ 'with_cpu' => 'with_cpu',
+ 'with_cpu_32' => 'with_cpu_32',
+ 'with_cpu_64' => 'with_cpu_64',
+ 'with_divide' => 'with_divide',
+ 'with_endian' => 'with_endian',
+ 'with_float' => 'with_float',
+ 'with_fp_32' => 'with_fp_32',
+ 'with_fpmath' => 'with_fpmath',
+ 'with_fpu' => 'with_fpu',
+ 'with_llsc' => 'with_llsc',
+ 'with_mips_plt' => 'with_mips_plt',
+ 'with_mode' => 'with_mode',
+ 'with_nan' => 'with_nan',
+ 'with_nds32_lib' => 'with_nds32_lib',
+ 'with_odd_spreg_32' => 'with_odd_spreg_32',
+ 'with_schedule' => 'with_schedule',
+ 'with_stack_offset' => 'with_stack_offset',
+ 'with_synci' => 'with_synci',
+ 'with_tls' => 'with_tls',
+ 'with_tune_32' => 'with_tune_32'
+ },
+ 'fixincludes' => {
+ 'enable_twoprocess' => 'TARGET',
+ 'with_local_prefix' => '-'
+ },
+ '.' => {
+ 'enable_objc_gc' => '-',
+ 'with_boot_ldflags' => 'poststage1_ldflags',
+ 'with_build_config' => 'BUILD_CONFIG',
+ 'with_stage1_ldflags' => 'stage1_ldflags',
+ 'with_gmp_include' => 'gmpinc',
+ 'with_gmp_lib' => 'gmplibs',
+ 'with_isl_include' => 'islinc',
+ 'with_isl_lib' => 'isllibs',
+ 'with_mpc_include' => 'gmpinc',
+ 'with_mpc_lib' => 'gmplibs',
+ 'with_mpfr_include' => 'gmpinc',
+ 'with_mpfr_lib' => 'gmplibs',
+ 'enable_libgcj' => 'enable_libgcj', #
+ 'enable_libgomp' => 'enable_libgomp',
+ 'enable_libsanitizer' => 'enable_libsanitizer',
+ 'enable_target_optspace' => 'enable_target_optspace',
+ 'with_avrlibc' => 'with_avrlibc',
+ 'with_slibdir' => 'with_slibdir',
+ 'with_tune' => 'with_tune'
+ }
+};
+
+my $gcc_common_help = {
+ '.' => {
+ 'enable_libgcj' => q(Specify that the run-time libraries used by GCJ should be built), #
+ 'enable_libgomp' => q(Specify that the GNU Offloading and Multi Processing Runtime Library should be built.),
+ 'enable_libsanitizer' => 'Specify that the run-time libraries for the various sanitizers should be built.',
+ 'enable_target_optspace' => q(Specify that target libraries should be optimized for code space instead of code speed. This is the default for the m32r platform.),
+ 'with_avrlibc' => q(Specifies that ‘AVR-Libc’ is being used as the target C library.),
+ 'with_slibdir' => q(Specify the installation directory for the shared libgcc library. The default is libdir.),
+ 'with_tune' => q(provide default values for the -mtune=)
+ },
+ 'gcc' => {
+ 'enable_targets' => q(Some GCC targets, e.g. powerpc64-linux, build bi-arch compilers. These are compilers that are able to generate either 64-bit or 32-bit code. Typically, the corresponding 32-bit target, e.g. powerpc-linux for powerpc64-linux, only generates 32-bit code. This option enables the 32-bit target to be a bi-arch compiler, which is useful when you want a bi-arch compiler that defaults to 32-bit, and you are building a bi-arch or multi-arch binutils in a combined tree. On mips-linux, this will build a tri-arch compiler (ABI o32/n32/64), defaulted to o32. Currently, this option only affects sparc-linux, powerpc-linux, x86-linux, mips-linux and s390-linux. ), #
+ 'with_abi' => q(provide default values for the -mabi=),
+ 'with_advance_toolchain' => q(On 64-bit PowerPC Linux systems, configure the compiler to use the header files, library files, and the dynamic linker from the Advance Toolchain release at instead of the default versions that are provided by the Linux distribution. In general, this option is intended for the developers of GCC, and it is not intended for general use. ),
+ 'with_arch' => q(provide default values for the -march=),
+ 'with_arch_32' => q(provide default values for the -march=),
+ 'with_arch_64' => q(provide default values for the -march=),
+ 'with_cpu' => q(Specify which cpu variant the compiler should generate code for by default. cpu will be used as the default value of the -mcpu= switch. This option is only supported on some targets, including ARC, ARM, i386, M68k, PowerPC, and SPARC. It is mandatory for ARC. The --with-cpu-32 and --with-cpu-64 options specify separate default CPUs for 32-bit and 64-bit modes; these options are only supported for i386, x86-64, PowerPC, and SPARC.),
+ 'with_cpu_32' => q(See --with-cpu=),
+ 'with_cpu_64' => q(See --with-cpu=),
+ 'with_divide' => q(Specify how the compiler should generate code for checking for division by zero. This option is only supported on the MIPS target. The possibilities for type are: traps, breaks),
+ 'with_endian' => q(Specify what endians to use. Currently only implemented for sh*-*-*. Possible values are: big, little, big,little, little,big),
+ 'with_float' => q(provide default values for the -mhard-float or -msoft-floa),
+ 'with_fp_32' => q(On MIPS targets, set the default value for the -mfp option when using the o32 ABI.),
+ 'with_fpmath' => q(This options sets -mfpmath=sse by default and specifies the default ISA for floating-point arithmetics. You can select either ‘sse’ which enables -msse2 or ‘avx’ which enables -mavx by default. This option is only supported on i386 and x86-64 targets.),
+ 'with_fpu' => q(provide default values for the -mfpu=),
+ 'with_llsc' => q(On MIPS targets, make -mllsc the default when no -mno-llsc option is passed. This is the default for Linux-based targets, as the kernel will emulate them if the ISA does not provide them.),
+ 'with_mips_plt' => q(On MIPS targets, make use of copy relocations and PLTs. These features are extensions to the traditional SVR4-based MIPS ABIs and require support from GNU binutils and the runtime C library.),
+ 'with_mode' => q(Specify if the compiler should default to -marm or -mthumb. This option is only supported on ARM targets.),
+ 'with_nan' => q(On MIPS targets, set the default encoding convention to use for the special not-a-number (NaN) IEEE 754 floating-point data.),
+ 'with_nds32_lib' => q(Specifies that library setting is used for building libgcc.a. Currently, the valid library is ‘newlib’ or ‘mculib’. This option is only supported for the NDS32 target.),
+ 'with_odd_spreg_32' => q(On MIPS targets, set the -modd-spreg option by default when using the o32 ABI.),
+ 'with_schedule' => q(provide default values for the -mschedule=),
+ 'with_stack_offset' => q(his option sets the default for the -mstack-offset=num option, and will thus generally also control the setting of this option for libraries. This option is only supported on Epiphany targets.),
+ 'with_synci' => q(On MIPS targets, make -msynci the default when no -mno-synci option is passed.),
+ 'with_tls' => q(Specify the default TLS dialect, for systems were there is a choice. For ARM targets, possible values for dialect are gnu or gnu2, which select between the original GNU dialect and the GNU TLS descriptor-based dialect.),
+ 'with_tune_32' => q(provide default values for the -mtune=)
+ }
+};
+
+my $binutils_common_rules = {};
+
+my $binutils_common_help = {};
+
+my $glibc_common_rules = {};
+
+my $glibc_common_help = {};
+
+sub merge_hash {
+ my ($dst, $src) = @_;
+
+ foreach my $key (keys %$src) {
+ $dst->{$key} = $src->{$key};
+ }
+}
+
+sub get_rules_gcc {
+ my ($gcc_vers) = @_;
+ my $rules = {};
+
+ merge_hash($rules, $gcc_common_rules);
+ merge_hash($rules, ISLRules::get_rules());
+ merge_hash($rules, MPCRules::get_rules());
+ merge_hash($rules, MPFRRules::get_rules());
+ merge_hash($rules, CLOOGRules::get_rules());
+ merge_hash($rules, GMPRules::get_rules());
+
+ my $gcc_rules = GCCRules::get_rules($gcc_vers);
+ if ($gcc_rules) {
+ foreach my $sect (keys %$gcc_rules) {
+ foreach my $opt (keys %{$gcc_rules->{$sect}}) {
+ if (exists $rules->{$sect}->{$opt}) {
+ warn "Overwriting gcc common rule: \'$sect:$rules->{$sect}->{$opt}\'";
+ }
+ $rules->{$sect}->{$opt} = $gcc_rules->{$sect}->{$opt};
+ }
+ }
+ }
+ return $rules;
+}
+
+sub get_rules_glibc {
+ my ($ver) = @_;
+ my $rules = {};
+ # merge_hash($rules, $glibc_common_rules);
+ return $rules;
+}
+
+sub get_rules_binutils {
+ my ($ver) = @_;
+ my $rules = {};
+ # merge_hash($rules, $binutils_common_rules);
+ return $rules;
+}
+
+sub get_rules {
+ my ($project, $version) = @_;
+ if ($project eq 'gcc') { return get_rules_gcc($version); }
+ if ($project eq 'binutils') { return get_rules_binutils($version); }
+ if ($project eq 'glibc') { return get_rules_glibc($version); }
+ return {};
+}
+
+sub get_help_gcc {
+ my ($gcc_vers) = @_;
+ my $help = {};
+
+ merge_hash($help, $gcc_common_help);
+ my $gcc_help = GCCRules::get_help($gcc_vers);
+ if ($gcc_help) {
+ foreach my $sect (keys %$gcc_help) {
+ foreach my $opt (keys %{$gcc_help->{$sect}}) {
+ if (exists $help->{$sect}->{$opt}) {
+ warn "Overwriting gcc common help: \'$sect:$help->{$sect}->{$opt}\'";
+ }
+ $help->{$sect}->{$opt} = $gcc_help->{$sect}->{$opt};
+ }
+ }
+ }
+ return $help;
+}
+
+sub get_help_glibc {
+ my ($ver) = @_;
+ my $help = {};
+ # merge_hash($help, $glibc_common_help);
+ return $help;
+}
+
+sub get_help_binutils {
+ my ($ver) = @_;
+ my $help = {};
+ # merge_hash($help, $binutils_common_help);
+ return $help;
+}
+
+sub get_help {
+ my ($project, $version) = @_;
+ if ($project eq 'gcc') { return get_help_gcc($version); }
+ if ($project eq 'binutils') { return get_help_binutils($version); }
+ if ($project eq 'glibc') { return get_help_glibc($version); }
+ return {};
+}
+
+1;
diff --git a/packaging/autoconf-2.64.tar.gz b/packaging/autoconf-2.64.tar.gz
new file mode 100644
index 0000000..151500e
--- /dev/null
+++ b/packaging/autoconf-2.64.tar.gz
Binary files differ
diff --git a/packaging/autoconf-2.69.tar.gz b/packaging/autoconf-2.69.tar.gz
new file mode 100644
index 0000000..1c7a3ad
--- /dev/null
+++ b/packaging/autoconf-2.69.tar.gz
Binary files differ
diff --git a/packaging/configure-dumper-1.1-0/autoconf-2.64.tar.gz b/packaging/configure-dumper-1.1-0/autoconf-2.64.tar.gz
new file mode 100644
index 0000000..151500e
--- /dev/null
+++ b/packaging/configure-dumper-1.1-0/autoconf-2.64.tar.gz
Binary files differ
diff --git a/packaging/configure-dumper-1.1-0/autoconf-2.69.tar.gz b/packaging/configure-dumper-1.1-0/autoconf-2.69.tar.gz
new file mode 100644
index 0000000..1c7a3ad
--- /dev/null
+++ b/packaging/configure-dumper-1.1-0/autoconf-2.69.tar.gz
Binary files differ
diff --git a/packaging/configure-dumper-1.1-0/configure-dumper-1.1.tar.gz b/packaging/configure-dumper-1.1-0/configure-dumper-1.1.tar.gz
new file mode 100644
index 0000000..37983b7
--- /dev/null
+++ b/packaging/configure-dumper-1.1-0/configure-dumper-1.1.tar.gz
Binary files differ
diff --git a/packaging/configure-dumper-1.1-0/configure-dumper.manifest b/packaging/configure-dumper-1.1-0/configure-dumper.manifest
new file mode 100644
index 0000000..017d22d
--- /dev/null
+++ b/packaging/configure-dumper-1.1-0/configure-dumper.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/configure-dumper-1.1-0/configure-dumper.spec b/packaging/configure-dumper-1.1-0/configure-dumper.spec
new file mode 100644
index 0000000..e17742b
--- /dev/null
+++ b/packaging/configure-dumper-1.1-0/configure-dumper.spec
@@ -0,0 +1,79 @@
+# spec file for package configure-dumper
+#
+# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany.
+#
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+
+# Please submit bugfixes or comments via http://bugs.opensuse.org/
+#
+
+Name: configure-dumper
+VCS: RS-RANO/configure-dumper.git#51d44e8987bf568fe3ade42c9b6fc78ff254ada4
+Summary: Utilities to make dump of GCC's configure options.
+Version: 1.1
+Release: 0
+License: GPL-2.0+
+Source: %name-%version.tar.gz
+Source1: autoconf-2.64.tar.gz
+Source2: autoconf-2.69.tar.gz
+Source3: configure-dumper.manifest
+Requires: perl-DBD-SQLite
+Requires: m4 >= 1.4.6
+BuildRequires: xz
+BuildRequires: m4 >= 1.4.6
+BuildArch: noarch
+
+
+%description
+Utilities to make dump of GCC's configure options.
+
+%prep
+%setup -q -n %{name}-%{version}
+cp %{SOURCE1} .
+cp %{SOURCE2} .
+cp %{SOURCE3} .
+%{__chmod} -Rf a+rX,u+w,g-w,o-w .
+%{__tar} -xf autoconf-2.64.tar.gz
+%{__tar} -xf autoconf-2.69.tar.gz
+
+%build
+cd autoconf-2.64 && ./configure --prefix=/usr/local/autoconf-2.64
+make %{?_smp_mflags}
+
+cd ../autoconf-2.69 && ./configure --prefix=/usr/local/autoconf-2.69
+make %{?_smp_mflags}
+
+%install
+cd autoconf-2.64 && %{?make_install} %{!?make_install:make install DESTDIR=%{buildroot}}
+cd ../autoconf-2.69 && %{?make_install} %{!?make_install:make install DESTDIR=%{buildroot}} && cd ..
+rm -rf %{buildroot}/usr/local/autoconf-2.64/share/{man,info}
+rm -rf %{buildroot}/usr/local/autoconf-2.69/share/{man,info}
+
+mkdir -p $RPM_BUILD_ROOT/usr/bin
+mkdir -p $RPM_BUILD_ROOT/etc/%{name}/modules
+install -m 0755 patch_configure.pl $RPM_BUILD_ROOT/%{_bindir}
+install -m 0755 dump_configure.pl $RPM_BUILD_ROOT/%{_bindir}
+install -m 0755 dump_differ.pl $RPM_BUILD_ROOT/%{_bindir}
+install -m 0755 modules/* $RPM_BUILD_ROOT/etc/%{name}/modules
+
+%postun
+
+%files
+%manifest %{name}.manifest
+%defattr(-,root,root)
+/usr/local/autoconf-2.64/bin/*
+/usr/local/autoconf-2.69/bin/*
+%{_bindir}/patch_configure.pl
+%{_bindir}/dump_configure.pl
+%{_bindir}/dump_differ.pl
+/etc/%{name}/modules/*
+/usr/local/autoconf-2.64/share/autoconf
+/usr/local/autoconf-2.69/share/autoconf
+
diff --git a/packaging/configure-dumper.manifest b/packaging/configure-dumper.manifest
new file mode 100644
index 0000000..017d22d
--- /dev/null
+++ b/packaging/configure-dumper.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/configure-dumper.spec b/packaging/configure-dumper.spec
new file mode 100644
index 0000000..4fcdeb4
--- /dev/null
+++ b/packaging/configure-dumper.spec
@@ -0,0 +1,78 @@
+# spec file for package configure-dumper
+#
+# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany.
+#
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+
+# Please submit bugfixes or comments via http://bugs.opensuse.org/
+#
+
+Name: configure-dumper
+Summary: Utilities to make dump of GCC's configure options.
+Version: 1.1
+Release: 0
+License: Apache-2.0
+Source: %name-%version.tar.gz
+Source1: autoconf-2.64.tar.gz
+Source2: autoconf-2.69.tar.gz
+Source3: configure-dumper.manifest
+Requires: perl-DBD-SQLite
+Requires: m4 >= 1.4.6
+BuildRequires: xz
+BuildRequires: m4 >= 1.4.6
+BuildArch: noarch
+
+
+%description
+Utilities to make dump of GCC's configure options.
+
+%prep
+%setup -q -n %{name}-%{version}
+cp %{SOURCE1} .
+cp %{SOURCE2} .
+cp %{SOURCE3} .
+%{__chmod} -Rf a+rX,u+w,g-w,o-w .
+%{__tar} -xf autoconf-2.64.tar.gz
+%{__tar} -xf autoconf-2.69.tar.gz
+
+%build
+cd autoconf-2.64 && ./configure --prefix=/usr/local/autoconf-2.64
+make %{?_smp_mflags}
+
+cd ../autoconf-2.69 && ./configure --prefix=/usr/local/autoconf-2.69
+make %{?_smp_mflags}
+
+%install
+cd autoconf-2.64 && %{?make_install} %{!?make_install:make install DESTDIR=%{buildroot}}
+cd ../autoconf-2.69 && %{?make_install} %{!?make_install:make install DESTDIR=%{buildroot}} && cd ..
+rm -rf %{buildroot}/usr/local/autoconf-2.64/share/{man,info}
+rm -rf %{buildroot}/usr/local/autoconf-2.69/share/{man,info}
+
+mkdir -p $RPM_BUILD_ROOT/usr/bin
+mkdir -p $RPM_BUILD_ROOT/etc/%{name}/modules
+install -m 0755 patch_configure.pl $RPM_BUILD_ROOT/%{_bindir}
+install -m 0755 dump_configure.pl $RPM_BUILD_ROOT/%{_bindir}
+install -m 0755 dump_differ.pl $RPM_BUILD_ROOT/%{_bindir}
+install -m 0755 modules/* $RPM_BUILD_ROOT/etc/%{name}/modules
+
+%postun
+
+%files
+%manifest %{name}.manifest
+%defattr(-,root,root)
+/usr/local/autoconf-2.64/bin/*
+/usr/local/autoconf-2.69/bin/*
+%{_bindir}/patch_configure.pl
+%{_bindir}/dump_configure.pl
+%{_bindir}/dump_differ.pl
+/etc/%{name}/modules/*
+/usr/local/autoconf-2.64/share/autoconf
+/usr/local/autoconf-2.69/share/autoconf
+
diff --git a/patch_configure.pl b/patch_configure.pl
new file mode 100755
index 0000000..3e1347a
--- /dev/null
+++ b/patch_configure.pl
@@ -0,0 +1,82 @@
+#!/usr/bin/perl -w
+
+use File::Basename;
+use Cwd qw(abs_path);
+use File::Temp qw(tempfile);
+use File::Copy;
+use File::Spec::Functions qw(abs2rel);
+
+if ( -d dirname(abs_path(__FILE__))."/modules") {
+ use lib dirname(abs_path(__FILE__))."/modules";
+} else {
+ use lib qw(/etc/configure-dumper/modules);
+}
+use DumperCommon;
+
+use strict;
+
+my $dump_fname = DumperCommon::dump_filename; # 'dump_vars.txt';
+my ($BEGIN_DUMP_STR, $END_DUMP_STR) = DumperCommon::dump_parsing_strings;
+
+my ($src_dir) = @ARGV;
+
+if (not defined $src_dir) {
+ die "Usage: ".basename($0)." src_dir\n";
+}
+
+sub get_rdir {
+ my ($file, $dir) = @_;
+ my $rdir = dirname($file);
+ return abs2rel($rdir, $dir);
+}
+
+sub inject_header {
+ my ($tmp_fh, $rdir) = @_;
+ die unless (defined $tmp_fh && defined $rdir);
+ print $tmp_fh "[ \"x\$CONFIGURE_DUMPER_OUT\" = \"x\" ] && CONFIGURE_DUMPER_OUT=$dump_fname\n";
+ print $tmp_fh "echo \'$BEGIN_DUMP_STR $rdir\' >> \$CONFIGURE_DUMPER_OUT\n";
+ print $tmp_fh "echo \$0 >> \$CONFIGURE_DUMPER_OUT\n";
+}
+
+chomp(my @confs = `find $src_dir -name configure`) or die "$!";
+foreach my $conf (@confs) {
+ # Need to search all files, because a template for call in Makefile:
+ # .... $(SHELL) $$S/$$module_src_dir/configure ...
+ # next unless -x $conf;
+
+ print "patching: $conf\n";
+ open(my $fh, '<', $conf) or die "Couldn't open $conf $!";
+ my ($tmp_fh, $tmp_fname) = tempfile();
+ my $rdir = get_rdir($conf, $src_dir);
+ my $already_patched = 0;
+ my $cur_line = 0;
+ while (<$fh>) {
+ $cur_line++;
+ if ($cur_line == 1) {
+ if (/^#!.*(\/sh|\/bash)/) {
+ print $tmp_fh $_;
+ inject_header($tmp_fh, $rdir);
+ } else {
+ inject_header($tmp_fh, $rdir);
+ print $tmp_fh $_;
+ }
+ next;
+ }
+ print $tmp_fh $_;
+ if (/^echo \$0 \>\> $dump_fname\n/) {
+ $already_patched = 1;
+ last;
+ }
+ }
+ close($fh);
+ if ($already_patched) {
+ close($tmp_fh);
+ unlink($tmp_fname);
+ next;
+ }
+ print $tmp_fh "(set -o posix ; set) >> \$CONFIGURE_DUMPER_OUT\n";
+ print $tmp_fh "echo \'$END_DUMP_STR $rdir\' >> \$CONFIGURE_DUMPER_OUT\n";
+
+ close($tmp_fh);
+ copy($tmp_fname, $conf) or die $!;
+}