目录
1.gcc处理复杂项目
2.Cmake处理复杂项目
2.1.搜索file
2.2.包含头文件路径
3.库文件
3.1.制作库文件
3.2.链接静态库
3.3.链接动态库
4.预处理
5.参考资料、视频
当一个项目中由多个.c文件组成时,再直接使用gcc指令编译会比较复杂。
// add.c
int add(int a,int b)
{
return a+b;
}
//sub.c
int sub(int a,int b)
{
return a-b;
}
//fun.h
#ifndef __FUN_H
#define __FUN_H
int add(int a,int b);
int sub(int a,int b);
#endif
//main.c
#include
#include "fun.h"
int main(void)
{
printf("1+2 = %d\n",add(1,2));
printf("2-1 = %d\n",sub(2,1));
return 0;
}
将上面的main.c编译成可执行文件,可以用下面的gcc指令。
gcc -o main main.c ./fun/add.c ./fun/sub.c -I./fun
-I(大写)是为了指定.h文件的路径,可预见项目结构越复杂,gcc指令也越复杂,也不方面对项目进行管理。
gcc的编译流程可以分为下面的情况:
可执行文件是由多个.o(可以重定位的目标文件)链接一起为可执行文件。
对于main.c
想要编译出可执行文件,可以分别生成main.o ,add.o,sub.o
文件,再链接成main.exe。
gcc -o main main.o ./fun/add.o ./fun/sub.o
对于复杂的项目,我们可以使用Cmake来构建。
#CMakeLists.txt
cmake_minimum_required(VERSION 3.5.0)
project(test1)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/fun/*.c ./main.c) #搜索.c文件
include_directories(./fun) #添加.h文件路径
set(EXECUTABLE_OUTPUT_PATH ..)
add_executable(app ${SRC})
下面介绍一下CMakeLists.txt中用到的几个函数。
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
GLOB
: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。
GLOB_RECURSE
:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。- CMAKE_CURRENT_SOURCE_DIR:CMakeLists.txt所在的文件路径
有时候.h文件不在当前目录下,在gcc中需要添加.h文件的路径,在cmake中可以用include_directories
包含。
include_directories(.h文件的路径)
库文件分为静态库与动态库,在linux中静态库后缀.a,动态库后缀.so。库文件名 = lib+"自定义名字"+.a/.so。
add_library(库名 STATIC/SHARED 源文件)
- STATIC 静态 默认值
- SHARED 动态
#指定静态库/动态库的路径
set(LIBRARY_OUTPUT_PATH 路径)
#CmakeList.txt 示例
cmake_minimum_required(VERSION 3.5.0)
project(test2)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.c)
set(LIBRARY_OUTPUT_PATH ..) #相对于Makefile的路径
add_library(fun STATIC ${SRC}) #制作库文件 libfun.a
link_directories(
) #指定路径 link_libraries( [ ...]) #链接静态库 #staic 可以是全名 lib+库名+.a
#或者 库名
#示例
cmake_minimum_required(VERSION 3.5.0)
project(test1)
include_directories(./fun)
link_directories(./fun) #指定库文件路径
link_libraries(fun) #链接库文件
set(EXECUTABLE_OUTPUT_PATH ..)
add_executable(app main.c)
target_link_libraries(
- ... [
- ...]...)
表示指定加载库的文件 - target_link_libraries()可以用来链接动态库,也可以用于链接静态库
#示例
cmake_minimum_required(VERSION 3.5.0)
project(test1)
include_directories(./fun)
link_directories(./fun) #指定动态库地址
add_executable(app main.c)
target_link_libraries(app libfun.so) #链接动态库
预处理关键是#,在我们的调试过程中常用到printf
观察结果,但发行版本又需要把调试代码剔除,这时可以用#ifdef #endif。
//C例子
void main(void)
{
#ifdef DEBUG
printf("DEBUG");
#endif
}
当程序中出现宏DEBUG
时才执行printf("DEBUG")
,在gcc指令中可以用 -D
添加宏定义:-DDEBUG
,在cmake中使用 add_definitions(-DDEBUG)。
5.参考资料、视频
CMake 保姆级教程【C/C++】