这里以glib的2.63.0版本,QNX系统的版本是:6.6 。这里是为了编译gstreamer的依赖库,也就是说最终目标,是将gstreamer移植到QNX6.6系统上。 我选择的是gstreamer 1.16,他需要的glib版本是2.40以上,因此就索性使用最新的glib版本。 编译用的host系统是Ubuntu18.04。
因为最新的glib其构建系统是使用的meson, 而我们这边是要交叉编译,所以需要准备一个cross-file的来配置交叉编译工具链
首先是需要填写CPU和系统信息,以及工具链信息, 顺便还可以填写编译完成之后,安装的目录,其内容如下:
[host_machine]
system = 'qnx'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'
[binaries]
c = 'arm-unknown-nto-qnx6.6.0eabi-gcc'
cpp = 'arm-unknown-nto-qnx6.6.0eabi-g++'
ar = 'arm-unknown-nto-qnx6.6.0eabi-ar'
strip = 'arm-unknown-nto-qnx6.6.0eabi-strip'
[paths]
prefix = '/media/guwen/workspace/project/gstreamer/out'
第一个就是需要定义一个 _QNX_SOURCE宏,不然在编译和POSIX thread相关的部分时,就会出现“error: #error POSIX Scheduling needs P1003.1b-1993 or later” 这类似的错误。
[properties]
c_args = ['-D_QNX_SOURCE=1']
c_link_args = []
修改之后的完整版cross-file文件,qnx_arm.txt如下所示:
host_machine]
system = 'qnx'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'
[binaries]
c = 'arm-unknown-nto-qnx6.6.0eabi-gcc'
cpp = 'arm-unknown-nto-qnx6.6.0eabi-g++'
ar = 'arm-unknown-nto-qnx6.6.0eabi-ar'
strip = 'arm-unknown-nto-qnx6.6.0eabi-strip'
[properties]
c_args = ['-D_QNX_SOURCE=1']
c_link_args = []
[paths]
prefix = '/media/guwen/workspace/project/gstreamer/out'
因为某些特性,qnx6.6的toolchain里面没有,比如xattr, 因此这里需要修改meson的option选项,这里有两种方式:
这里为了方便,就选择了修改meson.build 文件,免得每次敲命令 都要带一长串参数。 当然,也可以把这个配置过程写到一个shell脚本里面。
修改后的default_options如下所示:
default_options : [
'buildtype=release',
'warning_level=1',
'c_std=gnu99',
'xattr=false',
'force_posix_threads=true',
'libmount=false'
]
qnx的libintl没有ngettext这个函数,因此需要使用glib自带的libintl库,
修改前的原始版本:
# First check in libc, fallback to libintl, and as last chance build
# proxy-libintl subproject.
# FIXME: glib-gettext.m4 has much more checks to detect broken/uncompatible
# implementations. This could be extended if issues are found in some platforms.
if cc.has_function('ngettext')
libintl = []
have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset')
else
libintl = cc.find_library('intl', required : false)
if not libintl.found()
libintl = subproject('proxy-libintl').get_variable('intl_dep')
have_bind_textdomain_codeset = true # proxy-libintl supports it
else
have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset',
dependencies : libintl)
endif
endif
修改之后的版本:
# First check in libc, fallback to libintl, and as last chance build
# proxy-libintl subproject.
# FIXME: glib-gettext.m4 has much more checks to detect broken/uncompatible
# implementations. This could be extended if issues are found in some platforms.
if cc.has_function('ngettext')
libintl = []
have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset')
else
#libintl = cc.find_library('intl', required : false)
#if not libintl.found()
libintl = subproject('proxy-libintl').get_variable('intl_dep')
have_bind_textdomain_codeset = true # proxy-libintl supports it
#else
# have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset',
# dependencies : libintl)
#endif
endif
因为qnx里面没有libresolv,也没有libbind, res_query函数是在libsocket库里面。因此需要修改gio目录下的meson.build文件。
原始内容如下:
if host_system != 'windows'
# res_query()
res_query_test = '''#include
int main (int argc, char ** argv) {
return res_query("test", 0, 0, (void *)0, 0);
}' ''
res_query_test_full = '''#include
#include
#include
' '' + res_query_test
if not cc.links(res_query_test_full, name : 'res_query()')
if cc.links(res_query_test_full, args : '-lresolv', name : 'res_query() in -lresolv')
network_libs += [ cc.find_library('resolv') ]
network_args += [ '-lresolv' ]
elif cc.links(res_query_test, args : '-lbind', name : 'res_query() in -lbind')
network_libs += [ cc.find_library('bind') ]
network_args += [ '-lbind' ]
else
error('Could not find res_query()')
endif
endif
# socket()
socket_test = '''#include
#include
int main (int argc, char ** argv) {
return socket(1, 2, 3);
}' ''
if not cc.links(socket_test, name : 'socket()')
if cc.links(socket_test, args : '-lsocket', name : 'socket() in -lsocket')
network_libs += [ cc.find_library('socket') ]
network_args += [ '-lsocket' ]
else
error('Could not find socket()')
endif
endif
修改之后如下:
if host_system != 'windows'
# res_query()
res_query_test = '''#include
int main (int argc, char ** argv) {
return res_query("test", 0, 0, (void *)0, 0);
}' ''
res_query_test_full = '''#include
#include
#include
' '' + res_query_test
if not cc.links(res_query_test_full, name : 'res_query()')
if cc.links(res_query_test_full, args : '-lsocket', name : 'res_query() in -lsocket')
network_libs += [ cc.find_library('socket') ]
network_args += [ '-lsocket' ]
elif cc.links(res_query_test, args : '-lbind', name : 'res_query() in -lbind')
network_libs += [ cc.find_library('bind') ]
network_args += [ '-lbind' ]
else
error('Could not find res_query()')
endif
endif
# socket()
socket_test = '''#include
#include
int main (int argc, char ** argv) {
return socket(1, 2, 3);
}' ''
if not cc.links(socket_test, name : 'socket()')
if cc.links(socket_test, args : '-lsocket', name : 'socket() in -lsocket')
network_libs += [ cc.find_library('socket') ]
network_args += [ '-lsocket' ]
else
error('Could not find socket()')
endif
endif
因为glib没有实现qnx平台的 _g_get_unix_mounts 和 _g_get_unix_mount_points 以及get_mtab_monitor_file 函数,因此编译会出现如下错误:
…/gio/gunixmounts.c:954:2: error: #error No _g_get_unix_mounts() implementation for system
…/gio/gunixmounts.c:1477:2: error: #error No g_get_mount_table() implementation for system
因此需要在 954行和1477行添加qnx版本的的实现,其实也不是实现,就是留个空,代码如下:
//在954行添加
/* Common code {{{2 */
#elif defined(__QNX__)
static GList* _g_get_unix_mounts (void)
{
return NULL;
}
static const char* get_mtab_monitor_file (void)
{
return NULL;
}
#else
#error No _g_get_unix_mounts() implementation for system
#endif
//在1477行添加
/* Common code {{{2 */
#elif defined(__QNX__)
static GList * _g_get_unix_mount_points (void)
{
return NULL;
}
#else
#error No g_get_mount_table() implementation for system
#endif
mkdir build
cd build
meson .. --cross-file ../qnx_arm.txt
ninja
ninja install