永发信息网

如何在linux下构建强大的build系统

答案:1  悬赏:0  手机版
解决时间 2021-04-17 04:58
如何在linux下构建强大的build系统
最佳答案
大致目录构建如下:
├── uc-config.in : 用来生成配置环境信息的可执行程序
├── uc.pc.in : 用来生成配置环境信息的文件
├── uc.spec.in : 用来产生spec文件
├── autogen.sh : build工具
├── conf : 配置文件目录
├── config.h.in : 一些编译过程中的配置信息
├── configure : 配置工具
├── configure.ac : 形成build以及配置工具的文件
├── data : 数据目录
├── doc : 文档
├── Doxyfile.in : 生成Doxyfile的文件,主要用于doxygen的配置文件
├── include : 外部的头文件,工程内的文件不要放入
├── lib : 外部的库文件,工程内的库不要放入
├── m4 : m4文件
├── scripts : 常使用的一些script,用于运转系统
├── src : 源代码目录
│ ├── xxxMain.cpp : 用于产生xxx的gnome版本的源文件,含有main入口
│ ├── xxx.h : 用于外部开发的xxx接口
│ ├── xxxMain.cpp:用于产生xxx的kde版本,含有kde的main入口
│ ├── common : 普通的头文件
│ │ ├── xxxdef.h : xxx的一般定义
│ │ ├── xxxrst.h : xxx的返回值类型定义
│ │ ├── xxxtypes.h : xxx的类型定义
│ │ ├── common.h : 共用头文件,含有xxxdef.h、xxxrst.h和xxxtypes.h等头文件
│ ├── network : 网络通讯库
│ ├── ui : ui界面库
│ │ ├── gnome : gnome界面库,主要是gtk2的一些界面接口
│ │ ├── kde : kde界面库,主要是qt的一些界面接口
│ └── util : 常用的一些共用库
├── test : 单元测试
│ ├── dotest.cpp : 主要测试入口
│ ├── network
│ ├── template.cpp : 样例模板 cpp 文件
│ ├── template.h : 样例模板 头文件
│ ├── ui
│ │ ├── gnome
│ │ └── kde
│ └── util
└── tools : 常使用的一些工具,用于维护系统
如何编写configure.ac
configure.ac是产生configure以及automake重要文件,一般可以使用autoscan生成,这里就不太详细描述,网上可以google到很多资料。
一般开发人员只需要使用autogen.sh,这个脚本会完成所有的automake以及autoconf的操作,虽然其中m4文件定义的宏非常重要,但是不需要开发人员完全读懂,这里也不是关注的重点,等一步步的完全熟悉了,再过来了解也不迟。
这里项目中默认已经生成好了configure.ac。
如何编译Makefile.am
开发人员重点关注的是Makefile.am,Makefile.am完全和Makefile的语法一样,不过你可以写少量的信息就足够了。
如何编译源文件
这里所指的源文件一般指c/c++源文件,对于java的源文件,我们将ant放入Makefile.am,道理一样。编译源文件一般有两种方式,库文件和可执行文件,而库文件也有两种方式,静态库文件和动态库文件,一般静态库用:
lib_LIBRARIES = libcpthread.a

这种方式表示生成一个静态库,对应的源文件如何写呢?
libcpthread_a_SOURCES = thread.cpp thread.h

当然对于一般头文件可以忽略不写,不过建议写上,因为每个开发者都不是很规范,头文件不仅仅只有申明,有的头文件还会有实现。如果有多个cpp文件生成一个库文件,则全部添加;如果有多个.a文件需要生成,只需要用空格隔开.a文件,相应的源文件对应到.a文件即可,如下所示:
lib_LIBRARIES = libcpthread1.a libcpthread2.a libcpthread2.a

那么动态库该如何写呢?有人肯定会提到
lib_LIBRARIES = libcpthread.so
libcpthread_so_SOURCES = thread.cpp thread.h

不过可惜是错误的,这里顺便提到一个libtool,主要用来生成静态库和动态库的一个工具,不过在autogen.sh工具里面已经包含。正确写法如下:
lib_LTLIBRARIES = libcpthread.la
libcpthread_la_SOURCES = thread.cpp thread.h

有人看到这觉得很奇怪,为什么要生成.la这个文件呢?.la文件内容如下:
# libcpthread.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.5.6 (1.1220.2.95 2004/04/11 05:50:42)
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libcpthread-1.0.0.so.1'

# Names of this library.
library_names='libcpthread-1.0.0.so.1.0.0 libcpthread-1.0.0.so.1 libcpthread.so'

# The name of the static archive.
old_library='libcpthread.a'

# Libraries that this one depends upon.
dependency_libs=' -ldl /usr/lib64/libconfig++.la /usr/lib64/libconfig.la /usr/lib64/libchardet.la /usr/local/lib64/libalog.la -lz /usr/local/lib64/libanet.la -lpthread -lalog'

