perlboy
perlboy

Reputation: 108

dSYM not generated when building with make

On macOS 12.7.5 (Monterey) using gcc to compile *.c: gcc version 13.2.0, with gnu make 3.81, (I prefer command line tools over XCode), when I pass CFLAGS = -g in a makefile I get full debugging symbols inside the executable but no .dSYM directory. In other words, the symbols are not stripped. However, when I type a typical gcc command:

    gcc -g filename1.c filename2.c -o filename

directly from the command line, the .dSYM directory is generated. I can debug either image with lldb as lldb knows how to read a .dSYM. The unstripped executable has the symbols but the .dSYM is valuable in its own right. I can obviously build for release without -g, but this means two separate make tasks. How can I configure the makefile to cause the .dSYM to be generated? That's the whole point of make, to avoid having to type a complex multi-file build command. What am I missing re .dSYM?

Here is an example makefile. All of mine follow this pattern.

# make description file to build a family of hashing programs

LANG   = -std=c11
GCOBJS = distanceGC.o hashtblGC.o ../GreatCircle/greatcircle.o
FOBJS  = ftlhash.o
HOBJS  = hashtbl.o argv.o

GCHDRS = hashGC.h ../GreatCircle/greatcircle.h
FHDRS  = ftlhash.h
HHDRS  = hashtbl.h ftlhash.h

CC     = gcc
CFLAGS = -g -Wall

distanceGC : ${GCOBJS}
    ${CC} ${LANG} ${CFLAGS} -o $@ ${GCOBJS}

${GCOBJS} : ${GCHDRS}

../GreatCircle/greatcircle.o : ../GreatCircle/greatcircle.h
    cd /Users/wills/src/c/GreatCircle; make all

ftlhash : ${FOBJS}
    ${CC} ${LANG} ${CFLAGS} -o $@ ${FOBJS}

${FOBJS} : ${FHDRS}

hashtbl : ${HOBJS}
    ${CC} ${LANG} ${CFLAGS} -o $@ ${HOBJS}

${HOBJS} : ${HHDRS}

all : ftlhash hashtbl distanceGC

clean :
    /bin/rm -f core *.o
    cd /Users/wills/src/c/GreatCircle; /bin/rm -f core *.o
    /bin/rm /Users/wills/src/c/HASHTABLE/greatcircle.h
    /bin/ln -s /Users/wills/src/c/GreatCircle/    greatcircle.h /Users/wills/src/c/HASHTABLE/greatcircle.h

Here are sample build commands to recompile one of those targets:

touch ftlhash.c
make ftlhash

This yields:

gcc -g   -c -o ftlhash.o ftlhash.c
gcc -std=c11 -g -o ftlhash ftlhash.o

I'm guessing there is some Apple utility that an XCode build, or a command line invocation uses by defaut, to strip out the symbols and create the .dSYM, which my makefile is not doing. My command line direct invocation of gcc produced:

drwxr-xr-x   3 wills  staff     96 Jul 15 15:03 ftlhash.dSYM

UPDATE: Looks like Apple's dsymutil in macOS is that tool. Now to teach make how to use it.

Thank you Jonathan Leffler for back and forth discussion of issue. /usr/bin/dsymutil $@ added to make build targets solves the problem.

For conditional execution you can do:

ifneq (,$(findstring -g, $(CFLAGS)))
    /usr/bin/dsymutil $@
endif

But be aware. Only the actual command is preceded with a tab. The ifneq and endif make statements are not commands, so must not have a leading tab.

Upvotes: 1

Views: 175

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 754790

I've seen this behaviour.

There's an option to Clang (aka gcc on a Mac):

  • -dsym-dir <dir> — Directory to output dSYM's (if any) to

You might be able to use that in your linking command line, but see below.

I've not previously investigated when the .dSYM directory is not created. Using -g on the linking command line is one key factor. Without that, the .dSYM directory is not created. But there is more to it than that. If I link object files (and libraries) only, the .dSYM directory is not created, even with the -g flag. If I specify at least one source file on the linking command line (and -g), then I seem to get the .dSYM file.

Many makefiles compile the various source files to object files and then link those object files. So, those programs probably do not get a .dSYM directory created.

Here's a simple shell script to demo the behaviour:

#!/bin/sh

source=cmplx67

clean()
{
    rm -fr $source $source.o $source.dSYM
}

