一、linux中make的用法
 
目的:
       基本掌握了make 的用法,能在Linux系统上编程。
环境:
       Linux系统
准备:
       准备三个文件:file1.c, file2.c, file2.h
       file1.c:
              #include <stdio.h>
              #include "file2.h"
              int main()
              {
                     printf("print file1$$$$$$$$$$$$$$$$$$$$$$$$\n");
                     File2Print();
                     return 0;
              }
 
       file2.h:
 
              #ifndef FILE2_H_
              #define    FILE2_H_
 
                      #ifdef __cplusplus
 
                            extern "C" {
 
                     #endif
 
                     void File2Print();
 
                     #ifdef __cplusplus
 
                            }
 
                     #endif
 
              #endif
 
 
       file2.c:
              #include "file2.h"
              void File2Print()
              {
                     printf("Print file2**********************\n");
              }
 
基础:
       先来个例子:
       有这么个Makefile文件。(文件和Makefile在同一目录)
       === makefile 开始===
              helloworld:file1.o file2.o
                     gcc file1.o file2.o -o helloworld
 
              file1.o:file1.c file2.h
                     gcc -c file1.c -o file1.o
 
               file2.o:file2.c file2.h
 
                     gcc -c file2.c -o file2.o
 
 
              clean:
 
                     rm -rf *.o helloworld
 
       === makefile 结束===
 
一个makefile 主要含有一系列的规则,如下:
A: B
(tab)<command>
(tab)<command>
 
每个命令行前都必须有tab符号。
 
上面的makefile文件目的就是要编译一个helloworld的可执行文件。让我们一句一句来解释:
 
       helloworld : file1.o file2.o:                 helloworld依赖file1.o file2.o两个目标文件。
 
       gcc File1.o File2.o -o helloworld:      编译出helloworld可执行文件。-o表示你指定 的目标文件名。
 
     
 
       file1.o : file1.c:    file1.o依赖file1.c文件。
 
       gcc -c file1.c -o file1.o:                  编译出file1.o文件。-c表示gcc 只把给它的文件编译成目标文件, 用源码文件的文件名命名但把其后缀由“.c”或“.cc”变成“.o”。在这句中,可以省略-o
file1.o,编译器默认生成file1.o文件,这就是-c的作用。
 
 
              file2.o : file2.c file2.h
              gcc -c file2.c -o file2.o
 
这两句和上两句相同。
 
 
       clean:
 
              rm -rf *.o helloworld
 
当用户键入make clean命令时,会删除*.o 和helloworld文件。
 
 
如果要编译cpp文件,只要把gcc改成g++就行了。
 
写好Makefile文件,在命令行中直接键入make命令,就会执行Makefile中的内容了。
 
 
到这步我想你能编一个Helloworld程序了。
 
 
上一层楼:使用变量
 
       上面提到一句,如果要编译cpp文件,只要把gcc改成g++就行了。但如果Makefile中有很多gcc,那不就很麻烦了。
 
       第二个例子:
 
       === makefile 开始===
              OBJS = file1.o file2.o
              CC = gcc
              CFLAGS = -Wall -O -g
 
              helloworld : $(OBJS)
                     $(CC) $(OBJS) -o helloworld
 
              file1.o : file1.c file2.h
                     $(CC) $(CFLAGS) -c file1.c -o file1.o
 
              file2.o : file2.c file2.h
                     $(CC) $(CFLAGS) -c file2.c -o file2.o
 
 
              clean:
 
                     rm -rf *.o helloworld
=== makefile 结束===
 
 
       这里我们应用到了变量。要设定一个变量,你只要在一行的开始写下这个变量的名字,后 面跟一个= 号,后面跟你要设定的这个变量的值。以后你要引用 这个变量,写一个$ 符号,后面是围在括号里的变量名。
 
 
CFLAGS = -Wall -O –g,解释一下。这是配置编译器设置,并把它赋值给CFFLAGS变量。
 
-Wall:          输出所有的警告信息。
 
-O:              在编译时进行优化。
 
-g:               表示编译debug版本。
 
 
       这样写的Makefile文件比较简单,但很容易就会发现缺点,那就是要列出所有的c文件。如果你添加一个c文件,那就需要修改Makefile文件,这在项目开发中还是比较麻烦的。
 
 
 
