From 938d8528b896f15dc10c21a208b795f78acac127 Mon Sep 17 00:00:00 2001 From: Clemens Lang Date: Thu, 19 Nov 2020 23:57:22 +0100 Subject: [PATCH] port1.0: configure: Add check for implicit decls On macOS 11, implicit function declarations are now errors by default. This may affect configure checks and actually cause software to compile differently without us knowing. Add a post-configure check that scans any config.log files in ${configure.dir} for indicators of such problems and warn about them, so they will not go unnoticed. Extract the list of functions that were found to be undeclared and check them against a whitelist of glob expressions initialized from a file in _resources/port1.0/checks/implicit_function_declaration/macosx${configure.sdk_version}.sdk.list so that functions that are legitimately undeclared on macOS can be whitelisted globally. Note that the whitelist in configure.checks.implicit_function_declaration.whitelist can also be edited per-Portfile, should that become necessary. --- src/port1.0/portconfigure.tcl | 79 +++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/port1.0/portconfigure.tcl b/src/port1.0/portconfigure.tcl index e472fb2d00..af09bc3b62 100644 --- a/src/port1.0/portconfigure.tcl +++ b/src/port1.0/portconfigure.tcl @@ -33,11 +33,13 @@ package provide portconfigure 1.0 package require portutil 1.0 package require portprogress 1.0 +package require struct::set set org.macports.configure [target_new org.macports.configure portconfigure::configure_main] target_provides ${org.macports.configure} configure target_requires ${org.macports.configure} main fetch checksum extract patch target_prerun ${org.macports.configure} portconfigure::configure_start +target_postrun ${org.macports.configure} portconfigure::configure_end namespace eval portconfigure { } @@ -1723,3 +1725,80 @@ proc portconfigure::configure_main {args} { } return 0 } + +options configure.checks.implicit_function_declaration \ + configure.checks.implicit_function_declaration.whitelist +default configure.checks.implicit_function_declaration yes +default configure.checks.implicit_function_declaration.whitelist {[portconfigure::load_implicit_function_declaration_whitelist ${configure.sdk_version}]} + +proc portconfigure::check_implicit_function_declarations {} { + global \ + configure.dir \ + configure.checks.implicit_function_declaration.whitelist + + # Map from function name to config.log that used it without declaration + array set undeclared_functions {} + + fs-traverse -tails file ${configure.dir} { + if {[file tail $file] eq "config.log" && [file isfile [file join ${configure.dir} $file]]} { + # We could do the searching ourselves, but using a tool optimized for this purpose is likely much faster + # than using Tcl. + # + # Using /usr/bin/grep here, so we don't accidentally pick up a macports-installed grep which might + # currently not be runnable due to a missing library. + set args [list "/usr/bin/grep" "--" "-Wimplicit-function-declaration"] + lappend args [file join ${configure.dir} $file] + + if {![catch {set result [exec -- {*}$args]}]} { + foreach line [split $result "\n"] { + if {[regexp -- "implicit declaration of function '(\[^']+)'" $line -> function]} { + set is_whitelisted no + foreach whitelisted ${configure.checks.implicit_function_declaration.whitelist} { + if {[string match -nocase $whitelisted $function]} { + set is_whitelisted yes + break + } + } + if {!$is_whitelisted} { + ::struct::set include undeclared_functions($function) $file + } else { + ui_debug [format "Ignoring implicit declaration of function '%s', because it is whitelisted" $function] + } + } + } + } + } + } + + if {[array size undeclared_functions] > 0} { + ui_warn "Configuration logfiles contain indications of -Wimplicit-function-declaration, check that features were not accidentially disabled:" + foreach {function files} [array get undeclared_functions] { + ui_msg [format " %s: found in %s" $function [join $files ", "]] + } + } +} + +proc portconfigure::load_implicit_function_declaration_whitelist {sdk_version} { + set whitelist {} + + set whitelist_file [getdefaultportresourcepath "port1.0/checks/implicit_function_declaration/macosx${sdk_version}.sdk.list"] + if {[file exists $whitelist_file]} { + set fd [open $whitelist_file r] + while {[gets $fd whitelist_entry] >= 0} { + lappend whitelist $whitelist_entry + } + close $fd + } + + return $whitelist +} + +proc portconfigure::configure_end {args} { + global \ + configure.dir \ + configure.checks.implicit_function_declaration + + if {[file isdirectory ${configure.dir}] && ${configure.checks.implicit_function_declaration}} { + portconfigure::check_implicit_function_declarations + } +}