一 gcc编译器常用选项
-E 预处理 -S编译 -c汇编 输入均为.c文件,输出分别为.i .s .o
-std=standard 编译标准 如-std=c++11
-g 编译调试
-O 优化级别
-Wwarm 指定警告级别,可以-Wall -Wextra
-I指定include目录,通常用于包含其他文件夹下头文件
-L 指定链接库目录
-D 编译时添加宏定义 用于ifdefine代码可选择性生效
-U 取消宏定义 用于编译时某些c文件宏有定义,有些则没有
-f 编译动态库时,使用-fpic
-m 机器选项如-m64 -m32
-o 指定输出文件,即指定编译后可执行文件的文件名
infile 输入文件列表
二 利用gcc编译动态库和静态库
-E 预处理 -S编译 -c汇编 输入均为.c文件,输出分别为.i .s .o
-std=standard 编译标准 如-std=c++11
-g 编译调试
-O 优化级别
-Wwarm 指定警告级别,可以-Wall -Wextra
-I指定include目录,通常用于包含其他文件夹下头文件
-L 指定链接库目录
-D 编译时添加宏定义 用于ifdefine代码可选择性生效
-U 取消宏定义 用于编译时某些c文件宏有定义,有些则没有
-f 编译动态库时,使用-fpic
-m 机器选项如-m64 -m32
-o 指定输出文件,即指定编译后可执行文件的文件名
infile 输入文件列表
二 利用gcc编译动态库和静态库
1、制作动态库时必须加参数-fpic -shared,生成的动态库需要指定为libxxx.so文件
使用动态库时,动态库的名字为xxx,前后的lib和.so需要省略
例如:gcc -fpic -shared func.c -o libfunc.so
链接动态库时,即使动态库在当前目录也需要加参数-L指定链接库目录
例如:gcc main.c -L. -lfunc
如果程序编译时链接了动态库,运行时也需要加载动态库,这里提供两种方法
第一,运行前输入命令export LD_LIBRARY_PATH=动态库所在目录
这种方法每次重启linux都需要重新导入
第二,将动态库放入系统默认的库目录/usr/lib
这种方法重启系统不需要重新导入,但会导致系统库目录越来越大
最好的解决方案是将用到的动态库放入系统配置文件,每次开机自动加载
动态库并不会打包到程序中,而是利用共享映射,多个程序共享同一个库文件
优点是节约内存,精简程序,便于程序升级,维护方便
2、静态库
静态库制作利用打包命令
ar rcs libtest.a a.o b.o
rcs是指参数-r -c -s,libxxx.a是表示静态库,库名为xxx
打包库时需要用汇编文件.o进行打包
链接库时,如果动态库静态局同名,默认优先链接动态库
如果要链接静态库,需要使用-static
如:gcc a.c -lfunc -static
使用以下命令可以指定某些库静态链接,某些库动态链接
-wl,-Bstatic -lfunc1 -wl,-Bdynamic -lfunc2
静态库会直接打包到程序中,优点是程序运行速度快,但升级不方便,程序占用空间较大
三 makefile
使用动态库时,动态库的名字为xxx,前后的lib和.so需要省略
例如:gcc -fpic -shared func.c -o libfunc.so
链接动态库时,即使动态库在当前目录也需要加参数-L指定链接库目录
例如:gcc main.c -L. -lfunc
如果程序编译时链接了动态库,运行时也需要加载动态库,这里提供两种方法
第一,运行前输入命令export LD_LIBRARY_PATH=动态库所在目录
这种方法每次重启linux都需要重新导入
第二,将动态库放入系统默认的库目录/usr/lib
这种方法重启系统不需要重新导入,但会导致系统库目录越来越大
最好的解决方案是将用到的动态库放入系统配置文件,每次开机自动加载
动态库并不会打包到程序中,而是利用共享映射,多个程序共享同一个库文件
优点是节约内存,精简程序,便于程序升级,维护方便
2、静态库
静态库制作利用打包命令
ar rcs libtest.a a.o b.o
rcs是指参数-r -c -s,libxxx.a是表示静态库,库名为xxx
打包库时需要用汇编文件.o进行打包
链接库时,如果动态库静态局同名,默认优先链接动态库
如果要链接静态库,需要使用-static
如:gcc a.c -lfunc -static
使用以下命令可以指定某些库静态链接,某些库动态链接
-wl,-Bstatic -lfunc1 -wl,-Bdynamic -lfunc2
静态库会直接打包到程序中,优点是程序运行速度快,但升级不方便,程序占用空间较大
三 makefile
makefile为项目管理工具,通常为makefile或者Mikefile文件
makefile有三个要素:目标、依赖和命令
整个makefile只有一个终极目标,可以有多个子目标
当在命令行使用make xxx的时候,表示生成子目标,直接make生成终极目标
依赖表示目标需要依赖哪些文件来生成,命令表示具体生成的过程
可以使用变量
如果使用 := 那么立即赋值
如果使用 = 那么使用时才赋值
建议使用 := 不要使用=号
比如:target := libxxx.so 表示target这个变量就表示动态库libxxx.so
使用的时候需要$(target)
可以使用函数,也需要使用$
比如,查找所有.c文件
src:=(wildcard ./*.c) 或者
通过shell函数,去执行shell命令
srcs := $(shell ls *.c)
srcs := $(shell find -name "*.c")
再比如,把所有.c替换成.o
obj := $(patsubst ./%.c ,./%.o $(src)) 或者
objs := $(srcs:.c=.o)
makefile有三个要素:目标、依赖和命令
整个makefile只有一个终极目标,可以有多个子目标
当在命令行使用make xxx的时候,表示生成子目标,直接make生成终极目标
依赖表示目标需要依赖哪些文件来生成,命令表示具体生成的过程
可以使用变量
如果使用 := 那么立即赋值
如果使用 = 那么使用时才赋值
建议使用 := 不要使用=号
比如:target := libxxx.so 表示target这个变量就表示动态库libxxx.so
使用的时候需要$(target)
可以使用函数,也需要使用$
比如,查找所有.c文件
src:=(wildcard ./*.c) 或者
通过shell函数,去执行shell命令
srcs := $(shell ls *.c)
srcs := $(shell find -name "*.c")
再比如,把所有.c替换成.o
obj := $(patsubst ./%.c ,./%.o $(src)) 或者
objs := $(srcs:.c=.o)
gcc -MM命令可以查询.c文件所依赖的文件
通常可以通过引入.d文件来使得头文件加入依赖
比如,利用deps来使头文件加入依赖
deps := $(srcs:.c=.d) 具体使用看下面案例
-f 强制执行
.PHONY:clean声明伪目标
-rm -的作用是如果命令失败忽略 继续向下执行
可以通过include包含其他子makefile。
比如自己手写一个makefile规则def.mk,该文件包含生成的依赖所需条件
在主makefile中可以直接用include包含该文件,则规则被包含
include def.mk
使用-开头表示如果def.mk不存在,那么也继续执行
-include def.mk
通常可以通过引入.d文件来使得头文件加入依赖
比如,利用deps来使头文件加入依赖
deps := $(srcs:.c=.d) 具体使用看下面案例
-f 强制执行
.PHONY:clean声明伪目标
-rm -的作用是如果命令失败忽略 继续向下执行
可以通过include包含其他子makefile。
比如自己手写一个makefile规则def.mk,该文件包含生成的依赖所需条件
在主makefile中可以直接用include包含该文件,则规则被包含
include def.mk
使用-开头表示如果def.mk不存在,那么也继续执行
-include def.mk
可以包含子目录的makefile进行同时编译
make -C sub 执行子目录sub的makefile
内置变量
CC = g++(默认为gcc,可以手动赋值)
CPPFLAGS预编译时需要的参数,如- I
CFLAGS 编译时需要使用的参数 -Wall -g -cc即gcc
LDFLAGS 链接库使用的选项,如-L -l
make -C sub 执行子目录sub的makefile
内置变量
CC = g++(默认为gcc,可以手动赋值)
CPPFLAGS预编译时需要的参数,如- I
CFLAGS 编译时需要使用的参数 -Wall -g -cc即gcc
LDFLAGS 链接库使用的选项,如-L -l
环境变量可以用在Make中,但是不建议用
环境变量和本地变量名字相同时,本地变量覆盖环境变量
环境变量和本地变量名字相同时,本地变量覆盖环境变量
Make的自动变量
$^ 它表示所有的依赖
$@ 表示目标
$< 表示第一个依赖
$?是比Makefile更加新的文件,也就是最近修改文件
比如:
file_in_a = $(shell find a -type f)
Makefile: $(file_in_a)
cp $? b
touch Makefile
$^ 它表示所有的依赖
$@ 表示目标
$< 表示第一个依赖
$?是比Makefile更加新的文件,也就是最近修改文件
比如:
file_in_a = $(shell find a -type f)
Makefile: $(file_in_a)
cp $? b
touch Makefile
缺省规则
如果.o没有指定依赖,那么.o默认有一个依赖
%.o: %.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
默认的依赖可以被覆盖
如果.o没有指定依赖,那么.o默认有一个依赖
%.o: %.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
默认的依赖可以被覆盖
案例一:
target := libxxx.so
all: ${target}
-include $(deps)
target := libxxx.so
all: ${target}
-include $(deps)
%.d: %.c
gcc -MM $< > $@
$(target): ${objs}
$(CC) $^ -fpic -shared -o $@
clean:
rm *.o *.so *.d
install:
cp ${target} /usr/lib
uninstall:
rm /usr/lib/${target}
gcc -MM $< > $@
$(target): ${objs}
$(CC) $^ -fpic -shared -o $@
clean:
rm *.o *.so *.d
install:
cp ${target} /usr/lib
uninstall:
rm /usr/lib/${target}
test:
echo $(CC)
echo src file is: $(srcs)
案例二:
src = $(wildcard *.c)
obj = $(patsubst %.c, %.o, $(src))
soktfile = $(wildcard *.socket)
echo $(CC)
echo src file is: $(srcs)
案例二:
src = $(wildcard *.c)
obj = $(patsubst %.c, %.o, $(src))
soktfile = $(wildcard *.socket)
all: server client
server: server.o
gcc server.o -o server -Wall
client: client.o
gcc client.o -o client -Wall
gcc server.o -o server -Wall
client: client.o
gcc client.o -o client -Wall
%.o:%.c
gcc -c $< -Wall
gcc -c $< -Wall
.PHONY: clean all
clean:
-rm -rf server client $(obj) $(soktfile)
四 qmake
1 在需要编译的文件夹输入 qmake -project 会生成qmake-当前目录.pro
2 输入qmake 会自动生成Makefile文件
3 输入make 会自动生成qmake-当前目录文件 该文件就是可执行文件
五 cmake
1 安装cmake
Ubuntu系统,通过以下命令安装cmake
sudo apt-get install cmake
2 使用cmake需要编辑的是CMakeLists.txt文件
3 最简单的hello文件的实现
cd到当前目录,编辑CMakeLists.txt如下:
project(当前目录)
add_executable(hello.bin main.c)
//main.c为代码 hello.bin为生成的可执行程序名
随后退出CMakeLists.txt
创建一个build目录(非必须,但是惯例),用于保存中间文件与生成的程序
进入build,cmake ..
然后make,则可在当前目录(build)生成hello.bin
4 可以使用变量
通过set设置变量,通过${}取值
set(src main.c func1.c func2.c)
add_executable(HelloWorld.bin ${src})
5 可以使用函数
(1)搜索指定目录所有源码
aux_source_directory(搜索目录 存入的变量)
使用该函数前必须要加:cmake_minimum_required(VERSION 3.7)
aux_source_directory(. src)
aux_source_directory(./sub src) //搜索子目录
clean:
-rm -rf server client $(obj) $(soktfile)
四 qmake
1 在需要编译的文件夹输入 qmake -project 会生成qmake-当前目录.pro
2 输入qmake 会自动生成Makefile文件
3 输入make 会自动生成qmake-当前目录文件 该文件就是可执行文件
五 cmake
1 安装cmake
Ubuntu系统,通过以下命令安装cmake
sudo apt-get install cmake
2 使用cmake需要编辑的是CMakeLists.txt文件
3 最简单的hello文件的实现
cd到当前目录,编辑CMakeLists.txt如下:
project(当前目录)
add_executable(hello.bin main.c)
//main.c为代码 hello.bin为生成的可执行程序名
随后退出CMakeLists.txt
创建一个build目录(非必须,但是惯例),用于保存中间文件与生成的程序
进入build,cmake ..
然后make,则可在当前目录(build)生成hello.bin
4 可以使用变量
通过set设置变量,通过${}取值
set(src main.c func1.c func2.c)
add_executable(HelloWorld.bin ${src})
5 可以使用函数
(1)搜索指定目录所有源码
aux_source_directory(搜索目录 存入的变量)
使用该函数前必须要加:cmake_minimum_required(VERSION 3.7)
aux_source_directory(. src)
aux_source_directory(./sub src) //搜索子目录
(2)链接动态库
target_link_libraries(可执行程序名) //可执行程序名可以使用变量
需要放在该语句之后add_executable
(3)包含头文件
include_directories(头文件目录1 头文件目录2 头文件目录3 ...)
//也可以多次include
(4)设置库目录
link_directories()同上
target_link_libraries(可执行程序名) //可执行程序名可以使用变量
需要放在该语句之后add_executable
(3)包含头文件
include_directories(头文件目录1 头文件目录2 头文件目录3 ...)
//也可以多次include
(4)设置库目录
link_directories()同上
6 编译库文件
不适用add_executable而使用add_library()和set_target_properties
add_library(${target} SHARED ${srcs})
add_library(hello_a STATIC ${srcs}) //若不加中间参数,默认生成静态库
//只需指定编译的库名xxx,程序会自动生成libxxx.so或者libxxx.a
不适用add_executable而使用add_library()和set_target_properties
add_library(${target} SHARED ${srcs})
add_library(hello_a STATIC ${srcs}) //若不加中间参数,默认生成静态库
//只需指定编译的库名xxx,程序会自动生成libxxx.so或者libxxx.a
7 定义宏
add_definitions(-A -B ...)
通常在源代码添加ifdefine来灵活使用宏
8 编译选项
支持CFLAGS,CXXFLAGS
9 进阶
http://blog.chinaunix.net/uid-24512513-id-3196376.html
add_definitions(-A -B ...)
通常在源代码添加ifdefine来灵活使用宏
8 编译选项
支持CFLAGS,CXXFLAGS
9 进阶
http://blog.chinaunix.net/uid-24512513-id-3196376.html