(二)开源项目的Makefile编写

作者:阿龙。

链接:http://blog.csdn.net/tiny_210/article/details/14647753


对于开源项目的编译安装:

命令执行

[root@localhost valgrind-3.9.0]# mkdir /outfile

[root@localhost valgrind-3.9.0]# ./configure --prefix=/outfile/         //安装到/outfile目录

[root@localhost valgrind-3.9.0]# make && make install                 //编译并且安装


最终就会在outfile目录下产生以下目录:

[root@localhost valgrind-3.9.0]# ls /outfile/
bin  include  lib  share

其中bin存放可执行文件,include存放头文件,lib存放可使用的库,share存放一些说明文档。现在我们就实现这个功能。

而lib不单单只有库,还有一个XXX.pc文件,这个文件pkg-config命令使用,这个文件存放了很多信息,尤其是路径,所以通过pkg-config命令和XXX.pc文件可以很容易使用到库(因为路径存放该文件里了)。

[root@localhost lib]# ls
pkgconfig  valgrind



现在通过代码来实现这个功能。

1、构造项目模型:

[root@localhost automake]# mkdir include            //存放头文件

[root@localhost automake]# mkdir src                   //存放源文件

[root@localhost automake]# mkdir add_sub                   //存放加减法实现函数


2、开始写代码:

进入src目录,新建文件main.c:

[root@localhost src]# cat main.c 

#include<stdio.h>
#include<stdlib.h>


#include "myinclude.h"


int main(int argc,char *argv[])
{
        int a=1,b=2;
        int result;


        result=my_add(a,b);      //自己实现加法函数
        printf("a+b=%d\n",result);


        result=my_sub(a,b);          //自己实现的减法函数
        printf("a-b=%d\n",result);


        return 0;
}


进入add_sub目录实现加减法函数:

[root@localhost add_sub]# cat add_sub.c 


#include <stdio.h>
#include <stdlib.h>


#include "myinclude.h"

/*加法函数实现*/
int my_add(int a,int b)
{
        return (a+b);
}

/*减法函数实现*/
int my_sub(int a,int b)
{
        return (a-b);
}

在头文件目录建立myinclude.h声明函数:

[root@localhost include]# cat myinclude.h 

#ifndef __MYINCLUDE_H__
#define __MYINCLUDE_H__

#include<stdio.h>

int my_add(int a,int b);
int my_sub(int a,int b);

#endif  //__MYINCLUDE_H__

到此源码就OK了,接着就是使用autotools来生成Makefile了。


3、生成bin、lib、include目录:

编写Makefile.am(包括子目录和根目录都需有编写)

根目录:

[root@localhost automake]# cat Makefile.am 

SUBDIRS = \                               //DIST_SUBDIRS 全局变量表示有哪些子目录需要编译Makefile.am

        include \
        src/add_sub	\
	src
DIST_SUBDIRS  = $(SUBDIRS)
//生成xxx.pc,需要文件xx.pc.in
pkgconfigdir = $(libdir)/helloconfig
pkgconfig_DATA = hello.pc



src目录:

[root@localhost src]# cat Makefile.am 

 //bin_PROGRAMS表示编译为可执行文件,其中产生文件名为name,则name_SOURCE=当前目录的编译文件名字,
 //name_CFLAGS和name_CPPFLAGS表示当前编译的编译选项,name_LDFLAGS就是表示当前编译的链接选项等,
 //填充好这些变量autotools会自动帮我们组合为一组组编译命令

UTOMAKE_OPTIONS = foreign  

bin_PROGRAMS =main 

MEMCHECK_SOURCES_COMMON = \
        main.c



main_SOURCES      = \
        $(MEMCHECK_SOURCES_COMMON)
        
main_LDFLAGS	=\
	-L`pwd`/add_sub  -ladd_sub  //链接libadd_sub.so库,add_sub目录实现
	        
main_CFLAGS	= \
	-I`pwd`/../include   //指向include目录


add_sub目录:

