奇技淫巧之cmake
奇技淫巧之cmake如需转载请标明出处:http://blog.csdn.net/itas109QQ技术交流群:129518033文章目录奇技淫巧之cmake前言0.cmake常用配置及信息展示1.mingw(gcc)生成MSVC(vs)可用的dll(.lib)2.qt调试cmake工程3.cmake下载和编译其他工程3.1 FetchContent_MakeAvailable3.2 add_cu
奇技淫巧之cmake
如需转载请标明出处:http://blog.csdn.net/itas109
QQ技术交流群:129518033
文章目录
前言
CMake元构建系统,可以为平台首选的构建系统生成项目文件和构建脚本。例如,它可以为类Unix的系统, Ninja构建脚本, Visual Studio解决方案等生成Makefile。
https://cmake.org
https://github.com/Kitware/CMake
0.cmake常用配置及信息展示
适用于一般信息配置及展示
cmake_minimum_required(VERSION 2.8)
project(CSerialPort LANGUAGES CXX)
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
message(STATUS "CSerialPort CMake Info")
message(STATUS "=======================================================")
message(STATUS " Operation System : ${CMAKE_SYSTEM}")
message(STATUS " CPU Architecture : ${CMAKE_SYSTEM_PROCESSOR}")
message(STATUS " Build Type : ${CMAKE_BUILD_TYPE}${CMAKE_CONFIGURATION_TYPES}")
message(STATUS " Shared Library : ${BUILD_SHARED_LIBS}")
message(STATUS "=======================================================")
# operating system conditional compile
if (WIN32)
message(STATUS "Platform : windows")
elseif(APPLE)
message(STATUS "Platform : apple")
elseif (UNIX)
message(STATUS "Platform : unix")
endif()
示例:
-- CSerialPort CMake Info
-- =======================================================
-- Operation System : Linux-4.9.70-v7+
-- CPU Architecture : armv7l
-- Build Type : Release
-- Shared Library : ON
-- =======================================================
-- Platform : unix
1.mingw(gcc)生成MSVC(vs)可用的dll(.lib)
适用于msvc直接调用mingw的库
mingw(gcc)编译的动态库(DLL)默认MSVC无法调用。
CMAKE_GNUtoMS
Convert GNU import library (.dll.a) to MS format (.lib)
示例:
cmake -G "MinGW Makefiles" -DCMAKE_GNUtoMS=ON ..
注意:
也可以根据def文件手动生成msvc所需动态库
2.qt调试cmake工程
适合于qt直接编译或调试cmake的工程
- qtcreator直接打开CMakeLists.txt工程文件
- qmake -project可以生成qt的pro工程文件(CMakeLists.txt转换为pro)
3.cmake下载和编译其他工程
适合于编译依赖的前置库(包括非cmake工程)等
FetchContent_Declare支持git、svn、url、文件等的下载
3.1 FetchContent_MakeAvailable
CMakeLists.txt
include(FetchContent)
set(FETCHCONTENT_QUIET OFF CACHE INTERNAL "" FORCE)
FetchContent_Declare( # cmake 3.11 above
CSerialPort
GIT_REPOSITORY https://github.com/itas109/CSerialPort
GIT_TAG v4.1.0
USES_TERMINAL_DOWNLOAD TRUE
)
FetchContent_MakeAvailable(CSerialPort) # cmake 3.14 above
# FetchContent_MakeAvailable
#message(STATUS "CSerialPort_SOURCE_DIR : ${CSerialPort_SOURCE_DIR}")
#message(STATUS "CSerialPort_BINARY_DIR : ${CSerialPort_BINARY_DIR}")
3.2 add_custom_target
CMakeLists.txt
include(FetchContent)
set(FETCHCONTENT_QUIET OFF CACHE INTERNAL "" FORCE)
FetchContent_Declare( # cmake 3.11 above
ncurses
GIT_REPOSITORY https://gitee.com/itas109/ncurses
GIT_TAG v6.2 # 2020-02-12
USES_TERMINAL_DOWNLOAD TRUE
)
FetchContent_GetProperties(ncurses)
if(NOT ncurses_POPULATED)
# Fetch the content using previously declared details
FetchContent_Populate(ncurses)
endif()
add_custom_target(compile_ncurses
COMMAND ./configure --prefix=${ncurses_BINARY_DIR}
COMMAND make -j 8
COMMAND make install
COMMENT "configure, compile and install ncurses"
WORKING_DIRECTORY ${ncurses_SOURCE_DIR}
)
add_dependencies(${PROJECT_NAME} compile_ncurses) # excute before project compile
4.安装编译文件
适合于编译完安装
CMakeLists.txt
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/CSerialPort DESTINATION include FILES_MATCHING PATTERN "*.h")
install(TARGETS libcserialport
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
install(FILES ${PROJECT_SOURCE_DIR}/cserialport-config.cmake.in DESTINATION lib/cmake/CSerialPort RENAME cserialport-config.cmake)
5.解决-fPIC问题
适用于解决-fPIC问题
compile flag
relocation R_X86_64_32 against `.text' can not be used when making a shared object; recompile with -fPIC
5.1 修改原始CMakeLists.txt
add_compile_options(-fPIC)
或
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
5.2 不修改原始CMakeLists.txt
cmake -DCMAKE_C_FLAGS="-fPIC" cmake -DCMAKE_CXX_FLAGS="-fPIC" ..
6.编译静态程序
适合于编译无依赖的程序或库
#需要在CMakeLists.txt添加以下内容
#设置静态编译
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
add_compile_options(-static)
#链接静态库
#链接gcc-g++静态库
target_link_libraries(${PROJECT_NAME} libgcc.a)
target_link_libraries(${PROJECT_NAME} libstdc++.a)
#链接网络库(windows如需要)
target_link_libraries(${PROJECT_NAME} ws2_32)
#链接线程库(必须放到最后)
target_link_libraries(${PROJECT_NAME} libpthread.a)
7.cmake直接配置与编译
适合于CI/CD,特别是Visual Studio
mkdir bin && cd bin
cmake ..
cmake --build .
8.cmake交叉编译
适用于交叉编译
通过CMAKE_TOOLCHAIN_FILE实现,无需修改原有CMakeLists.txt
cmake -DCMAKE_TOOLCHAIN_FILE=./toolchain_arm.cmake ..
toolchain_arm.cmake
# 交叉编译的系统名称
set(CMAKE_SYSTEM_NAME Linux)
# 交叉编译的CPU架构
set(CMAKE_SYSTEM_PROCESSOR arm)
set(USER_PATH "/home/dev")
#代表了一系列的相关文件夹路径的根路径的变更,编译器到指定的根目录下寻找对应的系统库
set(CMAKE_SYSROOT ${USER_PATH}/toolchain/sysroot-linaro-eglibc-gcc4.9-2016.02-arm-linux-gnueabihf)
#set(CMAKE_FIND_ROOT_PATH ${USER_PATH}/)
# 指定主机上要安装的路径
set(CMAKE_STAGING_PREFIX ${USER_PATH}/cross_install)
#指明C和C++编译器
set(tools ${USER_PATH}/toolchain/gcc-linaro-4.9-2016.02-x86_64_arm-linux-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)
#对FIND_PROGRAM()起作用,有三种取值,NEVER,ONLY,BOTH,第一个表示不在你CMAKE_FIND_ROOT_PATH下进行查找,第二个表示只在这个路径下查找,第三个表示先查找这个路径,再查找全局路径,对于这个变量来说,一般都是调用宿主机的程序,所以一般都设置成NEVER
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
#下面的三个选项表示只在交叉环境中查找库和头文件
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
9.检查编译器是否支持C++11
适用于使用C++11的应用
cmake_minimum_required(VERSION 2.8)
# Set the project name
project (hello_cpp11)
# try conditional compilation
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
# check results and add flag
if(COMPILER_SUPPORTS_CXX11)#
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)#
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
# Add an executable
add_executable(hello_cpp11 main.cpp)
10.cmake生成源文件
适用于动态生成源文件
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
# Set the project name
project (cf_example)
# set a project version
set (cf_example_VERSION_MAJOR 0)
set (cf_example_VERSION_MINOR 2)
set (cf_example_VERSION_PATCH 1)
set (cf_example_VERSION "${cf_example_VERSION_MAJOR}.${cf_example_VERSION_MINOR}.${cf_example_VERSION_PATCH}")
# Call configure files on ver.h.in to set the version.
# Uses the standard ${VARIABLE} syntax in the file
configure_file(ver.h.in ${PROJECT_BINARY_DIR}/ver.h)
# Add an executable
add_executable(cf_example main.cpp)
# include the directory with the new files
target_include_directories( cf_example PUBLIC ${CMAKE_BINARY_DIR})
ver.h.in
#ifndef __VER_H__
#define __VER_H__
// version variable that will be substituted by cmake
// This shows an example using the $ variable type
const char* ver = "${cf_example_VERSION}";
#endif
main.cpp
#include <iostream>
#include "ver.h"
int main(int argc, char *argv[])
{
std::cout << "Hello Version " << ver << "!" << std::endl;
return 0;
}
未完待续
License
License under CC BY-NC-ND 4.0: 署名-非商业使用-禁止演绎
如需转载请标明出处:http://blog.csdn.net/itas109
QQ技术交流群:129518033
Reference:
1.https://github.com/ttroy50/cmake-examples
更多推荐


所有评论(0)