set -x
clean
ls -l
clang -o $source $source.c
ls -l
clean
clang -g -o $source $source.c
ls -l
clean
clang -g -c $source.c
clang -g -o $source $source.o
ls -l
clean
clang -g -c $source.c
clang -g -o $source $source.o -dsym-dir $source.dSYM
ls -l
clean

The file cmplx67.c is a trivial program.

When run, I get output such as:

2024-07-15 16:49:22
+ clean
+ rm -fr cmplx67 cmplx67.o cmplx67.dSYM
+ ls -l
total 24
-rw-r--r--  1 jonathanleffler  staff  478 Jul 15 16:20 cmplx67.c
-rw-r--r--  1 jonathanleffler  staff  333 Jul 15 16:47 demo.sh
-rw-r--r--  1 jonathanleffler  staff  194 Jul 15 16:23 makefile
+ clang -o cmplx67 cmplx67.c
+ ls -l
total 96
-rwxr-xr-x  1 jonathanleffler  staff  33496 Jul 15 16:49 cmplx67
-rw-r--r--  1 jonathanleffler  staff    478 Jul 15 16:20 cmplx67.c
-rw-r--r--  1 jonathanleffler  staff    333 Jul 15 16:47 demo.sh
-rw-r--r--  1 jonathanleffler  staff    194 Jul 15 16:23 makefile
+ clean
+ rm -fr cmplx67 cmplx67.o cmplx67.dSYM
+ clang -g -o cmplx67 cmplx67.c
+ ls -l
total 96
-rwxr-xr-x  1 jonathanleffler  staff  33832 Jul 15 16:49 cmplx67
-rw-r--r--  1 jonathanleffler  staff    478 Jul 15 16:20 cmplx67.c
drwxr-xr-x  3 jonathanleffler  staff     96 Jul 15 16:49 cmplx67.dSYM
-rw-r--r--  1 jonathanleffler  staff    333 Jul 15 16:47 demo.sh
-rw-r--r--  1 jonathanleffler  staff    194 Jul 15 16:23 makefile
+ clean
+ rm -fr cmplx67 cmplx67.o cmplx67.dSYM
+ clang -g -c cmplx67.c
+ clang -g -o cmplx67 cmplx67.o
+ ls -l
total 104
-rwxr-xr-x  1 jonathanleffler  staff  33800 Jul 15 16:49 cmplx67
-rw-r--r--  1 jonathanleffler  staff    478 Jul 15 16:20 cmplx67.c
-rw-r--r--  1 jonathanleffler  staff   2968 Jul 15 16:49 cmplx67.o
-rw-r--r--  1 jonathanleffler  staff    333 Jul 15 16:47 demo.sh
-rw-r--r--  1 jonathanleffler  staff    194 Jul 15 16:23 makefile
+ clean
+ rm -fr cmplx67 cmplx67.o cmplx67.dSYM
+ clang -g -c cmplx67.c
+ clang -g -o cmplx67 cmplx67.o -dsym-dir cmplx67.dSYM
clang: warning: argument unused during compilation: '-dsym-dir cmplx67.dSYM' [-Wunused-command-line-argument]
+ ls -l
total 104
-rwxr-xr-x  1 jonathanleffler  staff  33800 Jul 15 16:49 cmplx67
-rw-r--r--  1 jonathanleffler  staff    478 Jul 15 16:20 cmplx67.c
-rw-r--r--  1 jonathanleffler  staff   2968 Jul 15 16:49 cmplx67.o
-rw-r--r--  1 jonathanleffler  staff    333 Jul 15 16:47 demo.sh
-rw-r--r--  1 jonathanleffler  staff    194 Jul 15 16:23 makefile
+ clean
+ rm -fr cmplx67 cmplx67.o cmplx67.dSYM

As you can see, the -dsym-dir option was ignored when the object file was linked. When I compiled and linked the source file with the option, it was used. (I experimented with -dsym-dir=cmplx67.dSYM and got a directory =cmplx67.dSYM!)

You can adapt this to make more experiments. What .dSYM directory is created if there a multiple source files on the command line, for example.

Testing on an M2 MacBook Pro running macOS Sonoma 14.5 and using:

Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64-apple-darwin23.5.0

I've seen this behaviour on many prior versions of macOS, including those predating macOS Monterey 12.7.5. I've used MacOS X and macOS fairly solidly since at least Mac OS X Jaguar 10.2, and I think I used Mac OS X 10.0 Cheetah, but I'd be hard-pressed to prove that now.

Using the name gcc instead of clang doesn't change the behaviour.

Upvotes: 1

Related Questions