[root@localhost add_sub]# cat Makefile.am 

UTOMAKE_OPTIONS = foreign
//noinst_PROGRAMS表示编译为库,其他变量含义和前面一样

noinst_PROGRAMS =libadd_sub.so


MEMCHECK_SOURCES_COMMON = \
        add_sub.c

libadd_sub_so_SOURCES      = \
        $(MEMCHECK_SOURCES_COMMON)


libadd_sub_so_CFLAGS    = \
         -fPIC -shared   -I`pwd`/../../include   //指向include目录,fPIC表示生成库
	

/*当我们执行make install的时候,执行install-exec-loca,则install-noinst_PROGRAMS将会被执行
 *相当于在命令行输入:$f就是每次循环取出的元素,即libadd_sub.so
 *for f in libadd_sub.so; 
 *	do   
 *		 /usr/bin/install -c $f /(prefix路径)/lib/hello; \
 *       done
 */

install-noinst_PROGRAMS: $(noinst_PROGRAMS)  
        $(mkinstalldirs) $(DESTDIR)$(pkglibdir); \    //创建目录/(prefix路径)/lib/hello

        for f in $(noinst_PROGRAMS); do \         
          $(INSTALL_PROGRAM) $$f $(DESTDIR)$(pkglibdir); \    //安装库到目录/(prefix路径)/lib/hello

        done

install-exec-local: install-noinst_PROGRAMS





include目录:

[root@localhost automake]# cat include/Makefile.am 

# when they are installed into $(includedir)/valgrind.  //make install的时候起复制作用
nobase_pkginclude_HEADERS = \ 
        myinclude.h

现在创建hello.pc.in文件(主要是库和头文件路径信息):

[root@localhost automake]# cat hello.pc.in 

prefix=@prefix@          //也可写为prefix=/outfile  (prefix指定的目录)
libdir=@libdir@           //也可写为{exec_prefix}/lib
includedir=@includedir@/hello   //也可写为${prefix}/include/hello


Name: long 
Description: A test
Version: @VERSION@           //1.0,在configuer.ac写了的
Requires:
Libs: -L${libdir}/lib -ladd_sub -lgcc      //就是生成的库libadd_sub.so
Cflags: -I${includedir}                   //${prefix}/include



生成configure.scan文件:

[root@localhost automake]# autoscan

要将configure.scan重命名为confiugre.ac文件,现在看看这个文件:


[root@localhost automake]# cat configure.ac 

//以AC_INIT开头,以AC_OUTPUT结束

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)                   //需要autoconf版本至少为2.59
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) //定义本程序名称,当前版本、bug汇报地址
AC_CONFIG_SRCDIR([src/main.c])   //确定源码(目录文件)有效性
AC_CONFIG_HEADER([config.h])  //生成config.h文件
# Checks for programs. 
AC_PROG_CC                    //编译器指定,默认为gcc
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC                 //含有标准C(ANSI C)头文件就定义
AC_CHECK_HEADERS([stdlib.h])   //
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile
 		include/Makefile
                src/Makefile
                 src/add_sub/Makefile])  
AC_OUTPUT


修改之后:

[root@localhost automake]# cat configure.ac 

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.


AC_PREREQ([2.68])                         
AC_INIT(hello, 1.0, hello@126.com)        //修改1
AC_CONFIG_SRCDIR([src/main.c])            //有时需要修改,此时不用
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE(hello,1.0)               //修改2


# Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O    //库编译的时候使用          修改3
#AM_PROG_AS(CCAS)      //汇编编译器                 

# Checks for libraries.
#CFLAGS
#CFLAGS="-nostartfiles -g $CFLAGS"    //文件编译选项


# Checks for libraries.


# Checks for header files.
AC_CHECK_HEADERS([stdlib.h])


# Checks for typedefs, structures, and compiler characteristics.


# Checks for library functions.


AC_CONFIG_FILES([Makefile
                 include/Makefile
                 src/Makefile
                 src/add_sub/Makefile
                 hello.pc])              //修改4,生成xxx.pc文件,该文件作用前面说了
