Linux的基础命令的介绍使用

文章目录:

                一、ls命令    查看文件信息

                二、cd命令    切换路径

                三、clear 命令

                四、pwd 命令 

                五、目录文件和普通文件的创建和删除命令

                六、*模糊匹配

                七、man 命令

                八、cp 命令

                九、mv命令

                十、wc命令

                十一、 查看文本文件内容命令

                十二、gcc 的安装及命令

                十三、gdb 调试及命令

                十四、makefile 文件

                十五、find 和  grep 命令

                十六、关机和重启命令

                十七、文件的解压缩

俗话说Linux一切皆文件,所以对于Linux系统的学习,命令操作是必不可少的。

一、ls命令    查看文件信息

1.1 ls 命令

查看当前路径下的所有非隐藏文件

1.2 ls -l 命令

查看当前路径下的所有非隐藏文件的详细信息,如权限,创建日期,大小等

1.3 ls -a 命令

查看当前路径下的所有包括隐藏文件的文件

1.4 ls -i  命令 

查看当前路径下的所有非隐藏文件的inode节点号

1.5 ls + 路径 

查看指定路径下所有非隐藏文件

 二、cd命令    切换路径

对于路径分为相对路径和绝对路径

相对路径:由于是相对的,所以必须有一个基准作为参照物来说明,./ 基准所在的当前目录。如下图中的mybin/cc就是相对路径,其基准为 ./ 。

 绝对路径:就是完全路径,对于Linux系统,所有路径的绝对路径都以根目录(/)为起点

2.1 cd  +  路径

切换到该路径下

 对于cd命令,其后面可以是相对路径也可以是绝对路径

特殊的,对于ls -a展示的文件中有  .   和   ..   ,也是两个路径,分别是当前路径和上层路径。以及,对于家目录可以使用  ~  符号。/ home / dy  和  ~  代表相同路径即家目录。

 

 三、clear 命令

用于清屏,也可使用快捷键 ctrl+l

四、pwd 命令 

查看当前路径的绝对路径

 五、目录文件和普通文件的创建和删除命令

5.1目录文件的创建

mkdir  目录文件名        在当前路径下创建一个目录文件

可以批量创建,如:

mkdir   dir1  dir2  dir3  ...

  

5.2目录文件的删除 

rmdir  目录文件名        删除当前路径下的该目录文件(目录文件为空才可以删除,非空则不能删除)

可以批量删除,如:

rmdir   dir1  dir2  dir3  ...

 

5.3普通文件的创建 

touch   普通文件名           在当前路径下创建一个普通文件

可以批量创建,如:

touch   a.c  b.c  c.c  ...

5.4普通文件的删除 

rm   普通文件名          删除当前路径下的该普通文件

可以批量删除,如:

rm   a.c  b.c  c.c  ...

 5.5强制删除普通文件或者目录文件

rm  -r   文件名       强制删除文件(目录文件是否为空都可以删除)

rm  -rf   文件名      不展示提示(警告)信息,强制删除文件(目录文件是否为空都可以删除)

5.6上述操作中的文件名均可以加上指定路径进行相同操作

rmdir    rm   touch   rm -r   rm -rf  都可以如上述操作 

*Linux系统不同于Windows系统不存在回收站,文件删除后无法恢复,所以删除需谨慎*

六、*模糊匹配

rm *.c                         ->    删除当前目录下的以.c结尾的所有普通文件

rm    *                         ->    删除当前目录下的所有普通文件

rmdir dir*                   ->    删除当前目录下的以 dir 开头的所有目录文件

rmdir    *                    ->     删除当前目录下的所有目录文件

rm -r *.c 或者 dir *     ->     强制删除当前目录下的以 .c 结尾或者以 dir 开头的的所有文件

rm  -r   *                     ->     强制删除当前目录下的所有普通文件

七、man 命令

查看帮助手册

man    数字   内容

数字对应的内容类型:

1 —> 命令

2 —>系统调用函数

3 —>库函数

 回车后会出现如下界面:

 使用上下键进行翻页,按q键退出

数字的作用是,有些函数和命令的名字相同,如chmod既是系统调用又是命令,所以数字就可以进行区分要查的是命令还是系统调用

