CMakeLists.txt学习
---------------- 3-26
编译过程:源文件.c/.h --> 预编译(处理#开头的预编译指令,如#inclide、#define等) --> 编译(语法、语义分析并优化) --> 汇编(将上一步整理的代码转为机器码) --> 链接(将编译出来的目标文件和代码里用到的库文件打包成最终的可执行文件)
静态库和动态库区别:
静态库在链接这一步的时候把自己直接加载到程序中;程序(可执行文件)运行时就不再需要该静态库,意味着如果库文件更新了,需要重新编译可执行文件;最终生成的可执行文件大
动态库在链接这一步的时候只是给了个接口;程序(可执行文件)运行时通过接口加载,所以程序(可执行文件)运行时还需要动态库存在,意味着库文件更新了,此可执行文件也就更新了;最终生成的可执行文件小
生成静态库和动态库(先生成.o 再生成库 分两步):
注:无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件(就是汇编成机器码那一步)
Linux生成静态库:(win: gcc -c max.c \n ar -cr max.lib max.o)
gcc -c hello.c // 生成目标文件hello.o, 或者 gcc hello.c -c
ar crv libhello.a hello.o // 将目标文件hello.o 打包成静态库文件libhello.a
Linux联合编译静态库(假如静态库文件是libhello.a ,main.c要使用它):
gcc main.c -L . -lhello // -L 后面是静态库文件所在的目录,h-l加上库名,这个库名是去掉lib和后面的.a。或者 gcc main.c libhello.a -o main
Linux生成动态库:(win: gcc deivde.cpp -shared -o deivde.dll)
gcc -fPIC -shared -o libhello.so hello.c // -fPIC 是为了能够在多个应用程序间共享,-shared指定生成动态库。
Linux联合编译动态库:
gcc mian.c -o mian -L ./ -lhello // -L后面是库文件的路径,h-l加上库名,这个库名是去掉lib和后面的.so。或者 gcc main.c libhello.so -o main
补充:
当使用gcc联合编译源文件和库时,只需要源文件(或源文件加载的头文件)里有库里的实现函数的声明即可。因为联合声明时你只要定义了再使用,它会去联合了的库里面或者其它源文件里自动找这个实现函数。linux动态、静态库&win动态、静态库:so、a & dll、lib。
编译源文件生成可执行文件:gcc ts.c -o ts || gcc main.c main.h ts.c -o main || gcc main.c libhello.so -o main // 可以将其它的源文件、头文件、库文件一起联合编译
gcc的GBK编码方式:gcc -fexec-charset=GBK test.c contact.c -o contact
------------------ 3-27
前言:
1.使用gcc联合编译,如果修改了其中的一个源文件,所有文件都会被重新编译一次。为此就出现了makefile文件,makefile就是规则、规则、还是TMD规则~,比如执行makefile时发现依赖比目标要新,那么就不会再编译依赖,而要执行makefile文件就需要命令make。但有些人觉得写makefile规则很麻烦,于是就搞了一个cmake工具,该工具使用cmake命令根据CMakeLists.txt自动生成makefile,而这个生成的makefile可以监听CMakeLists.txt的改变,所以后续如果不是新增编译规则直接make编译即可
2.常见的预处理指令 :#ifndef F(如果没有定义F就执行下面的内容)、#ifdef F(如果定义了F就执行下面的内容)、#define F(定义一个标识符F,特点是它定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了)、#else 、#endif;我们很多时候在头文件里会看到:
#ifndef __hello_h__ #define __hello_h__ // 内容 #endif //意思是在预编译的时候如果没有__hello_h__ 就执行下面的内容,下面呢就通过#define生成了__hello_h__,这个生成的__hello_h__在预编译完之前是不会消失的。 //假设在预编译完之前又有其它的地方需要这个头文件,想再编译它的时候__hello_h__已经存在了,所以不会再次编译。也就是防止多次编译。那为什么标识符要起的这么复杂,因为怕和其他define的内容搞重了
基本使用:
首先 cmake . (. 表示CMakeLists.txt所在的目录,cmake就是通过CMakeLists.txt来生成makefile的。或指定编译器生成makefile:cmake .. -G "Unix Makefiles") --> make(根据makefile里的规则开始编译,所以要和makefile在同目录) --> 生成CMakeLists.txt里定义的项目名称的可执行文件,最后执行一下就好了。
注意:cmake会在当前目录生成makefile等其它文件和源文件混在一起就很乱了,一般是建一个build文件夹在里面执行cmake .. ;
------------------ 3-28
全局变量:
${PROJECT_BINARY_DIR} :执行make的目录如 xxx/build/
${PROJECT_SOURCE_DIR}: CMakeLists.txt 所在目录
生成可执行文件:add_executable(hi main.c)
#======================================================================= #Cmake最低版本要求 CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(audiomix) #项目名称 #允许gdb调试 set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") #添加C++11支持及其他选项 set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g") #========================================================================= #添加所有头文件 include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/." "${CMAKE_CURRENT_SOURCE_DIR}/../../ffmpeg/ffoutput/include" ) #将所有的源文件 file(GLOB td_src "${CMAKE_CURRENT_SOURCE_DIR}/*" ) #添加动态库so link_directories( "${CMAKE_CURRENT_SOURCE_DIR}/../../ffmpeg/ffoutput/lib" ) #========================================================================= #生成可执行文件 add_executable(audiomix ${td_src}) #添加链接库 target_link_libraries(audiomix avfilter avformat swscale swresample avcodec avdevice avutil pthread z lzma )
本文来自博客园,作者:封兴旺,转载请注明原文链接:https://www.cnblogs.com/fxw1/p/16061761.html