/cmake-templates

Some CMake Templates (examples). Qt, Boost, OpenCV, C++11, etc 一些栗子

Primary LanguageC++MIT LicenseMIT

cmake-templates

Some CMake Templates.

1. Overview

Conventions

  • 😄 means tested okay/good
  • 😡 means test result not sufficiently good
  • ❓ means not tested yet
Project Linux + GCC 4.8+ Win + VS2010 Win + VS2015 macOS
c 😄 😄 😄 😄
c++ 😄 😄 😄 😄
c++11 😄 😡 😄 😄
c++11vs2010 😄 😄 😄 😄
module 😄 😄 😄 😄
opencv 😄 😡
opencv3 😄 😄 😄
boost 😄 😄 😄
qt4-console 😄 😄 😄 😡
qt4-gui 😄 😄 😄 😡
qt4-project 😄 😄 😄 😡
qt5-project 😄 😄 😄

2. Usage

2.1. Windows

Use CMake-GUI to generate Visual Studio 2010 project, then use Visual Studio to compile & run.

Here is a Tutorial: HOWTO: Win + CMake + Visual Studio 2010 · Issue #1 · district10/cmake-templates.

2.2. Linux

Most commonly, we build Makefile project:

# cd source dir (there should be a CMakeLists.txt)
mkdir build && cd build
cmake ..            # want a release build? try `cmake -DCMAKE_BUILD_TYPE=Release ..'
make

# then checkout the generated binary files

But we can build CodeBlocks projects too, see my tutorial: HOWTO: Linux + CMake + CodeBlocks + GNU Make · Issue #2 · district10/cmake-templates, or use qt-creator to open CMakeLists.txt directly, see my tutorial: HOWTO: Use Qt creator to Open CMakeLists.txt directly (will generate proper project files) · Issue #5 · district10/cmake-templates.

3. Examples

3.1. C Example

Simple C project.

project( C )
cmake_minimum_required( VERSION 2.6 )
add_executable( ${PROJECT_NAME} main.c )

cmake_minimum_required( ... ) is needed in root CMakeLists.txt, always.

The ${PROJECT_NAME} is variable with value C, which is set by the project( C ).

See c.

3.2. C++ Example

Simple C++ project.

project( CPP )
make_minimum_required( VERSION 2.6 )
file( GLOB SRCS *.c *.cpp *.cc *.h *.hpp )  # a variable called SRCS with all files whose path match "*.c *.cpp..."
add_executable( ${PROJECT_NAME} ${SRCS} )

See cpp.

3.3. C++11 Example

C++11 project.

include( CheckCXXCompilerFlag )
check_cxx_compiler_flag( "-std=c++11"   COMPILER_SUPPORTS_CXX11 )
check_cxx_compiler_flag( "-std=c++0x"   COMPILER_SUPPORTS_CXX0X )
if( COMPILER_SUPPORTS_CXX11 )
    if( CMAKE_COMPILER_IS_GNUCXX )
        set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11" )
    else()
        set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
    endif()
elseif( COMPILER_SUPPORTS_CXX0X)
    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" )
else()
    # MSVC, On by default (if available)
endif()

See cpp11.

I recommend Visual Studio 2015 Community Edition.

3.4. Example to Show How to Modualize Your Project

# root cmakelists.txt
project( MODULES )
cmake_minimum_required( VERSION 2.8.3 )

include_directories( ${CMAKE_SOURCE_DIR}/includes )

add_subdirectory( src )
add_subdirectory( demo )

# src dir
add_subdirectory( cubic )
add_subdirectory( extras )
add_subdirectory( square )

# cubic
add_library( LibCubic ${CUBICS} cubic.c )

# demo
project( CALC )
cmake_minimum_required( VERSION 2.6 )

set( EXTRA_LIBS ${EXTRA_LIBS} LibSquare )
set( EXTRA_LIBS ${EXTRA_LIBS} LibExtras )
set( EXTRA_LIBS ${EXTRA_LIBS} LibCubic )

add_executable( Calc calc.c )
target_link_libraries( Calc  ${EXTRA_LIBS} )

See modules.

3.5. Example with Support of Boost

project( BOOST )
cmake_minimum_required( VERSION 2.6 )

