编译相关

本文详细介绍了GCC编译器的各种参数用法,包括预处理、编译、汇编、链接以及优化级别的设置。同时,文章还探讨了CMakeLists.txt的编写,讲解了如何定义工程、设置源文件、添加编译选项、指定头文件路径、库搜索路径以及调试信息的生成。此外,还涵盖了CMake中变量的使用、输出信息的控制、目标属性的设置、第三方库的链接以及安装指令的使用等。
摘要由CSDN通过智能技术生成

gcc参数说明

无选项编译 gcc test.c,默认生成a.out
-E只激活预处理,不生成文件,需要重定向到一个文件中

gcc -E test.c | more或者gcc -E test.c -o test.i

-S只激活预处理和编译,就是指把文件编译成汇编代码,生成.s文件

gcc -S test.c或者gcc -S test.i

-c只激活预处理、编译和汇编,生成.o文件

gcc -c test.c或者gcc -c test.s

-o指定目标名称,缺省的时候文件为a.out

gcc -o test test.c

-pipe使用管道代替编译中临时文件

gcc -pipe -o test test.c

-llibrary定制编译的时候使用的库

gcc -lpthread test.c //编译的时候要依赖pthread这个库,动态库静态库都可以

-L dir定制编译的时候搜索库的路径,比如自己定义的库的路径

-L .//当前文件夹查找库

-D添加宏定义

gcc -DENABLE_DEBUG

-Iinclude路径
-o0没有优化
-o1缺省值
-o2二级优化
-o3最高优化级别
级别越大优化越好,但编译时间越长
-g在编译的时候加入debug调试信息,用于gdb调试
-ggdb产生的debug信息更倾向于给GDB使用
-g33是级别,级别越高会产生的更多的额外debug信息,3这个级别可以调试宏
-static链接时使用静态链接,但是要保证系统中有静态库
-share尽量使用动态库,所以生成文件比较小,但是系统必须有动态库
-w不生成任何警告信息
-wall生成所有警告信息

CMakeLists.txt编写说明

CMakeList.txt中命令不区分大小写,变量区分大小写,make clean对构建结果进行清理

  • 定义工程名字,并可指定工程支持的语言,可忽略
    project(projectname [CXX][C][Java])隐式定义两个cmake变量
    <projectname>_BINARY_DIR<projectname_SOURCE_DIR>,与PROJECT_BINARY_DIRPROJECT_SOURCE_DIR一样,对于out-of-source编译方式来说,PROJECT_SOURCE_DIR为工程路径/backup/cmake/t1PROJECT_BINARY_DIR为编译路径/backup/cmake/t1/build

  • 定义变量,或者设置CMAKE常用变量和环境变量
    set(VAR [Value])
    SET(SRC_LIST main.c),多个源文件也可以SET(SRC_LIST main.c t1.c t2.c)

  • list 追加或者删除变量的值
    list(APPEND SRC_LIST test.cpp)
    list(REMOVE_ITEM SRC_LIST main.cpp)

  • 向终端输出用户定义的信息
    message([WARNING | SEND_ERROR | STATUS | FATAL_ERROR] "message to display")
    三种类型:
    WARNING,警告
    SEND_ERROR,产生错误,会继续执行,生成过程被跳过;
    STATUS,输出前缀为-的信息;
    FATAL_ERROR,立即终止所有cmake过程

  • 生成可执行文件
    add_executable(hello ${SRC_LIST})
    源文件可以在后面列ADD_EXECUTABLE(hello main.c fun.c),也可以用引用变量的方式${}。变量引用在控制语句中如if中直接使用变量名,不需要加${}

  • 生成动态库或静态库
    add_library(common SHARED/STATIC util.cpp)
    默认生成静态库,若需要默认生成动态库,则需要set(BUILD_SHARED_LIBS ON)
    注意add_executable\add_library生成的可执行文件和库文件不能同名,否则会报错,若需要同名,则采用以下方式:

	add_library(hello SHARED ${LIBHELLO_SRC})
	add_library(hello_static STATIC ${LIBHELLO_SRC})
	set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")
  • 添加一个文件夹进行编译
    add_subdirectory(sub_name) ,该文件夹下的CMakeLists.txt负责编译该文件夹下的源码。每一级文件目录用一个cmakelist,如果需要用到上层cmakelist文件参数如projectname_SOURCE_DIR,应采用projectname_SOURCE_DIR而不是PROJECT_SOURCE_DIR,因为在子目录中的cmakelistPROJECT_SOURCE_DIR是子目录

  • 添加头文件查找路径
    include_directories(${PROJECT_SOURCE_DIR}/include)

  • 设置目标属性
    set_target_properties(target1 target2.. PROPERTIES prop1 value1 prop2 value2)
    set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")重新设置目标名字

  • 获取目标属性
    get_target_property(VAR target property)
    get_target_property(OUTPUT_VALUE hello_static OUTPUT_NAME)获取hello_static库的OUTPUT_NAME属性,保存在OUTPUT_VALUE中,可以通过${OUTPUT_VALUE}得到

  • 添加第三方库
    target_link_libraries(target lib1 lib2)
    有多种方式:

 link_directory(path)//添加第三方库查找路径
 //target为目标,hello为第三方库,这里使用libhello.so会报错
 target_link_libraries(target hello)
