linux C编程之makefile

目的:
       基本掌握了 make 的用法,能在Linux系统上编程。
环境:
       Linux系统,或者有一台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文件了,上面所有的例子都假定所有的文件都在同一个目录下,不包括子目录。

那么文件不在一个目录可以吗?

怎么编写Makefile生成静态库?

你还想更上一层楼吗?

请听下回分解。

posted on 2014-03-07 20:42 秦瑞It行程实录 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/ruiy/p/Mfs.html

linux C编程之makefile相关推荐

  1. linux c编程之fcntl

    fcntl可实现对指定文件描述符的各种操作,其函数原型如下: int fcntl(int fd, int cmd, ... /* arg */ ); 其中,操作类型由cmd决定.cmd可取如下值: F ...

  2. Linux网络编程之IP地址转换为无符号整数的方法

    Linux网络编程之IP地址转换为无符号整数的方法,代码如下:(没考虑异常输入) #include <stdio.h> #include <string.h> #include ...

  3. Linux网络编程之sockaddr与sockaddr_in,sockaddr_un结构体详细讲解

    Linux网络编程之sockaddr与sockaddr_in,sockaddr_un结构体详细讲解 (1)sockaddr struct sockaddr { unsigned  short  sa_ ...

  4. linux读取文件修改时间函数,Linux服务器编程之utime()函数修改文件存取时间

    Linux服务器编程之utime()函数修改文件存取时间 C语言utime()函数:修改文件的存取时间和更改时间 头文件: #include #include 定义函数: int utime(cons ...

  5. Linux网络编程之TCP状态转移

    Linux网络编程之TCP状态转移 一.TCP状态转移时序 二.半关闭及shutdown函数 一.TCP状态转移时序 TCP状态转移图: netstat -apn | grep client 查看客户 ...

  6. 数据连接linux网络编程之TCP/IP基础(四):TCP连接的建立和断开、滑动窗口

    在写这篇文章之前,xxx已经写过了几篇关于改数据连接主题的文章,想要了解的朋友可以去翻一下之前的文章 一.TCP段格式: TCP的段格式如下图所示 源端口号与目标端口号 源端口号和目标端口号,加上IP ...

  7. Linux C编程之二:Linux基础

    1.Linux的特点 (1)Linux就是一个操作系统(作为用户和计算机之间接口的软件程序) 注:操作系统的功能:命令解释,进程管理,内存管理,输入输出(I/O)操作和外围设备管理,文件管理 (2)特 ...

  8. linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时

    一.使用alarm 函数设置超时 C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13   void handler( int sig) { } signal(SIGALRM ...

  9. linux socket编程之TCP与UDP

    转:http://blog.csdn.net/gaoxin1076/article/details/7262482 TCP/IP协议叫做传输控制/网际协议,又叫网络通信协议 TCP/IP虽然叫传输控制 ...

最新文章

  1. 生成对抗网络(GAN)应用于图像分类
  2. 比特币现金网络会看到什么样的代币?
  3. Golang之envconfig的使用
  4. Curator实现分布式锁的基本原理-InterProcessMutex.internalLock
  5. MassTransit中RequestResponse基本使用
  6. Python中的虚拟环境-virtualenv
  7. 嵌入式系统——指令操作扩展
  8. this.controls指所有控件吗?_Excel 控件【窗体控件】和【ActiveX控件】使用基础教程...
  9. python制造童年回忆:猫和老鼠小游戏【附源码】
  10. 775针服务器cpu性能排行,775针cpu排行榜说明
  11. 企业信息化建设中流程梳理的步骤及方法
  12. 江苏电信iFree卡再升级黄金版:全国无漫游,流量不清零
  13. jQuery常用API(六)
  14. 微信朋友圈,模仿微信朋友圈,朋友圈点赞评论
  15. 【记录】easyexcel导出后打开文件报已损坏
  16. iOS开发月报#11|201905
  17. CASCADE: Contextual Sarcasm Detection in Online Discussion Forums(2018)论文笔记
  18. Python 图算法系列13-cypher 查询以及模糊查询
  19. 大前端养成之路:学一点MongoDB(一)
  20. 项目管理工程师岗位职责

热门文章

  1. UVa10905 - Children's Game(贪心算法)
  2. 题目1164:旋转矩阵
  3. oracle数据库逐步学习总结【基础一】
  4. spring的@Transactional注解详细用法
  5. Spring-boot 启动完成时执行指定任务
  6. 全球主要城市经纬度api
  7. docker环境下solr6.0配置(中文分词+拼音)
  8. 什么是Zookeeper,Zookeeper的作用是什么,在Hadoop及hbase中具体作用是什么
  9. 利用partition分组查询 查询每个分组第一条数据
  10. 安装Debian 7.8 过程,以及该系统的配置过程