find_package( Boost REQUIRED )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
LINK_DIRECTORIES( ${Boost_LIBRARY_DIRS} )
set( Boost_USE_STATIC_LIBS        OFF )
set( Boost_USE_MULTITHREADED      ON )
set( Boost_USE_STATIC_RUNTIME     OFF )
set( BOOST_ALL_DYN_LINK           ON ) # force dynamic linking for all libraries

add_executable( ${PROJECT_NAME} main.cpp )
target_link_libraries( ${PROJECT_NAME} ${Boost_LIBRARIES} )

Ubuntu install: sudo apt-get install libboost-all-dev.

See boost.

3.6. Example with Support of OpenCV

Want to how to configure both opencv 2 & 3 on your system? Checkout my tutorial: HOWTO: OpenCV 2 & OpenCV 3 · Issue #4 · district10/cmake-templates.

opencv 2 or less

project( OPENCV )
cmake_minimum_required( VERSION 2.6 )

include( $ENV{OpenCV2_DIR}/OpenCVConfig.cmake ) # find_package( OpenCV REQUIRED )

message( STATUS "OpenCV library status:" )
message( STATUS "    version: ${OpenCV_VERSION}" )
message( STATUS "    libraries: ${OpenCV_LIBS}" )
message( STATUS "    include path: ${OpenCV_INCLUDE_DIRS}" )

include_directories( ${OpenCV_INCLUDE_DIRS} )

add_executable( ${PROJECT_NAME}  minarea.c )
target_link_libraries( ${PROJECT_NAME} ${OpenCV_LIBS} )

opencv 3

project( OPENCV3 )
cmake_minimum_required( VERSION 2.8 )

include( $ENV{OpenCV3_DIR}/OpenCVConfig.cmake ) # find_package( OpenCV REQUIRED )

message( STATUS "OpenCV library status:" )
message( STATUS "    version: ${OpenCV_VERSION}" )
message( STATUS "    libraries: ${OpenCV_LIBS}" )
message( STATUS "    include path: ${OpenCV_INCLUDE_DIRS}" )

include_directories( ${OpenCV_INCLUDE_DIRS} )

add_executable( ${PROJECT_NAME} example.cpp )
target_link_libraries( ${PROJECT_NAME} ${OpenCV_LIBS} )

See

  • opencv: for opencv2 or less (VS2010 😄, Linux ❓)
  • opencv3: for opencv3 (VS2010 ❓, Linux 😄)

3.7. Example with Support of Qt4

Be sure to make qmake caught by CMake, put it in your $PATH.

qt4 console

find_package( Qt4 REQUIRED )
include( ${QT_USE_FILE} )
set( QT_DONT_USE_QTGUI TRUE )

add_executable( ${PROJECT_NAME} main.cpp )
target_link_libraries( ${PROJECT_NAME}  ${QT_LIBRARIES} )

configure file

configure_file(
    "${PROJECT_SOURCE_DIR}/Configs.h.in"
    "${PROJECT_BINARY_DIR}/Configs.h" )

moc, uic

file( GLOB_RECURSE HDRS_FILES *.h *.hpp )
file( GLOB_RECURSE SRCS_FILES *.cpp )
file( GLOB_RECURSE UI_FILES *.ui )

qt4_wrap_cpp( MOC_SRCS ${HDRS_FILES} )
qt4_wrap_ui( UI_HDRS ${UI_FILES} )

source_group( "UI Files" FILES ${UI_FILES} )
source_group( "Generated Files" FILES ${MOC_SRCS} ${UI_HDRS} )

add_library( ${PROJECT_NAME} STATIC ${SRCS_FILES} ${UI_FILES} ${HDRS_FILES} ${MOC_SRCS} ${UI_HDRS} )
target_link_libraries( ${PROJECT_NAME} ${QT_LIBRARIES} )

Works like qmake -project, one ring to rule them all:

project( QT4 )
cmake_minimum_required( VERSION 2.6 )

find_package( Qt4 REQUIRED )
include( ${QT_USE_FILE} )

include_directories( ${CMAKE_SOURCE_DIR}/ )
include_directories( ${CMAKE_BINARY_DIR}/ )