# Version information for libcpthread.
current=1
age=0
revision=0

# Is this an already installed library?
installed=no

# Should we warn about portability when linking against -modules?
shouldnotlink=no

# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''

# Directory that this library needs to be installed in:
libdir='/usr/lib'

看到了吧?里面指定了关于静态库和动态库的依赖等一系列的信息,具体还可以参考项目框架设计模式中库公约的部分。
静态文件和动态文件都会在当前目录的.libs下,当然开发者也不需要关注库文件本身,了解在这个路径下即可。
可执行文件如何编译呢?

bin_PROGRAMS = threadpool
threadpool_SOURCES = threadpoolMain.cpp

此处的bin_PROGRAMS会将程序安装到${prefix}路径下,如果不想安装,可以采用:

noinst_PROGRAMS = testthreadpool
threadpool_SOURCES = threadpoolMain.cpp

同理,如果有多个cpp文件生成一个库文件,则全部添加;如果有多个.la文件或者可执行文件需要生成,只需要用空格隔开.a文件,相应的源文件对应到.a文件即可,如下所示:

lib_LTLIBRARIES = libcpthread1.la libcpthread2.la libcpthread2.la
noinst_PROGRAMS = testthreadpool1 testthreadpool2 testthreadpool3

如果库文件或者二进制文件有头文件的申明依赖或追加一些编译选项,则可以使用CFLAGS或CPPFLAGS,如下所示:

threadpool_CPPFLAGS = -I$(top_srcdir)/include/example.h

如果是java源文件,只需要遵循普通makefile写法即可,如:

all: threadpool.jar
.PHONY: threadpool.jar clean
threadpool.jar:

@ant jar
clean:

ant clean

当然,ant需要配置好build.xml哟!

如何连接库

连接库的的时候,同样也会有区分,工程外部的连接需使用LDFLAGS,如下所示:

libcpthread_la_LDFLAGS = -pthread

如果是内部库,我们就直接使用.la文件,这样在选择静态连接或者动态连接的时候,就给开发者很大的空间。值得注意的是,库文件和二进制的内部库连接宏并不相同,表现如下:

libcpthread_la_LIBADD = $(top_srcdir)/src/util/libutil.la
threadpool_LDADD = libcpthread.la

现在编译和连接是否都了解了呢?

非编译的一些开发

当创建一个脚本或配置文件的时候:

make dist

则形成一个.gz的压缩包,但刚才创建的脚本或配置文件并没有加入,于是:

EXTRA_DIST = conf/config.cfg
script/example.sh

即可将脚本或配置文件放入到压缩包中;

若在多层目录上的时候,还可以使用宏SUBDIRS指定内部编译的顺序(包括当前目录),比如:

SUBDIRS = util /
thread /
. /
log
/
common

在编译系统make的时候,会严格按照顺序进行。
提供外部开发
如果工程完成了,别人想使用上面的库文件进行二次开发,该如何做呢?
libcpthreadincludedir = $(includedir)/@PACKAGE_NAME@/util/thread
libcpthreadinclude_HEADERS = thread.h

这样在编译系统make install的时候,会将头文件安装到上面指定的目录下,别人依照上面的build系统继续下面的build了。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
新浪微博手机登录个人中心在哪
用手机美图如何改像素,怎么调手机版的美图秀
春天在那日子进补最好
洗手做羹汤是什么意思,洗手作羹汤什么意思?
从上海怎么去张家港,上海到张家港,怎么走最
动画脚本的特点
宣传标语对人民代表大会的简称应该是“几届人
Computer-education advocates forsake this
带语蝶柔的诗句有哪些,形容 水 句子是
第一批修建雷州青年运河的民工有什么补助金?
描写老师的诗句
白记葫芦头这个地址在什么地方,我要处理点事
单选题目前,居民利用双休日、节假日进夜校、
钉钉推荐好友怎么删除,钉钉怎么删除离职人员
单选题Nostudent &
推荐资讯
描写红辣椒炒菜的诗句,我们炒菜用的红辣椒叫
有电影吗。来。个网。
夏天同样充满诗意,看,下雨了( , 。)诗句
微信,信而签,具体怎么操作谁知道?
描写盛开的桃花的诗句,描写或赞美桃花盛开的
外面一层薄纱到小脚的是什么裙子
做面包怎么发酵,面包要怎样发酵?
593乘以一位数使他小于3000,有几种填法
一池清潭水 两眼跨忘川这是什么意思啊
揭阳市锡中村办理未婚证明的民政局电话号码是
如何提高优质服务,什么是优质服务
想问一下从南通火车站到南通汽车站坐哪路公交
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?