CMake交叉编译小结

通过gcc/g++编译一个简单的main.c源文件,可以通过如下命令:

gcc -g -o main main.c

1、 gcc表示表示使用的编译工具,如果不额外声明,会使用系统路径下的编译工具,如/usr/bin

2、-g表示生成的可执行程序、动态库、静态库具有symbol信息,可调试,但这样往往会使得target更大,release版本一般会使用相同路径下的strip工具对其瘦身。

3、-o main Target命名为main

4、main.c表示生成Target的源文件

但是大型工程往往由很多模块组成,各模块间也都有一定的依赖关系,因此可通过CMake来构建整个工程的编译。通过CMake来编译的核心还是上面的例子,在执行cmake path/to/CMakeLists.txt生成makefile之后,执行make。需要通过CMakeLists.txt设置以下七个主要参数:编译工具 编译参数 头文件位置 依赖库位置 依赖库 Target-name 源文件

1、编译工具。可以通过以下两种方法设置

1、set(CMAKE_CXX_COMPILER "/usr/bin/g++")//CMAKE_C_COMPILER类似
2、include(CMakeForceCompiler)
    FILE(GLOB_RECURSE COMPILER_BIN_G++ "path/to/g++/*-g++")//path/to/g++路径可能含有多个版本的g++
    LIST(GET COMPILER_BIN_G++ 0 COMPILER_BIN_G++)//0代表索引
    if(COMPILER_BIN_G++)
        cmake_force_cxx_compiler( "${COMPILER_BIN_G++}" GNU)
    endif()

2、编译参数,头文件位置,依赖库位置,依赖库。不同模块可以设置不同的编译参数,而有些特性可能是所有模块共同的,所以可分别设置GLOBAL和PRIVATE

set(GLOBAL_CXX_FLAGS "-g -Wall -W -funroll-loops -Wno-narrowing -fPIC -g -O0 -fsigned-char -funwind-tables -fexceptions -std=c++11 -fpermissive -pthread -Wno-unused-parameter -Wno-error=comment")

set(GLOBAL_EXE_LINK_FLAGS "-Wl,-rpath-link=${LIBS_DIR1}:${LIBS_DIR2}")

set(GLOBAL_LINK_FLAGS "$ENV{LDFLAGS} -Wl,-rpath,'$ORIGIN/../libs',-rpath,'$ORIGIN/./'")

set_property(CACHE CMAKE_CXX_FLAGS PROPERTY VALUE "${GLOBAL_CXX_FLAGS}")
set_property(CACHE CMAKE_SHARED_LINKER_FLAGS PROPERTY VALUE  "${GLOBAL_LINK_FLAGS}")
set_property(CACHE CMAKE_EXE_LINKER_FLAGS PROPERTY VALUE  "${GLOBAL_EXE_LINK_FLAGS} ${GLOBAL_LINK_FLAGS}")


set(GLOBAL_DEFINES "-DCommandMacro=1 -DSampleMacro -D_LINUX_ -DLINUX")
其中-DCommandMacro=1相当于#define CommandMacro 1
    -DSampleMacro相当于#define SampleMacro

set(PRIVATE_CXX_FLAGS "-Wno-error=unused-function -Wno-error=reorder -Wno-error=unused-variable -Wno-deprecated -Wno-error=unused-but-set-variable -Wno-error=misleading-indentation -Wno-error=format-overflow= -Wno-error=format= -Wno-error=int-to-pointer-cast")

set(PRIVATE_DEFINES "-DPRIVATE_MACRO")

set(build_cxx_flags  "" CACHE STRING INTERNAL FORCE)
set(build_cxx_flags "${build_cxx_flags} ${PRIVATE_CXX_FLAGS}")
set(build_cxx_flags "${build_cxx_flags}  ${GLOBAL_DEFINES}")
set(build_cxx_flags "${build_cxx_flags}  ${PRIVATE_DEFINES}")

set(inc_dir_flag "")
//build_inc_dir变量表示该模块中include头文件的位置
string(STRIP "${build_inc_dirs}" strip_inc_dirs)
string(REGEX REPLACE "#[^\n]*\n" " " strip_inc_dirs "${strip_inc_dirs}")
string(REPLACE "\n" " " INC_OUTPUT "${strip_inc_dirs}")
string(STRIP "${INC_OUTPUT}" INC_OUTPUT)
string(REGEX REPLACE " [ \t]*" " " INC_OUTPUT "${INC_OUTPUT}")
separate_arguments(INC_OUTPUT)
foreach(inc_dir ${INC_OUTPUT})
    string(STRIP "${inc_dir}" inc_dir)
	if(inc_dir)
        set(inc_dir_flag  "${inc_dir_flag} -I${inc_dir}")
    endif()
