how to prevent cmake from stripping the created shared library - linux

When running the executable in the debugger, I don't see any meaningful stacktrace for the shared library -- but only the address of the function and the path of the shared library.
This applies to cmake version 3.7.2.

CMake does not strip your debug symbols by default.
You need to compile your shared libs with proper debug options, e.g.
cmake -DCMAKE_BUILD_TYPE=Debug ..
Or you can modify your CMakeLists.txt to add the debug flags.
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall")
Edit
CMake is a build scripting tool, itself does not do stripping on your binary, but you can ask it to help with this if you want. See my other post here: Android NDK path variable for **strip** command in CMake build tool chain
Below lines will do symbol stripping if you want to let CMake to strip your debug symbols.
add_custom_command(TARGET ${SHARED_LIBRARY_NAME} POST_BUILD
COMMAND "<path-to-your-bin>/strip" -g -S -d --strip-debug --verbose
"<path-to-your-lib>/lib${SHARED_LIBRARY_NAME}.so"
COMMENT "strip debug symbols done on final binary.")
For the warnings, you can choose to have it or not, doesn't really matter.
Get back to the question and clarify further, in order to have debug symbols, you need to build your binary in DEBUG or RelWithDebInfo build type by typing below cmake command.
cmake -DCMAKE_BUILD_TYPE=Debug ..
or
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
If you are building C source code (not the cpp which I assumed), then you can check the corresponding CMAKE_C_FLAGS.
See the official document from here: https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html

Related

will cmake build type RelWithDebInfo strip symbol table?

I was building a shared library using cmake with RelWithDebInfo build type, the output .so file has no symbol table.
I inspect the output .so file with readelf -S myoutput.so | grep -i debug with gives me nothing.
If I change the build type to Debug, the symbol table is there.
I suppose RelWithDebInfo is equivalent to -O2 -g, which should be able to reserver debug symbol. There must be something wrong in my CMakeList.txt......but it's a very large project I don't have a clear where to look at, any idea or hint?
sorry, I've figured out the problem. I was using pybind11 for my project, and pybind11 internally strip unneeded symbols.

How to set LD_LIBRARY_PATH from a CMake toolchain file?

