作者:阿龙。
链接: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]# lspkgconfig 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
[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