八、cp 命令

8.1 cp  a.c   b.c  命令

用于拷贝普通文件

cp   a.c  b.c   将a.c文件中的内容拷贝到b.c文件中(a.c文件必须存在,b.c文件可以不存在,若不存在,则该命令会创建一个b.c普通文件,再进行拷贝)

 8.2 cp  -r  dir1  dir2

用于拷贝目录文件

cp   dir1   dir2    将dir1文件中的内容拷贝到dir2文件中(dir1文件必须存在,dir2文件可以不存在,若不存在,则该命令会创建一个dir2目录文件,再进行拷贝)

 上述拷贝操作中可以在文件名前加上路径,两个文件可以是不同路径,当为不同路径时,文件的名字也可以相同。

九、mv命令

mv 命令有两种作用:重命名  和  文件移动(剪切)

 9.1 重命名

mv   文件名1   文件名2      文件名1和文件名2要在相同的路径下才会进行重命名,若在不同路径下,则会变成文件移动

9.2 文件移动(剪切)

mv   路径1+文件名   路径2        路径1和路径2不相同才能进行剪切,否则会变成重命名

 十、wc命令

用来统计文件内容的个数

10.1 wc  文件名

数字的含义从左往右依次为 行数 单词个数 总共占字节数(包含 \n 字符)

10.2 wc 文件名1 文件名2 ...

10.3 wc -l 文件名 统计行数

10.4 wc -w 文件名 统计单词个数

 

10.5 wc -c 文件名 统计字符个数

 十一、 查看文本文件内容命令

11.1 cat 命令

适用于内容少的文件

11.1.1查看文件

cat 文件名

11.1.2重定向(删除原内容,进行覆盖)

cat > 文件名

ctrl + d 退出编辑

11.1.3追加(不删除原内容,进行追加)

cat >> 文件名

ctrl + d 退出编辑

11.1.4合并文件(将多个文件内容合并到一个文件中)

cat 文件名1 文件名2 ... > 文件名a (将文件1,文件2,...中的内容合并到 文件a中)

 11.2 more 和 less 命令

适用于内容多的文件

11.2.1.  more + 文件名

向下翻页按键:

回车 :一行一行往下翻页

空格 :一屏幕一屏幕往下翻页

向上翻页按键

b :一屏幕一屏幕往上翻页

还有 s d f 会不同比例往下翻页

退出(当文件内容浏览完会自动退出)

q :退出浏览

进入模式

在浏览过程中按 v 可进入命令模式

在命令模式下按a i o s 可进入插入模式

在插入模式下按Esc 可进入命令模式

11.2.2  less + 文件名

向下翻页按键:

方向下键 :一行一行往下翻页

PGDN :一屏幕一屏幕往下翻页

向上翻页按键

方向上键 :一行一行往上翻页

PGUP :一屏幕一屏幕往上翻页

退出

内容展示完后不会自己退出,会出现(END) 的字样。此时仍然可以往上翻页

想退出按 q 即可

11.3 head 和 tail 命令

head  +  文件名

默认显示内容的前十行

head  -n  +  文件名

显示文件内容 前 n 行

tail  +  文件名  

默认显示内容后十行 

tail  -n  +  文件名

显示文件内容 后 n 行

tail   -f   +   文件名   

一般用于跟踪日志文件,实时编写展示

十二、gcc 的安装及命令

安装 gcc(用来编译C语言程序)编译器命令:sudo apt install gcc

安装 g++(用来编译C++程序)编译器命令:sudo apt install g++

12.1编译链接原理

a.c —(预编译)> a.i —(编译)> a.s —(汇编)> a.o —(链接)> a

12.2逐步编译命令

预编译命令: gcc -E a.c -o a.i 在a.c所在目录下会生成a.i文件

编译命令: gcc -S a.i -o a.s 在a.i所在目录下会生成a.s文件

汇编命令: gcc -C a.s -o a.o 在a.s所在目录下会生成a.o文件(a.o文件为可执行文件)

链接命令: gcc a.o -o a 在a.o所在目录下会生成a文件

