如何在linux下编译C/C++

169 阅读3分钟

本文已参与 \lceil新人创作礼\rfloor 活动,一起开启掘金创作之路

最近这段时间有接触到在linux下编译C++代码,生成动态链接库。其实之前在学校搞物联网竞赛做嵌入式的时候也有玩过,只不过现在都忘得差不多了,今天就来总结下如何在linux环境下编译C/C++代码吧,以及如何生成动态链接库。(PS:C/C++的速度是Python和perl所无法比拟的)

首先准备C/C++编译环境

# yum install gcc gcc-c++ -y    //gcc和g++都是GNU组织的一个编译器。

image.png

编译C代码步骤

1、准备C文件:

# vim hellworld.c
#include<stdio.h>
int main()
{
    printf("hello world\n");
    return 0;
}

第一句是包含头文件,头文件以.h结尾,stdio 指的是 "standard input & output",下面是一个main函数,返回int类型。该函数输出了helloword字符串,最后返回值是0,C语言的每一句都需要以;结尾

2、编译

标准的三步骤:


//预编译,生成已编译通过的C原始程序 *.i

# gcc -E helloworld.c -o helloworld.i

//编译,生成汇编语言原始程序 *.s

# gcc -S helloworld.i -o helloworld.s

//链接,生成可执行程序

# gcc -o helloworld helloworld.s

image.png

如果不想看到中间过程可以一步完成:

# gcc -o helloworld helloworld.c

gcc常用参数:

-E  激活预处理

-S  把文件编译成为汇编代码

-o  指定目标文件名

3、运行

# ./helloworld

image.png

编译C++代码步骤

1、准备C++文件:

# vim hellothread.cpp

image.png

2、编译

# g++ hellothread.cpp -lpthread -o hellothread

g++常用参数: -l   指定所使用到的函数库 -L  指定函数库所在的文件夹 -I   指定头文件所在的文件夹 -o  输出的可执行文件的文件名

3、运行

# ./hellothread  //创建5个线程,输出“Hello Wuxi”

image.png

关于静态库和动态库

linux系统下的静态函数库的后缀是.a,动态库是.so。静态库和动态库的区别是:

  • 静态库由一系列的.o文件组成,在链接过程中,这些.o文件与主要的目标文件一起生成目标文件,生成之后就不需要这些.o文件了;

  • 动态库在链接过程中并没有用到具体函数使用,它是在程序的运行过程中才动态的调用。正如windows系统中,我们看到需要的.exe文件夹中,包含了各式各样的.dll文件(windows下的动态库),当然所需要的.dll文件也有一部分在系统的默认路径下。

实战:在ARM平台下将C++代码编译成动态链接库:

# g++ -I"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.aarch64/include" -I"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.aarch64/include/linux" -fPIC -shared -o YUtils.so YUtils.cpp\

注意这里的几个参数: -I            指定搜索头文件的路径,这里有用到java相关的头文件jni.h,所以需要指定java搜索路径路径,否则可能找不到相关头文件。(JNI即Java Native Interface,Java本地接口,是一个协议,主要作用为:实现Java调用c/c++代码(类库),或者C/C++调用Java代码) -shared   此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库 -fPIC       作用于编译阶段,告诉编译器产生与位置无关代码,产生的代码中没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

好了,今天的分享就到这里了,希望对大家有所帮助,我们下期再见~~