1 初步使用
新建个工程,把下面这个demo里的3个文件拷贝到src目录
https://github.com/zorgnax/gobject-examples/tree/master/01-media-from-book
编写Makefile
# 请自行新建一个bld文件夹
OBJ_DIR = ../bld
# 获取所以源文件
SRC = cleanable.c media.c
# 把.c后缀替换为.o,并加上目录
OBJ = ${patsubst %.c, ${OBJ_DIR}/%.o, ${SRC}}
LIBS = -L/d/msys64/mingw64/bin -lgobject-2.0-0 -lglib-2.0-0
INC = -I/mingw64/include/glib-2.0 -I/mingw64/lib/glib-2.0/include
TARGET=${OBJ_DIR}/media
CC=cc
CCFLAGS=-g -Wall -mms-bitfields ${LIBS} ${INC}
all:${TARGET}
${TARGET}: ${OBJ}
${CC} $^ -o $@ ${LIBS} -lwinmm
@echo "Compile done."
${OBJ_DIR}/%.o:%.c
@echo "Compiling $< ==> $@"
${CC} ${CCFLAGS} -c $< -o $@
clean:
# -r删除目录,-f删除文件
rm -f ${OBJ_DIR}/*.o
rm -f ${TARGET}
编译后正常运行,由于我之前装过GTK,所以这步问题不是很大。
2 编译glib
去开源镜像站下载glib2-2.48.0-1.src.tar.gz,解压后执行 makepkg --skippgpcheck
Administrator@DESKTOP-2020PCY MINGW64 /d/source/glib2
# makepkg --skippgpcheck
==> 正在创建软件包:glib2 2.48.0-1 (2021年02月25日 21:30:01)
==> 正在检查运行时依赖关系...
==> 正在检查编译时依赖关系
==> 缺少依赖关系:
-> pkg-config
-> python
-> libxslt-devel
-> docbook-xsl
-> pcre-devel
-> libffi-devel
-> gamin-devel
-> gtk-doc
==> 错误: 无法解决所有的依赖关系。
提示缺少依赖,安装依赖
pacman -S pkg-config python libxslt-devel docbook-xsl pcre-devel libffi-devel gamin-devel gtk-doc
安装完后继续上一步编译,接下来等待编译成功,没碰到什么问题
3 单步调试
在源码目录的D:\source\glib2\src\glib-2.48.0\gobject.libs里编译出了libgobject-2.0.dll.a文件,修改Makefie,使用源码里的库
LIBS = -L/d/msys64/mingw64/bin \
-L/d/source/glib2/src/glib-2.48.0/gobject/.libs \
-lgobject-2.0 -lglib-2.0-0
可以编译通过,但是单步调试没法设断点,因为编译出来没有符号表
b g_object_new
Note: breakpoint 3 also set at pc 0x100401a38.
Breakpoint 5 at 0x100401a38
修改glib-2.48.0/gobject和glib-2.48.0这2个目录下的Makefile
#CFLAGS = -march=x86-64 -mtune=generic -O2 -pipe -fvisibility=hidden
CFLAGS = -march=x86-64 -mtune=generic -g3 -pipe -fvisibility=hidden
修改后重新编译,没有效果。
经过调试,发现是libtool的问题,把sqlite编译后的bld文件夹里的libtool替换src/glib-2.48.0文件夹里的libtool,libtool的这一行控制生成动态库,如果是no,则只生成静态库
(更新:目前在gtk工程下调试会出现以下错误
(exampleapp.exe:10444): GLib-GObject-CRITICAL **: 09:05:48.169: g_param_spec_pool_lookup: assertion ‘pool != NULL’ failed
因为gtk是用x86_64-w64-mingw32编译,所以用x86_64-pc-msys编译出来glib不兼容,glib也要改为x86_64-w64-mingw32编译,且configure也要重新运行一下,另外这个跟libtool没什么关系,可能之前生成和的库系统目录下的库同名了)
# Whether or not to build shared libraries.
build_libtool_libs=yes
接下来再到glib-2.48.0/gobject目录里重新编译,生成下面几个文件
在.libs文件夹下分别生成了3个文件,分布是.a .dll.a .dll。 .dll.a和.a的区别是.dll.a不带调试信息,这点从文件大小就可以看出,还有使用.dll.a时不用自己再加其他库,但是使用.a文件的话还要自己加-ffi等其他依赖库才能编译通过(因为.a仅仅是把.o打个包,并不检查依赖项)
现在.libs文件夹下存在同名的libgobject-2.0.a和libgobject-2.0.dll.a库,默认是优先链接libgobject-2.0.dll.a,因为这个是不带调试信息的,所以还是无法进行单步,可以把libgobject-2.0.dll.a改成其他名字,这样就不会链接到了.dll.a而是去链接.a,但是这时候会发现编译报错
从报错信息里大概可以猜出是缺失什么ffi之类的库,这是因为.a文件并没有链接libffi.dll.a,需要在makefile里再添加-lffi
LIBS = -L/d/msys64/mingw64/bin \
-L/d/source/glib2/src/glib-2.48.0/gobject/.libs \
-lgobject-2.0 -lglib-2.0-0 -lffi
这样就可以编译通过了,也可以单步调试了
4 动态库
一般我们希望通过一下命令生成动态库
gcc -shared *.o xxx.dll
这时候有可能会报错,这就需要我们再添加-l -L等相关依赖参数了,生成exe需要什么参数,生成dll就是什么参数。那为什么生成.a时不会报错呢,因为生成.a文件仅仅只是把所有.o文件打个包而已。
另外可能会报下面这个错误
./.libs/lt-glib-genmarshal.c: In function 'main':
./.libs/lt-glib-genmarshal.c:512:10: warning: implicit declaration of function '_spawnv' [-Wimplicit-function-declaration]
rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
^~~~~~~
./.libs/lt-glib-genmarshal.c:512:19: error: '_P_WAIT' undeclared (first use in this function); did you mean '__VALIST'?
rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
^~~~~~~
__VALIST
./.libs/lt-glib-genmarshal.c:512:19: note: each undeclared identifier is reported only once for each function it appears in
这个错误对结果没有影响,有强迫症的可以把libtool的# include <process.h>移到#include <stdio.h>前面,就不会报错了。