12.3一步编译成.o文件

gcc -c a.c b.c .... 生成a.o b.o .... 文件

12.4一步编译命令 

gcc -o a a.c b.c ... 在a.c所在目录下会生成a文件

a为可执行程序 a.c b.c ...为可执行程序生成依赖的文件

// gcc a.c 在a.c所在目录下会生成a.out文件

12.5执行可执行文件的命令

上述生成的  a  为可执行文件,可使用命令:路径 / a  执行可执行文件

若想要想系统命令一样,在执行时不加路径,则需要将该可执行文件移动到 /bin 路径下。

十三、gdb 调试及命令

13.1调试的分类:

Debug(调试版本)

使用 gcc -o main main.c -g 指令 生成的main文件为debug调试版本

Release(发行版本)

使用 gcc -o main main.c 指令 生成的main文件为release发行版本(gcc默认是生成发行版本)

13.2安装gdb

sudo apt install gdb

13.3调试步骤:

1.gcc -o main main.c -g 切换到Debug版本

2.启用调试:gdb main(main 必须是Debug版本,否则无法调试)

3.当出现 (gdb) 提示符时就可以输入命令

4.下断点:b 行号 或者 break 行号

5.运行:r 或者 run

6.退出调试:quit 或者 q 回车

13.4运行代码之前的操作(运行代码后也可以使用):

l 行号 查看当前行号前后总共10行的代码内容

不加行号时默认从第一行开始展示10行代码内容

b 行号 或者 break 行号 在当前行号下断点

b 函数名 给该函数的第一个有效行下断点

info b 或者 info break 查看断点信息

13.5运行代码后的操作:

r 或者 run 运行代码(碰到断点或者scanf,fgets需要输入的函数会自己阻塞住)

当想要执行带参数的命令时,需要在r后面加上参数即可

n 或者 next 一条语句逻辑运行

c 或者 continue 从当前位置直接执行到下一个断点处

s 进入要被调用的函数中执行

finish 跳出函数

delete 断点号(及上图中的Num) 删除指定的断点

disable 断点号 将该断点号处断点设为无效

disable 将所有断点设为无效

enable 断点号 将该断点号处断点设为有效

enable 将所有断点设为有效

13.6 监视操作

p a 打印变量a的值

p &a 打印变量a的地址

p a+b 打印变量(a+b)表达式的值

p arr(数组名) 打印数组arr所有元素的值

p *p 用指向数组的指针打印数组所有元素的值

display a或者&a或者a+b(表达式) 自动显示a的值或者a的地址或者a+b表达式的值

执行一步操作就显示一次 a的值或者a的地址或者a+b表达式的值

info display 显示 ' 自动显示 ' 信息 和 info b 相同

undiaplay 编号 删除指定的自动显示

编号为上述图片中 1: a=3 或者 1: y a中的 1

ptype a 显示变量a的类型

bt 显示函数调用栈

 13.7 fork函数的父子进程的调试

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
  pid_t pid=fork();
  if(pid==0)
  {
  	printf("child\n");//语句一
  }
  else 
  {
    printf("father\n");
  }
  exit(0);  
}   

在使用gdb调试时,断点下到语句一处,运行后不会在语句一处阻塞,因为调试时默认是跟父进程代码调试。

改成跟子进程代码调试:set follow-fork-mode child

如果想从子进程改到父进程使用:set follow-fork-mode parent

十四、makefile 文件

用于实现自动化编译

安装make的命令:sudo apt install make

make命令只针对makefile文件。执行make命令时,默认直接调用makefile文件

第一步:编辑c源文件222222

编辑好main.c add.c mul.c等文件

第二步:创建并编辑makefile文件(文件名必须是makefile,否则无法编译)

vim makefile 之后编辑格式如下:

all:要生成的文件名字(如main)

可以空一行也可以不空

要生成的文件名(如main):要生成该文件的所需的源文件的 .o 文件

必须以按tab空行,四个空格无法编译 gcc -o main add.o max.o main.o

add.o : add.c

必须以按tab空行,四个空格无法编译 gcc -c add.c

max.o : max.c

