I am generating a visual studio solution using cmake. And now I want to generate pdb files for a Release build. (Why? because I want to have the symbols in case that the user found some bug)
I tried by setting the following flags without succeed:
set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE STRING "Build Types" FORCE)
IF(WIN32)
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release")
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "/debug /INCREMENTAL")
set( CMAKE_SHARED_LINKER_FLAGS_RELEASE "/debug /INCREMENTAL")
set( CMAKE_MODULE_LINKER_FLAGS_RELEASE "/debug /INCREMENTAL")
set( CMAKE_CXX_FLAGS_RELEASE "/MD /Zi /O2 /Ob1 /D NDEBUG")
set( CMAKE_C_FLAGS_RELEASE "/MD /Zi /O2 /Ob1 /D NDEBUG")
ENDIF(WIN32)
It looks like Cmake is ignoring these sets:
thanks in advance for the help!
I used the flags
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
This site explains the details
Another way to do it is to use cmake generator expressions (https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html), e.g.:
for all targets and all configurations:
add_compile_options("$<$<NOT:$<CONFIG:Debug>>:/Zi>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/DEBUG>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:REF>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:ICF>")
for particular target and Release configuration only:
target_compile_options(my_exe PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(my_exe PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
target_link_options(my_exe PRIVATE "$<$<CONFIG:Release>:/OPT:REF>")
target_link_options(my_exe PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>")
In 'Modern Cmake' you can set this per target, this is the way to go:
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" AND CMAKE_BUILD_TYPE MATCHES "Release")
target_compile_options(${TARGET_NAME} PRIVATE /Zi)
# Tell linker to include symbol data
set_target_properties(${TARGET_NAME} PROPERTIES
LINK_FLAGS "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF"
)
# Set file name & location
set_target_properties(${TARGET_NAME} PROPERTIES
COMPILE_PDB_NAME ${TARGET_NAME}
COMPILE_PDB_OUTPUT_DIR ${CMAKE_BINARY_DIR}
)
endif()
These flags are MSVC specific not WIN32.
Related
I am developing an C++ project that need to set specific compiler flags for each Visual Studio (MSVC) project configurations. We know that the configurations that CMake creates by default are these: Debug, RelWithDebInfo, Release and MinSizeRel.
In my CMakeLists.txt I am trying to do something like this:
# For each one Visual Studio configuration
# Some specifics compiler flags for MSVC
# For all RELEASE based configurations (Debug and RelWithDebInfo)
set(MSVC_FLAGS_REL STRING "/Ox /Ob2 /Oi /Ot /GF /Zc:wchar_t /MT")
# For all DEBUG based configurations (Release and MinSizeRel)
set(MSVC_FLAGS_DBG STRING "/MTd /Od /Zi /RTC1 /Zc:wchar_t /GS")
add_compile_options($<$<CONFIG:Debug>:${MSVC_FLAGS_DBG}>$<$<CONFIG:RelWithDebInfo>:${MSVC_FLAGS_DBG}>$<$<CONFIG:Release>:${MSVC_FLAGS_REL}>$<$<CONFIG:MinSizeRel>:${MSVC_FLAGS_REL}>)
However, I try to build each one configurations I noticed that the compiler flags are not been successfully set. Also, I noticed a few posts that the Generator Expressions are sometimes inadvisable in some situations.
How should I properly set the compiler variables for Debug and Release based configurations?
A bit dated, possibly, but I used this to good effect back in the days:
if ( MSVC )
set_property( TARGET ... APPEND_STRING PROPERTY COMPILE_FLAGS <your set of flags> )
endif()
(My setup figured out the BUILD_TYPE and assembled the right set of flags based on that, instead of setting one set for Release and one for Debug just in case. This was pretty early in CMake's lifespan, so some of the more advanced plumbing just was not available yet.)
I'm creating a C++ Windows service.
I would like to add Boost Process to my application, but for some reason I keep getting this error:
LINK : fatal error LNK1104: cannot open file 'optimized.lib'
Everything worked fine before I tried adding Boost. When I open my Visual Studio solution, I notice the application is trying to link with an optimized.lib and a debug.lib library that I am unfamiliar with. CMake only tries to link with these libraries when I try to add Boost.
My directory structure:
UpdateService/
CMakeLists.txt
app/
CMakeLists.txt
Driver.cpp
build/
include/
stdafx.h
UpdateService/
# a bunch of *.h files
src/
CMakeLists.txt
# a bunch of *.cpp files
My UpdateService/CMakeLists.txt file:
cmake_minimum_required(VERSION 3.12...3.14)
if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()
project(UpdateService
VERSION 1.0
DESCRIPTION "Service that runs the update manager"
LANGUAGES CXX)
add_subdirectory(src)
add_subdirectory(app)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT UpdateService)
My UpdateService/src/CMakeLists.txt file:
cmake_minimum_required(VERSION 3.12...3.14)
if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()
set(FMT_DIR "E:/Repositories/fmt-5.3.0")
set(FMT_INCLUDE "${FMT_DIR}/include")
set(SPDLOG_INCLUDE "E:/Repositories/spdlog/include")
set(Boost_DEBUG ON)
# set(Boost_USE_STATIC_LIBS ON)
# set(Boost_USE_STATIC_RUNTIME ON)
find_package(Boost 1.67 REQUIRED COMPONENTS system filesystem)
# Needed to suppress a warning in boost process.
add_compile_definitions(_SCL_SECURE_NO_WARNINGS)
add_library(UpdateServiceLib STATIC
"${CMAKE_SOURCE_DIR}/include/stdafx.h"
"${CMAKE_SOURCE_DIR}/include/UpdateService/CLI11.hpp"
"${CMAKE_SOURCE_DIR}/include/UpdateService/Config.h"
"${CMAKE_SOURCE_DIR}/include/UpdateService/CmdParams.h"
"${CMAKE_SOURCE_DIR}/include/UpdateService/LogUtils.h"
"${CMAKE_SOURCE_DIR}/include/UpdateService/ServiceBase.h"
"${CMAKE_SOURCE_DIR}/include/UpdateService/UpdateService.h"
"${FMT_DIR}/src/format.cc"
"Config.cpp"
"CmdParams.cpp"
"LogUtils.cpp"
"ServiceBase.cpp"
"UpdateService.cpp")
target_include_directories(UpdateServiceLib PUBLIC
"${Boost_INCLUDE_DIRS}"
"${CMAKE_SOURCE_DIR}/include"
"${FMT_INCLUDE}"
"${SPDLOG_INCLUDE}")
target_link_libraries(UpdateServiceLib PUBLIC "${Boost_LIBRARIES}")
My UpdateService/app/CMakeLists.txt file:
cmake_minimum_required(VERSION 3.12...3.14)
if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()
add_executable(UpdateService "Driver.cpp")
target_include_directories(UpdateService
PRIVATE "${CMAKE_SOURCE_DIR}/include" "${FMT_INCLUDE}" "${SPDLOG_INCLUDE}")
target_link_libraries(UpdateService PRIVATE UpdateServiceLib)
I am building the project with something like this:
rmdir /S /Q build
mkdir build
mkdir build\x64
pushd build\x64
cmake -G "Visual Studio 14 2015 Win64" ..\..
cmake --build . --config Debug
popd
Remove double quotes around ${Boost_LIBRARIES}.
Double quotes tells CMake to treat enclosed value as a single parameter, but Boost_LIBRARIES is actually a list (multivalue variable).
Normally, double quotes are used only for:
"string literals" (when an argument contains no variables' dereferences), e.g.
"abc"
when it is definitely known that an argument represents a single value, e.g.
"${CMAKE_SOURCE_DIR}/include"
Plural number for "LIBRARIES" word implies that Boost_LIBRARIES variable may contain multiple values, so do not enclose it with double quotes.
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(source_files
a.cpp
b.cpp
...
)
set(header_files
a.hpp
b.hpp
...
)
set(Qt_libs
Qt5::Core
Qt5::Gui
Qt5::Widget
...
)
add_library(demo SHARED ${header_files} ${source_files})
target_link_libraries(demo ${Qt_libs} ...)
set_properties(TARGET demo PROPERTY FOLDER "somewhere")
install(...)
I have a sample CMakeLists.txt shows above.
The most weird thing is, it won't generate those moc files until I manually modified (like adding a empty line to the file) those header files (where Q_OBJECT presents).
The situation not happen every time. But, once it happens, clean build nor deleting whole project file won't help.
I'm using qt 5.11, CMake 3.7, Visual Studio 2015.
You are setting the global setting with set() which could be overwritten.
Please use set_target_properties, for example
project(exampleProj)
add_executable(exampleProj main.cpp)
set_target_properties(exampleProj
PROPERTIES
CMAKE_INCLUDE_CURRENT_DIR ON
CMAKE_AUTOMOC ON)
I'm using CMake Guid 3.0.0 and Visual Studio Express 2013 (64-bit). My CMakeLists.txt file does not generate an INSTALL target for my visual studio build. I can compile by building the ALL_BUILD project. I can then run the executable that's left in the Debug and Release folders. What do I need to add in order for the INSTALL target to build?
project(intraoperative_adjustments)
cmake_minimum_required(VERSION 2.8)
if(POLICY CMP0020)
cmake_policy(SET CMP0020 NEW)
endif()
find_package(VTK COMPONENTS
vtkCommonCore
vtkFiltersCore
vtkInfovisCore
vtkInteractionStyle
vtkRenderingFreeTypeOpenGL
vtkIOGeometry
vtkViewsQt
)
include(${VTK_USE_FILE})
if("${VTK_QT_VERSION}" STREQUAL "")
message(FATAL_ERROR "VTK was not built with Qt")
endif()
# Use the include path and library for Qt that is used by VTK.
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
# Set your files and resources here
set( Srcs main.cxx SimpleView.cxx )
set( Hdrs SimpleView.h )
set( MOC_Hdrs SimpleView.h )
set( UIs SimpleView.ui )
set( QRCs Icons/icons.qrc )
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
# The rest should just work (sure...)
if(VTK_QT_VERSION VERSION_GREATER "4")
# We have ui files, this will bring in the macro: qt5_wrap_ui
find_package(Qt5Widgets REQUIRED QUIET)
qt5_wrap_ui(UI_Srcs ${UIs})
qt5_add_resources(QRC_Srcs ${QRCs} )
source_group("Resources" FILES
${UIs}
${QRCs}
${EXE_ICON} # Not present
)
source_group("Generated" FILES
${UI_Srcs}
${MOC_Srcs}
${QRC_Srcs}
${QRC_Srcs}
)
add_executable(intraoperative_adjustments
${Srcs} ${Hdrs} ${UI_Srcs} ${MOC_Hdrs} ${QRC_Srcs})
qt5_use_modules(intraoperative_adjustments Core Gui Widgets)
target_link_libraries(intraoperative_adjustments ${VTK_LIBRARIES})
else()
find_package(Qt4 REQUIRED)
include(${QT_USE_FILE})
# Use what VTK built with
set(QT_QMAKE_EXECUTABLE ${VTK_QT_QMAKE_EXECUTABLE} CACHE FILEPATH "")
set(QT_MOC_EXECUTABLE ${VTK_QT_MOC_EXECUTABLE} CACHE FILEPATH "")
set(QT_UIC_EXECUTABLE ${VTK_QT_UIC_EXECUTABLE} CACHE FILEPATH "")
qt4_wrap_ui(UI_Srcs ${UIs})
qt4_wrap_cpp(MOC_Srcs ${MOC_Hdrs} )
qt4_add_resources(QRC_Srcs ${QRCs})
source_group("Resources" FILES
${UIs}
${QRCs}
${EXE_ICON} # Not present
)
source_group("Generated" FILES
${UI_Srcs}
${QRC_Srcs}
${QRC_Srcs}
)
add_definitions(-DQT_GUI_LIBS -DQT_CORE_LIB -DQT3_SUPPORT)
add_executable(intraoperative_adjustments
${Srcs} ${Hdrs} ${UI_Srcs} ${MOC_Hdrs} ${QRC_Srcs})
target_link_libraries(intraoperative_adjustments
${QT_LIBRARIES}
${VTK_LIBRARIES}
)
endif()
You have to create the INSTALL target using CMake's install command. See the according CMake documentation for more details.
Visual Studio insists that it has to create executables in bin/Debug/ instead of just bin/, when using CMake.
Is there a way to fix this?
Yes, but is not really pretty...
You will need to update the RUNTIME_OUTPUT_DIRECTORY, LIBRARY_OUTPUT_DIRECTORY and ARCHIVE_OUTPUT_DIRECTORY properties on ALL your targets. And you will need to do this for every configuration (Debug, RelWithDebInfo, etc.)
The easiest way is to do this "globally" with their CMAKE_... equivalents. E.g. check the following sample which sets bin/ and lib/ as the "global" binary/library output-directories:
# First for the generic no-config case (e.g. with mingw)
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
# Second, for multi-config builds (e.g. msvc)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib )
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
Alternatively, you can try to run through all the available targets and modify its properties afterwards...
Note that this does not set the location of your .pdb files. I still have not found a satisfying way to put all the relevant .pdb files in the bin/ directory.