3

I recently started using CMake and I haven't been able to figure out how to get my debug symbols to work for Valgrind. So, I made a test project to demonstrate my problem. Without CMake, I would just compile with -g:

g++ -std=c++11 -g main.cpp -o test

and I get the test.dSYM directory that I want. According to How do you set GDB debug flag with cmake?, to get the -g flag, I should use the argument

-D CMAKE_BUILD_TYPE=Debug

So that is what I tried. In a folder named Testing, I created a test file main.cpp with the following contents:

#include <iostream>
using std::cout;

int main( int argc , const char* argv[] ) {
    int* leak = new int;
    int arr[] = { 1 , 2 , 3 , 4 };
    for ( int i : arr ) {
        cout << i << "\n";      
    }
    return 0;
}

Inside Testing, I also created a file CMakeLists.txt with the following contents:

cmake_minimum_required( VERSION 3.1 )
project( Testing )
add_executable( test1 main.cpp )
set_property(TARGET test1 PROPERTY CXX_STANDARD 11)
set_property(TARGET test1 PROPERTY CXX_STANDARD_REQUIRED ON)

Then I created a new directory, Testing/cmake_build and in that directory I ran the following commands:

Testing/cmake_build$ cmake -D CMAKE_BUILD_TYPE=Debug ..
Testing/cmake_build$ make
Testing/cmake_build$ valgrind --leak-check=yes ./test

And Valgrind complains that the dSYM directory is missing. I looked around for it myself, and haven't found it. Thus, I don't get line numbers in the leak check output and I can't debug my project:

==2388== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==2388== Command: ./test
==2388== 
--2388-- ./test:
--2388-- dSYM directory is missing; consider using --dsymutil=yes
1
2
3
4
==2388== 
==2388== HEAP SUMMARY:
==2388==     in use at exit: 29,443 bytes in 378 blocks
==2388==   total heap usage: 472 allocs, 94 frees, 36,027 bytes allocated
==2388== 
==2388== 4 bytes in 1 blocks are definitely lost in loss record 1 of 76
==2388==    at 0x47F1: malloc (vg_replace_malloc.c:300)
==2388==    by 0x4928D: operator new(unsigned long) (in /usr/lib/libc++.1.dylib)
==2388==    by 0x1000012E5: main (in ./test)
==2388== 
==2388== LEAK SUMMARY:
==2388==    definitely lost: 4 bytes in 1 blocks
==2388==    indirectly lost: 0 bytes in 0 blocks
==2388==      possibly lost: 0 bytes in 0 blocks
==2388==    still reachable: 4,096 bytes in 1 blocks
==2388==         suppressed: 25,343 bytes in 376 blocks
==2388== Reachable blocks (those to which a pointer was found) are not shown.
==2388== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==2388== 

It should say

==2530==    by 0x1000012E5: main (main.cpp:5)

Could anyone show me how I can use CMake so that I get the dSYM directory? Thanks.

Edit 1 (make all command):

Here is the make all command that was generated in my makefile:

all: cmake_check_build_system
    $(CMAKE_COMMAND) -E cmake_progress_start <Path>/Testing/cmake_build/CMakeFiles <Path>/Testing/cmake_build/CMakeFiles/progress.marks
    $(MAKE) -f CMakeFiles/Makefile2 all
    $(CMAKE_COMMAND) -E cmake_progress_start <Path>/Testing/cmake_build/CMakeFiles 0