endforeach()
set(build_cxx_flags "${build_cxx_flags} ${inc_dir_flag}" CACHE STRING INTERNAL FORCE)

set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_FLAGS "${build_cxx_flags}")


//指定依赖库的位置,通常可分别设置全局依赖和单一模块库依赖的dirs
set(build_link_dirs  "${GLOBAL_LINK_DIRS} ${PRIVATE_LINK_DIRS}")
set(link_dir_flag "")
string(REGEX REPLACE "#[^\n]*\n" " " build_link_dirs "${build_link_dirs}")
string(REPLACE "\n" " " build_link_dirs "${build_link_dirs}")
string(REGEX REPLACE " [ \t]*" " " build_link_dirs "${build_link_dirs}")
separate_arguments(build_link_dirs)
foreach(link_dir ${build_link_dirs})
	string(STRIP "${link_dir}" link_dir)
	if (WIN32)
		set(link_dir_flag "${link_dir_flag} /LIBPATH:\"${link_dir}\"")
	else()
		set(link_dir_flag "${link_dir_flag} -L${link_dir}")
	endif()
endforeach()
set(build_link_flags "${build_link_flags} ${link_dir_flag}")

//依赖库
set(build_link_libs  "${GLOBAL_LINK_LIBS} ${PRIVATE_LINK_LIBS}")
set(link_lib_flag "")
set(depend_static_libs "")
string(REGEX REPLACE "#[^\n]*\n" " " build_link_libs "${build_link_libs}")
string(REPLACE "\n" " " build_link_libs "${build_link_libs}")
string(REGEX REPLACE " [ \t]*" " " build_link_libs "${build_link_libs}")
separate_arguments(build_link_libs)
foreach(link_lib  ${build_link_libs})
	if (WIN32)
		set(link_lib_flag  "${link_lib_flag} /DYNAMICBASE ${link_lib}")
	else()
        if(${link_lib} MATCHES "lib.*.a")
			set(depend_static_libs "${depend_static_libs} ${link_lib}")
        else()
			string(STRIP "${link_lib}" link_lib)
			set(link_lib_flag  "${link_lib_flag} -l${link_lib}")
        endif()
    endif()
endforeach()
set(build_link_flags  " ${build_link_flags} ${link_lib_flag}" CACHE STRING INTERNAL FORCE)

set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "${build_link_flags}")

 3、Target-name,源文件。

set(build_src_files "")
string(REGEX REPLACE "#[^\n]*\n" " " PRIVATE_SRC_FILES "${PRIVATE_SRC_FILES}")
string(REPLACE "\n" " " bld_src_files "${PRIVATE_SRC_FILES}")
separate_arguments(bld_src_files)
set(build_src_files "${bld_src_files}" CACHE STRING INTERNAL FORCE)

add_library(${TARGET_NAME} SHARED "${build_src_files}")
add_library(${TARGET_NAME} STATIC "${build_src_files}")
add_executable(${TARGET_NAME} "${build_src_files}")

//自定义so/executable存放路径
set(BIN_OUTPUT_PATH ${output-path}/bins)
set(LIB_OUTPUT_PATH ${output-path}/libs)
ADD_CUSTOM_COMMAND(TARGET ${TARGET_NAME}
        POST_BUILD
		COMMAND ${CMAKE_COMMAND} -E make_directory ${BIN_OUTPUT_PATH}
		COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${BIN_OUTPUT_PATH}
		)

可以通过以下方法递归设置源文件:

file(GLOB_RECURSE  SRC_FILES  ${path-to/files}/*.cpp
                              ${path-to/files}/*.cc
                              ${path-to/files}/*.c )

 从中删除某个文件的方法:

list(REMOVE_ITEM SRC_FILES ${path-to-files}/to_be_removed.cpp)

设置动态库名字为name,默认为libname.so,也可以自行设置前后缀,Happyname.love:

set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "Happy")
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".love")

你可能感兴趣的:(编译,CMake,cmake,gcc/gdb编译调试)