1# Copyright (C) 2003-2021 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 2, or (at your option) 6# any later version. 7 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <https://www.gnu.org/licenses/>. 15 16package Automake::Options; 17 18use 5.006; 19use strict; 20use warnings FATAL => 'all'; 21 22use Exporter; 23 24use Automake::Config; 25use Automake::ChannelDefs; 26use Automake::Channels; 27use Automake::Version; 28 29our @ISA = qw (Exporter); 30our @EXPORT = qw (option global_option 31 set_option set_global_option 32 unset_option unset_global_option 33 process_option_list process_global_option_list 34 set_strictness $strictness $strictness_name 35 &FOREIGN &GNU &GNITS); 36 37=head1 NAME 38 39Automake::Options - keep track of Automake options 40 41=head1 SYNOPSIS 42 43 use Automake::Options; 44 45 # Option lookup and setting. 46 $opt = option 'name'; 47 $opt = global_option 'name'; 48 set_option 'name', 'value'; 49 set_global_option 'name', 'value'; 50 unset_option 'name'; 51 unset_global_option 'name'; 52 53 # Batch option setting. 54 process_option_list $location, @names; 55 process_global_option_list $location, @names; 56 57 # Strictness lookup and setting. 58 set_strictness 'foreign'; 59 set_strictness 'gnu'; 60 set_strictness 'gnits'; 61 if ($strictness >= GNU) { ... } 62 print "$strictness_name\n"; 63 64=head1 DESCRIPTION 65 66This packages manages Automake's options and strictness settings. 67Options can be either local or global. Local options are set using an 68C<AUTOMAKE_OPTIONS> variable in a F<Makefile.am> and apply only to 69this F<Makefile.am>. Global options are set from the command line or 70passed as an argument to C<AM_INIT_AUTOMAKE>, they apply to all 71F<Makefile.am>s. 72 73=cut 74 75# Values are the Automake::Location of the definition. 76our %_options; # From AUTOMAKE_OPTIONS 77our %_global_options; # From AM_INIT_AUTOMAKE or the command line. 78 79# Whether process_option_list has already been called for the current 80# Makefile.am. 81our $_options_processed; 82# Whether process_global_option_list has already been called. 83our $_global_options_processed; 84 85=head2 Constants 86 87=over 4 88 89=item FOREIGN 90 91=item GNU 92 93=item GNITS 94 95Strictness constants used as values for C<$strictness>. 96 97=back 98 99=cut 100 101# Constants to define the "strictness" level. 102use constant FOREIGN => 0; 103use constant GNU => 1; 104use constant GNITS => 2; 105 106=head2 Variables 107 108=over 4 109 110=item C<$strictness> 111 112The current strictness. One of C<FOREIGN>, C<GNU>, or C<GNITS>. 113 114=item C<$strictness_name> 115 116The current strictness name. One of C<'foreign'>, C<'gnu'>, or C<'gnits'>. 117 118=back 119 120=cut 121 122# Strictness levels. 123our ($strictness, $strictness_name); 124 125# Strictness level as set on command line. 126our ($_default_strictness, $_default_strictness_name); 127 128 129=head2 Functions 130 131=over 4 132 133=item C<Automake::Options::reset> 134 135Reset the options variables for the next F<Makefile.am>. 136 137In other words, this gets rid of all local options in use by the 138previous F<Makefile.am>. 139 140=cut 141 142sub reset () 143{ 144 $_options_processed = 0; 145 %_options = %_global_options; 146 # The first time we are run, 147 # remember the current setting as the default. 148 if (defined $_default_strictness) 149 { 150 $strictness = $_default_strictness; 151 $strictness_name = $_default_strictness_name; 152 } 153 else 154 { 155 $_default_strictness = $strictness; 156 $_default_strictness_name = $strictness_name; 157 } 158} 159 160=item C<$value = option ($name)> 161 162=item C<$value = global_option ($name)> 163 164Query the state of an option. If the option is unset, this 165returns the empty list. Otherwise it returns the option's value, 166as set by C<set_option> or C<set_global_option>. 167 168Note that C<global_option> should be used only when it is 169important to make sure an option hasn't been set locally. 170Otherwise C<option> should be the standard function to 171check for options (be they global or local). 172 173=cut 174 175sub option ($) 176{ 177 my ($name) = @_; 178 return () unless defined $_options{$name}; 179 return $_options{$name}; 180} 181 182sub global_option ($) 183{ 184 my ($name) = @_; 185 return () unless defined $_global_options{$name}; 186 return $_global_options{$name}; 187} 188 189=item C<set_option ($name, $value)> 190 191=item C<set_global_option ($name, $value)> 192 193Set an option. By convention, C<$value> is usually the location 194of the option definition. 195 196=cut 197 198sub set_option ($$) 199{ 200 my ($name, $value) = @_; 201 $_options{$name} = $value; 202} 203 204sub set_global_option ($$) 205{ 206 my ($name, $value) = @_; 207 $_global_options{$name} = $value; 208} 209 210 211=item C<unset_option ($name)> 212 213=item C<unset_global_option ($name)> 214 215Unset an option. 216 217=cut 218 219sub unset_option ($) 220{ 221 my ($name) = @_; 222 delete $_options{$name}; 223} 224 225sub unset_global_option ($) 226{ 227 my ($name) = @_; 228 delete $_global_options{$name}; 229} 230 231 232=item C<process_option_list (@list)> 233 234=item C<process_global_option_list (@list)> 235 236Process Automake's option lists. C<@list> should be a list of hash 237references with keys C<option> and C<where>, where C<option> is an 238option as they occur in C<AUTOMAKE_OPTIONS> or C<AM_INIT_AUTOMAKE>, 239and C<where> is the location where that option occurred. 240 241These functions should be called at most once for each set of options 242having the same precedence; i.e., do not call it twice for two options 243from C<AM_INIT_AUTOMAKE>. 244 245Return 0 on error, 1 otherwise. 246 247=cut 248 249# $BOOL 250# _option_is_from_configure ($OPTION, $WHERE) 251# ---------------------------------------------- 252# Check that the $OPTION given in location $WHERE is specified with 253# AM_INIT_AUTOMAKE, not with AUTOMAKE_OPTIONS. 254sub _option_is_from_configure ($$) 255{ 256 my ($opt, $where)= @_; 257 return 1 258 if $where->get =~ /^configure\./; 259 error $where, 260 "option '$opt' can only be used as argument to AM_INIT_AUTOMAKE\n" . 261 "but not in AUTOMAKE_OPTIONS makefile statements"; 262 return 0; 263} 264 265# $BOOL 266# _is_valid_easy_option ($OPTION) 267# ------------------------------- 268# Explicitly recognize valid automake options that require no 269# special handling by '_process_option_list' below. 270sub _is_valid_easy_option ($) 271{ 272 my $opt = shift; 273 return scalar grep { $opt eq $_ } qw( 274 check-news 275 color-tests 276 dejagnu 277 dist-bzip2 278 dist-lzip 279 dist-xz 280 dist-zip 281 dist-zstd 282 info-in-builddir 283 no-define 284 no-dependencies 285 no-dist 286 no-dist-built-sources 287 no-dist-gzip 288 no-exeext 289 no-installinfo 290 no-installman 291 no-texinfo.tex 292 nostdinc 293 readme-alpha 294 serial-tests 295 parallel-tests 296 silent-rules 297 std-options 298 subdir-objects 299 ); 300} 301 302# $BOOL 303# _process_option_list (\%OPTIONS, @LIST) 304# ------------------------------------------ 305# Process a list of options. \%OPTIONS is the hash to fill with options 306# data. @LIST is a list of options as get passed to public subroutines 307# process_option_list() and process_global_option_list() (see POD 308# documentation above). 309sub _process_option_list (\%@) 310{ 311 my ($options, @list) = @_; 312 my @warnings = (); 313 my $ret = 1; 314 315 foreach my $h (@list) 316 { 317 local $_ = $h->{'option'}; 318 my $where = $h->{'where'}; 319 $options->{$_} = $where; 320 if ($_ eq 'gnits' || $_ eq 'gnu' || $_ eq 'foreign') 321 { 322 set_strictness ($_); 323 } 324 # TODO: Remove this special check in Automake 3.0. 325 elsif (/^(.*\/)?ansi2knr$/) 326 { 327 # Obsolete (and now removed) de-ANSI-fication support. 328 error ($where, 329 "automatic de-ANSI-fication support has been removed"); 330 $ret = 0; 331 } 332 # TODO: Remove this special check in Automake 3.0. 333 elsif ($_ eq 'cygnus') 334 { 335 error $where, "support for Cygnus-style trees has been removed"; 336 $ret = 0; 337 } 338 # TODO: Remove this special check in Automake 3.0. 339 elsif ($_ eq 'dist-lzma') 340 { 341 error ($where, "support for lzma-compressed distribution " . 342 "archives has been removed"); 343 $ret = 0; 344 } 345 # TODO: Make this a fatal error in Automake 2.0. 346 elsif ($_ eq 'dist-shar') 347 { 348 msg ('obsolete', $where, 349 "support for shar distribution archives is deprecated.\n" . 350 " It will be removed in Automake 2.0"); 351 } 352 # TODO: Make this a fatal error in Automake 2.0. 353 elsif ($_ eq 'dist-tarZ') 354 { 355 msg ('obsolete', $where, 356 "support for distribution archives compressed with " . 357 "legacy program 'compress' is deprecated.\n" . 358 " It will be removed in Automake 2.0"); 359 } 360 elsif (/^filename-length-max=(\d+)$/) 361 { 362 delete $options->{$_}; 363 $options->{'filename-length-max'} = [$_, $1]; 364 } 365 elsif ($_ eq 'tar-v7' || $_ eq 'tar-ustar' || $_ eq 'tar-pax') 366 { 367 if (not _option_is_from_configure ($_, $where)) 368 { 369 $ret = 0; 370 } 371 for my $opt ('tar-v7', 'tar-ustar', 'tar-pax') 372 { 373 next 374 if $opt eq $_ or ! exists $options->{$opt}; 375 error ($where, 376 "options '$_' and '$opt' are mutually exclusive"); 377 $ret = 0; 378 } 379 } 380 elsif (/^\d+\.\d+(?:\.\d+)?[a-z]?(?:-[A-Za-z0-9]+)?$/) 381 { 382 # Got a version number. 383 if (Automake::Version::check ($VERSION, $&)) 384 { 385 error ($where, "require Automake $_, but have $VERSION"); 386 $ret = 0; 387 } 388 } 389 elsif (/^(?:--warnings=|-W)(.*)$/) 390 { 391 my @w = map { { cat => $_, loc => $where} } split (',', $1); 392 push @warnings, @w; 393 } 394 elsif (! _is_valid_easy_option $_) 395 { 396 error ($where, "option '$_' not recognized"); 397 $ret = 0; 398 } 399 } 400 401 # We process warnings here, so that any explicitly-given warning setting 402 # will take precedence over warning settings defined implicitly by the 403 # strictness. 404 foreach my $w (@warnings) 405 { 406 msg 'unsupported', $w->{'loc'}, 407 "unknown warning category '$w->{'cat'}'" 408 if switch_warning $w->{cat}; 409 } 410 411 return $ret; 412} 413 414sub process_option_list (@) 415{ 416 prog_error "local options already processed" 417 if $_options_processed; 418 $_options_processed = 1; 419 _process_option_list (%_options, @_); 420} 421 422sub process_global_option_list (@) 423{ 424 prog_error "global options already processed" 425 if $_global_options_processed; 426 $_global_options_processed = 1; 427 _process_option_list (%_global_options, @_); 428} 429 430=item C<set_strictness ($name)> 431 432Set the current strictness level. 433C<$name> should be one of C<'foreign'>, C<'gnu'>, or C<'gnits'>. 434 435=cut 436 437# Set strictness. 438sub set_strictness ($) 439{ 440 $strictness_name = $_[0]; 441 442 Automake::ChannelDefs::set_strictness ($strictness_name); 443 444 if ($strictness_name eq 'gnu') 445 { 446 $strictness = GNU; 447 } 448 elsif ($strictness_name eq 'gnits') 449 { 450 $strictness = GNITS; 451 } 452 elsif ($strictness_name eq 'foreign') 453 { 454 $strictness = FOREIGN; 455 } 456 else 457 { 458 prog_error "level '$strictness_name' not recognized"; 459 } 460} 461 4621; 463