再上一层楼:使用函数
 
       学到这里,你也许会说,这就好像编程序吗?有变量,也有函数。其实这就是编程序,只不过用的语言不同而已。
 
       第三个例子:
 
       === makefile 开始===
              CC = gcc
 
              XX = g++
              CFLAGS = -Wall -O –g
 
              TARGET = ./helloworld
 
              %.o: %.c
 
                     $(CC) $(CFLAGS) -c $< -o $@
 
              %.o:%.cpp
 
                     $(XX) $(CFLAGS) -c $< -o $@
 
 
              SOURCES = $(wildcard *.c *.cpp)
              OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
 
 
              $(TARGET) : $(OBJS)
                     $(XX) $(OBJS) -o $(TARGET)
 
                     chmod a+x $(TARGET)
 
clean:
 
       rm -rf *.o helloworld
=== makefile 结束===
 
函数1:wildcard
 
       产生一个所有以'.c' 结尾的文件的列表。
 
       SOURCES = $(wildcard *.c *.cpp)表示产生一个所有以.c,.cpp结尾的文件的列表,然后存入变量SOURCES 里。
 
 
函数2:patsubst
 
       匹配替换,有三个参数。第一个是一个需要匹配的式样,第二个表示用什么来替换它,第三个是一个需要被处理的由空格分隔的列表。
 
OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES)))表示把文件列表中所有的.c,.cpp字符变成.o,形成一个新的文件列表,然后存入OBJS变量中。
 
 
%.o: %.c
 
       $(CC) $(CFLAGS) -c $< -o $@
 
%.o:%.cpp
 
       $(XX) $(CFLAGS) -c $< -o $@
 
       这几句命令表示把所有的.c,.cpp编译成.o文件。
 
       这里有三个比较有用的内部变量。$@ 扩展成当前规则的目的文件名,$< 扩展成依靠       列表中的第一个依靠文件,而$^ 扩展成整个依靠的列表(除掉了里面所有重 复的文件名)。
 
 
       chmod a+x $(TARGET)表示把helloworld强制变成可执行文件。
 
       到这里,我想你已经能够编写一个比较简单也比较通用的Makefile文件了,上面所有的例子都假定所有的文件都在同一个目录下,不包括子目录。
 
二,make用法
 
曾经查找过很多资料,对于makefile的写法是相当熟悉,可是对于怎么使用makefile是一无所知。兄弟我所写的程序,gcc单步运行一点问题都没有,顺利过关;就是放在makefile中的时候不停地报错,弄得兄弟我像个救火队员似的。于是痛下决心来个超级简单的,先把这关过了再说,当然这是对我这种没有抽象思维的人来说的,高手到这里的话可以顺便鄙视一把。
 
      首先,顺手写个func.h文件。##################################################//func.hvoid func();##################################################      再次,顺手写个func.c文件。##################################################//func.c#includevoid
func(){       printf("hello world!\n");}##################################################     然后,编个主文件test.c。###################################################include#includevoid main(){      func();}##################################################     写完程序之后,在linux单步执行下面语句:    
gcc -c func.c -o func.o      gcc -c test.c -o test.o     gcc func.o test.o -o test     顺利编译通过。然后执行./test就输出hello world!     但是按照上面的写的语句编制makefile文件:*******************************************************************//makefiletest:test.o func.o      gcc test.o
func.o -o testtest.o:test.c      gcc -c test.c -o test.ofunc.o:func.c      gcc -c func.c -o func.o*******************************************************************make后,输出却是'test' is up to date,说明有错误,或者是test不存在,不然就是被覆盖掉了。
 
(其实不是的,只是表示test文件已经是最新版本,不必重新编译,若强制编译可以touch test.c,香巴拉)
      于是按照下面的方法编制makefile:*******************************************************************//makefileall:testbuild      echo "build ok!"testbuild:test.o func.o      gcc test.o
func.o -o testtest.o:test.c      gcc -c test.c -o test.ofunc.o:func.c      gcc -c func.c -o func.o*******************************************************************make后,运行成功,输出结果为:*******************************************************************gcc -c
test.c -o test.ogcc -c func.c -o func.ogcc test.o func.o -o testecho "build ok!"build ok!*******************************************************************./test,输出结果为hello world!    最后makefile精简为:*******************************************************************//makefileall:test.o
func.o      gcc test.o func.o -o testtest.o:test.c      gcc -c test.c -o test.ofunc.o:func.c      gcc -c func.c -o func.o*******************************************************************所以浪费一个小时的时间就是为了验证应该是all而不是test,^_^。

