本文目的旨在介绍fvcom编译的全过程,顺便介绍linux中make命令的文件写法和一般的编程过程简述一下。

1.编程过程

编程,一般就是编写可执行程序过程。这个过程主要是源文件生成中间代码文件,再到可执行文件的两步过程:

1.1.源文件

即我们编写好的源程序,为文本文件。这代表着写文件时候可以非常随意,我们可以直接打开一个txt文件,然后直接编写程序,编写好的源程序(文件后缀改成相应源程序后缀即可)与用编程IDE软件写好的程序无异。我们习惯用IDE的原因,只不过是可以用些现成弹出来的代码段,或者是关键字提示这些特殊功能而已。也就是说,IDE是个比较人性化的文本编辑器。

1.2.中间代码文件

写好源程序后,编译器首先将源文件进行编译。

这个过程只是对源文件是否有语法错误,函数及变量是否声明正确进行判断。源程序全部正确的话,就把它专为机器码的二进制文件,linux中文件后缀为".o"。

1.3.可执行文件

全部的源程序转为".o"文件后,编译器将中间代码全部链接起来,生成可执行文件。

链接过程是链接函数和全局变量,错误时提示为链接错误(Linker Error),在VC下,这种错误一般是:Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的Object File。

2.linux的make命令

window系统下有很多IDE直接为你做了编译、链接的工作,在linux中,make命令也是用来干这种活的。

对于一个大型工程项目,需要编译的文件不计其数,而且可能需要哪些文件需要
先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,make命令带来的好处就是——"自动化编译",一旦写好,只需要一个命令,整个工程完全自动编译,极大的提高了软件开发的效率。

2.1.makefile原则

make命令执行时,需要一个 Makefile 文件,以告诉make命令需要怎么样的去编译和链接。我们用三个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册,在这个示例中,我们的工程有2个C文件,和1个头文件,我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的目的是:

  1. 如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
  2. 如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。

  3. 如果这个工程的头文件被改变了,那么我们需要编译引用了这个头文件的所有C文件,并链接目标程序。

2.2.显式规则

我们再来看下makefile文件的显式规则:

target ... : prerequisites ...
command
......
  • target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label)。
  • prerequisites就是,要生成那个target所需要的文件或是目标。
  • command也就是make需要执行的命令。(任意的Shell命令)

这是一个文件的依赖关系,也就是说:target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是 Makefile的规则。也就是Makefile中最核心的内容。

例一:

#helloworld依赖file1.o、file2.o文件
#链接生成helloworld可执行文件
helloworld: file1.o file2.o
gcc file1.o file2.o -o helloworld #file1.o文件依赖file1.c、file1.h文件
#编译生成file1.o中间代码文件
file1.o: file1.c file1.h
gcc –c file1.c -o file1.o #file2.o文件依赖file2.c、file1.h文件
#编译生成file2.o中间代码文件
file2.0: file2.c file1.h
gcc -c file2.c -o file2.o

文件的执行过程如下:

首先识别出helloworld是首个目标文件,依赖file1.o file2.o两个中间代码文件;然后查看file1.o file2.o,寻找它们为target的两栏:查看file1.o,file2.o所依赖的文件,若其中任何一个新于target,则执行下面command那行命令,对应的target重新编译;最后,若file1.o file2.o其中任何一个新于helloworld,则执行helloworld下面的command命令,重新连接生成helloworld文件。

其实整个文件真正的target只有helloworld一个,假如目录中file1.o和file2.0都存在,且并不新于target,那么什么也不会执行。(真的么?)

例二:进阶:使用变量

OBJS = file1.o file2.o          这里OBJS是字符变量
CC = gcc CC、CFLAGS同理
CFLAGS = -Wall –O –g
helloworld : $(OBJS) $(OBJS)代表取出变量OBJS的内容,即file1.o file2.o
$(CC) $(OBJS) -o helloworld $(CC)、$(CFLAGS)同理
file1.o : file1.c file1.h
$(CC) $( CFLAGS) -c file1.c -o file1.o
file2.o : file2.c file1.h
$(CC) $( CFLAGS) -c file2.c -o file2.o

其实,我们将变量内容展开后,和例一中makefile文件内容无异。

前面生成文件的方法为依赖原则,即目标文件依赖某些文件,然后再根据这些依赖文件,依次生成目标文件。

还有一个规则是隐含规则,其中的后缀规则重点介绍下。

"隐含规则"也就是一种惯例,make会按照这种"惯例"心照不喧地来运行,那怕我们的Makefile中没有书写这样的规则。例如,把[.c]文件编译成[.o]文件这一规则,你根本就不用写出来,make会自动推导出这种规则,并生成我们需要的[.o]文件。

"隐含规则"又有"模式规则"和"后缀规则"两种,使用 "后缀规则"可以有效的保证我们Makefile的兼容性。

2.3.后缀规则

后缀规则:目标文件的后缀和依赖目标的后缀

若需要把所有的后缀为".c"的文件编译成中间代码".o"文件,命令格式为:

.c.o:
$(CC) -c $(CFLAGS) $(INCS) $*.c

第一行类似我们的依赖规则,相当于 : %o:%c.
(这里 % 代表任意个数的字符,%.c即所有的.c文件;%.o 的表示把所有后缀为.c文件名(%),后缀加上.o,作为生成的中间代码文件名。)

那么去除 % 后含义就是:

name1.o : name1.c
$(CC) -c $(CFLAGS) $(INCS) $ name1.c name2.o : name2.c
$(CC) -c $(CFLAGS) $(INCS) $ name2.c
name3.o : name3.c
$(CC) -c $(CFLAGS) $(INCS) $ name3.c
……
……

