1_04_GLib库入门与实践_GLib库的编译

GLib-2.0支持动态编译,也支持静态编译,支持交叉编译,也支持automake、meson自动构建系统编译。默认情况下,编译GLib-2.0会生成三个库,GLib,GObject和GIO,如果只需要Glib-2.0的GLib库,还可以修改编译脚本,只编译GLib部分,GLib只依赖glibc、libpthread及libpcre几个库,比GObject及GIO的依赖要少很多,好多依赖都不需要再安装。

GLib-2.0的依赖库

GLib-2.0编译完毕,一般有以下三个重要so库

  • libglib-2.0.so
  • libgobject-2.0.so
  • libgio-2.0.so

使用ldd命令可以看到以上so库的依赖

[root@centos7 glib-2.56.4]# ldd /lib64/libglib-2.0.so
        linux-vdso.so.1 =>  (0x00007ffcbabdb000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f4f9a057000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4f99e3b000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f4f99a6e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4f9a5cf000)
[root@centos7 glib-2.56.4]# ldd /lib64/libgobject-2.0.so
        linux-vdso.so.1 =>  (0x00007ffeb35a8000)
        libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007f85781fd000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f8577f9b000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8577d7f000)
        libffi.so.6 => /lib64/libffi.so.6 (0x00007f8577b77000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f85777aa000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8578763000)
[root@centos7 glib-2.56.4]# ldd /lib64/libgio-2.0.so
        linux-vdso.so.1 =>  (0x00007fff575f6000)
        libgobject-2.0.so.0 => /lib64/libgobject-2.0.so.0 (0x00007eff87b84000)
        libffi.so.6 => /lib64/libffi.so.6 (0x00007eff8797c000)
        libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0 (0x00007eff87778000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007eff87574000)
        libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007eff8725e000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007eff86ffc000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007eff86de0000)
        libz.so.1 => /lib64/libz.so.1 (0x00007eff86bca000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007eff869a3000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007eff8678a000)
        libmount.so.1 => /lib64/libmount.so.1 (0x00007eff86547000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007eff86331000)
        libc.so.6 => /lib64/libc.so.6 (0x00007eff85f64000)
        /lib64/ld-linux-x86-64.so.2 (0x00007eff88173000)
        libblkid.so.1 => /lib64/libblkid.so.1 (0x00007eff85d24000)
        libuuid.so.1 => /lib64/libuuid.so.1 (0x00007eff85b1f000)

在实际编译GLib-2.0库时,一般会遇到缺少以下几个基础库。
libffi
zlib
libpcre
libmount
在centos7.6系统上,通过yum命令可以安装。

#yum install libffi libffi-devel -y
#yum install zlib zlib-devel -y
#yum install pcre pcre-devel -y
#yum install libmount-devel -y

对于pcre和libmount库的依赖,还可以通过传入编译参数的方式来解决,本部分将在下一节讲解。

常用GLib-2.0编译参数

GLib-2.0的configure有很多选项,使用./configure --help命令可以查看到全部编译选项。其中经常用到的有以下几个:

  • –prefix=PREFIX // 安装路径默认安装到/usr/local/目录下
  • –enable-libmount // 启用libmount,默认启用
  • –disable-libmount // 禁用libmount,需要显式加此参数才能生效
  • –with-pcre=internal //使用GLib内部自带的pcre库,默认为使用系统的即system
  • –enable-static // 默认不编译静态库,需要显式加此参数才能编译出静态库

--with-pcre=internal--with-pcer=system为例,查看生成库的差异。
使用GLib自带的pcre库,选项为--with-pcre=internal,可以发现pcer库被编进glib库中。

[root@centos7 lib]# ar -t libglib-2.0.a | grep pcre
libpcre_la-pcre_compile.o
libpcre_la-pcre_config.o
libpcre_la-pcre_exec.o
libpcre_la-pcre_get.o
......
libpcre_la-pcre_newline.o
libpcre_la-pcre_string_utils.o
libpcre_la-pcre_study.o
libpcre_la-pcre_tables.o
[root@centos7 lib]# nm libglib-2.0.so.0.5600.4 | grep pcre
000000000009b4d0 t pcre_compile
000000000009b4e0 t pcre_config
......
00000000000b4350 t pcre_copy_substring
0000000000117ee0 r _pcre_default_tables
00000000000b29c0 t pcre_exec
000000000033ebc0 d pcre_free

使用系统自带的pcer库,选项为--with-pcer=system,可以发现PCRE库的符号并不在GLib库内。

[root@centos7 nopcre]# ar -t libglib-2.0.a | grep pcre
[root@centos7 nopcre]#
[root@centos7 nopcre]# nm libglib-2.0.so.0.5600.4 | grep pcre
                 U pcre_compile2
                 U pcre_config
                 ......
                 U pcre_exec
                 U pcre_free
                 U pcre_fullinfo
                 U pcre_study

动态编译GLib-2.0

#./configure --prefix=/opt/glib-2.0/
#make
#make install

静态编译GLib-2.0

静态编译GLib-2.0,只需要在configure的时候加一个--enable-static参数即可

#./configure --prefix=/opt/glib-2.0/ --enable-static
#make
#make install

AutoMake方式编译GLib-2.0

GLib-2.0库提供了AutoMake方式编译GLib-2.0,最简单的使用方式是调用autogen.sh脚本。

#./autogen.sh
#make
#make install