//libhello.so为库,libpath为查找路径,VAR保存查找后的路径,包括libhello.so
find_library(VAR libhello.so libpath)
//等价target_link_libraries(target .../libhello.so)
target_link_libraries(target ${VAR})
//相当于在gcc指令中添加
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/hello/lib")
//或者target_link_libraries(target libhello.so)
target_link_libraries(target hello)
  • 查找一个目录下的所有源文件
    aux_source_directory(dir VAR)
    找到文件夹dir下的所有源文件并保存在变量VAR中,不包括头文件

  • 第三方头文件和库
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/hello/lib")
    添加第三方头文件和库通用,与gcc使用方式相同 -L为库文件路径 -l(小写L)为库文件 -I(大写i)为头文件查找路径,CMAKE_CXX_FLAGS为cpp,CMAKE_C_FLAGS为c

  • 添加-D定义
    add_definitions(-DENABLE_DEBUG -DABC)定义了ENABLE_DEBUG和ABC两个宏,可以在代码中使用,也可以通过CMAKE_CXX_FLAGS添加

  • 查找指令
    find_XX(VAR target path)
    查找文件路径
    find_path查找后结果不包括文件本身,会在默认路径中查找,然后在path中查找,也可以通过环境变量CMAKE_INCLUDE_PATH进行设置,如export CMAKE_INCLUDE_PATH=/usr/include/hello
    查找文件
    find_file用于查找文件,查找后结果包括文件本身
    查找库
    find_library用于查找库文件,可以通过环境变量CMAKE_LIBRARY_PATH进行设置
    查找程序
    find_program
    查找包
    find_package(pack [QUIET][NO_MODULE][REQUIRED]])查找.cmake包
    模块查找模式:查找路径先在CMAKE_MODULE_PATH中查找,然后在模块目录/usr/share/cmake/Module中查找,查找路径可以通过set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)设置。
    配置查找模式:如果没找到这样的文件,find_package()会在~/.cmake/packages/或/usr/local/share/中的各个包目录中查找,寻找<库名字的大写>Config.cmake 或者 <库名字的小写>-config.cmake (比如库Opencv,它会查找/usr/local/share/OpenCV中的OpenCVConfig.cmake或opencv-config.cmake)
    find_package指令可以生成一些cmake变量,如查找BZIP2包:

BZIP2_FOUND - system has BZip2 
BZIP2_INCLUDE_DIR - the BZip2 include directory 
BZIP2_LIBRARIES - Link these to use BZip2 
BZIP2_NEED_PREFIX - this is set if the functions are prefixed with BZ2_ BZIP2_VERSION_STRING - the version of BZip2 found (since CMake 2.8.8)

因此可以在cmakelist中使用:

project(helloworld) 
add_executable(helloworld hello.c)
find_package (BZip2)
if (BZIP2_FOUND) 
	include_directories(${BZIP_INCLUDE_DIRS}) 
	target_link_libraries (helloworld ${BZIP2_LIBRARIES}) 
endif (BZIP2_FOUND)

编写属于自己的 FindHello 模块。