AC_OUTPUT


生成aclocal.m4 ,主要处理本地的宏定义:

[root@localhost automake]# aclocal 


生成configure,主要处理本地的宏定义

[root@localhost automake]# autoconf 


生成config.h.in文件

[root@localhost automake]# autoheader 



新建几个文件:

[root@localhost automake]# touch NEWS README AUTHORS ChangeLog


生成Makefile.in文件:

[root@localhost automake]# automake --add-missing 


最后看看这个超小型项目的文件目录框架

[root@localhost automake]# tree

.
|-- AUTHORS
|-- COPYING -> /usr/local/share/automake-1.11/COPYING
|-- ChangeLog
|-- INSTALL -> /usr/local/share/automake-1.11/INSTALL
|-- Makefile
|-- Makefile.am
|-- Makefile.in
|-- NEWS
|-- README
|-- aclocal.m4
|-- autoscan.log
|-- compile -> /usr/local/share/automake-1.11/compile
|-- config.h
|-- config.h.in
|-- config.h.in~
|-- config.log
|-- config.status
|-- configure
|-- configure.ac
|-- configure.scan
|-- depcomp -> /usr/local/share/automake-1.11/depcomp
|-- hello.pc
|-- hello.pc.in
|-- include
|   |-- Makefile
|   |-- Makefile.am
|   |-- Makefile.in
|   `-- myinclude.h
|-- install-sh -> /usr/local/share/automake-1.11/install-sh
|-- missing -> /usr/local/share/automake-1.11/missing
|-- src
|   |-- Makefile
|   |-- Makefile.am
|   |-- Makefile.in
|   |-- add_sub
|   |   |-- Makefile
|   |   |-- Makefile.am
|   |   |-- Makefile.in
|   |   |-- add_sub.c
|   |   |-- libadd_sub.so
|   |   `-- libadd_sub_so-add_sub.o
|   |-- main
|   |-- main-main.o
|   `-- main.c
`-- stamp-h1
4 directories, 55 files

============================================================================

============================================================================

到这里就OK了,现在开始配置编译:

[root@localhost automake]# mkdir  /outfile

[root@localhost automake]# ./configure --prefix=/outfile/

[root@localhost automake]# make &&make install



到这里就结束了,看看安装后的文件(安装在/outfile目录):

[root@localhost automake]# tree /outfile/

outfile/
|-- bin
|   `-- main
|-- include
|   `-- hello
|       `-- myinclude.h
`-- lib
    |-- hello
    |   `-- libadd_sub.so
    `-- helloconfig
        `-- hello.pc


6 directories, 4 files
运行命令:

由于main函数会调用到我们的库,所以需要指定库路径:

做法1:把libadd_sub.so放到lib目录下,然后:

[root@localhost /]# ./outfile/bin/main 

a+b=3
a-b=-1


做法2:编辑ld.so.conf文件

[root@localhost bin]# cat /etc/ld.so.conf

include ld.so.conf.d/*.conf
/usr/lib
/usr/local/lib
/outfile/lib/hello  //添加

然后运行命令是文件生效即可:

[root@localhost /]# ldconfig

[root@localhost /]# ./outfile/bin/main 

a+b=3
a-b=-1


现在我们再编写一个函数来调用我们生成的库:

[root@localhost automake]# cat test.c 

#include<stdio.h>
#include<stdlib.h>


#include"myinclude.h"


int main()
{
        int a=0,b=0;
        printf("Input two number:");
        scanf("%d %d",&a,&b);
        printf("\n");
        printf("sum=%d and sub=%d\n",my_add(a,b),my_sub(a,b));
        return 0;
}
[root@localhost automake]# gcc -o test test.c -I/outfile/include/hello/  -L/outfile/lib/hello -ladd_sub
[root@localhost automake]# ./test
[root@localhost automake]# ./test 
Input two number:10 5


sum=15 and sub=5





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值