必须以按tab空行,四个空格无法编译 gcc -c max.c

min.o : min.c

必须以按tab空行,四个空格无法编译 gcc -c min.c

clean:

必须以按tab空行,四个空格无法编译 rm -r *.o(使用指令make clean后会删除当前路径下的.o文件)

编辑好后保存退出

终端执行make命令

make之后,在当前路径下会出现main可执行文件。若make执行失败,则可能是代码语法问题,或者makefile文件格式错误

终端执行:make clean命令

调用makefile文件中的clean

十五、find 和  grep 命令

find 用于查找文件        grep 用于过滤(需要和管道结合使用)

15.1查找该路径下的该文件名:

find 路径 -name 文件名

若该文件名不存在,则不会显示。若文件名为命令,则也不会显示

15.2模糊匹配查找:

find 路径 | grep ".c"

在该路径下找含有.c的文件

15.3 grep过滤命令的例子:

ls /bin | grep man

查看 /bin 路径下所有的文件,过滤条件是命令名包含man内容

该命令会显示该路径下所有含有man的文件

从文件中查找信息:grep "hello" 文件名 会将该文件中含有hello的一行显示出来

十六、关机和重启命令

16.1 关机命令:

halt

poweroff

shutdown -h now 立刻关机(root用户使用)

shutdown -h 10 10分钟后自动关机 该处10可以换做5:30,意思是5:30关机

上面的 -h 均可以省略

init 0

16.2 重启命令:

reboot

shutdown -r now 立刻重启(root用户使用)

shutdown -r 10 10分钟后重启 该处10可以换做5:30,意思是5:30重启

init 6

16.3 如果想取消定时关机重启则可以使用shutdown  -c

十七、文件的解压缩

17.1文件的分步压缩:

第一步:打包文件

tar cf其他参数 生成的文件名要以.tar结尾 需要打包的文件名...

会在当前路径下生成.tar文件

第二步:压缩文件

gzip 第一步打包好的文件名

会将第一步生成的.tar文件更改为.tar.gz文件

17.2文件的一步压缩:

tar zcf其他参数 生成的压缩文件要以.tar.gz结尾 需要压缩的文件...

会直接生成.tar.gz文件

17.3文件的分步解压:

第一步:解压文件

gzip -d 压缩好的.tar.gz文件

会生成.tar文件

第二步:解包文件

tar xf其他参数 上一步解压好的文件

会生成源文件

17.4文件的一步解压

tar zxf其他参数 压缩好的.tar.gz文件

