I want to debug a single file in the source code of LLVM. Because building the whole project with debug info will waste a great amount of space. LLVM uses CMake as its build system. How can I add debuginfo to a single file?
Here is a cross-platform version of "setting a debuginfo flags on a single file":
cmake_minimum_required(VERSION 2.8)
project(DebugInfoForSingleFile)
separate_arguments(_flags_release UNIX_COMMAND "${CMAKE_CXX_FLAGS_RELEASE}")
separate_arguments(_flags_with_dbg_info UNIX_COMMAND "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
list(REMOVE_ITEM _flags_with_dbg_info ${_flags_release})
string(REPLACE ";" " " _flags_with_dbg_info "${_flags_with_dbg_info}")
file(WRITE main.cpp "int main() { return 0; }")
add_executable(${PROJECT_NAME} main.cpp)
set_source_files_properties(main.cpp PROPERTIES COMPILE_FLAGS "${_flags_with_dbg_info}")
Please note that CMake normally also reduces the optimization level together with activating debug info.
Reference
Is Cmake set variable recursive?
Related
I am using the arm-linux-androideabi-g++ compiler. When I try to compile a simple "Hello, World!" program it compiles fine. When I test it by adding a simple exception handling in that code it works too (after adding -fexceptions .. I guess it is disabled by default).
This is for an Android device, and I only want to use CMake, not ndk-build.
For example - first.cpp
#include <iostream>
using namespace std;
int main()
{
try
{
}
catch (...)
{
}
return 0;
}
./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions
It works with no problem...
The problem ... I am trying to compile the file with a CMake file.
I want to add the -fexceptions as a flag. I tried with
set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )
and
set ( CMAKE_C_FLAGS "fexceptions")
It still displays an error.
Note: Given CMake evolution since this was answer was written in 2012, most of the suggestions here are now outdated/deprecated and have better alternatives.
Suppose you want to add those flags (better to declare them in a constant):
SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS "-lgcov")
There are several ways to add them:
The easiest one (not clean, but easy and convenient, and works only for compile flags, C & C++ at once):
add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
Appending to corresponding CMake variables:
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
Using target properties, cf. doc CMake compile flag target property and need to know the target name.
get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
if(TEMP STREQUAL "TEMP-NOTFOUND")
SET(TEMP "") # Set to empty string
else()
SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
endif()
# Append our values
SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )
Right now I use method 2.
In newer versions of CMake you can set compiler and linker flags for a single target with target_compile_options and target_link_libraries respectively (yes, the latter sets linker options too):
target_compile_options(first-test PRIVATE -fexceptions)
The advantage of this method is that you can control propagation of options to other targets that depend on this one via PUBLIC and PRIVATE.
As of CMake 3.13 you can also use target_link_options to add linker options which makes the intent more clear.
Try setting the variable CMAKE_CXX_FLAGS instead of CMAKE_C_FLAGS:
set (CMAKE_CXX_FLAGS "-fexceptions")
The variable CMAKE_C_FLAGS only affects the C compiler, but you are compiling C++ code.
Adding the flag to CMAKE_EXE_LINKER_FLAGS is redundant.
The preferred way to specify toolchain-specific options is using CMake's toolchain facility. This ensures that there is a clean division between:
instructions on how to organise source files into targets -- expressed in CMakeLists.txt files, entirely toolchain-agnostic; and
details of how certain toolchains should be configured -- separated into CMake script files, extensible by future users of your project, scalable.
Ideally, there should be no compiler/linker flags in your CMakeLists.txt files -- even within if/endif blocks. And your program should build for the native platform with the default toolchain (e.g. GCC on GNU/Linux or MSVC on Windows) without any additional flags.
Steps to add a toolchain:
Create a file, e.g. arm-linux-androideadi-gcc.cmake with global toolchain settings:
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_CXX_FLAGS_INIT "-fexceptions")
(You can find an example Linux cross-compiling toolchain file here.)
When you want to generate a build system with this toolchain, specify the CMAKE_TOOLCHAIN_FILE parameter on the command line:
mkdir android-arm-build && cd android-arm-build
cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc.cmake ..
(Note: you cannot use a relative path.)
Build as normal:
cmake --build .
Toolchain files make cross-compilation easier, but they have other uses:
Hardened diagnostics for your unit tests.
set(CMAKE_CXX_FLAGS_INIT "-Werror -Wall -Wextra -Wpedantic")
Tricky-to-configure development tools.
# toolchain file for use with gcov
set(CMAKE_CXX_FLAGS_INIT "--coverage -fno-exceptions -g")
Enhanced safety checks.
# toolchain file for use with gdb
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-fsanitize=address,undefined -fsanitize-undefined-trap-on-error")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address,undefined -static-libasan")
You can also add linker flags to a specific target using the LINK_FLAGS property:
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")
If you want to propagate this change to other targets, you can create a dummy target to link to.
This worked for me when I needed a precompile definition named "NO_DEBUG":
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DNO_DEBUG")
Then from code
#ifdef NO_DEBUG
.....
With CMake 3.4+, APPEND can be used with the string command to add flags.
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fexceptions")
I have a very simple CMake script. Unfortunately, the project uses a *.pde file which is plain C++ or C code.
CMake is working with any file ending, but I get a compiler error, because GCC does not know how to handle it. How can I add a global file extension to GCC, so that the *.pde file is compiled as a usual *.cpp file?
The -x c++ foo.pde command is nice if I want to use the console, but for CMake it is (I think) not applicable.
cmake_minimum_required(VERSION 2.8)
project(RPiCopter)
SET( RPiCopter
absdevice
containers
device
exceptions
navigation
frame
vehicle
receiver
scheduler
tinycopter.pde
)
message( STATUS "Include ArduPilot library directories" )
foreach( DIR ${AP_List} ${AP_List_Linux} ${AP_Headers} )
include_directories( "../libraries/${DIR}" )
endforeach()
include_directories( zserge-jsmn )
# ***************************************
# Build the firmware
# ***************************************
add_subdirectory ( zserge-jsmn )
#set(CMAKE_CXX_FLAGS "-x c++ *.pde")
ADD_EXECUTABLE ( RPiCopter ${RPiCopter} )
target_link_libraries ( RPiCopter -Wl,--start-group ${AP_List} ${AP_List_Linux} jsmn -Wl,--end-group )
You should be able to use set_source_files_properties along with the LANGUAGE property to mark the file(s) as C++ sources:
set_source_files_properties(${TheFiles} PROPERTIES LANGUAGE CXX)
As #steveire pointed out in his own answer, this bug will require something like the following workaround:
set_source_files_properties(${TheFiles} PROPERTIES LANGUAGE CXX)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_definitions("-x c++")
endif()
Normally you should be able to just extend CMAKE_CXX_SOURCE_FILE_EXTENSIONS. This would help, if you have a lot of files with unknown file extensions.
But this variable is not cached - as e.g. CMAKE_CXX_FLAGS is - so the following code in CMakeCXXCompiler.cmake.in will always overwrite/hide whatever you will set:
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP)
I consider this non-caching being a bug in CMake, but until this is going to be changed I searched for a workaround considering the following:
You normally don't want to change files in your CMake's installation
It won't have any effect if you change CMAKE_CXX_SOURCE_FILE_EXTENSIONS after project()/enable_language() (as discussed here).
I have successfully tested the following using one of the "hooks"/configuration variables inside CMakeCXXCompiler.cmake.in:
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_SYSROOT_FLAG_CODE "list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS pde)")
project(RPiCopter CXX)
message("CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")
add_executable(RPiCopter tinycopter.pde)
I decided to use this approach. I just remove the file ending by cmake in the temporary build directory.
So GCC is not confused anymore because of the strange Arduino *.pde file extension.
# Exchange the file ending of the Arduino project file
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tinycopter.pde ${CMAKE_CURRENT_BINARY_DIR}/tinycopter.cpp)
CMake doesn't do this for you:
http://public.kitware.com/Bug/view.php?id=14516
I hope someone is able to help me:
I try to use the cmake plugin in a jenkins server to create a hex file, but i don't know my fault.
I also try to run the example of this site: http://robot-develop.org/archives/2952 but if i use the "make" command, i get this error message:
make: *** No targets specifed and no makefile found. Stop
Here is my code:
CMakeLists.txt:
cmake_minimum_required (VERSION 2.6.0)
INCLUDE("C:/Users/name/Desktop/example/Code/test_crosscompile.cmake")
INCLUDE("C:/Users/name/Desktop/example/Code/macro.cmake")
project (Code)
MESSAGE(STATUS "\n -------------------------------->Creating Test-Projekt...")
IF( NOT CMAKE_BUILD_TYPE )
SET( CMAKE_BUILD_TYPE Release ... FORCE )
ENDIF()
SET(MAIN_FILE
class.c)
# add the executable
add_executable(Code ${MAIN_FILE})
#makro
AVR_CREATE_HEX(class)
makro.cmake:
# create avr hex
MACRO(AVR_CREATE_HEX name)
ADD_CUSTOM_COMMAND(TARGET ${name} POST_BUILD COMMAND avr-objcopy ARGS -O ihex -R.eeprom ${name} "C:/Users/name/Desktop/example/Code/class.hex")
MESSAGE(STATUS "\n ----------JONAS---------------------->Macro")
ENDMACRO(AVR_CREATE_HEX)
test_crosscompile.cmake:
SET(CMAKE_SYSTEM_NAME "Windows")
SET(CMAKE_C_COMPILER avr-gcc)
SET(CMAKE_CXX_COMPILER avr-g++)
SET(CSTANDARD "-std=gnu99")
SET(CDEBUG "-gstabs")
SET(CWARN "-Wall -Wstrict-prototypes")
SET(CTUNING "-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums")
SET(COPT "-Os")
SET(CMCU "-mmcu=atmega32")
SET(CDEFS "-DF_CPU=12000000UL")
SET(CFLAGS "${CMCU} ${CDEBUG} ${CDEFS} ${CINCS} ${COPT} ${CWARN} ${CSTANDARD} ${CEXTRA}")
SET(CXXFLAGS "${CMCU} ${CDEFS} ${CINCS} ${COPT}")
SET(CMAKE_C_FLAGS ${CFLAGS})
SET(CMAKE_CXX_FLAGS ${CXXFLAGS})
I use the cmake GUI, but i don't know how to use it.
I try as generator visual studio 10 (specify toolchain file for cross compiling), but it generates no makefile or hex file.
If i choose MinGW Makefiles as the generator, i get the error:
The C compiler "C:/WinAVR-20100110/bin/avr-gcc.exe" is not able to compile
a simple test program.
I hope somebody can help me, THANKS!
You have the CMAKE_SYSTEM_NAME set to windows, you need to set this to generic to enable Cross compiling eg:
SET(CMAKE_SYSTEM_NAME Generic)
I'm writing a Python extension module in C++ using Boost.Python. However, I
would like to use a newer version of the Boost library than the system
installation offers. This newer version of boost is contained in
BOOST_ROOT=$HOME/opt/boost/1.55.0.
Following this guide on how
to use RPath in CMake I came up with the following CMakeLists.txt.
cmake_minimum_required(VERSION 2.8)
project("test")
set(PROJECT_DESC "Test Boost.Python")
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_definitions(-std=c++11 -Wall -Wextra -pedantic)
find_package(PythonInterp REQUIRED)
find_package(PythonLibsNew REQUIRED)
find_package(Boost COMPONENTS python REQUIRED)
message(STATUS "Using Boost installation in:")
message(STATUS " INCLUDE: ${Boost_INCLUDE_DIRS}")
message(STATUS " LIB: ${Boost_LIBRARIES}")
include_directories(
${PROJECT_SOURCE_DIR}
${PYTHON_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
macro(add_python_module _name _srccpp)
PYTHON_ADD_MODULE(${_name} ${_srccpp})
target_link_libraries(${_name} ${Boost_LIBRARIES})
endmacro()
add_python_module(ownership ownership.cpp)
Then I run the following commands to build the module
mkdir build; cd build
cmake -DCMAKE_INSTALL_PATH="$BOOST_ROOT/lib" ..
make
The status message after running cmake points to the right boost
installation. (The CMake boost module picks up the environment variable
$BOOST_ROOT) I.e. the CMake variable Boost_LIBARIES points to
$BOOST_ROOT/lib/libboost_python.so.
But, if I check which libraries would actually be used, the system libraries
are listed:
$ ldd ownership.so
# ...
libboost_python.so.1.53.0 => /usr/lib64/libboost_python.so.1.53.0 (0x00007f09abfc1000)
# ...
This is version 1.53, even though the status message above explicitely pointed
to 1.55.
What am I doing wrong? How can I get ldd to pick the library in
$BOOST_ROOT/lib/libboost_python.so.1.55.0?
First of all as I already mentioned in commens you don't need to use CMake RPATH-manipulations
options. Example: http://pastebin.com/UDyYbQ1d, output: standard and custom
Do you know of a way of convincing CMake otherwise even if LIBRARY_PATH is set
This issue is not related to CMake, it's compiler responsibility. Read this discussion.
Solution
You can clear LIBRARY_PATH if you set BOOST_ROOT variable explicitly. And you can check
environment variable in CMakeLists.txt to avoid this problem in future:
string(COMPARE NOTEQUAL "$ENV{LIBRARY_PATH}" "" library_path_warning)
if(library_path_warning)
message(
WARNING
"LIBRARY_PATH environment variable is not empty ($ENV{LIBRARY_PATH}) "
"This may cause dynamic linking errors!"
)
endif()
Even though CMake has successfully configured and generated the makefile with Boost, I just can't produce an executable file for ARM processor using the make command as shown below.
Here is my configuration setting:
1.) I downloaded boost library 1.49 compiled in Raspberry Pi in this link:
http://www.raspberrypi.org/phpBB3/viewtopic.php?t=8111&p=195468
2.) The file hierarchy is as follows:
sample-boost
-> boost-stage (Contains the lib, and include directories of the boost taken from number 1)
-> build (Contains the generated files from CMake)
-> CMakeLists.txt
-> main.cpp
NOTE: The ARM Cross Compiler is fully working and I've cross compiled a hello world and run it in Raspberry Pi successfully using CMake in Cygwin (using a cross toolchain file located in C:/cygwin/arm-pi.toolchain.cmake).
main.cpp
#include <iostream>
#include <boost/thread.hpp>
int main(){
cout << "Hello" << endl;
boost::this_thread::sleep(boost::posix_time::millisec(20));
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
Project(main)
SET(Boost_INCLUDE_DIR C:/Users/Emmett/Documents/EMMETT/sample-boost/boost-stage/include)
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "C:/Users/Emmett/Documents/EMMETT/sample-boost/boost-stage/include")
SET(BOOST_ROOT C:/Users/Emmett/Documents/EMMETT/sample-boost/boost-stage)
FIND_PACKAGE(Boost)
message("BOOST LIBRARY" ${Boost_LIBRARY_DIRS})
message("Boost LIBRARIES:" ${Boost_LIBRARIES})
IF(Boost_FOUND)
message("Boost include directory is found")
message("Boost_INCLUDE_DIRS": ${Boost_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
add_executable(main main.cpp)
target_link_libraries( main ${Boost_LIBRARIES} )
ENDIF(Boost_FOUND)
Boost-stage
-> include (came from sample-boost\boost_1_49_0\boost)
-> lib (came from boost_1_49_0(bin-only)\lib
Also, invoking ccmake . shows that boost_dir is not found. However, boost package is found!
As you can see, it has successfully generated makefiles using CMake but I can't create an executable file for it. I think I missed out something in setting up boost. Maybe I've failed to successfully link the libraries? Does not the
message("Boost LIBRARIES:" ${Boost_LIBRARIES})
display the library files?
ADDITION: I did what you ask for. Here is my new cmakelists.txt
cmake_minimum_required(VERSION 2.8)
Project(main)
SET(Boost_INCLUDE_DIR C:/Users/Emmett/Documents/EMMETT/sample-boost/boost-stage/include)
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "C:/Users/Emmett/Documents/EMMETT/sample-boost/boost-stage/include")
SET(BOOST_ROOT C:/Users/Emmett/Documents/EMMETT/sample-boost/boost-stage)
SET(Boost_USE_STATIC_LIBS TRUE)
SET(Boost_DEBUG ON)
#FIND_PACKAGE(Boost)
FIND_PACKAGE(Boost COMPONENTS thread)
message("BOOST LIBRARY: " ${Boost_LIBRARY_DIRS})
message("Boost LIBRARIES: " ${Boost_LIBRARIES})
message("LIBS : " ${LIBS})
IF(Boost_FOUND)
message("Boost include directory is found")
message("Boost_INCLUDE_DIRS: "${Boost_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
add_executable(main main.cpp)
target_link_libraries( main ${Boost_LIBRARIES} )
ENDIF(Boost_FOUND)
Here is the output console:
For using the boost thread module with CMake you must do
find(Boost COMPONENTS thread)
Normaly, this add the path to the boost thread lib in Boost_LIBRARIES var.