Linux下的CC++混合编译
Linux下的C/C++开发基础(编写makefile、编译C/C++、链接、可执⾏程序)
本⽂重点介绍C/C++源码⼯程的编译链接,编译器gcc/g++的安装配置略过...
1. 安装配置gcc g++
2. 创建⽂件 test.h /test.c / file.h  / file.cpp
3. 编译.o库: gcc -c / g++ -c
链接⽣成静态库.a库: ar -r
链接⽣成动态库.soK库:gcc -shared -o/ g++ -shared -o
编译可执⾏程序并链接.a或.so 库 g++ -o file file.cpp -L. -ltest / gcc -o test test.c -L. -lfile
运⾏可执⾏程序 ./file  / ./test
note:l指定库名称,优先链接so动态库,没有动态库再链接.a静态库;
如果链接的是静态库就可以直接运⾏了,如果链接的是动态库可能会提⽰:./cppmain: error while loading shared libraries: libCAdd.so: cannot open shared object file: No such file or directory,是因为Linux系统程序和Windows不⼀样,Linux系统只会从系统环境变量指定的路径加载动态库,可以把⽣成的动态库放到系统⽬录,或者执⾏export LD_LIBRARY_PATH=./设置当前路径为系统链接库⽬录就可以了。
3.1 编译 C调C++库
a. 编译C++ .o 库:                g++ -c file.cpp
b. 链接⽣成静态 .a库:            ar -r libfile.a file.o
c. 编译C⽂件并链接 .a库⽣成可执⾏程序:    gcc -o test test.c -L. -llibfile
d. 运⾏可执⾏程序:                ./test
3.2 编译C++调C库
a. 编译C .o库:                gcc -c test.c
b. 链接⽣成静态.a 库:            ar -r libtest.a test.o
c. 编译C++⽂件并链接.a 库⽣成可执⾏程序:    g++ file file.cpp -L. -llibtest
d. 运⾏可执⾏程序:                ./file
4. 查看符号表:
$ nm test.o
0000000000000000 T test
$ nm test1.o
0000000000000000 T _Z4testiPc
C语⾔编译后的函数符号还是原函数名,⽽C++编译后的函数符号由test变成了_Z4testiPc,test前⾯有个数字4应该是函数名长度,test 后⾯i Pc应该就是函数的参数签名。C++之所以这样规定编译后的函数符号是因为对⾯对象的C++具有函数重载功能,以此来区分不同的函数。
5. linux下的.o .a .so
.o,是⽬标⽂件,相当于windows中的.obj⽂件
.a为静态库,是好多个.o合在⼀起,⽤于静态连接
.so 为共享库,是shared object,⽤于动态连接的,相当于windows下的dll
程序的运⾏都要经过编译和链接两个步骤。假如⽂件test.c,使⽤命令gcc -c test.c进⾏编译,⽣成test.o中间⽂件,使⽤命令ar -r libtest.a test.o可以⽣成libadd.a静态库⽂件。静态库⽂件其实就是对.o中间⽂件进⾏的封装,使⽤nm libtest.a命令可以查看其中封装的中间⽂件以及函数符号。
链接静态库就是链接静态库中的.o⽂件,这和直接编译多个⽂件再链接成可执⾏⽂件⼀样。
动态链接库是程序执⾏的时候直接调⽤的“插件”,使⽤命令gcc -shared -o libtest.so test.c⽣成so动态库。
动态库链接的时候可以像静态库⼀样链接,告诉编译器函数的定义在这个静态库中(避免不到函数定义的错误),只是不把这个so打包到可执⾏⽂件中。如果没有头⽂件的话,可以使⽤dlopen/dlsum函数⼿动去加载相应的动态库
6.linux下的Makefile编写:
makefile phony
6.1 纯C或纯C++⽂件:
test: test.o test1.o test2.o
gcc test.o test1.o test2.o -o libtest  #-o链接成可执⾏程序
test.o: test.c
gcc -c test.c -o test.o  #加-c 指定⽣成为可重链接.o⽂件
test1.o: test1.c
gcc -c test1.c -o test1.o
test2.o: test2.c
gcc -c test2.c -o test2.o
.PHONY:clean
clean:
-rm -rf *.o libtest
每个命令⾏前必须要有tab符号(如Makefile中书写⽅法);
上⾯的Makefile⽂件就是要编译出⼀个libtest的可执⾏⽂件;
test:test.o test1.o test2.o :test依赖于test.o test1.o、test2.o三个⽬标⽂件;
gcc test.o test1.o test2.o -o libtest:编译出可执⾏⽂件libtest, -o表⽰指定可执⾏⽂件的名称;
test.o: test.c: test.o 依赖于 test.c ⽂件;
gcc -c test.c -o test.o 编译出test.o⽂件,-c表⽰只把给它的⽂件编译成⽬标⽂件,⽤源码⽂件的⽂件名命名,但把其后缀由“.c”变成“.o”;也可以省略 -o test.o ,编译器默认⽣成test.o
clean:
rm -rf *.o firstTest:当键⼊make clean的时候,会删除所有.o⽂件和libtest⽂件
如果要编译c++⽂件,把gcc改成g++即可。如果⼀⾏写的内容过多,可以⽤“\”来分解多⾏,注意“\”后⾯不加空格.
6.2 C/C++混合编译:
CC = gcc
C++ = g++
LINK = g++
#LIBS = -lz -lm -lpcre(#如果还要链接其他库如libz、libm、libpcre等,加上这句)
#must add -fPIC option
CCFLAGS = $(COMPILER_FLAGS) -c -g -fPIC
C++FLAGS = $(COMPILER_FLAGS) -c -g -fPIC
TARGET=libtestmain
INCLUDES = -I. -I../../
C++FILES = testmain.cpp
CFILES = test.c test1.c test2.c
OBJFILE = $(CFILES:.c=.o) $(C++FILES:.cpp=.o)
all:$(TARGET)
$(TARGET): $(OBJFILE)
$(LINK) $^ $(LIBS) -Wall -fPIC (编so加 -shared)-o $@
%.o:%.c
$(CC) -o $@ $(CCFLAGS) $< $(INCLUDES)
%.o:%.cpp
$(C++) -o $@ $(C++FLAGS) $< $(INCLUDES)
install:
tsxs -i -o $(TARGET)
clean:
rm -rf $(TARGET)
rm -rf $(OBJFILE)
上⾯的Makefile是实现编译C⽂件编译成.o,然后⼀起连接到cpp编译的.o(或.so)上编译出可执⾏⽂件;
note:
a.如果LIBS的位置放置不对,这⼏个基础库将不会编进so中。LIBS只应该在最后链接为so时才调⽤,前⾯编译c和cpp⽂件时⽤不到。
b.c源⽂件放到CFILES宏后⾯, cpp⽂件放到C++Files宏后⾯,第三⽅库放到LIBS宏后⾯,头⽂件的包含路径放到INCLUDES后⾯,库⽂件的包含路径放到使⽤-L./等表达式放到LIBS中的开头即可。
c.这⾥严格区分c和cpp⽂件的⽬的是,c⽂件使⽤gcc编译,⽽cpp⽂件会使⽤g++编译,它们必须严格区分开。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。