参考资料:
使用qt构建cmake程序的问题?出现“Parse error. Expected a command name, got unquoted argument with text”错误,这个是由于CMakeLists.txt文件的编码被无意之中改变导致的。在qtcreator中选择CMakeLists.txt文件,右键用binary格式打开:
正常的文件格式应该为:
如果发现在cmake前面有其他的字符,比如ef,bf之类的,说明文件格式已经被修改为其他格式了,此时需要修改文件的编码格式!一种方法是在qtcreator中找到选项,文本编辑,行为,文件编码,将文件编码设置为UTF-8编码格式;另一种方法是复制CMakeLists.txt中的文本内容,然后清空文本保存,会提示你空文本不能保存,此时输入任意一个字符再保存,会发现前面的编码识别字符已经不见了,此时再粘贴之前复制的文本回来,就再次找回了原来的编码!
cmake构建C++应用程序示例=>
#指定cmake最小版本
cmake_minimum_required(VERSION 2.8)
#指定项目名称
project(linux_rdma_server)
#设置C++编译器和添加编译器选项
set(CMAKE_CXX_COMPILER g++)
add_compile_options(-std=c++11)
#设置编译模式
#set(CMAKE_BUILD_TYPE "Release")
#cmake -DCMAKE_BUILD_TYPE=Debug
#根据不同的编译模式设置不同的生成路径
IF (CMAKE_BUILD_TYPE MATCHES "Release")
message("set CMAKE_BUILD_TYPE = Release")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/release)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/release)
ELSEIF (CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
message("set CMAKE_BUILD_TYPE = MinSizeRel")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/minSizeRel)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/minSizeRel)
ELSEIF(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
message("set CMAKE_BUILD_TYPE = RelWithDebInfo")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/relWithDebInfo)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/relWithDebInfo)
ELSEIF(CMAKE_BUILD_TYPE MATCHES "Debug")
message("set CMAKE_BUILD_TYPE = Debug")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/debug)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/debug)
ELSE()
message("set CMAKE_BUILD_TYPE = Default")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/default)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/default)
ENDIF()
#重置动态库查找目录
#如果使用了其他第三方库,不必在linux系统安装第三方库
#拷贝动态库文件到本地目录,加上下面几句即可解决!!!
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TURE)
#设置自定义变量并根据变量参数设置不同的编译选项
set(USE_CAMERA_TEST "YES")
IF (USE_CAMERA_TEST MATCHES "YES")
message("Set USE_CAMERA_TEST = YES")
ELSE()
message("set USE_CAMERA_TEST = NO")
ENDIF()
#添加预定义指令,每条指令前都需要加上-D,之后才是预定义名称
#预定义指令可以在程序中识别,使用#ifdef RDMA_DEBUG 即可!!!
add_definitions(-DRDMA_DEBUG)
#添加源文件路径,使用cpplib替换./cpplib名称
aux_source_directory(./cpplib cpplib)
#包含子项目路径,子项目中的cmakelist.txt文件会被自动识别
add_subdirectory(cpplib)
#添加头文件路径
include_directories(./rdma_server)
include_directories(./cpplib)
#生成动态库,包含所有需要编译的文件,注意,这里只需要包含.cpp文件,.h和.hpp文件可以选择不包含
ADD_LIBRARY(rdma_server SHARED
cpplib/cpplogger.cpp
cpplib/cppfilesystem.cpp
rdma_server/rdma_server.cpp)
#生成执行文件,同样包含所有需要编译的文件
ADD_EXECUTABLE(rdma_server_test
rdma_server_test/main.cpp)
#将动态库连接到指定的应用程序上,最紧密的依赖库在前,间接依赖库在后
target_link_libraries(rdma_server ibverbs rdmacm pthread)
target_link_libraries(rdma_server_test rdma_server ibverbs rdmacm pthread)
#拷贝文件或文件夹到目标程序生成目录,执行cmake的时候就会执行拷贝
file(COPY "rdma_camera_test/copy_files" DESTINATION ${EXECUTABLE_OUTPUT_PATH})
file(COPY "rdma_camera_test/settings.cfg" DESTINATION ${EXECUTABLE_OUTPUT_PATH})
#注意链接动态库设置:
#1) target_link_libraries(rdma_server ibverbs rdmacm pthread)
#2) target_link_libraries(rdma_server_test rdma_server ibverbs rdmacm pthread)
#这里曾经踩过一个坑:只设置了2,未设置1,导致在运行时出现segment faul错误,
#排查原因是因为rdma_server_test被设置了link库,但rdma_server这个库并没有。
#因此我们需要给每个library和execute都设置like库,否则运行时就会报告segment fault错误!!!
针对上面的cmake编写的自动编译生成bash文件=>
#!/bin/sh
if [ ! -d "build" ]; then
echo "creat build directory"
mkdir build
fi
echo "================= debug build ================="
if [ ! -d "build/debug" ]; then
echo "creat debug directory"
mkdir build/debug
fi
cd build/debug
cmake -D CMAKE_BUILD_TYPE=Debug ../..
make
cd ../..
echo "================= release build ================="
if [ ! -d "build/release" ]; then
echo "creat release directory"
mkdir build/release
fi
cd build/release
cmake -D CMAKE_BUILD_TYPE=Release ../..
make
echo "================= build complete ================="