这里command行里 *.c 就代表后缀为 .c 的依赖文件

隐含规则的妙处就是,仅需短短两行;代替了大片的重复命令。

还有一个问题,那就是make命令不能识别所有种类的后缀,仅能识别其中一部分。令它识别一种特定后缀时候,我们需要修改.SUFFIXES变量的值:

.SUFFIXES = .o .f90 .F .F90

.SUFFIXES是makefile中一种特殊变量(所以是以"."开头的),专门储存可以识别的特定后缀种类。

3.fvcom的makefile

经过前两部分的铺垫,终于讲到中心了:我们的fvcom是怎样编译的?

下面贴出fvcom的makefile内容。(这应该没有什么侵权问题吧,喂?)

FVCOM编译过程详解的更多相关文章

  1. Android编译过程详解(一)

    Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...

  2. cegui-0.8.2编译过程详解

    cegui 编译过程详解(cegui-0.8.2) cegui配置整了好长时间了,在一位大牛帮助下终于搞定了,网上的教程大多是老版本的,cegui-0.8.2版的配置寥寥无几,现在总结一下,献给正在纠 ...

  3. GCC 概述:C 语言编译过程详解

    Tags: C Description: 关于 GCC 的个人笔记 GCC 概述 对于 GCC 6.1 以及之后的版本,默认使用的 C++ 标准是 C++ 14:使用 -std=c++11 来指定使用 ...

  4. uboot主Makefile分析(t配置和编译过程详解)

    1.编译uboot前需要三次make make distcleanmake x210_sd_configmake -j4 make distclean为清楚dist文件. make x210_sd_c ...

  5. uboot配置和编译过程详解【转】

    本文转载自:http://blog.csdn.net/czg13548930186/article/details/53434566 uboot主Makefile分析1 1.uboot version ...

  6. uboot配置和编译过程详解

    根据朱有鹏老师讲解整理 一.uboot主Makefile分析 1.uboot version确定(Makefile的24-29行) include/version_autogenerated.h文件是 ...

  7. C语言编译过程详解

    前言 C语言程序从源代码到二进制行程序都经历了那些过程?本文以Linux下C语言的编译过程为例,讲解C语言程序的编译过程. 编写hello world C程序: // hello.c #include ...

  8. Android编译过程详解(三)

    前面两节讲解了自定义Android编译项和创建Product产品配置文件,除了编译和定义产品相关环境变量外,还需要定义Board相关环境变量. 1. build/core/config.mk 109 ...

  9. gcc 编译过程详解-(转自CarpenterLee)

    前言 C语言程序从源代码到二进制行程序都经历了那些过程?本文以Linux下C语言的编译过程为例,讲解C语言程序的编译过程. 编写hello world C程序: // hello.c #include ...

随机推荐

  1. BUAA SE | 提问回顾与个人总结

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 提问回顾与个人总结 我在这个课程的目标是 深入理解软件工程 这个作业在哪个具体方面帮助我实现目标 ...

  2. Noip模拟46 2021.8.23

    给了签到题,但除了签到题其他的什么也不会.... T1 数数 人均$AC$,没什么好说的,就是排个序,然后双指针交换着往中间移 1 #include<bits/stdc++.h> 2 #d ...

  3. ST表 ----kzsn考挂后有感

    ST表,一个十分神奇的东西,需要O(nlogn)的时间预处理,但是他查询只需要O(1). 看似与线段树等数据结构时间复杂度一样,但是ST表的复杂度只在于预处理,预处理之后可以当做不耗时! 而想线段树这 ...

  4. linux安装后ping不通局域网其他主机的解决方式

    安装了linux后尝试进行机器间的相互通讯,发现自己虚拟机并不能查看ip地址,也不能够ping通任何一台局域网内的主机 上网查了一下发现是网卡并没有打开,需要进行如下配置 查看ls 一下/etc/sy ...

  5. 好的编程习惯是减少bug最有效的方法

    公司来了几个新手,有时候很简单的一个功能模块都要耗费好几天时间,总是在一些不相关的问题上死耗一整天,搞出莫名其妙的问题,找不到具体原因,总是怀疑编译出问题了,系统出问题了,板子出问题了,搞到快下班了叫 ...

  6. POJ 2536 Gopher II(二分图最大匹配)

    题意: N只地鼠M个洞,每只地鼠.每个洞都有一个坐标. 每只地鼠速度一样,对于每只地鼠而言,如果它跑到某一个洞的所花的时间小于等于S,它才不会被老鹰吃掉. 规定每个洞最多只能藏一只地鼠. 问最少有多少 ...

  7. Python——Excel转Json工具

    Python工具Excel转Json 前置条件 1.安装python 下载python 我下载的是2.7: 2.配置环境变量 我的电脑右键--属性--高级系统设置--环境变量: 添加python的安装 ...

  8. shell脚本 PHP+swoole的安装

    #!bin/bash set -e # Check if user is root if [ $(id -u) != "0" ]; then echo "Error: p ...

  9. QuantumTunnel:协议路由 vs 端口路由

    本篇来聊一下内网穿透中流量转发的问题 内网穿透和核心逻辑是根据流量的路由信息准确地将公网流量路由到指定的机器端口上,从而完成一次流量的内网穿透. 这里有一个核心问题,路由信息从哪里获取? 常见的有将路 ...

  10. 攻防世界 Misc 新手练习区 如来十三掌 Writeup

    攻防世界 Misc 新手练习区 如来十三掌 Writeup 题目介绍 题目考点 佛曰加密.base64.Rot13等加密方法的了解 Writeup 下载并打开附件 联想到佛曰加密,复制内容到 佛曰加密 ...