linux中make的用法的更多相关文章

  1. Linux中find常见用法

    Linux中find常见用法示例 ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数 ...

  2. [转]Linux中find常见用法示例

    Linux中find常见用法示例[转]·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;find命令的参 ...

  3. Linux中“!"的神奇用法

    前言 实际上,不起眼的“!”在linux中有着很多让你惊叹的妙用.本文就来细数那些“!”的神奇用法. 执行上一条命令 例如,在执行完上面一条命令后,可以使用下面的方式再次执行上一条命令: $ wher ...

  4. Linux中sed的用法实践

    Linux中sed的用法实践 参考资料:https://www.cnblogs.com/emanlee/archive/2013/09/07/3307642.html http://www.fn139 ...

  5. Linux中Sed的用法

    Linux中Sed的用法 sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为: ...

  6. (转)linux 中特殊符号用法详解

    linux 中特殊符号用法详解 原文:https://www.cnblogs.com/lidabo/p/4323979.html # 井号 (comments)#管理员  $普通用户 脚本中 #!/b ...

  7. Linux中 find 常见用法示例

    Linux中find常见用法示例 #find path -option [ -print ] [ -exec -ok command ] {} \; #-print 将查找到的文件输出到标准输出 #- ...

  8. linux中comm命令用法

    linux系统中comm命令用法详解 linux系统下的comm命令是一个非常实用的文件对比命令. comm命令功能:   选择或拒绝两个已排序的文件的公共的行. comm命令语法:comm [-12 ...

  9. Linux中curl的用法

    一.简介:在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,是一款强大的http命令行工具.支持文件的上传和下载,是综合传输工具. 二.语法:curl [option] [url ...

随机推荐

  1. eclipse中如何自动生成构造函数

    eclipse中如何自动生成构造函数 eclipse是一个非常好的IDE,我在写java程序的时候使用eclipse感觉开发效率很高.而且有很多的快捷和简便方式供大家使用,并且能直接生成class文件 ...

  2. java继承多态和抽象类接口

    一.继承 通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类.已有的称为父类,新的类称为子类(父类派生子类,子类继承父类).(1)继承的优点:    ①代码的可重用性:    ②父类的属性 ...

  3. node.js服务器搭建

    //1.导入http 核心模块 const http = require("http"); //2.调用http.createServer 方法,创建一个web 服务器对象 con ...

  4. 第42节:Java知识点回顾复习

    Java介绍 Java是一门面向对象的程序设计的编程语言,在1995年,sun公司发布了Java这门编程语言,有咖啡的名称,是当时灵机一动的想法.在2010年的时候被Oracle公司收购了,目前jdk ...

  5. SpringBoot中集成redis

    转载:https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html 不是使用注解而是代码调用 需要在springbo ...

  6. 机器学习入门03 - 降低损失 (Reducing Loss)

    原文链接:https://developers.google.com/machine-learning/crash-course/reducing-loss/ 为了训练模型,需要一种可降低模型损失的好 ...

  7. Express中间件的意思 next()的方法

    一.什么是express?Express是一个简洁.灵活的noode.jsWeb应用开发框架,它提供一系列强大的特性,帮助你创建各种Web和移动设备应用.Express项目的底层由许多的中间件在协同工 ...

  8. 关于DB Link

    概述 DB Link是一个定义了本地数据库到远程数据库路径的对象,是schema object,它是单向连接 通过DB Link可查询remote数据库的对象及运行其程序 在分布式环境里,DB Lin ...

  9. 课程五(Sequence Models),第二 周(Natural Language Processing & Word Embeddings) —— 2.Programming assignments:Emojify

    Emojify! Welcome to the second assignment of Week 2. You are going to use word vector representation ...

  10. Kubernetes 服务入口管理与 Nginx Ingress Controller

    Kubernetes 具有强大的副本,动态扩容等特性,每一次 Pod 的变化 IP 地址都会发生变化,所以 Kubernetes 引进了 Service 的概念.Kubernetes 中使用 Serv ...