会直接生成源文件

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作者:胡彦 2013-5-21 本文档可能有更新,更新版本请留意http://blog.csdn.net/huyansoft/article/details/8924624 一 目的:编写一个实际可用的makefile,能自动编译当前目录下所有.c源文件,并且任何.c、.h或依赖的源文件被修改后,能自动重编那些改动了的源文件,未改动的不编译。 二 要达到这个目的,用到的技术有: 1-使用wildcard函数来获得当前目录下所有.c文件的列表。 2-make的多目标规则。 3-make的模式规则。 4-用gcc -MM命令得到一个.c文件include了哪些文件。 5-用sed命令对gcc -MM命令的结果作修改。 6-用include命令包含依赖描述文件.d。 三 准备知识 (一)多目标 对makefile里下面2行,可看出多目标特征,执行make bigoutput或make littleoutput可看到结果: bigoutput littleoutput: defs.h pub.h @echo $@ $(subst output,OUTPUT,$@) $^ # $@指这个规则里所有目标的集合,$^指这个规则里所有依赖的集合。该行是把目标(bigoutput或littleoutput)里所有子串output替换成大写的OUTPUT (二)隐含规则 对makefile里下面4行,可看出make的隐含规则,执行foo可看到结果: 第3、4行表示由.c得到.o,第1、2行表示由.o得到可执行文件。 如果把第3、4行注释的话,效果一样。 即不写.o来自.c的规则,它会自动执行gcc -c -o foo.o foo.c这条命令,由.c编译出.o(其中-c表示只编译不链接),然后自动执行gcc -o foo foo.o链接为可执行文件。 foo:foo.o gcc -o foo foo.o; ./foo foo.o:foo.c #注释该行看效果 gcc -c foo.c -o foo.o #注释该行看效果 (三)定义模式规则 下面定义了一个模式规则,即如何由.c文件生成.d文件的规则。 foobar: foo.d bar.d @echo complete generate foo.d and bar.d %.d: %.c #make会对当前目录下每个.c文件,依次做一次里面的命令,从而由每个.c文件生成对应.d文件。 @echo from $< to $@ g++ -MM $ $@ 假定当前目录下有2个.c文件:foo.c和bar.c(文件内容随意)。 验证方法有2种,都可: 1-运行make foo.d(或make bar.d),表示想要生成foo.d这个目标。 根据规则%.d: %.c,这时%匹配foo,这样%.c等于foo.c,即foo.d这个目标依赖于foo.c。 此时会自动执行该规则里的命令gcc -MM foo.c > foo.d,来生成foo.d这个目标。 2-运行make foobar,因为foobar依赖于foo.d和bar.d这2个文件,即会一次性生成这2个文件。 四 下面详述如何自动生成依赖性,从而实现本例的makefile。 (一) 本例使用了makefile的模式规则,目的是对当前目录下每个.c文件,生成其对应的.d文件,例如由main.c生成的.d文件内容为: main.o : main.c command.h 这里指示了main.o目标依赖于哪几个源文件,我们只要把这一行的内容,通过make的include指令包含到makefile文件里,即可在其任意一个依赖文件被修改后,重新编译目标main.o。 下面详解如何生成这个.d文件。 (二) gcc/g++编译器有一个-MM选项,可以对某个.c/.cpp文件,分析其依赖的源文件,例如假定main.c的内容为: #include //标准头文件(以方式包含的),被-MM选项忽略,被-M选项收集 #include "stdlib.h"//标准头文件(以""方式包含的),被-MM选项忽略,被-M选项收集 #include "command.h" int main() { printf("##### Hello Makefile #####\n"); return 0; } 则执行gcc -MM main.c后,屏幕输出: main.o: main.c command.h 执行gcc -M main.c后,屏幕输出: main.o: main.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \ /usr/include/gnu/stubs-64.h \ /usr/lib/gcc/x86_64-linux-gnu/4.4.3/include/stddef.h \ /usr/include/bits/types.h /usr/include/bits/typesizes.h \ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \ /usr/lib/gcc/x86_64-linux-gnu/4.4.3/include/stdarg.h \ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \ /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \ /usr/include/endian.h /usr/include/bits/endian.h \ /usr/include/bits/byteswap.h /usr/include/sys/select.h \ /usr/include/bits/select.h /usr/include/bits/sigset.h \ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h command.h (三) 可见,只要把这些行挪到makefile里,就能自动定义main.c的依赖是哪些文件了,做法是把命令的输出重定向到.d文件里:gcc -MM main.c > main.d,再把这个.d文件include到makefile里。 如何include当前目录每个.c生成的.d文件: sources:=$(wildcard *.c) #使用$(wildcard *.cpp)来获取工作目录下的所有.c文件的列表。 dependence=$(sources:.c=.d) #这里,dependence是所有.d文件的列表.即把串sources串里的.c换成.d。 include $(dependence) #include后面可以跟若干个文件名,用空格分开,支持通配符,例如include foo.make *.mk。这里是把所有.d文件一次性全部include进来。注意该句要放在终极目标all的规则之后,否则.d文件里的规则会被误当作终极规则了。 (四) 现在main.c command.h这几个文件,任何一个改了都会重编main.o。但是这里还有一个问题,如果修改了command.h,在command.h中加入#include "pub.h",这时: 1-再make,由于command.h改了,这时会重编main.o,并且会使用新加的pub.h,看起来是正常的。 2-这时打开main.d查看,发现main.d中未加入pub.h,因为根据模式规则%.d: %.c中的定义,只有依赖的.c文件变了,才会重新生成.d,而刚才改的是command.h,不会重新生成main.d、及在main.d中加入对pub.h的依赖关系,这会导致问题。 3-修改新加的pub.h的内容,再make,果然问题出现了,make报告up to date,没有像期望那样重编译main.o。 现在问题在于,main.d里的某个.h文件改了,没有重新生成main.d。进一步说,main.d里给出的每个依赖文件,任何一个改了,都要重新生成这个main.d。 所以main.d也要作为一个目标来生成,它的依赖应该是main.d里的每个依赖文件,也就是说make里要有这样的定义: main.d: main.c command.h 这时我们发现,main.d与main.o的依赖是完全相同的,可以利用make的多目标规则,把main.d与main.o这两个目标的定义合并为一句: main.o main.d: main.c command.h 现在,main.o: main.c command.h这一句我们已经有了,如何进一步得到main.o main.d: main.c command.h呢? (五) 解决方法是行内字符串替换,对main.o,取出其中的子串main,加上.d后缀得到main.d,再插入到main.o后面。能实现这种替换功能的命令是sed。 实现的时候,先用gcc -MM命令生成临时文件main.d.temp,再用sed命令从该临时文件中读出内容(用输出到最终文件main.d。 命令可以这么写: g++ -MM main.c > main.d.temp sed 's,\(main\)\.o[ :]*,\1.o main.d : ,g' main.d 其中: sed 's,\(main\)\.o[ :]*,\1.o main.d : ,g',是sed命令。 main.d,把行内替换结果输出到最终文件main.d。 (六) 这条sed命令的结构是s/match/replace/g。有时为了清晰,可以把每个/写成逗号,即这里的格式s,match,replace,g。 该命令表示把源串内的match都替换成replace,s指示match可以是正则表达式。 g表示把每行内所有match都替换,如果去掉g,则只有每行的第1处match被替换(实际上不需要g,因为一个.d文件中,只会在开头有一个main.o:)。 这里match是正则式\(main\)\.o[ :]*,它分成3段: 第1段是\(main\),在sed命令里把main用\(和\)括起来,使接下来的replace中可以用\1引用main。 第2段是\.o,表示匹配main.o,(这里\不知何意,去掉也是可以的)。 第3段是正则式[ :]*,表示若干个空格或冒号,(其实一个.d里只会有一个冒号,如果这里写成[ ]*:,即匹配若干个空格后跟一个冒号,也是可以的)。 总体来说match用来匹配'main.o :'这样的串。 这里的replace是\1.o main.d :,其中\1会被替换为前面第1个\(和\)括起的内容,即main,这样replace值为main.o main.d : 这样该sed命令就实现了把main.o :替换为main.o main.d :的目的。 这两行实现了把临时文件main.d.temp的内容main.o : main.c command.h改为main.o main.d : main.c command.h,并存入main.d文件的功能。 (七) 进一步修改,采用自动化变量。使得当前目录下有多个.c文件时,make会依次对每个.c文件执行这段规则,生成对应的.d: gcc -MM $ $@.temp; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' $@; (八) 现在来看上面2行的执行流程: 第一次make,假定这时从来没有make过,所有.d文件不存在,这时键入make: 1-include所有.d文件的命令无效果。 2-首次编译所有.c文件。每个.c文件中若#include了其它头文件,会由编译器自动读取。由于这次是完整编译,不存在什么依赖文件改了不会重编的问题。 3-对每个.c文件,会根据依赖规则%.d: %.c,生成其对应的.d文件,例如main.c生成的main.d文件为: main.o main.d: main.c command.h 第二次make,假定改了command.h、在command.h中加入#include "pub.h",这时再make: 1-include所有.d文件,例如include了main.d后,得到依赖规则: main.o main.d: main.c command.h 注意所有include命令是首先执行的,make会先把所有include进来,再生成依赖规则关系。 2-此时,根据依赖规则,由于command.h的文件戳改了,要重新生成main.o和main.d文件。 3-先调用gcc -c main.c -o main.o生成main.o, 再调用gcc -MM main.c > main.d重新生成main.d。 此时main.d的依赖文件里增加了pub.h: main.o main.d: main.c command.h pub.h 4-对其它依赖文件没改的.c(由其.d文件得到),不会重新编译.o和生成其.d。 5-最后会执行gcc $(objects) -o main生成最终可执行文件。 第三次make,假定改了pub.h,再make。由于第二遍中,已把pub.h加入了main.d的依赖,此时会重编main.c,重新生成main.o和main.d。 这样便实现了当前目录下任一源文件改了,自动编译涉及它的.c。 (九) 进一步修改,得到目前大家普遍使用的版本: set -e; rm -f $@; \ $(CC) -MM $(CPPFLAGS) $ $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' $@; \ rm -f $@.$$$$ 第一行,set -e表示,如果某个命令的返回参数非0,那么整个程序立刻退出。 rm -f用来删除上一次make时生成的.d文件,因为现在要重新生成这个.d,老的可以删除了(不删也可以)。 第二行:前面临时文件是用固定的.d.temp作为后缀,为了防止重名覆盖掉有用的文件,这里把temp换成一个随机数,该数可用$$得到,$$的值是当前进程号。 由于$是makefile特殊符号,一个$要用$$来转义,所以2个$要写成$$$$(你可以在makefile里用echo $$$$来显示进程号的值)。 第三行:sed命令的输入也改成该临时文件.$$。 每个shell命令的进程号通常是不同的,为了每次调用$$时得到的进程号相同,必须把这4行放在一条命令中,这里用分号把它们连接成一条命令(在书写时为了易读,用\拆成了多行),这样每次.$$便是同一个文件了。 你可以在makefile里用下面命令来比较: echo $$$$ echo $$$$; echo $$$$ 第四行:当make完后,每个临时文件.d.$$,已经不需要了,删除之。 但每个.d文件要在下一次make时被include进来,要保留。 (十) 综合前面的分析,得到我们的makefile文件: #使用$(wildcard *.c)来获取工作目录下的所有.c文件的列表 sources:=$(wildcard *.c) objects:=$(sources:.c=.o) #这里,dependence是所有.d文件的列表.即把串sources串里的.c换成.d dependence:=$(sources:.c=.d) #所用的编译工具 CC=gcc #当$(objects)列表里所有文件都生成后,便可调用这里的 $(CC) $^ -o $@ 命令生成最终目标all了 #把all定义成第1个规则,使得可以把make all命令简写成make all: $(objects) $(CC) $^ -o $@ #这段是make的模式规则,指示如何由.c文件生成.o,即对每个.c文件,调用gcc -c XX.c -o XX.o命令生成对应的.o文件。 #如果不写这段也可以,因为make的隐含规则可以起到同样的效果 %.o: %.c $(CC) -c $< -o $@ include $(dependence) #注意该句要放在终极目标all的规则之后,否则.d文件里的规则会被误当作终极规则了 %.d: %.c set -e; rm -f $@; \ $(CC) -MM $(CPPFLAGS) $ $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' $@; \ rm -f $@.$$$$ .PHONY: clean #之所以把clean定义成伪目标,是因为这个目标并不对应实际的文件 clean: rm -f all $(objects) $(dependence) #清除所有临时文件:所有.o和.d。.$$已在每次使用后立即删除。-f参数表示被删文件不存在时不报错 (十一) 上面这个makefile已经能正常工作了(编译C程序),但如果要用它编译C++,变量CC值要改成g++,每个.c都要改成.cpp,有点繁琐。 现在我们继续完善它,使其同时支持C和C++,并支持二者的混合编译。 #一个实用的makefile,能自动编译当前目录下所有.c/.cpp源文件,支持二者混合编译 #并且当某个.c/.cpp、.h或依赖的源文件被修改后,仅重编涉及到的源文件,未涉及的不编译 #详解文档:http://blog.csdn.net/huyansoft/article/details/8924624 #author:胡彦 2013-5-21 #---------------------------------------------------------- #编译工具用g++,以同时支持C和C++程序,以及二者的混合编译 CC=g++ #使用$(winldcard *.c)来获取工作目录下的所有.c文件的列表 #sources:=main.cpp command.c #变量sources得到当前目录下待编译的.c/.cpp文件的列表,两次调用winldcard、结果连在一起即可 sources:=$(wildcard *.c) $(wildcard *.cpp) #变量objects得到待生成的.o文件的列表,把sources中每个文件的扩展名换成.o即可。这里两次调用patsubst函数,第1次把sources中所有.cpp换成.o,第2次把第1次结果里所有.c换成.o objects:=$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(sources))) #变量dependence得到待生成的.d文件的列表,把objects中每个扩展名.o换成.d即可。也可写成$(patsubst %.o,%.d,$(objects)) dependence:=$(objects:.o=.d) #---------------------------------------------------------- #当$(objects)列表里所有文件都生成后,便可调用这里的 $(CC) $^ -o $@ 命令生成最终目标all了 #把all定义成第1个规则,使得可以把make all命令简写成make all: $(objects) $(CC) $(CPPFLAGS) $^ -o $@ @./$@ #编译后立即执行 #这段使用make的模式规则,指示如何由.c文件生成.o,即对每个.c文件,调用gcc -c XX.c -o XX.o命令生成对应的.o文件 #如果不写这段也可以,因为make的隐含规则可以起到同样的效果 %.o: %.c $(CC) $(CPPFLAGS) -c $< -o $@ #同上,指示如何由.cpp生成.o,可省略 %.o: %.cpp $(CC) $(CPPFLAGS) -c $< -o $@ #---------------------------------------------------------- include $(dependence) #注意该句要放在终极目标all的规则之后,否则.d文件里的规则会被误当作终极规则了 #因为这4行命令要多次凋用,定义成命令包以简化书写 define gen_dep set -e; rm -f $@; \ $(CC) -MM $(CPPFLAGS) $ $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' $@; \ rm -f $@.$$$$ endef #指示如何由.c生成其依赖规则文件.d #这段使用make的模式规则,指示对每个.c文件,如何生成其依赖规则文件.d,调用上面的命令包即可 %.d: %.c $(gen_dep) #同上,指示对每个.cpp,如何生成其依赖规则文件.d %.d: %.cpp $(gen_dep) #---------------------------------------------------------- #清除所有临时文件(所有.o和.d)。之所以把clean定义成伪目标,是因为这个目标并不对应实际的文件 .PHONY: clean clean: #.$$已在每次使用后立即删除。-f参数表示被删文件不存在时不报错 rm -f all $(objects) $(dependence) echo: #调试时显示一些变量的值 @echo sources=$(sources) @echo objects=$(objects) @echo dependence=$(dependence) @echo CPPFLAGS=$(CPPFLAGS) #提醒:当混合编译.c/.cpp时,为了能够在C++程序里调用C函数,必须把每一个要调用的C函数,其声明都包括在extern "C"{}块里面,这样C++链接时才能成功链接它们。 五 makefile学习体会: 刚学过C语言的读者,可能会觉得makefile有点难,因为makefile不像C语言那样,一招一式都那么清晰明了。 在makefile里到处是“潜规则”,都是一些隐晦的东西,要弄明白只有搞清楚这些“潜规则”。 基本的规则无非是“一个依赖改了,去更新哪些目标”。 正因为隐晦动作较多,写成一个makefile才不需要那么多篇幅,毕竟项目代码才是主体。只要知道makefile的框架,往它的套路里填就行了。 较好的学习资料是《跟我一起写Makefile.pdf》这篇文档(下载包里已经附带了),比较详细,适合初学者。 我们学习的目的是,能够编写一个像本文这样的makefile,以满足简单项目的基本需求,这要求理解前面makefile几个关键点: 1-多目标 2-隐含规则 3-定义模式规则 4-自动生成依赖性 可惜的是,这篇文档虽然比较全面,却没有以一个完整的例子为引导,对几处要点没有突出指明,尤其是“定义模式规则”在最后不显眼的位置(第十一部分第五点),导致看了“自动生成依赖性”一节后还比较模糊。 所以,看了《跟我一起写Makefile.pdf》后,再结合本文针对性的讲解,会有更实际的收获。 另一个学习资料是《GNU make v3.80中文手册v1.5.pdf》,这个手册更详细,但较枯燥,不适合完整学习,通常是遇到问题再去查阅。 其它文章和代码请留意我的blog: http://blog.csdn.net/huyansoft [END]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值