# based on: https://cmake.org/Wiki/CMakeMacroFilterOut
macro( filter_out FILTERS INPUTS OUTPUTS )
    set( FOUT "" )
    foreach( INP ${INPUTS} )
        set( FILTERED 0 )
        foreach( FILT ${FILTERS} )
            if( ${FILTERED} EQUAL 0 )
                if( "${FILT}" STREQUAL "${INP}" )
                    set( FILTERED 1 )
                endif( "${FILT}" STREQUAL "${INP}" )
                if( ${INP} MATCHES ${FILT} )
                    set( FILTERED 1 )
                endif( ${INP} MATCHES ${FILT} )
            endif( ${FILTERED} EQUAL 0 )
        endforeach( FILT ${FILTERS} )
        if( ${FILTERED} EQUAL 0 )
            set( FOUT ${FOUT} ${INP} )
        endif( ${FILTERED} EQUAL 0 )
    endforeach( INP ${INPUTS} )
    set( ${OUTPUTS} ${FOUT} )
endmacro( filter_out FILTERS INPUTS OUTPUTS )

file( GLOB_RECURSE UI_FILES *.ui )
file( GLOB_RECURSE HDRS_FILES *.h *.hpp )
file( GLOB_RECURSE SRCS_FILES *.cpp *.c )
file( GLOB_RECURSE RCS_FILES *.qrc )

set( FILTERS ".*CompilerId.*" )
set( FILTERS ".*CMakeFiles/.*" )
filter_out("${FILTERS}" "${SRCS_FILES}" SRCS_FILES )

qt4_wrap_cpp( MOC_SRCS ${HDRS_FILES} )
qt4_wrap_ui( UI_HDRS ${UI_FILES} )
qt4_add_resources( RCS ${RCS_FILES} )

source_group( "UI Files" FILES ${UI_FILES} )
source_group( "Generated Files" FILES ${MOC_SRCS} ${UI_HDRS} )
source_group( "All Resource Files" FILES ${RCS} )

add_executable( ${PROJECT_NAME}
    ${MOC_SRCS}
    ${HDRS_FILES}
    ${SRCS_FILES}
    ${UI_FILES}
    ${UI_HDRS} ${RCS} )
target_link_libraries( ${PROJECT_NAME} ${QT_LIBRARIES} )

See

3.8. Example with Support of Qt5

project( Qt5Project )
cmake_minimum_required( VERSION 2.8.11 )

#                                           root of your msvc14 x64 prebuild
set( CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:/Qt/Qt5-msvc14/5.6/msvc2015_64" )
set( CMAKE_INCLUDE_CURRENT_DIR ON )
set( CMAKE_AUTOMOC ON )

find_package( Qt5Widgets REQUIRED )
qt5_wrap_ui( UI_HEADERS mainwindow.ui )
qt5_add_resources( QRCS resources.qrc )
add_executable( ${PROJECT_NAME} main.cpp mainwindow.cpp ${UI_HEADERS} ${QRCS} )
target_link_libraries( ${PROJECT_NAME} Qt5::Widgets )

See qt5 project.

3.9. Get'em Together (advanced examples)

This part is called CMake in Action.

4. TODO

  • More documentation
  • More elegant & illustrative examples
  • Planned Examples
    • for Windows, link *.lib files
    • for Linux, link *.a, *.so files, set rpath
    • etc.

5. Snippets & Helper Functions

cpp -> exe

file( GLOB SRCS src/*.cpp)
foreach( src ${SRCS} )
    string( REGEX REPLACE "(^.*/|.cpp$)" "" exe ${src} )
    message( STATUS "${exe} <-- ${src}" )
    add_executable( ${exe} ${src} )
endforeach( src )

There are some utility functions in utilities.cmake, use include(utilities.cmake) to include, then use

  • print_include_directories() to print all included directories,
  • print_all_linked_libraries(your_exe_or_lib) to print all linked libs,
  • print_all_variables() to print all variables

Tip, use cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=YES .. to generate compile commands (a json file).

6. ReadingList

These links may be useful:

7. Koan

  • CMake's documentation is not for human. It really smells
  • Adapt to various standards is by no means easy, it's kind of brain fucking