On Linux, I want to create a CMake toolchain file for cross-compilation.
The compiler needs some shared libraries that are located in non-standard directories, so I have to set LD_LIBRARY_PATH before invoking it. That worked when calling the compiler from the command line, but not when calling it from CMake.
I tried to set LD_LIBRARY_PATH via set(ENV{LD_LIBRARY_PATH} "${CMAKE_CURRENT_LIST_DIR}/<shared library directory>") from the toolchain file. However the compiler complained that it couldn't find the shared libraries.
Table of contents:
Setting it in a toolchain file isn't going to do what you want.
I'm not sure why setting LD_LIBRARY_PATH before invoking the buildsystem isn't working for you.
There's a more idiomatic way in CMake to do what you want.
Setting it in a toolchain file isn't going to do what you want
I'm pretty sure the approach you are asking how to take won't work because set(ENV) just sets an environment variable that will only be known to CMake at the configure stage (not the build stage). Here's a minimal reproducible example of that:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(Foo)
set(ENV{FOO} "hello world!")
message("\$ENV{FOO} at configure time: $ENV{FOO}")
add_custom_target(echo
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/echo.cmake"
VERBATIM
)
echo.cmake:
cmake_minimum_required(VERSION 3.23)
message("\$ENV{FOO} at build time: $ENV{FOO}")
run the following:
$ cmake -S . -B build --fresh
<...>
$ENV{FOO} at configure time: hello world!
<...>
$ cmake --build build/ --target echo
$ENV{FOO} at build time:
Since environment variables are "passed downward" to child processes and not upward, when you do set(ENV), that's just setting it in the CMake process that performs the configure step (the one invoked by the cmake -S ... command in the example above). As the example shows, CMake doesn't do anything fancy to make those environment variables known at its configure time to the generated buildsystem at build time.
I'm not sure why setting LD_LIBRARY_PATH before invoking the buildsystem isn't working for you
So I have to set LD_LIBRARY_PATH before invoking it. It works when calling the compiler from the command line, but not from CMake.
As long as you're exporting the variable for it to be made available to the shell's child processes (using the correct mechanism for whichever shell you're using), that should work. A minimal reproducible example would help here.
There's a more idiomatic way in CMake to do what you want
Try using the find_library() command. It does what its name says it does at configuration time (instead of build time). If you use it, you'll also get the benefit of your buildsystems being more cross-platform.
It has several ways of tweaking how it searches for libraries. You can read about exactly how it works in the official docs.
For your case here, one of the suitable configuration points to guide the library search would be the CMAKE_LIBRARY_PATH variable, although as you'll read about, there are other configuration points you could use as well.

Setting up Kdevelop

I'm trying to setup Kdevelop and am getting a compiler error.
C:/Users/alexm/projects/SFMLGL/build> "C:/Program Files/CMake/bin/cmake.exe" "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON" "-DCMAKE_BUILD_TYPE=Debug" C:/Users/alexm/projects/SFMLGL
-- The C compiler identification is unknown
CMake Error at C:/Program Files/CMake/share/cmake-3.6/Modules/CMakeDetermineCompilerId.cmake:141 (file):
file problem creating directory:
C:/Users/alexm/projects/SFMLGL/build/CMakeFiles/3.6.1/CompilerIdCXX
Call Stack (most recent call first):
C:/Program Files/CMake/share/cmake-3.6/Modules/CMakeDetermineCompilerId.cmake:40 (CMAKE_DETERMINE_COMPILER_ID_BUILD)
C:/Program Files/CMake/share/cmake-3.6/Modules/CMakeDetermineCXXCompiler.cmake:113 (CMAKE_DETERMINE_COMPILER_ID)
CMakeLists.txt:2 (project)
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:2 (project):
The CMAKE_C_COMPILER:
cl
is not a full path and was not found in the PATH.
To use the NMake generator with Visual C++, cmake must be run from a shell
that can use the compiler cl from the command line. This environment is
unable to invoke the cl compiler. To fix this problem, run cmake from the
Visual Studio Command Prompt (vcvarsall.bat).
Tell CMake where to find the compiler by setting either the environment
variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
the compiler, or to the compiler name if it is in the PATH.
CMake Error at CMakeLists.txt:2 (project):
The CMAKE_CXX_COMPILER:
cl
is not a full path and was not found in the PATH.
To use the NMake generator with Visual C++, cmake must be run from a shell
that can use the compiler cl from the command line. This environment is
unable to invoke the cl compiler. To fix this problem, run cmake from the
Visual Studio Command Prompt (vcvarsall.bat).
Tell CMake where to find the compiler by setting either the environment
variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
to the compiler, or to the compiler name if it is in the PATH.
-- Configuring incomplete, errors occurred!
See also "C:/Users/alexm/projects/SFMLGL/build/CMakeFiles/CMakeOutput.log".
See also "C:/Users/alexm/projects/SFMLGL/build/CMakeFiles/CMakeError.log".
*** Failure: Exit code 1 ***
I've been googling a lot and read that I should download "Make", so I have and it did reduce the amount of errors I have, but I still have this and I don't understand a word of it.
I think it wants me to download a C compiler? How would I go about doing this?
The default toolchain for CMake tries to use the Visual Studio C++ Compiler.
If you want to use Visual Studio (you need to have that installed) you can run your CMake command from the »VS201X x64 Native Tools Command Prompt« shortcut in the start menu.
An alternative would be to use GCC for Windows via mingw-w64 which is available in msys2. There you would have to install the compiler via pacman -S mingw-w64-x86_64-toolchain and optionally cmake too via pacman -S mingw-w64-x86_64-cmake.
You could then run your command from the mingw64 prompt of msys2.
If you want to use that in KDevelop you’d have to add your msys64/mingw64/ folder to the path, or start it from the Visual Studio command prompt mentioned above. I’m not sure if there is an easier way.
Your question raises the question^^ what you want to achieve in the end. You don’t seem to know about which compiler to use (this may be important if you have binary dependencies) or what make is (which is a bit alarming).

CMake save stripped debug information

It's a usual practice to compile with debug symbols and then separate the binary using objcopy into the release executable and the file with debug information (then wrap that into separate packages or store on the symbol server).
How to separate debug symbols properly in CMake? I've seen just some discussions and incomplete code samples.
Platform is Linux and GCC.
CMake doesn't have direct support for this, but you can use some POST_BUILD and INSTALL steps to achieve the result you want. It is, however, worth noting that using objcopy isn't the only way to do this sort of thing. You can also make use of the build-id and this may well be easier to implement robustly with CMake.
Rather than repeat the whole thing here, there's a pretty good description of your choices and the methods that was posted to the CMake mailing list few years ago by Michael Hertling. I'll just pick out the working alternative here for reference, but I recommend reading that link. There's also an even more complete discussion of the two alternatives in the GDB documentation which should fill in any remaining blanks about the two approaches (debug link versus build-id). Here's Michael's general build-id approach (the build-id is explicitly given in his example, read the referenced articles for an explanation of what it is expected to represent):
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(BUILDID C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(BUILDID "abcdef1234")
STRING(SUBSTRING "${BUILDID}" 0 2 BUILDIDPREFIX)
STRING(SUBSTRING "${BUILDID}" 2 8 BUILDIDSUFFIX)
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(main main.c)
SET_TARGET_PROPERTIES(main PROPERTIES
LINK_FLAGS "-Wl,--build-id=0x${BUILDID}")
ADD_CUSTOM_COMMAND(TARGET main POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:main>
${CMAKE_BINARY_DIR}/main.debug
COMMAND ${CMAKE_STRIP} -g $<TARGET_FILE:main>)
INSTALL(FILES ${CMAKE_BINARY_DIR}/main.debug
DESTINATION ${CMAKE_BINARY_DIR}/.build-id/${BUILDIDPREFIX}
RENAME ${BUILDIDSUFFIX}.debug)
Configure with CMAKE_BUILD_TYPE==debug and build; subsequently, invoke
gdb -ex "set debug-file-directory ." -ex "file main"
from within CMAKE_BINARY_DIR, and you will read "no debugging symbols
found" as expected. Now, issue "make install", re-invoke gdb and read:
"Reading symbols from .../.build-id/ab/cdef1234.debug"
As you can see, the debug info file is connected with the stripped
executable solely by the build ID; no objcopy in sight.
The above makes use of the fact that the .debug file is expected to be a normal executable with debug info not stripped.

How to build boost library (program options) without using bjam

I need to build boost program options static library in both PC/Mac.
It has only 11 cpp source code, so I expect to compile it by g++ SOURCE_CODE, but I got an error something like utf8_codecvt_facet.cpp:15:47: error: ../../detail/utf8_codecvt_facet.cpp: No such file or directory.
How to build boost library (program options) without using bjam? Is there a way to see what compiler options/commands bjam uses for both Mac/PC?
bjam -n will print the commands instead of executing them. bjam -d 2 will print the commands as they are executed.
http://www.boost.org/boost-build2/doc/html/jam/usage.html
http://www.boost.org/boost-build2/doc/html/bbv2/overview/invocation.html

Resources