//查找hello.h头文件路径,保存在HELLO_INCLUDE_DIR中
find_path(HELLO_INCLUDE_DIR hello.h /usr/include/hello /usr/local/include/hello)
//查找hello库文件,保存在HELLO_LIBRARY中
find_library(HELLO_LIBRARY NAMES hello PATH /usr/lib /usr/local/lib)
if(HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
	//设置查找标志
	set(HELLO_FOUND TRUE)
endif(HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
if(HELLO_FOUND)
	if(NOT HELLO_FIND_QUIETLY)
		message(STATUS "Found Hello: ${HELLO_LIBRARY}")ENDIF (NOT HELLO_FIND_QUIETLY)
	endif(NOT HELLO_FIND_QUIETLY)
else(HELLO_FOUND)
	if(HELLO_FIND_REQUIRED)
		message(FATAL_ERROR "Could not find hello library")
	endif(HELLO_FIND_REQUIRED)
endif(HELLO_FOUND)

QUIET参数,对应编写中的HELLO_FIND_QUIETLY,如果不指定该参数,就会打印相应的信息
REQUIRED参数,其含义是指这个共享库是否是工程必须的,如果使用了这个参数,说明这个链接库是必备库,如果找不到这个链接库,则工程不能编译。对应于FindHELLO.cmake 模块中的 HELLO_FIND_REQUIRED 变量。

  • 安装指令
    通过make install指令安装,同时可以通过CMAKE_INSTALL_PREFIX变量添加前缀路径
 cd build 
 cmake -DCMAKE_INSTALL_PREFIX=/usr ..
 make 
 make install 

安装动态库、静态库和目标二进制

install(TARGETS targets ...
			[ [ARCHIVE | LIBRARY | RUNTIME] 
			  [DESTINATION <dir>]
			  [PERMISSIONS] permissions...
			  [CONFIGURATIONS [Debug | Release | ...]]
			  [COMPONENT <component>]
			  [OPTIONAL]][...]
			)
install(TARGETS myrun mylib mystaticlib
		    RUNTIME DESTINATION bin
			LIBRARY DESTINATION lib
			ARCHIVE DESTINATION libstatic
)

上面的例子会将:
可执行二进制myrun安装到${CMAKE_INSTALL_PREFIX}/bin目录
动态库libmylib 安装到${CMAKE_INSTALL_PREFIX}/lib目录
静态库libmystaticlib安装到${CMAKE_INSTALL_PREFIX}/libstatic目录

安装文件

 install(FILES files... DESTINATION <dir>
			[PERMISSIONS permissions...]
			[CONFIGURATIONS [Debug|Release|...]]
			[COMPONENT <component>]
			[RENAME <name>] [OPTIONAL])

可用于安装一般文件,并可以指定访问权限,文件名是此指令所在路径下的相对路径。如果
默认不定义权限 PERMISSIONS,安装后的权限为:OWNER_WRITE, OWNER_READ,
GROUP_READ,和 WORLD_READ,即 644 权限。

非目标文件的可执行程序安装(比如脚本)

install(PROGRAMS files... DESTINATION <dir>
		[PERMISSIONS permissions...]
		[CONFIGURATIONS [Debug|Release|...]]
		[COMPONENT <component>]
		[RENAME <name>] [OPTIONAL])

跟上面的 FILES 指令使用方法一样,唯一的不同是安装后权限为:
OWNER_EXECUTE, GROUP_EXECUTE, 和 WORLD_EXECUTE,即 755 权限

目录的安装:

INSTALL(DIRECTORY dirs... DESTINATION <dir>
		[FILE_PERMISSIONS permissions...]
		[DIRECTORY_PERMISSIONS permissions...]
		[USE_SOURCE_PERMISSIONS]
		[CONFIGURATIONS [Debug|Release|...]]
		[COMPONENT <component>]
		[[PATTERN <pattern> | REGEX <regex>]
		[EXCLUDE] [PERMISSIONS permissions...]] [...])

DIRECTORY 后面连接的是所在 Source 目录的相对路径,但务必注意:abc 和 abc/有很大的区别。
如果目录名不以/结尾,那么这个目录将被安装为目标路径下的 abc,如果目录名以/结尾,代表将这个目录中的内容安装到目标路径,但不包括这个目录本身。
PATTERN 用于使用正则表达式进行过滤,
PERMISSIONS 用于指定 PATTERN 过滤后的文件权限。

INSTALL(DIRECTORY icons scripts/ DESTINATION share/myprojPATTERN "CVS" EXCLUDE
PATTERN "scripts/*"
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READGROUP_EXECUTE GROUP_READ)

这条指令的执行结果是:
将 icons 目录安装到 /share/myproj,将 scripts/中的内容安装到/share/myproj
不包含目录名为 CVS 的目录,对于 scripts/* 文件指定权限为 OWNER_EXECUTE
OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ.

  • set(LIBRARY_OUTPUT_PATH ${projectname_SOURCE_DIR}/lib)设置库文件生成路径
  • set(EXECUTABLE_OUTPUT_PATH ${projectname_SOURCE_DIR}/bin)设置可执行文件生成路径
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值