目的:
       基本掌握了 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生成静态库?

你还想更上一层楼吗?

请听下回分解。

linux C编程之makefile的更多相关文章

  1. linux c编程之fcntl

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

  2. linux网络编程之shutdown() 与 close()函数详解

    linux网络编程之shutdown() 与 close()函数详解 参考TCPIP网络编程和UNP: shutdown函数不能关闭套接字,只能关闭输入和输出流,然后发送EOF,假设套接字为A,那么这 ...

  3. Linux应用编程之lseek详解

    Linux应用编程之lseek详解 1.lseek函数介绍 (1).文件指针:当我们要对一个文件进行读写时,一定要先打开这个文件,所以我们读写的所有文件都是动态文件.动态文件在内存中的形态就是文件流的 ...

  4. Linux内核模块编程之Helloworld(初级)

    注意printk那里,KERN_ALERT和打印消息之间是没有逗号的,搞得劳资查了半天才发现一直没有提示信息的原因 #include <linux/init.h> #include < ...

  5. (十)Linux 网络编程之ioctl函数

    1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...

  6. (ubuntu)linux C编程之sleep()和usleep()的使用和区别

    ### 函数名: sleep 头文件: #include <windows.h> // 在VC中使用带上头文件 #include <unistd.h> // 在gcc编译器中, ...

  7. linux socket编程之TCP与UDP

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

  8. linux网络编程之IO模型

    本文转自作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓 ...

  9. linux网络编程之IO函数

    Linux操作系统中的IO函数主要有read(),write(),recv(),send(),recvmsg(),sendmsg(),readv(),writev(). 接收数据的recv()函数 # ...

随机推荐

  1. Top命令内存占用剖析

    原文: http://yalung929.blog.163.com/blog/static/203898225201212981731971/ 引 言: top命令作为Linux下最常用的性能分析工具 ...

  2. java中List集合及其遍历详解

    1. 首先List<E>集合继承与Collection<E>,是一个接口. ①  Collection (集合框架是JDK1.2版本出现的) ②   list:是有序的,元素可 ...

  3. HeadFirst设计模式之门面模式

    一. 1.The Facade Pattern provides a unifi ed interface to a set of interfaces in a subsytem. Facade d ...

  4. SQL Server Mobile 和 .NET 数据访问接口之间的数据类型映射

      .NET 数据类型 SQL Server Mobile 数据类型 binary varbinary boolean bit byte tinyint byte[] varbinary dateti ...

  5. P137、面试题23:从上往下打印二叉树

    题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印.例如输入如图的二叉树,则依次打印出8,6,10,5,7,9,11.(其实是按层遍历)二叉树结点的定义如下:struct Bin ...

  6. Convert boolean values to strings 'Yes' or 'No'.

    Convert boolean values to strings 'Yes' or 'No'. Complete the bool_to_word (Javascript: boolToWord ) ...

  7. git commit 之后 push 之前,想删除 个别的commit 文件

    git rm --cached <file_name> git commit "删除了<file_name>文件" git rm --cached < ...

  8. POI 中Cell的backgroundcolor和foregroundcolor

    刚开始以为要获得cell的背景色是使用  getFillBackgroundColor()这个函数(这里返回的是调色板的索引,要获得RGB需要先获得系统的Pallete,然后在获得 RGB).结果出来 ...

  9. bzoj3205

    和bzoj2595类似,也是斯坦纳树 设f[l,r,]表示在点i机器人组合成了l-r最少推的次数,然后可得 f[l,r,i]=min(f[l,m,i]+f[m+1,r,i]) f[l,r,i]=min ...

  10. SSH2中memcached作为hibernate二级缓存

    一.安装memcached服务端 1. 下载memcached的windows稳定版,解压放某个盘下面,比如在c:\memcached2. 在CMD下输入 "c:\memcached\mem ...