Edit 2 (Makefile2's all command):

# Target rules for target CMakeFiles/test1.dir

# All Build rule for target.
CMakeFiles/test1.dir/all:
    $(MAKE) -f CMakeFiles/test1.dir/build.make CMakeFiles/test1.dir/depend
    $(MAKE) -f CMakeFiles/test1.dir/build.make CMakeFiles/test1.dir/build
    @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=<Path>/Testing/cmake_build/CMakeFiles --progress-num=1,2 "Built target test1"
.PHONY : CMakeFiles/test1.dir/all

# Include target in all.
all: CMakeFiles/test1.dir/all

Edit 3 (CmakeFiles/test1.dir/build.make):

# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.4

# Delete rule output on recipe failure.
.DELETE_ON_ERROR:


#=============================================================================
# Special targets provided by cmake.

# Disable implicit rules so canonical targets will work.
.SUFFIXES:


# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =

.SUFFIXES: .hpux_make_needs_suffix_list


# Suppress display of executed commands.
$(VERBOSE).SILENT:


# A target that is always out of date.
cmake_force:

.PHONY : cmake_force

#=============================================================================
# Set environment variables for the build.

# The shell in which to execute make rules.
SHELL = /bin/sh

# The CMake executable.
CMAKE_COMMAND = /usr/local/bin/cmake

# The command to remove a file.
RM = /usr/local/bin/cmake -E remove -f

# Escaping for special characters.
EQUALS = =

# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = <Path>/Desktop/Testing

# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = <Path>/Desktop/Testing/cmake_build

# Include any dependencies generated for this target.
include CMakeFiles/test1.dir/depend.make

# Include the progress variables for this target.
include CMakeFiles/test1.dir/progress.make

# Include the compile flags for this target's objects.
include CMakeFiles/test1.dir/flags.make

CMakeFiles/test1.dir/main.cpp.o: CMakeFiles/test1.dir/flags.make
CMakeFiles/test1.dir/main.cpp.o: ../main.cpp
    @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=<Path>/Desktop/Testing/cmake_build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/test1.dir/main.cpp.o"
    /Applications/Xcode6-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++   $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/test1.dir/main.cpp.o -c <Path>/Desktop/Testing/main.cpp

CMakeFiles/test1.dir/main.cpp.i: cmake_force
    @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/test1.dir/main.cpp.i"
    /Applications/Xcode6-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++  $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E <Path>/Desktop/Testing/main.cpp > CMakeFiles/test1.dir/main.cpp.i

CMakeFiles/test1.dir/main.cpp.s: cmake_force
    @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/test1.dir/main.cpp.s"
    /Applications/Xcode6-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++  $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S <Path>/Desktop/Testing/main.cpp -o CMakeFiles/test1.dir/main.cpp.s

CMakeFiles/test1.dir/main.cpp.o.requires:

.PHONY : CMakeFiles/test1.dir/main.cpp.o.requires

CMakeFiles/test1.dir/main.cpp.o.provides: CMakeFiles/test1.dir/main.cpp.o.requires
    $(MAKE) -f CMakeFiles/test1.dir/build.make CMakeFiles/test1.dir/main.cpp.o.provides.build
.PHONY : CMakeFiles/test1.dir/main.cpp.o.provides

CMakeFiles/test1.dir/main.cpp.o.provides.build: CMakeFiles/test1.dir/main.cpp.o


# Object files for target test1
test1_OBJECTS = \
"CMakeFiles/test1.dir/main.cpp.o"

# External object files for target test1
test1_EXTERNAL_OBJECTS =

test1: CMakeFiles/test1.dir/main.cpp.o
test1: CMakeFiles/test1.dir/build.make
test1: CMakeFiles/test1.dir/link.txt
    @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=<Path>/Desktop/Testing/cmake_build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking CXX executable test1"
    $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/test1.dir/link.txt --verbose=$(VERBOSE)

# Rule to build all files generated by this target.
CMakeFiles/test1.dir/build: test1

.PHONY : CMakeFiles/test1.dir/build

CMakeFiles/test1.dir/requires: CMakeFiles/test1.dir/main.cpp.o.requires

.PHONY : CMakeFiles/test1.dir/requires

CMakeFiles/test1.dir/clean:
    $(CMAKE_COMMAND) -P CMakeFiles/test1.dir/cmake_clean.cmake
.PHONY : CMakeFiles/test1.dir/clean

CMakeFiles/test1.dir/depend:
    cd <Path>/Desktop/Testing/cmake_build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" <Path>/Desktop/Testing <Path>/Desktop/Testing <Path>/Desktop/Testing/cmake_build <Path>/Desktop/Testing/cmake_build <Path>/Desktop/Testing/cmake_build/CMakeFiles/test1.dir/DependInfo.cmake --color=$(COLOR)
.PHONY : CMakeFiles/test1.dir/depend

Edit 4 (make verbose output):

/usr/local/bin/cmake -H<Path>/Desktop/Testing -B<Path>/Desktop/Testing/cmake_build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/local/bin/cmake -E cmake_progress_start <Path>/Desktop/Testing/cmake_build/CMakeFiles <Path>/Desktop/Testing/cmake_build/CMakeFiles/progress.marks
/Applications/Xcode6-Beta5.app/Contents/Developer/usr/bin/make -f CMakeFiles/Makefile2 all
/Applications/Xcode6-Beta5.app/Contents/Developer/usr/bin/make -f CMakeFiles/test1.dir/build.make CMakeFiles/test1.dir/depend
cd <Path>/Desktop/Testing/cmake_build && /usr/local/bin/cmake -E cmake_depends "Unix Makefiles" <Path>/Desktop/Testing <Path>/Desktop/Testing <Path>/Desktop/Testing/cmake_build <Path>/Desktop/Testing/cmake_build <Path>/Desktop/Testing/cmake_build/CMakeFiles/test1.dir/DependInfo.cmake --color=
/Applications/Xcode6-Beta5.app/Contents/Developer/usr/bin/make -f CMakeFiles/test1.dir/build.make CMakeFiles/test1.dir/build
Community
  • 1
  • 1
user2570465
  • 2,437
  • 2
  • 18
  • 22
  • I wonder if it is space between -D and the CMAKE_BUILD_TYPE which breaks it. – SergeyA Dec 23 '15 at 17:34
  • @SergeyA I tried `-DCMAKE_BUILD_TYPE=Debug` and it unfortunately produces the same result. I've also renamed the executable from `test` to `test1` because I missed a warning saying that `test` was reserved. – user2570465 Dec 23 '15 at 17:39
  • Did you see if the proper make file was generated? Does it have -g in it? – SergeyA Dec 23 '15 at 17:44
  • 1
    Please note that the `CXX_STANDARD_REQUIRED` property has been introduced in CMake 3.1, so I recommend you to adjust your cmake_minimum_required version. – SirDarius Dec 23 '15 at 17:46
  • @SergeyA I edited in the make all command that was generated. It has several variables and references other files. Could you let me know if there's any specific files you're interested in seeing? – user2570465 Dec 23 '15 at 17:58
  • @SirDarius Thanks for letting me know. I've changed the property to 3.1 – user2570465 Dec 23 '15 at 18:00
  • @SergeyA Looking into generated Makefiles is useless for CMake. It is done somewhere internally. – usr1234567 Dec 23 '15 at 18:00
  • @usr1234567, to the contrary, in my experience, it was enlightening. In tells you exactly what command is going to be ran. Look into CMakeFiles/Makefile2 – SergeyA Dec 23 '15 at 18:01
  • @SergeyA I've added in the `all` command that is in Makefile2. Hopefully that is the command your're interested in - my knowledge of makefiles is not too great either. – user2570465 Dec 23 '15 at 18:06
  • Now you need CMakeFiles/test1.dir/build.make – SergeyA Dec 23 '15 at 18:10
  • try `make VERBOSE=1` to see the complete list of passed arguments to g++ – Mohammad Dec 23 '15 at 18:41
  • @SergeyA I added in the CMakeFiles/test1.dir/build.make in an edit. – user2570465 Dec 23 '15 at 18:46
  • @Mohammad I used that command and I noticed that g++ does not appear, but it references Xcode. I remember linking CMake with Xcode a few weeks ago so that I could create an Xcode project using CMake. Is that a problem? I'll post the verbose output above. – user2570465 Dec 23 '15 at 18:49
  • when trying the same thing, I get `--11687-- run: /usr/bin/dsymutil "./myprogram"` the first time I invoke valgrind. This is on OSX 10.11.2 with all latest updates. – SirDarius Dec 23 '15 at 20:13

2 Answers2

4

Try explicitly setting the -g flag for the debug configuration by adding
set(CMAKE_CXX_FLAGS_DEBUG "-g") To your CMakeLists.txt then re-running cmake with
-DCMAKE_BUILD_TYPE=Debug

shay
  • 755
  • 10
  • 22
  • 2
    I tried this, but it didn't work, unfortunately. The .dSYM directory is still not there. – user2570465 Dec 23 '15 at 18:53
  • Have you tried running Valgrind with the `--dsymutil=yes` option? I don't know much about build systems for osx, but according to [Valgrind's manual](http://valgrind.org/docs/manual/manual-core.html) that option should result in `dsymutil` being run to generate the .dSYM directory. This doesn't solve the larger problem of generating the .dSYM directory from cmake, but it seems like it should at least get Valgrind working – shay Dec 23 '15 at 19:39
  • Another thing to try: From my rudimentary understanding of things the .dSYM directory contains debugging information for xcode projects. GCC doesn't actually create the .dSYM directory, that's created by an application called `dsymutil` using the debugging symbols provided by gcc, and called later in your makefile. With cmake you can specify the type of makefile that is being generated with the `-G` option, so perhaps something like `cmake -G Xcode -D CMAKE_BUILD_TYPE=Debug ..` will include the dsymutil steps in the resulting makefile. – shay Dec 23 '15 at 19:52
0
  1. valgrind + leak-check - AFAIK debug build is recommended
  2. Nowadays I would use compiler option address sanitizer instead of valgrind with leak-check. Sanitizes are faster and more reliable (valgrind has some technical limitation so it can't find all memory issues).
  3. Note that in cmake projects there are 4 default configurations: Debug, Release, RelWithDebInfo and MinSizeRel. Configuration with RelWithDebInfo creates release build with symbol files (I'm trying to find if there are some drawbacks of this configuration, that is why I've encounter this SO question). So most probably you should build your project like this:
cd build_dir
cmake .. -G <YOUR GENERATOR> <other config options>
cmake --build . --config RelWithDebInfo
Marek R
  • 32,568
  • 6
  • 55
  • 140