| # Wrapper for compilers on macOS | |
| # that lose debug information in the final link of an executable. | |
| scriptversion=2024-05-20.15; # UTC | |
| # Copyright (C) 2024-2025 Free Software Foundation, Inc. | |
| # | |
| # This file is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published | |
| # by the Free Software Foundation, either version 3 of the License, | |
| # or (at your option) any later version. | |
| # | |
| # This file is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <https://www.gnu.org/licenses/>. | |
| # Written by Bruno Haible <bruno@clisp.org>, 2024. | |
| # The problem: | |
| # 1) On macOS, debug information for executables is not stored in the | |
| # executable itself, but in a separate file: If the executable is in | |
| # ${DIR}/${BASENAME} | |
| # the debug info is in | |
| # ${DIR}/${BASENAME}.dSYM/Contents/Resources/DWARF/${BASENAME} | |
| # 2) The Apple compilers on macOS, in the linking step that creates an | |
| # executable from object files, do not create this debug info. | |
| # An extra command | |
| # dsymutil ${DIR}/${BASENAME} | |
| # is necessary in order to create it. | |
| # | |
| # See | |
| # https://stackoverflow.com/questions/32297349/why-does-a-2-stage-command-line-build-with-clang-not-generate-a-dsym-directory | |
| # https://stackoverflow.com/questions/10044697/where-how-does-apples-gcc-store-dwarf-inside-an-executable/12827463#12827463 | |
| # https://wiki.dwarfstd.org/Apple%27s_%22Lazy%22_DWARF_Scheme.md | |
| # The solution: | |
| # Make | |
| # macos-compile clang [OPTION...] FILE... | |
| # behave like | |
| # clang [OPTION...] FILE... | |
| # does on other platforms, namely to create the debug info during linking | |
| # of the executable (instead of leaving it for later). | |
| # Note: 1) is also a problem for the 'install' command that installs an | |
| # executable in a public location. This is not handled here. | |
| # func_usage | |
| # outputs to stdout the --help usage message. | |
| func_usage () | |
| { | |
| echo "\ | |
| Usage: macos-compile COMPILER [OPTION...] FILE... | |
| Invokes COMPILER [OPTION...] FILE... and handles debug information. | |
| Report bugs to <bug-gnulib@gnu.org>." | |
| } | |
| # Handle --help and --version. | |
| case "$1" in | |
| --help) | |
| func_usage | |
| exit $? | |
| ;; | |
| --version) | |
| echo "macos-compile (GNU gnulib) $scriptversion | |
| Copyright (C) 2024-2025 Free Software Foundation, Inc. | |
| License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. | |
| This is free software: you are free to change and redistribute it. | |
| There is NO WARRANTY, to the extent permitted by law. | |
| Written by Bruno Haible." | |
| exit $? | |
| ;; | |
| esac | |
| # Set to true for the linking step that creates an executable. | |
| linking=true | |
| # The executable created by the command. | |
| output_file='a.out' | |
| output_file_is_next=false | |
| # Whether debug information is requested. | |
| debugging=false | |
| # Process the command-line options. | |
| first=true | |
| for arg | |
| do | |
| if $first; then | |
| first=false | |
| set -- "$arg" | |
| else | |
| if $output_file_is_next; then | |
| output_file="$arg" | |
| output_file_is_next=false | |
| else | |
| case "$arg" in | |
| -c | -E | -S | -fdriver-only | --precompile ) | |
| linking=false | |
| ;; | |
| -o ) | |
| output_file_is_next=true | |
| ;; | |
| -g* ) | |
| debugging=true | |
| ;; | |
| esac | |
| fi | |
| set -- "$@" "$arg" | |
| fi | |
| done | |
| # Execute the command and the $output_file.dSYM workaround. | |
| if $linking; then | |
| rm -rf "$output_file.dSYM" | |
| fi | |
| "$@" || exit $? | |
| if $linking; then | |
| # Do this dsymutil invocation also when not $debugging. | |
| # The linking step is supposed to copy and link the debug information from | |
| # the previous steps always. | |
| # Example: $CC -g -O2 -c foo.c && $CC foo.o | |
| dsymutil "$output_file" || exit $? | |
| fi | |
| exit 0 | |