gstreamer移植qnx(二):交叉編譯glib

一、簡介

​ 這裏以glib的2.63.0版本,QNX系統的版本是:6.6 。這裏是爲了編譯gstreamer的依賴庫,也就是說最終目標,是將gstreamer移植到QNX6.6系統上。 我選擇的是gstreamer 1.16,他需要的glib版本是2.40以上,因此就索性使用最新的glib版本。 編譯用的host系統是Ubuntu18.04。

二、準備cross-file

​ 因爲最新的glib其構建系統是使用的meson, 而我們這邊是要交叉編譯,所以需要準備一個cross-file的來配置交叉編譯工具鏈

2.1 填寫工具鏈

​ 首先是需要填寫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'
      

2.2 填寫編譯flag信息

​ 第一個就是需要定義一個 _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'

三、 修改meson.build

​ 因爲某些特性,qnx6.6的toolchain裏面沒有,比如xattr, 因此這裏需要修改meson的option選項,這裏有兩種方式:

  • 直接在meson的命令行參數,以 -Dxattr=false的方式進
  • 修改glib裏面的meson.build文件裏面default_options部分

​ 這裏爲了方便,就選擇了修改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

四、修改 gio目錄下的內容

4.1 修改gio目錄下的meson.build

​ 因爲qnx裏面沒有libresolv,也沒有libbind, res_query函數是在libsocket庫裏面。因此需要修改gio目錄下的meson.build文件。

原始內容如下:

if host_system != 'windows'
  # res_query()
  res_query_test = '''#include <resolv.h>
                      int main (int argc, char ** argv) {
                        return res_query("test", 0, 0, (void *)0, 0);
                      }'''
  res_query_test_full = '''#include <sys/types.h>
                           #include <netinet/in.h>
                           #include <arpa/nameser.h>
                        ''' + 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 <sys/types.h>
                   #include <sys/socket.h>
                   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 <resolv.h>
                      int main (int argc, char ** argv) {
                        return res_query("test", 0, 0, (void *)0, 0);
                      }'''
  res_query_test_full = '''#include <sys/types.h>
                           #include <netinet/in.h>
                           #include <arpa/nameser.h>
                        ''' + 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 <sys/types.h>
                   #include <sys/socket.h>
                   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

4.2 修改gunixmounts.c

​ 因爲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

五、編譯過程

  • 新建build目錄並進入build目錄:
mkdir build
cd build
  • meson配置
meson .. --cross-file ../qnx_arm.txt
  • ninja編譯和安裝
ninja
ninja install
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章