Linux代码运行详解

程序执行的过程

检查程序的语法错误

预处理

进行简单的替换。

//程序名称:test.cpp
#include
#define hello "六六六"
int main(){
    std::cout<

此命令将 test.cpp文件进行预编译,编译的结果放在了test.txt文件中。

如果没有 ">test.txt" 命令,则预编译的结果会直接打印在屏幕上。

编译 

linux中默认生成.o文件;windows中生成.exe文件。 

 链接

把多个目标文件链接成可执行文件

//程序名称:main.c
#include 
#include "add.h"
#include "sub.h"

int main(){
	int a,b;
	printf("请输入a和b:");
	scanf("%d%d",&a,&b);
	
	printf("%d + %d = %d\n",a,b,add(a,b));
	printf("%d - %d = %d\n",a,b,sub(a,b));
	
	return 0;
}
//程序名称:add.h
int add(int,int);
//程序名称:add.c
int add(int a,int b){
    return a+b;
}
//程序名称:sub.h
int sub(int,int);
//程序名称:sub.c
int sub(int a,int b){
    return a-b;
}

 Linux代码运行详解_第1张图片

 Linux代码运行详解_第2张图片

gcc *.o -o test.exe
//将所有.o文件链接为一个.exe文件

 制作makefile文件

/*
目的:依赖
    通过依赖生成目的的语句
*/
demo.exe:main.o add.o sub.o                #顶头书写;要生成的文件:依赖的文件
    gcc main.o add.o sub.o -o demo.exe     #空一个tab键的位置(不能是空格);书写编译语言
main.o:main.c
    gcc -c main.c -o main.o
add.o:add.c
    gcc -c add.c -o add.o
sub.o:sub.c
    gcc -c sub.c -o sub.o
clean:
    rm -f *.o *exe                         #删除所有.o和.exe文件

Linux代码运行详解_第3张图片

Linux代码运行详解_第4张图片

 Linux代码运行详解_第5张图片

#将以上的makefile文件进行优化
/*
$@————代表“目的”
* ————代表任意个任意字符
*/
demo.exe:main.o add.o sub.o             
    gcc *.o -o $@     
%.o:%.c                        #这两句按照第一行main.o add.o sub.o的顺序依次执行
    gcc -c %< -o $@            #更改时,只用更改main.o add.o sub.o这部分依赖的顺序就可以了
clean:
    rm -f *.o *exe                  

 Linux代码运行详解_第6张图片

制作CMakeLists.txt文件

是一个高级编译配置工具。当多个人使用不同的编程语言开发同一个项目时就要用到CMake命令,最终输出一个可执行文件或者共享库(dll,so等)。

所有操作都是通过遍历CMakeList.txt来完成的。官网,各个版本的下载地址

(PS:建议直接安装最新版本,删除旧版本很费劲。推荐一个安装方案,我卸载的最后一步是which cmake查找路径后删除)

在Linux上安装cmake的命令(需要用root权限执行) 

用CMake写一个helloworld

步骤1:写一个helloworld程序

//程序名称:main.cpp
#include 
int main(){
    std::cout<<"helloworld"<

步骤2:写CMakeLists.txt 

//文件名称:CMakeLists.txt,必须严格区分大小写,且名称只能是这个
PROJECT (HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "This is BINARY dir" ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir" ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})

步骤3:执行CMakeLists.txt文件

当CMakeLists.txt文件存放在当前路径时,使用cmake . 命令(cmake .. 命令表示CMakeList.txt文件存放在上一级目录中),表示执行当前路径的CMakeLists.txt文件,执行结束后,生成一个Makefile文件,用make执行该命令即可

语法介绍

PROJECT关键字

指定工程名字和支持的语言(语言用大写),默认支持所有语言。

PROJECT (HELLO C CXX JAVA)支持C,C++,Java

源代码的组织(多文档编译)

我们通常把公用的自定义函数和类从主程序中分离出来,函数和类的声明在头文件中,定义在程序文件中,主程序中要包含头文件,编译时要和程序文件一起编译。

//程序名:public.h,公共功能函数声明的头文件,用于测试静态和动态链接
#ifndef PUBLIC_H
#define PUBLIC_H 1
 
#include 
 
void func();   // 自定义函数的声明
 
#endif
//程序名:public.cpp,公共功能函数定义的程序文件,用于测试静态和动态链接
#include "public.h"  // 包含自定义函数声明的头文件
 
void func()   // 自定义函数的实现
{
  printf("我心匪石,不可转也。我心匪席,不可卷也。威仪棣棣,不可选也。\n");
  //printf("生活美好如鲜花,不懂享受是傻瓜;\n");
  //printf("傻呀傻呀傻呀傻,比不上小鸟和乌鸦。\n");
  //printf("芳草地啊美如画,谁要不去是傻瓜;\n");
  //printf("我是一只傻傻鸟,独在枯枝丫上趴。\n");
}
//程序名:book265.cpp,此程序用于测试静态和动态链接
#include "public.h"  // 把public.h头文件包含进来
 
int main()
{
  func();
}

 公用函数库的程序文件public.cpp程序文件是源代码,对任何程序员是可见的,没有安全性可言。

把公共的程序文件编译成库文件,库文件是一种可执行代码的二进制形式,可以与其它的源程序一起编译,也可以被操作系统载入内存执行。

静态库

主程序文件与静态库一起编译,把主程序与主程序中用到的库函数一起整合进了目标文件。

优点:

在编译后的可执行程序可以独立运行——删去.a文件,则可执行程序正常运行

不需要像动态库那样有动态加载和识别函数地址的开销,也就是说采用静态链接编译的可执行程序运行更快

缺点:

1)静态链接生成的可执行程序比动态链接生成的大很多,运行时占用的内存也更多。

2)库文件的更新不会反映到可执行程序中,可执行程序需要重新编译。

静态库命名方式:“libxxx.a”,库名前加”lib”,后缀用”.a”,“xxx”为静态库名

把程序文件public.cpp编译成静态库的指令(自动生成libpublic.a文件;没有public.h文件,则该命令报错)

方法一:直接把调用者源代码和静态库文件名一起编译

方法二:采用L参数指定静态库文件的目录,-l参数指定静态库名

注意事项:

1、指定多个静态库文件的目录:“-L/目录1 -L目录2 -L目录3”

2、链接库的文件名是libpublic.a,但链接库名是”public”

3、指定多个静态库,用法是“-l库名1 -l库名2 -l库名3”

动态库 

动态库在程序运行时才被载入,因此在程序运行时还需要指定动态库的目录。

优点:

1)相对于静态库,动态库在时候更新(修复bug,增加新的功能)不需要重新编译。

2)全部的可执行程序共享动态库的代码,运行时占用的内存空间更少。

缺点:

1)使可执行程序在不同平台上移植变得更复杂,因为它需要为每每个不同的平台提供相应平台的共享库——删去.so文件,则可执行程序报错

2)增加可执行程序运行时的时间和空间开销,因为应用程序需要在运行过程中查找依赖的库函数,并加载到内存中。

动态库的命名方式:“libxxx.so”,库名前加“lib”,后缀变为“.so” “xxx”为动态库名。

把程序文件public.cpp编译成动态库的指令(自动生成libpublic.so文件;没有public.h文件,则该命令报错)

 如果在动态库文件和静态库文件同时存在,优先使用动态库编译。除非用-static参数指定链接静态库。

 

 动态函数库并没有整合进程序,所以程序的运行环境必须提供动态库路径。Linux系统中采用LD_LIBRARY_PATH环境变量指定动态库文件的目录,设置命令如下:

 注意事项:

指定多个动态库文件的目录:“export LD_LIBRARY_PATH=目录1:目录2:目录3:.”,目录之间用半角的冒号分隔,最后的圆点指当前目录

Linux代码运行详解_第7张图片

你可能感兴趣的:(linux,linux,运维,服务器)