<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      AWTK項目編譯問題整理(1)

      三方庫組織

      公司的項目初步三方庫路徑組織是這樣,awtk-widget開頭的是awtk的自定義控件,無源碼的二進制庫放在sourceless這個文件夾:

      ./3rd
        ├── awtk-widget-battery-widget
        ├── awtk-widget-border-text
        ├── awtk-widget-option-box
        ├── awtk-widget-range-rule-widget
        ├── awtk-widget-range-slider
        ├── awtk-widget-sonar-image
        └── sourceless

      sourceless文件夾下,分不同平臺版本,平臺文件夾下集合所有依賴庫。每個依賴庫我都按一個文件夾整理,include文件夾存放頭文件,bin文件夾存放so庫(為什么是bin不是lib?因為awtk內置的拷貝庫腳本定死了只找bin文件夾下的庫)。

      project/3rd/sourceless/ubuntu$ tree -L 2
      .
      ├── cairo
      │   ├── bin
      │   └── include
      ├── freetype
      │   ├── bin
      │   ├── include
      │   └── share
      ├── libjpeg-turbo
      │   ├── bin
      │   └── include
      ├── libpng
      │   ├── bin
      │   ├── include
      │   └── share
      ├── openssl
      │   ├── bin
      │   └── include
      ├── pixman
      │   ├── bin
      │   └── include
      ├── poco
      │   ├── bin
      │   └── include
      ├── version.md
      └── zlib
        ├── bin
        ├── include
        └── share
      ?

      為什么這樣放?估計當時覺得一個庫就是一個package, 看著比較整潔。

      這種堆放方式后面證明對項目維護十分麻煩,對于上面的cairo, poco, libjpeg, zlib等庫,每一個包我都要在SConscript里面指明路徑:

      SOURCE_3RD_DEPS_PATH = os.path.normpath(os.path.join(os.getcwd(), '3rd/sourceless'))
      ?
      if PLATFORM == 'Linux':
         if LINUX_FB == True:
             SOURCE_3RD_DEPS_PATH = (os.path.join(SOURCE_3RD_DEPS_PATH, 'T113'))
         else:
              SOURCE_3RD_DEPS_PATH = (os.path.join(SOURCE_3RD_DEPS_PATH, 'ubuntu'))
      elif PLATFORM == 'Windows':
         SOURCE_3RD_DEPS_PATH = os.path.join(SOURCE_3RD_DEPS_PATH, 'win')
         
      DEPENDS_LIBS += [
        {
                 'root' : os.path.join(SOURCE_3RD_DEPS_PATH, 'cairo'),
                 'shared_libs' : ['cairo']
            },
            {
                 'root' : os.path.join(SOURCE_3RD_DEPS_PATH, 'freetype'),
                 'shared_libs' : ['freetype']
            },
            {
                 'root' : os.path.join(SOURCE_3RD_DEPS_PATH, 'libjpeg-turbo'),
                 'shared_libs' : ['jpeg', 'turbojpeg']
            },
            {
                 'root' : os.path.join(SOURCE_3RD_DEPS_PATH, 'pixman'),
                 'shared_libs': ['pixman-1']
            },
            {
                 'root' : os.path.join(SOURCE_3RD_DEPS_PATH, 'libpng'),
                 'shared_libs' : ['png16']
            },
            {
                 'root' : os.path.join(SOURCE_3RD_DEPS_PATH, 'zlib'),
                 'shared_libs' : ['z']
            },
            {
                 'root': os.path.join(SOURCE_3RD_DEPS_PATH, 'openssl'),
                 'shared_libs': ['crypto', 'ssl']
            },
            {
                 'root' : os.path.join(SOURCE_3RD_DEPS_PATH, 'poco'),
                 'shared_libs' : ['PocoFoundation', 'PocoUtil', 'PocoXML', 'PocoJSON', 'PocoCrypto', 'PocoNet', 'PocoNetSSL']
            }
      ]
      ...
      ?
      helper.set_deps(DEPENDS_LIBS)

      這樣每加一個庫我都要更新一次DEPEND_LIBS,幾個庫的小項目還好說,要是幾十個庫還得了。

      awtk的helper.set_deps()函數可以自動把shared_libs指定的庫列表拷貝過去,但一些情景也有失靈的時候,只能手動拷貝,這種結構一個個文件夾去拷貝肯定特別酸爽。

      后面我參考linux內對頭文件和so文件的組織方法,把頭文件和庫文件夾都扁平化了:

      project/3rd/binary/ubuntu$ tree -L 2
      .
      ├── bin
      │   ├── addsymlinks.sh
      │   ├── libcairo.so -> libcairo.so.2
      │   ├── libcairo.so.2 -> libcairo.so.2.11600
      │   ├── libcairo.so.2.11600 -> libcairo.so.2.11600.0
      │   ├── libcairo.so.2.11600.0
      │   ├── libcrypto.so -> libcrypto.so.1
      │   ├── libcrypto.so.1 -> libcrypto.so.1.1
      │   ├── libcrypto.so.1.1
      │   ├── libfreetype.so -> libfreetype.so.6
      │   ├── libfreetype.so.6 -> libfreetype.so.6.20
      │   ├── libfreetype.so.6.20 -> libfreetype.so.6.20.0
      │   ├── libfreetype.so.6.20.0
      │   ├── libjpeg.so -> libjpeg.so.62
      │   ├── libjpeg.so.62 -> libjpeg.so.62.4
      │   ├── libjpeg.so.62.4 -> libjpeg.so.62.4.0
      │   ├── libjpeg.so.62.4.0
      ....
      ├── include
      │   ├── cairo
      │   ├── cJSON.h
      │   ├── evconfig-private.h
      │   ├── event2
      │   ├── freetype2
      │   ├── jconfig.h
      │   ├── jerror.h
      │   ├── jmorecfg.h
      │   ├── jpeglib.h
      │   ├── libpng16
      │   ├── mosquitto_broker.h
      │   ├── mosquitto.h
      ....
      └── VERSION.md

      這樣后面加三方庫只需要CV include和bin就行了,不用修改SConstruct, 要手動拷貝直接cp -P xxx/bin/* *就行。

      THIRD_SRC = os.path.join(os.getcwd(), '3rd/')
      BINARY_SRC = os.path.join(THIRD_SRC, 'binary')
      if PLATFORM == 'Linux':
        if LINUX_FB == True:
            BINARY_SRC = (os.path.join(BINARY_SRC, 't113'))
        else:
            BINARY_SRC = (os.path.join(BINARY_SRC, 'ubuntu'))
      ?
      BINARY_LIB_PATH = [
        os.path.join(BINARY_SRC, 'bin')
      ]
      ?
      BINARY_LIB_NAMES = ["mosquitto", "mosquittopp", "nanomsg"]
      BINARY_LIB_NAMES += ["cairo", "freetype", "jpeg", "turbojpeg", "pixman-1", "png16", "z", "crypto", "ssl"]
      BINARY_LIB_NAMES += ["PocoFoundation", "PocoUtil", "PocoXML", "PocoJSON", "PocoCrypto", "PocoNet", "PocoNetSSL"]
      ?
      ?
      DEPENDS_LIBS += [
        {
            "root" : os.path.join(BINARY_LIB_PATH, ''),
            'shared_libs': BINARY_LIB_NAMES,
            'static_libs': []
        }
      ]  

      項目連帶自定義控件一起編譯

      需要加這么一行,不然scons只會編譯項目本身:

      app.prepare_depends_libs(ARGUMENTS, helper, DEPENDS_LIBS)

      這個方法也適用于其他基于Sconstruct的三方庫項目。

      不同平臺區分文件夾輸出

      awtk的scons編譯默認會把執行文件輸出到bin文件夾,而.o文件會和源代碼混在一起。

      這樣涉及跨平臺編譯會有個問題,由于不管什么平臺到默認輸出到bin文件夾,而后一個平臺的編譯輸出會覆蓋前一個平臺的編譯輸出,導致如果編了機器版本的軟件,pc版本的軟件就沒法用了,得重編,反之亦然,不方便同時看測試效果。

      上網查了下scons的SConscript有個variant_dir參數可以輸出build文件夾位置,然后我就去看awtk對于scons的封裝腳本,果然在app_helper_base.py看到這么一段:

      def SConscript(self, SConscriptFiles):
             if not self.BUILD_DIR:
                 Script.SConscript(SConscriptFiles)
             else:
                 env = Environment.Environment()
                 env.Default(self.BUILD_DIR)
                 for sc in SConscriptFiles:
                     dir = os.path.dirname(sc)
                     build_dir = os.path.join(self.BUILD_DIR, dir)
                     Script.SConscript(sc, variant_dir=build_dir, duplicate=False)

      其中self.BUILD_DIR是awtk可通過ARGUMENTS指定的環境參數。

      在項目的SConstrct里可以這么加,我的情況是需要跨windows, ubuntu, 嵌入式linux機器三個平臺:

      PLATFORM = platform.system()
      if PLATFORM == 'Linux':
         if LINUX_FB == True:
             ARGUMENTS['BUILD_DIR'] = 'build_linux_fb'
         else:
             ARGUMENTS['BUILD_DIR'] = 'build_ubuntu'
      elif PLATFORM == 'Windows':
         ARGUMENTS['BUILD_DIR'] = 'build_windows'
      ?

      測試環境為ubuntu20.04, 現在在項目根目錄分別執行sconsscons LINUX_FB=true, 就能看到兩個平臺的輸出分別被放到build_ubuntubuild_linux_fb文件夾了。

      ├── build_linux_fb
      │ ├── bin
      │ ├── lib
      │ ├── src
      │ └── tests
      ├── build_ubuntu
      │ ├── bin
      │ ├── lib
      │ ├── src
      │ └── tests

      不過也有副作用,如果加了三方庫的話,對于之前用helper.set_deps(DEPENDS_LIBS) , DEPEND_LIBS里指定的每個三方庫文件夾三方庫必須被放在BUILD_DIR下,也就是我現在對于之前的二進制庫不得不改成這樣:

      project/3rd/binary$ tree -L 2
      .
      ├── build_linux_fb
      │ ├── bin
      │ ├── include
      │ └── VERSION.md
      └── build_ubuntu
      ├── bin
      ├── include
      └── VERSION.md

      同時項目的scripts/release.py需要修改輸出路徑,默認是寫死bin的。

      OS_NAME = platform.system()
      PRJ_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
      OUTPUT_DIR = join_path(PRJ_DIR, 'release')
      # old
      # BIN_DIR = join_path(PRJ_DIR, 'bin')
      # new
      BIN_DIR = join_path(PRJ_DIR, 'build_linux_fb/bin')

      三方庫軟鏈接問題

      項目用到mosquitto和poco兩個庫,編譯的時候發現bin/ld報找不到庫:

      /bin/ld: cannot find -lmosquitto
      /bin/ld: cannot find -lmosquittopp
      /bin/ld: cannot find -lnanomsg
      /bin/ld: cannot find -lPocoFoundation
      /bin/ld: cannot find -lPocoUtil
      /bin/ld: cannot find -lPocoXML
      /bin/ld: cannot find -lPocoJSON
      /bin/ld: cannot find -lPocoCrypto
      /bin/ld: cannot find -lPocoNet
      /bin/ld: cannot find -lPocoNetSSL

      工作由于趕工,一時半會找不到辦法,只好把用到的庫都拷貝到/usr/local/lib去,但畢竟會污染環境,每次部署到一個新環境就得這么做一次,不是什么好方法。

      有時間后開始探索,檢查編譯log,明明-L路徑已經指明到有庫的路徑3rd/binary/build_ubuntu/bin

      scons: Building targets ...
      g++ -o build_ubuntu/bin/demo -Wl,-rpath=./bin -Wl,-rpath=./ -Wl,-rpath=/project/build_ubuntu/bin build_ubuntu/src/common/battery.o -L3rd/binary/build_ubuntu/bin -L3rd/binary/build_ubuntu/lib -lmosquitto -lmosquittopp -lnanomsg -lPocoFoundation -lPocoUtil -lPocoXML -lPocoJSON -lPocoCrypto -lPocoNet -lPocoNetSSL -lsetting_slider -lsonar_image -lrange_slider -lrange_rule_widget -loption_box -lborder_text -lbattery_widget -lmvvm -lawtk -lGL -lgtk-3 -lgdk-3 -lglib-2.0 -lgobject-2.0 -lXext -lX11 -lsndio -lstdc++ -lasound -lpthread -lm -ldl

      百思不得上網搜索,查到了ld --verbose可以輸出鏈接庫的查找過程,于是我試了下輸出:

      ld -lPocoFoundation --verbose
      中間略去一堆....
      ==================================================
      ld: mode elf_x86_64
      attempt to open /usr/local/lib/x86_64-linux-gnu/libPocoFoundation.so failed
      attempt to open /usr/local/lib/x86_64-linux-gnu/libPocoFoundation.a failed
      attempt to open /lib/x86_64-linux-gnu/libPocoFoundation.so failed
      attempt to open /lib/x86_64-linux-gnu/libPocoFoundation.a failed
      attempt to open /usr/lib/x86_64-linux-gnu/libPocoFoundation.so failed
      attempt to open /usr/lib/x86_64-linux-gnu/libPocoFoundation.a failed
      attempt to open /usr/lib/x86_64-linux-gnu64/libPocoFoundation.so failed
      attempt to open /usr/lib/x86_64-linux-gnu64/libPocoFoundation.a failed
      attempt to open /usr/local/lib64/libPocoFoundation.so failed
      attempt to open /usr/local/lib64/libPocoFoundation.a failed
      attempt to open /lib64/libPocoFoundation.so failed
      attempt to open /lib64/libPocoFoundation.a failed
      attempt to open /usr/lib64/libPocoFoundation.so failed
      attempt to open /usr/lib64/libPocoFoundation.a failed
      attempt to open /usr/local/lib/libPocoFoundation.so failed
      attempt to open /usr/local/lib/libPocoFoundation.a failed
      attempt to open /lib/libPocoFoundation.so failed
      attempt to open /lib/libPocoFoundation.a failed
      attempt to open /usr/lib/libPocoFoundation.so failed
      attempt to open /usr/lib/libPocoFoundation.a failed
      attempt to open /usr/x86_64-linux-gnu/lib64/libPocoFoundation.so failed
      attempt to open /usr/x86_64-linux-gnu/lib64/libPocoFoundation.a failed
      attempt to open /usr/x86_64-linux-gnu/lib/libPocoFoundation.so failed
      attempt to open /usr/x86_64-linux-gnu/lib/libPocoFoundation.a failed

      原來定死了是從無后綴的.so開始找的,無后綴so通常都是指向帶后綴版本so庫的軟鏈接,而我的lib路徑下都是帶版本后綴的,反而沒有軟鏈接,估計是當時源碼編譯后直接CV手動拷貝,于是那些軟鏈接就丟失了,后面才查到應該用cp -P去拷貝。

      一個個ln -s去給這些so庫建鏈接肯定不是什么好辦法,遂在網上尋找可以自動建鏈接的腳本,果然找到一個, 自己學習過程加工了下,如下:

      #!/bin/bash
      # liblinks - generate symbolic links
      # given libx.so.0.0.0 this would generate links for libx.so.0.0, libx.so.0, libx.so
      #
      # ref: https://stackoverflow.com/questions/462100/bash-script-to-create-symbolic-links-to-shared-libraries
      LIBFILES=`ls lib*.so.*`
      for FILE in $LIBFILES;
      do
      shortlib=$FILE
      basename=$FILE
      echo "=================In loop========================"
      while extn=$(echo $shortlib | sed -n '/\.[0-9][0-9]*$/s/.*\(\.[0-9][0-9]*\)$/\1/p')
      echo "basename: $basename extn:$extn"

      [ -n "$extn" ]

      do
      shortlib=$(basename $shortlib $extn)
      echo "ln -fs $basename $shortlib"
      ln -fs $basename $shortlib
      basename=$shortlib
      done
      echo "=====================Out loop=================="
      done

      將腳本命名為addsymlink.sh,放到三方庫bin文件夾中,執行,然后回到項目根目錄scons編譯,就沒再報bin/ld的問題了,看來就是無軟鏈接所致,當前在windows上只知道dll不知道lib的教訓在linux上又演了一把。

       

      不過這個方法并沒有完美解決所有問題,有些庫十分頑固,必須提供帶版本號的版本,否則就無法運行:

      kp25s_expo$ ./bin/demo 
      ./bin/demo: error while loading shared libraries: libjpeg.so.62: cannot open shared object file: No such file or directory

      Poco庫同樣帶版本號就沒有這種現象,ldd一查,發現Poco庫已經自動鏈接到我存放的庫路徑了,libjpeg庫就沒有,不知道是我設了什么環境變量導致還是庫的特性。

      ldd ./bin/demo 
      linux-vdso.so.1 (0x00007fff637d0000)
      libPocoFoundation.so.64 => /home/zhangdalin/AWStudioProjects/project/3rd/sourceless/ubuntu/poco/bin/libPocoFoundation.so.64 (0x00007f15a20d5000)
      libPocoNet.so.64 => /home/zhangdalin/AWStudioProjects/project/3rd/sourceless/ubuntu/poco/bin/libPocoNet.so.64 (0x00007f15a1f94000)
      libPocoNetSSL.so.64 => /home/zhangdalin/AWStudioProjects/project/3rd/sourceless/ubuntu/poco/bin/libPocoNetSSL.so.64 (0x00007f15a1f47000)
      libjpeg.so.62 => not found

      目前也想不到很好的解決方法,zlib和libjpeg都有這種問題,還好出問題的庫就一兩個,在機器打包后可以直接ln -s libxx.so libxx.so.x給這些庫建軟鏈接解決問題,要是大量庫都是這種情況只能cp -P大法了。

      (2025.1.24 ADD 上述問題已經得到解決,見:https://github.com/zlgopen/awtk/issues/895

      找到兩個解決方法: 1.自己寫拷貝函數,指定文件夾把庫拷過去:

      import os
      import shutil
      import subprocess
      import sys
      import glob
      import platform

      def copy_binary_libs_to_build_dir(dst_path, lib_list, src_path):
      """
      將 dst_path 中匹配 lib_list 的文件拷貝到 src_path 文件夾。
      對于 Linux 系統,會查找 lib_list 中對應元素的 .so 文件是否存在,
      如果不存在就調用 dst_path 中的 addsymlink.sh 更新軟鏈接。
      Linux 系統情況下,將拷貝對應元素所有的匹配 .so* 的文件(包括軟鏈接和帶版本號后綴的 so 文件)。
      """
      PLATFORM = platform.system()
      # 確保目標目錄存在
      os.makedirs(src_path, exist_ok=True)

      for lib_name in lib_list:
      # 根據平臺確定庫文件的后綴
      if PLATFORM == 'Windows':
      lib_file = f'{lib_name}.dll'
      src_lib_path = os.path.join(dst_path, lib_file)
      dest_lib_path = os.path.join(src_path, lib_file)

      # 檢查庫文件是否存在
      if not os.path.exists(src_lib_path):
      print(f"Warning: Library {lib_file} not found in {dst_path}.")
      continue

      # 拷貝文件
      shutil.copy2(src_lib_path, dest_lib_path)
      print(f"Copied {src_lib_path} to {dest_lib_path}.")

      elif PLATFORM == 'Linux':
      # Linux 系統下,查找 lib_name 對應的 .so 文件
      lib_file_pattern = f'lib{lib_name}.so*'
      src_lib_pattern = os.path.join(dst_path, lib_file_pattern)
      matching_files = glob.glob(src_lib_pattern)

      if not matching_files:
      # 如果找不到 .so 文件,嘗試調用 addsymlink.sh 更新軟鏈接
      addsymlink_script = os.path.join(dst_path, 'addsymlink.sh')
      if os.path.exists(addsymlink_script):
      print(f"Library {lib_file_pattern} not found. Running addsymlink.sh to update symlinks...")
      try:
      subprocess.check_call([addsymlink_script], cwd=dst_path)
      except subprocess.CalledProcessError as e:
      print(f"Error: Failed to run addsymlink.sh: {e}")
      sys.exit(1)

      # 再次查找 .so 文件
      matching_files = glob.glob(src_lib_pattern)
      if not matching_files:
      print(f"Error: Library {lib_file_pattern} still not found after running addsymlink.sh.")
      sys.exit(1)
      else:
      print(f"Error: Library {lib_file_pattern} not found and addsymlink.sh does not exist.")
      sys.exit(1)

      # 拷貝所有匹配的 .so* 文件
      for src_lib_path in matching_files:
      dest_lib_path = os.path.join(src_path, os.path.basename(src_lib_path))
      shutil.copy2(src_lib_path, dest_lib_path)
      print(f"Copied {src_lib_path} to {dest_lib_path}")

      else:
      print(f"Unsupported platform: {PLATFORM}")
      sys.exit(1)

      2.看了下prepare_depends_libs函數有這么一段,可以指定把對應文件夾給拷貝到BUILD_DIR下:

       if 'needed_files' in lib:
      if Script.GetOption('clean'):
      clear_needed_files(helper, lib['root'], lib['needed_files'])
      else:
      copy_needed_files(helper, lib['root'], lib['needed_files'])

      那么SConstruct可以改成這樣:

      DEPENDS_LIBS += [
      {
      'root': BINARY_LIB_PATHS,
      'shared_libs':[],
      'needed_files': ['bin']
      }

      ]
      app.prepare_depends_libs(ARGUMENTS, helper, DEPENDS_LIBS)

      效果一致,后者好處是不用寫新函數(雖然這種邏輯AI編寫成本挺低)

      上面兩個方法適用于三方庫都在同一個文件夾的情況。

      posted @ 2025-07-06 10:07  另一種開始  閱讀(123)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 国产99青青成人A在线| 午夜福利在线观看6080| 丰满的少妇一区二区三区| 中文文精品字幕一区二区| 久久综合香蕉国产蜜臀av| 国产播放91色在线观看| 国产精品国产高清国产专区| 国产精品综合一区二区三区| 国产成人午夜福利院| 亚洲av色在线播放一区| 中文字幕日韩精品人妻| 国产一卡2卡三卡4卡免费网站| 国产片一区二区三区视频| 最新精品国偷自产在线 | 久久精品国产福利一区二区| 午夜福利免费区在线观看| 女人与公狍交酡女免费| 国产在线98福利播放视频| 99久久国产一区二区三区| 精品少妇爆乳无码aⅴ区| 国产精品三级黄色小视频| 国产精品一区 在线播放| 国产高清精品在线91| 亚洲精品国产综合麻豆久久99| 国内精品久久久久影院网站| 真实国产精品视频400部| 亚洲精品一区二区三区大| 精品国偷自产在线视频99| 国产做a爱片久久毛片a片| 人妻中文字幕一区二区三 | 日本伊人色综合网| 午夜激情福利一区二区| 国产欧美综合在线观看第十页| 体态丰腴的微胖熟女的特征| 亚洲国产精品高清久久久| 亚洲色婷婷综合久久| 国产精选一区二区三区| 五月综合网亚洲乱妇久久| 18禁极品一区二区三区| 绍兴县| 无码伊人久久大杳蕉中文无码 |