* Raphael Hertzog <hert...@debian.org> [120316 09:36]: > Suggestion of a better sentence: > Reworded:
incorporated > IMO this is not the proper way to extract it automatically. If you want > this feature, you should add a unique (and fixed) start/end marker. > > Maybe something like this ? > > --- BEGIN DPKG-BUILDFLAGS STATUS --- > […] > --- END DPKG-BUILDFLAGS STATUS --- Things requiring context like that are no fun to parse at all. You cannot grep them, a line parser needs additional context. > If you really want to keep the "dpkg-builflags: " prefix, then you should > use one of the functions exported by Dpkg::ErrorHandling. But I don't > think it's required. That seems to always want to output some extra (at least a colon) and most even seem to have localized messages, so do not look very suiteable. > You can easily do that... instead of hardcoding it here, create > a new vendor hook for this purpose. Either the vendor hook > allows to extend your @envvars or it prints directly supplementary > information to include... done. > And indeed I was puzzled by seeing DEB_BUILD_HARDENING but realized thanks > to your comment that it was only relevant for Ubuntu... Actually I seem to have read that part to fast. It seems to be a output and not a input variable... > > + # note that DEB_*_MAINT_* currently is not reflected > > + # by $origin... > > This was on purpose. It's a choice of the maintainer and thus of the > vendor. And since it happens at the end, it would hide any > user/system-wide customization... and I don't want this. Added a patch on top of it to show more information here. I've split the first one into preparations to the infrastructure and the --status introduction. If you prefer them merged let me know... Bernhard R. Link
>From d21eed0dcf768d1f6509eb799ee6929a7f1147fe Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" <brl...@debian.org> Date: Fri, 16 Mar 2012 09:56:52 +0100 Subject: [PATCH 1/4] Dpkg::BuildFlags: add get_feature_areas() Add a way a caller can enumerate all possible values for get_features(). Signed-off-by: Bernhard R. Link <brl...@debian.org> --- scripts/Dpkg/BuildFlags.pm | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/scripts/Dpkg/BuildFlags.pm b/scripts/Dpkg/BuildFlags.pm index 3800470..31a54d9 100644 --- a/scripts/Dpkg/BuildFlags.pm +++ b/scripts/Dpkg/BuildFlags.pm @@ -320,6 +320,18 @@ sub get { return $self->{'flags'}{$key}; } +=item $bf->get_feature_areas() + +Return the feature areas +(i.e. the area values has_features will return true for). + +=cut + +sub get_feature_areas { + my ($self) = @_; + return keys $self->{'features'}; +} + =item $bf->get_features($area) Return, for the given area, a hash with keys as feature names, and values @@ -392,7 +404,8 @@ based on the package maintainer directives. =head Version 1.02 -New methods: $bf->get_features(), $bf->has_features(), $bf->set_feature(). +New methods: $bf->get_features(), $bf->has_features(), $bf->set_feature(), + $bf->get_feature_areas(). =head1 AUTHOR -- 1.7.9.1
>From f9b17acfd98f0c539f0f70d204397963ab09e9dc Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" <brl...@debian.org> Date: Fri, 16 Mar 2012 10:23:38 +0100 Subject: [PATCH 2/4] Dpkg::BuildFlags: record environment variables looked at Record environment variables looked at by Dpkg::BuildFlags and the vendor hooks and make them available via the new get_used_environment(). Signed-off-by: Bernhard R. Link <brl...@debian.org> --- scripts/Dpkg/BuildFlags.pm | 39 ++++++++++++++++++++++++++++++++++++++- scripts/Dpkg/Vendor/Debian.pm | 1 + scripts/Dpkg/Vendor/Ubuntu.pm | 1 + 3 files changed, 40 insertions(+), 1 deletions(-) diff --git a/scripts/Dpkg/BuildFlags.pm b/scripts/Dpkg/BuildFlags.pm index 31a54d9..4a84c57 100644 --- a/scripts/Dpkg/BuildFlags.pm +++ b/scripts/Dpkg/BuildFlags.pm @@ -69,7 +69,9 @@ sub load_vendor_defaults { $self->{'options'} = {}; $self->{'source'} = {}; $self->{'features'} = {}; + $self->{'used_envs'} = {}; my $build_opts = Dpkg::BuildOptions->new(); + $self->environment_used("DEB_BUILD_OPTIONS"); my $default_flags = $build_opts->has("noopt") ? "-g -O0" : "-g -O2"; $self->{flags} = { CPPFLAGS => '', @@ -87,6 +89,8 @@ sub load_vendor_defaults { }; # The Debian vendor hook will add hardening build flags run_vendor_hook("update-buildflags", $self); + # run_vendor_hook looked at DEB_VENDOR + $self->environment_used("DEB_VENDOR"); } =item $bf->load_system_config() @@ -126,18 +130,22 @@ sub load_environment_config { my ($self) = @_; foreach my $flag (keys %{$self->{flags}}) { my $envvar = "DEB_" . $flag . "_SET"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->set($flag, $ENV{$envvar}, "env"); } $envvar = "DEB_" . $flag . "_STRIP"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->strip($flag, $ENV{$envvar}, "env"); } $envvar = "DEB_" . $flag . "_APPEND"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->append($flag, $ENV{$envvar}, "env"); } $envvar = "DEB_" . $flag . "_PREPEND"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->prepend($flag, $ENV{$envvar}, "env"); } @@ -155,18 +163,22 @@ sub load_maintainer_config { my ($self) = @_; foreach my $flag (keys %{$self->{flags}}) { my $envvar = "DEB_" . $flag . "_MAINT_SET"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->set($flag, $ENV{$envvar}, undef); } $envvar = "DEB_" . $flag . "_MAINT_STRIP"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->strip($flag, $ENV{$envvar}, undef); } $envvar = "DEB_" . $flag . "_MAINT_APPEND"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->append($flag, $ENV{$envvar}, undef); } $envvar = "DEB_" . $flag . "_MAINT_PREPEND"; + $self->environment_used($envvar); if (exists $ENV{$envvar}) { $self->prepend($flag, $ENV{$envvar}, undef); } @@ -390,6 +402,31 @@ sub list { return sort keys %{$self->{'flags'}}; } +=item $bf->environment_used($envvar) + +Records that the given environment variable had influenced +or could have influenced (if it had existed or had a different +value) the calculated flags. + +=cut + +sub environment_used { + my ($self, $envvar) = @_; + $self->{'used_envs'}->{$envvar} = 1; +} + +=item my @list = $bf->get_used_environment() + +Returns a list of all environment variables that had a +possible influence. + +=cut + +sub get_used_environment { + my ($self) = @_; + return keys $self->{'used_envs'}; +} + =back =head1 CHANGES @@ -405,7 +442,7 @@ based on the package maintainer directives. =head Version 1.02 New methods: $bf->get_features(), $bf->has_features(), $bf->set_feature(), - $bf->get_feature_areas(). + $bf->get_feature_areas(), $bf->environment_used(), $bf->get_used_environment(). =head1 AUTHOR diff --git a/scripts/Dpkg/Vendor/Debian.pm b/scripts/Dpkg/Vendor/Debian.pm index b4ce4cf..0a1ab8e 100644 --- a/scripts/Dpkg/Vendor/Debian.pm +++ b/scripts/Dpkg/Vendor/Debian.pm @@ -100,6 +100,7 @@ sub add_hardening_flags { # Adjust features based on Maintainer's desires. my $opts = Dpkg::BuildOptions->new(envvar => "DEB_BUILD_MAINT_OPTIONS"); + $flags->environment_used("DEB_BUILD_MAINT_OPTIONS"); foreach my $feature (split(",", $opts->get("hardening") // "")) { $feature = lc($feature); if ($feature =~ s/^([+-])//) { diff --git a/scripts/Dpkg/Vendor/Ubuntu.pm b/scripts/Dpkg/Vendor/Ubuntu.pm index 7e60fcf..8cf4569 100644 --- a/scripts/Dpkg/Vendor/Ubuntu.pm +++ b/scripts/Dpkg/Vendor/Ubuntu.pm @@ -108,6 +108,7 @@ sub run_hook { $self->SUPER::run_hook($hook, $flags); # Allow control of hardening-wrapper via dpkg-buildpackage DEB_BUILD_OPTIONS + $flags->used_environment("DEB_BUILD_OPTIONS"); my $build_opts = Dpkg::BuildOptions->new(); my $hardening; if ($build_opts->has("hardening")) { -- 1.7.9.1
>From b90483512ca7181d8b72287ea669b281640d7314 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" <brl...@debian.org> Date: Thu, 15 Mar 2012 11:25:39 +0100 Subject: [PATCH 3/4] dpkg-buildflags: add --status action to describe what is happening It's hard to see from a build log file what values should have been used and why. The new --status action added by this tries to output all meaningful information in way useful for human consumption and for automatic log parsers. Signed-off-by: Bernhard R. Link <brl...@debian.org> --- man/dpkg-buildflags.1 | 10 +++++++++ scripts/dpkg-buildflags.pl | 47 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/man/dpkg-buildflags.1 b/man/dpkg-buildflags.1 index 4244b82..234d1cf 100644 --- a/man/dpkg-buildflags.1 +++ b/man/dpkg-buildflags.1 @@ -72,6 +72,16 @@ Print the list of flags supported by the current vendor (one per line). See the \fBSUPPORTED FLAGS\fP section for more information about them. .TP +.BI \-\-status +Display any information that can be useful to explain the behaviour +of dpkg-buildflags: +relevant environment variables, current vendor, state of all feature flags. +Also print the resulting compiler flags with their origin. + +This is intended to be run from \fBdebian/rules\fP, so that the +build log keeps a clear trace of the build flags used. This can +be useful to diagnose problems related to them. +.TP .BI \-\-export= format Print to standard output shell (if \fIformat\fP is \fBsh\fP) or make (if \fIformat\fP is \fBmake\fP) commands that can be used to export diff --git a/scripts/dpkg-buildflags.pl b/scripts/dpkg-buildflags.pl index d0f9fa8..66069a5 100755 --- a/scripts/dpkg-buildflags.pl +++ b/scripts/dpkg-buildflags.pl @@ -24,6 +24,7 @@ use Dpkg; use Dpkg::Gettext; use Dpkg::ErrorHandling; use Dpkg::BuildFlags; +use Dpkg::Vendor qw(get_current_vendor); textdomain("dpkg-dev"); @@ -52,6 +53,9 @@ Actions: compilation flags in a shell script, in make, or on a ./configure command line. --dump output all compilation flags with their values + --status print a synopsis with all parameters affecting + the behaviour of dpkg-buildflags and the resulting + flags and their origin. --help show this help message. --version show the version. "), $progname; @@ -72,14 +76,10 @@ while (@ARGV) { if defined($action); my $type = $1 || "sh"; $action = "export-$type"; - } elsif (m/^--dump$/) { - usageerr(_g("two commands specified: --%s and --%s"), "dump", $action) - if defined($action); - $action = "dump"; - } elsif (m/^--list$/) { - usageerr(_g("two commands specified: --%s and --%s"), "list", $action) + } elsif (m/^--(list|status|dump)$/) { + usageerr(_g("two commands specified: --%s and --%s"), $1, $action) if defined($action); - $action = "list"; + $action = $1; } elsif (m/^-(h|-help)$/) { usage(); exit 0; @@ -147,6 +147,39 @@ if ($action eq "get") { print "$flag=$value\n"; } exit(0); +} elsif ($action eq "status") { + # prefix everything with "dpkg-buildflags: " to allow easy extraction + # from a buildd log. + # First print all environment variables that might have changed the + # results (only existing ones, might make sense to add a option to + # also show which could have set to modify it). + my @envvars = $build_flags->get_used_environment(); + for my $envvar (@envvars) { + if (exists $ENV{$envvar}) { + printf "dpkg-buildflags: environment variable %s=%s\n", + $envvar, $ENV{$envvar}; + } + } + my $vendor = Dpkg::Vendor::get_current_vendor(); + $vendor = "undefined" unless defined($vendor); + print "dpkg-buildflags: vendor is $vendor\n"; + # Then the resulting features: + foreach my $area (sort $build_flags->get_feature_areas()) { + print "dpkg-buildflags: $area features:"; + my %features = $build_flags->get_features($area); + foreach my $feature (sort keys %features) { + printf " %s=%s", $feature, $features{$feature} ? "yes" : "no"; + } + print "\n"; + } + # Then the resulting values (with their origin): + foreach my $flag ($build_flags->list()) { + my $value = $build_flags->get($flag); + my $origin = $build_flags->get_origin($flag); + # Note that DEB_*_MAINT_* does not effect $origin. + print "dpkg-buildflags: $flag [$origin]: $value\n"; + } + exit(0); } exit(1); -- 1.7.9.1
>From 6a600d3f9d2b438ca59d0e81f69b91249bd197b1 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" <brl...@debian.org> Date: Fri, 16 Mar 2012 11:05:17 +0100 Subject: [PATCH 4/4] dpkg-buildflags: make --status output which flags are modified by maintainer As flags modified by DEB_*_MAINT_* are not reflected by its origin, add a new flag to describe flags modified that way. Signed-off-by: Bernhard R. Link <brl...@debian.org> --- scripts/Dpkg/BuildFlags.pm | 61 ++++++++++++++++++++++++++++++++----------- scripts/dpkg-buildflags.pl | 4 +- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/scripts/Dpkg/BuildFlags.pm b/scripts/Dpkg/BuildFlags.pm index 4a84c57..af8d93b 100644 --- a/scripts/Dpkg/BuildFlags.pm +++ b/scripts/Dpkg/BuildFlags.pm @@ -87,6 +87,13 @@ sub load_vendor_defaults { FFLAGS => 'vendor', LDFLAGS => 'vendor', }; + $self->{maintainer} = { + CPPFLAGS => 0, + CFLAGS => 0, + CXXFLAGS => 0, + FFLAGS => 0, + LDFLAGS => 0, + }; # The Debian vendor hook will add hardening build flags run_vendor_hook("update-buildflags", $self); # run_vendor_hook looked at DEB_VENDOR @@ -165,22 +172,22 @@ sub load_maintainer_config { my $envvar = "DEB_" . $flag . "_MAINT_SET"; $self->environment_used($envvar); if (exists $ENV{$envvar}) { - $self->set($flag, $ENV{$envvar}, undef); + $self->set($flag, $ENV{$envvar}, undef, 1); } $envvar = "DEB_" . $flag . "_MAINT_STRIP"; $self->environment_used($envvar); if (exists $ENV{$envvar}) { - $self->strip($flag, $ENV{$envvar}, undef); + $self->strip($flag, $ENV{$envvar}, undef, 1); } $envvar = "DEB_" . $flag . "_MAINT_APPEND"; $self->environment_used($envvar); if (exists $ENV{$envvar}) { - $self->append($flag, $ENV{$envvar}, undef); + $self->append($flag, $ENV{$envvar}, undef, 1); } $envvar = "DEB_" . $flag . "_MAINT_PREPEND"; $self->environment_used($envvar); if (exists $ENV{$envvar}) { - $self->prepend($flag, $ENV{$envvar}, undef); + $self->prepend($flag, $ENV{$envvar}, undef, 1); } } } @@ -202,17 +209,19 @@ sub load_config { $self->load_maintainer_config(); } -=item $bf->set($flag, $value, $source) +=item $bf->set($flag, $value, $source, $maint) Update the build flag $flag with value $value and record its origin as -$source (if defined). +$source (if defined). Record it as maintainer modified if $maint is +defined and true. =cut sub set { - my ($self, $flag, $value, $src) = @_; + my ($self, $flag, $value, $src, $maint) = @_; $self->{flags}->{$flag} = $value; $self->{origin}->{$flag} = $src if defined $src; + $self->{maintainer}->{$flag} = $maint if $maint; } =item $bf->set_feature($area, $feature, $enabled) @@ -228,15 +237,16 @@ sub set_feature { $self->{'features'}{$area}{$feature} = $enabled; } -=item $bf->strip($flag, $value, $source) +=item $bf->strip($flag, $value, $source, $maint) Update the build flag $flag by stripping the flags listed in $value and -record its origin as $source (if defined). +record its origin as $source (if defined). Record it as maintainer modified +if $maint is defined and true. =cut sub strip { - my ($self, $flag, $value, $src) = @_; + my ($self, $flag, $value, $src, $maint) = @_; foreach my $tostrip (split(/\s+/, $value)) { next unless length $tostrip; $self->{flags}->{$flag} =~ s/(^|\s+)\Q$tostrip\E(\s+|$)/ /g; @@ -244,40 +254,45 @@ sub strip { $self->{flags}->{$flag} =~ s/^\s+//g; $self->{flags}->{$flag} =~ s/\s+$//g; $self->{origin}->{$flag} = $src if defined $src; + $self->{maintainer}->{$flag} = $maint if $maint; } -=item $bf->append($flag, $value, $source) +=item $bf->append($flag, $value, $source, $maint) Append the options listed in $value to the current value of the flag $flag. -Record its origin as $source (if defined). +Record its origin as $source (if defined). Record it as maintainer modified +if $maint is defined and true. =cut sub append { - my ($self, $flag, $value, $src) = @_; + my ($self, $flag, $value, $src, $maint) = @_; if (length($self->{flags}->{$flag})) { $self->{flags}->{$flag} .= " $value"; } else { $self->{flags}->{$flag} = $value; } $self->{origin}->{$flag} = $src if defined $src; + $self->{maintainer}->{$flag} = $maint if $maint; } -=item $bf->prepend($flag, $value, $source) +=item $bf->prepend($flag, $value, $source, $maint) Prepend the options listed in $value to the current value of the flag $flag. -Record its origin as $source (if defined). +Record its origin as $source (if defined). Record it as maintainer modified +if $maint is defined and true. =cut sub prepend { - my ($self, $flag, $value, $src) = @_; + my ($self, $flag, $value, $src, $maint) = @_; if (length($self->{flags}->{$flag})) { $self->{flags}->{$flag} = "$value " . $self->{flags}->{$flag}; } else { $self->{flags}->{$flag} = $value; } $self->{origin}->{$flag} = $src if defined $src; + $self->{maintainer}->{$flag} = $maint if $maint; } @@ -368,6 +383,17 @@ sub get_origin { return $self->{'origin'}{$key}; } +=item $bf->is_maintainer_modified($flag) + +Return true if the flag is modified by the maintainer. + +=cut + +sub is_maintainer_modified { + my ($self, $key) = @_; + return $self->{'maintainer'}{$key}; +} + =item $bf->has_features($area) Returns true if the given area of features is known, and false otherwise. @@ -444,6 +470,9 @@ based on the package maintainer directives. New methods: $bf->get_features(), $bf->has_features(), $bf->set_feature(), $bf->get_feature_areas(), $bf->environment_used(), $bf->get_used_environment(). +New method $bf->is_maintainer_modified() and new optional parameter to +$bf->set(), $bf->append(), $bf->prepend(), $bf->strip(). + =head1 AUTHOR Raphaël Hertzog <hert...@debian.org> diff --git a/scripts/dpkg-buildflags.pl b/scripts/dpkg-buildflags.pl index 66069a5..af685ca 100755 --- a/scripts/dpkg-buildflags.pl +++ b/scripts/dpkg-buildflags.pl @@ -176,8 +176,8 @@ if ($action eq "get") { foreach my $flag ($build_flags->list()) { my $value = $build_flags->get($flag); my $origin = $build_flags->get_origin($flag); - # Note that DEB_*_MAINT_* does not effect $origin. - print "dpkg-buildflags: $flag [$origin]: $value\n"; + my $maintainer = $build_flags->is_maintainer_modified($flag) ? "+maintainer" : ""; + print "dpkg-buildflags: $flag [$origin$maintainer]: $value\n"; } exit(0); } -- 1.7.9.1