Meson方式编译GLib-2.0

Meson和Makefile、AutoMake、CMake类似,都是C语言构建系统。Meson使用Python编写,因此需要先安装Python,推荐3.x以上的Python版本。然后使用pip3 install meson ninja命令安装Meson和Ninja。Ninja也是一个轻量级构建系统,一般将Meson和Ninja配合使用,Meson负责构建项目依赖关系,Ninja进行编译。
安装完Meson和Ninja后,执行以下命令,编译GLib-2.0。

meson build
ninja -C build
ninja -C build install

交叉编译GLib-2.0

GLib-2.0库的交叉编译与其他库大同小异,只要有交叉编译工具链,设置好编译工具路径即可编译。configure文件有两个参数和交叉编译有关,cache-filehost,前者指定了交叉编译的特殊参数,后者指定目标平台。下面是在Linux系统上编译MingW32可用的GLib库。
先设置交叉编译器编译路径,再指定–cache-file文件和目标平台。

PATH=/path/to/mingw32-compiler/bin:$PATH
chmod a-w win32.cache   # 防止被修改
./configure --cache-file=win32.cache --host=mingw32

这里说一下cache文件。由于GLib-2.0与系统底层关系密切,不同系统对某一函数的实现也不一样,绝大多数差异GLib已经在内部做了检测,但有些无法检测到的,只能通过一个cache文件进行设置。当然,这些参数绝大多数情况下是不需要设置的,只有在一些非常特殊平台上才需要手动设置。将需要的参数写入一个文件,就是cache文件。所有参数及其取值如下:

glib_cv_long_long_format=[ll/q/I64]
glib_cv_stack_grows=[yes/no]
glib_cv_working_bcopy=[yes/no]
glib_cv_sane_realloc=[yes/no]
glib_cv_have_strlcpy=[yes/no]
glib_cv_have_qsort_r=[yes/no]
glib_cv_va_val_copy=[yes/no]
glib_cv_rtldglobal_broken=[yes/no]
glib_cv_uscore=[yes/no]
ac_cv_func_posix_getpwuid_r=[yes/no]
ac_cv_func_nonposix_getpwuid_r=[yes/no]
ac_cv_func_posix_getgrgid_r=[yes/no]
glib_cv_use_pid_surrogate=[yes/no]
ac_cv_func_printf_unix98=[yes/no]
ac_cv_func_vsnprintf_c99=[yes/no]

由于以上参数用到的可能性非常小,这里就不做展开介绍了,各参数含义见官方文档《
Cross-compiling the GLib package》一节。

只编译GLib-2.0的GLib部分

如果不需要GObject和GIO两个库,只需要GLib库,则可以先执行./configure生成Makefile,然后修改生成的Makefile文件即可。
在执行./configure时,如果缺少libffi依赖,还可以在configure文件中将libffi检查的选项注释掉,如下所示:

// 7801-7891行
pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFFI" >&5
 $as_echo_n "checking for LIBFFI... " >&6; }
......
 LIBFFI_CFLAGS=$pkg_cv_LIBFFI_CFLAGS
       LIBFFI_LIBS=$pkg_cv_LIBFFI_LIBS
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }

fi

如果还缺少其他依赖比如zlib库,也可以按照相似方法注释掉configure文件的内容,然后修改生成的Makefile文件,将下面一行只保留当前目录和glib目录,其他的都注释掉。

#修改前
SUBDIRS = . m4macros glib gmodule gthread gobject gio po docs tests
#修改后
SUBDIRS = . glib

再执行make,即可在glib-2.56.4/glib/.libs目录下生成libglib-2.0.so.0.5600.4动态库。

GLib-2.0库编译完后的安装结果

GLib-2.0的GLib部分编译完毕后的安装结果,可以看到有bin、include、lib和share四个目录。

/opt/glib-2.0
├── bin
│   ├── glib-gettextize
│   ├── gtester
│   └── gtester-report
├── include
│   └── glib-2.0
│       ├── glib
│       │   ├── deprecated
│       │   │   ├── gallocator.h
│       │   │   ├── ......
│       │   │   └── gthread.h
│       │   ├── galloca.h
│       │   ├── ......
│       │   └── gwin32.h
│       ├── glib.h
│       ├── glib-object.h
│       ├── glib-unix.h
│       └── gmodule.h
├── lib
│   ├── glib-2.0
│   │   └── include
│   │       └── glibconfig.h
│   ├── libglib-2.0.a
│   ├── libglib-2.0.la
│   ├── libglib-2.0.so -> libglib-2.0.so.0.5600.4
│   ├── libglib-2.0.so.0 -> libglib-2.0.so.0.5600.4
│   ├── libglib-2.0.so.0.5600.4
│   ├── ......
│   └── pkgconfig
│       ├── glib-2.0.pc
│       └── ......
└── share
    ├── aclocal
    │   └── *.m4
    ├── gdb
    │   └── auto-load
    └── glib-2.0
        ├── gdb
        │   └── glib_gdb.py
        └── valgrind
            └── glib.supp

基于Glib库开发,只需要头文件和so库,涉及的目录如下:

/opt/glib-2.0/include/glib-2.0/
/opt/glib-2.0/include/glib-2.0/glib
/opt/glib-2.0/lib/glib-2.0/include/glibconfig.h
/opt/glib-2.0/lib/libglib-2.0.so

你可能感兴趣的:(GLib库入门与实践,c语言)