Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configure 脚本无法构建 .so 动态库,但 xmake f -k shared 可以 #214

Closed
mochaaP opened this issue Jun 21, 2023 · 28 comments
Closed

Comments

@mochaaP
Copy link

mochaaP commented Jun 21, 2023

描述问题

https://github.com/tboox/tbox/blob/master/src/tbox/xmake.sh?plain=1#L4

static 改为 shared 后:

linking.release build/linux/x86_64/release/libtbox.so
/usr/bin/ld: build/.objs/tbox/linux/x86_64/release/src/tbox/math/fixed16.c.o: relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
make: *** [makefile:46: build/linux/x86_64/release/libtbox.so] Error 1

期待的结果

xmake f -k shared && xmake b 相同:

[ 99%]: linking.release libtbox.so
[100%]: build ok, spent 4.317s

相关环境

gcc (GCC) 13.1.1 20230614 (Red Hat 13.1.1-4)
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
GNU ld version 2.40-9.fc39
Copyright (C) 2023 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

其他信息

请提供其他附加信息帮助我们诊断问题。

@waruqi
Copy link
Member

waruqi commented Jun 21, 2023

tbox 应该还不支持动态库,xmake.lua 里面是走了 xmake 自动全量导出符号的,xmake 帮忙做了很多事情在里面,configure 是精简版,目前是不支持的,只能构建静态 tbox 库 ,建议使用静态库版本

@topazus
Copy link

topazus commented Jun 24, 2023

I think we can package tbox as static library, though the Fedora packaging guidelines said that it is should be avoided as possible. Maybe later when xmake is packaged in Fedora repository, so it can attempt to use xmake to build tbox as shared library?

Ref: https://docs.fedoraproject.org/en-US/packaging-guidelines/#_packaging_static_libraries

@waruqi
Copy link
Member

waruqi commented Jun 25, 2023

I have support shared library for xmake.sh

./configure --kind=shared
make

@mochaaP
Copy link
Author

mochaaP commented Jun 26, 2023

cflags 需要添加 -fPIC

diff --git a/src/xmake.sh b/src/xmake.sh
index f6fea02c..3d7c7440 100755
--- a/src/xmake.sh
+++ b/src/xmake.sh
@@ -22,6 +22,8 @@ else
     set_strip "all"
     if ! is_kind "shared"; then
         set_symbols "hidden"
+    elif is_kind "shared"; then
+        add_cxflags "-fPIC"
     fi
     set_optimizes "smallest"
 fi

waruqi added a commit that referenced this issue Jun 26, 2023
@waruqi
Copy link
Member

waruqi commented Jun 26, 2023

试下 应该可以了

@topazus
Copy link

topazus commented Jun 26, 2023

For the building of shared library, it needs to be set soname versioning.

@mochaaP
Copy link
Author

mochaaP commented Jun 26, 2023

@topazus:
I doubt that tbox have a stable or versioned ABI?

@mochaaP
Copy link
Author

mochaaP commented Jun 27, 2023

@waruqi

Considering adding -Wl,-soname,libtbox.so.{major}(.{minor}) to linker flags?

@waruqi
Copy link
Member

waruqi commented Jun 27, 2023

-Wl,-soname,libtbox.so.{major}(.{minor})

这有点跟系统平台相关了,这边不太好内置添加,也许其他发行版不是约定的这种 soname 格式呢,例如有可能是 libtbox.1.7.so 呢。。没有统一的规范,像 android 上通常也只需要 libtbox.so 不需要加版本。。

要么你们加个 patch ,仅仅对 fedora 处理这个。

    if is_kind "shared"; then
        add_shflags "-Wl,-soname,libtbox.so.1.7"
    fi

@mochaaP
Copy link
Author

mochaaP commented Jun 27, 2023

其實是統一的,DT_SONAME 這個字段在 Android 上也是有相同語義的。

https://en.wikipedia.org/wiki/Soname

@waruqi
Copy link
Member

waruqi commented Jun 27, 2023

https://en.wikipedia.org/wiki/Soname

但是通常构建的 jni so 库,对 app 加载来讲,是不需要这个的,也不需要加版本,我说的不是 android 系统库

另外 macos 上又是 libtbox.1.7.3.dylib ,又不同

@mochaaP
Copy link
Author

mochaaP commented Jun 27, 2023

DT_SONAME 不影響你 dlopen() 時的實際名字啊。你最終成品如果生成 libtbox.so 也沒問題的。
只要頭裡有這個信息就好了,symlink 什麼的 rpm 這邊會自動搞定。

另外 macos 上又是 libtbox.1.7.3.dylib ,又不同

那就 libtbox.so.x.y.z 也可以

waruqi added a commit that referenced this issue Jun 27, 2023
@waruqi
Copy link
Member

waruqi commented Jun 27, 2023

加了,再试试

@mochaaP
Copy link
Author

mochaaP commented Jun 27, 2023

xmake.lua 的部分是不是要同步一下這個行為?

@mochaaP
Copy link
Author

mochaaP commented Jun 27, 2023

DESCRIPTION
ldconfig creates the necessary links and cache to the most recent shared
libraries found in the directories specified on the command line, in the
file /etc/ld.so.conf, and in the trusted directories, /lib and /usr/lib.
On some 64-bit architectures such as x86-64, /lib and /usr/lib are the
trusted directories for 32-bit libraries, while /lib64 and /usr/lib64 are
used for 64-bit libraries.

The cache is used by the run-time linker, ld.so or ld-linux.so. ldconfig
checks the header and filenames of the libraries it encounters when
determining which versions should have their links updated. ldconfig
should normally be run by the superuser as it may require write
permission on some root owned directories and files.

ldconfig will look only at files that are named lib*.so* (for regular
shared objects) or ld-.so (for the dynamic loader itself). Other files
will be ignored. Also, ldconfig expects a certain pattern to how the
symbolic links are set up, like this example, where the middle file
(libfoo.so.1 here) is the SONAME for the library:

 libfoo.so -> libfoo.so.1 -> libfoo.so.1.12

Failure to follow this pattern may result in compatibility issues after
an upgrade.

ref: https://manned.org/ldconfig

好像還是。。不太對?

soname 後面好像是只有一位 major version,但是最終文件上應該是完整的版本號

能考慮一下 build .so 的時候最終生成 libtbox.so.<version>,讓 libtbox.solibtbox.so.1 作為 symlink 指向最終文件?

e.g. libsodium 是這樣的:
libsodium artifacts

@waruqi
Copy link
Member

waruqi commented Jun 27, 2023

所以 这个平台相关性太强了。。暂时不考虑内部搞了。。soname 那个我打算先去了,,要不你外面打个 patch 吧。。

@mochaaP
Copy link
Author

mochaaP commented Jun 27, 2023

也行吧,那issue先挂这,我先自己patch了

@waruqi
Copy link
Member

waruqi commented Jun 27, 2023

那我 soname 那个先 revert 了

@mochaaP
Copy link
Author

mochaaP commented Jun 28, 2023

我稍微研究了一下 CMake 构建 shared lib 的行为:

(尖括号内的均为 CMake target property,箭头表示 symlink)

  • 构建目标为 ELF shared object 时:
    libexample.so.<VERSION> 是最终构建目标(实际的文件)。
    libexample.so.<SOVERSION>libexample.so.<VERSION>
    libexample.solibexample.so.<SOVERSION>

    Details
    $ readelf -d libexample.so | grep SONAME
     0x000000000000000e (SONAME)             Library soname: [libexample.so.<SOVERSION>]
    

    SOVERSION 未定义,回落到 VERSION,再回落到没有版本号的 soname。

  • 构建目标为 Windows DLL 时:
    libexample.dll 是最终构建目标。
    <VERSION_MAJOR><VERSION_MINOR> 写入目标的 _IMAGE_OPTIONAL_HEADER

    Details
    $ x86_64-w64-mingw64-objdump -x libexample.dll | grep ImageVersion
    MajorImageVersion	<VERSION_MAJOR>
    MinorImageVersion	<VERSION_MINOR>
    

    SOVERSIONVERSION 均未定义,不写入。

  • 构建目标为 Mach-O 时:
    未测试,没有设备。

ref: cmake.org/...


GNU autotools 的处理行为见上条。

@mochaaP
Copy link
Author

mochaaP commented Jun 28, 2023

所以感觉,如果要确保 shared libs 没兼容性问题的话得实现一下

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


So I feel that if you want to ensure that shared libs has no compatibility issues, you have to implement it

@mochaaP
Copy link
Author

mochaaP commented Jun 28, 2023

diff --git a/configure b/configure
index fc11bd2b..9810e98e 100755
--- a/configure
+++ b/configure
@@ -1443,6 +1443,24 @@ _get_target_filename() {
     _ret="${filename}"
 }
 
+# get target soname
+_get_target_soname() {
+    local name="${1}"
+    _get_target_item "${name}" "filename"; local filename="${_ret}"
+    if test_z "${filename}"; then
+        _get_target_basename "${name}"; local basename="${_ret}"
+        _get_target_extension "${name}"; local extension="${_ret}"
+        _get_target_prefixname "${name}"; local prefixname="${_ret}"
+        filename="${prefixname}${basename}${extension}"
+    fi
+    _get_target_item "${name}" "soversion"; local soversion="${_ret}"
+    if test_nz "${soversion}"; then
+        filename="${filename}.${soversion}"
+    fi
+
+    _ret="${filename}"
+}
+
 # get target directory
 _get_targetdir() {
     local name="${1}"
@@ -1594,6 +1612,13 @@ _get_target_toolchain_flags_for_gcc() {
             flags="${flags} -fPIC"
         fi
     fi
+    # add soname, https://github.com/tboox/tbox/issues/214#issuecomment-1608882997
+    if test_eq "${targetkind}" "shared" && test_eq "${toolkind}" "sh" && is_plat "linux"; then
+        _get_target_soname "${name}"; local soname="${_ret}"
+        if test_nz "${soname}"; then
+            flags="${flags} -Wl,-soname,${soname}"
+        fi
+    fi
     _ret="${flags}"
 }
 
@@ -1613,6 +1638,11 @@ _get_target_toolchain_flags_for_clang() {
             flags="${flags} -fPIC"
         fi
     fi
+    # add soname, https://github.com/tboox/tbox/issues/214#issuecomment-1608882997
+    if test_eq "${targetkind}" "shared" && test_eq "${toolkind}" "sh" && is_plat "linux"; then
+        _get_target_soname "${name}"; local soname="${_ret}"
+        flags="${flags} -Wl,-soname,${soname}"
+    fi
     if is_plat "macosx"; then
         _os_iorunv "xcrun" "-sdk" "macosx" "--show-sdk-path"; local sdkdir="${_ret}"
         if test_nz "${sdkdir}"; then
@@ -1946,8 +1976,10 @@ set_version() {
     fi
     local version="${1}"
     local version_build="${2}"
+    local soversion="${3:-${version%%.*}}"
     _set_target_item "${_xmake_sh_target_current}" "version" "${version}"
     _set_target_item "${_xmake_sh_target_current}" "version_build" "${version_build}"
+    _set_target_item "${_xmake_sh_target_current}" "soversion" "${soversion}"
 }
 
 # set default in target

简单写了一下 soname 支持,symlink 和 targetfile 的重命名没写

@waruqi
Copy link
Member

waruqi commented Jun 28, 2023

暂时不考虑,另外即使要做,这个也应该是在安装时候处理,而不是构建阶段

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


I don't think about it for the time being, and even if it is done, this should be processed during installation, not during the construction phase

@waruqi
Copy link
Member

waruqi commented Jun 29, 2023

macOS

cmake

drwxr-xr-x  3 ruki  staff     96  6 29 17:00 cmake
-rwxr-xr-x  1 ruki  staff  53368  6 29 17:00 libogg.0.8.4.dylib
lrwxr-xr-x  1 ruki  staff     18  6 29 17:00 libogg.0.dylib -> libogg.0.8.4.dylib
lrwxr-xr-x  1 ruki  staff     14  6 29 17:00 libogg.dylib -> libogg.0.dylib
drwxr-xr-x  3 ruki  staff     96  6 29 17:00 pkgconfig

autoconf

-rwxr-xr-x  1 ruki  staff  88048  6 29 17:15 libffi.8.dylib
lrwxr-xr-x  1 ruki  staff     14  6 29 17:15 libffi.dylib -> libffi.8.dylib
-rwxr-xr-x  1 ruki  staff    960  6 29 17:15 libffi.la
drwxr-xr-x  3 ruki  staff     96  6 29 17:15 pkgconfig

meson

-rwxr-xr-x  1 ruki  staff  918912  6 29 17:20 libui.A.dylib
lrwxr-xr-x  1 ruki  staff      13  6 29 17:20 libui.dylib -> libui.A.dylib
drwxr-xr-x  3 ruki  staff      96  6 29 17:20 pkgconfig
-rwxr-xr-x   1 ruki  staff  1242128  6 29 17:25 libglib-2.0.0.dylib
lrwxr-xr-x   1 ruki  staff       19  6 29 17:25 libglib-2.0.dylib -> libglib-2.0.0.dylib

各家还是有差异的,cmake 搞了两层软链,autoconf/meson 一层软链。。感觉也没有统一的规范。。

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


macOS

cmake

drwxr-xr-x 3 ruki staff 96 6 29 17:00 cmake
-rwxr-xr-x 1 ruki staff 53368 6 29 17:00 libogg.0.8.4.dylib
lrwxr-xr-x 1 ruki staff 18 6 29 17:00 libogg.0.dylib -> libogg.0.8.4.dylib
lrwxr-xr-x 1 ruki staff 14 6 29 17:00 libogg.dylib -> libogg.0.dylib
drwxr-xr-x 3 ruki staff 96 6 29 17:00 pkgconfig

autoconf

-rwxr-xr-x 1 ruki staff 88048 6 29 17:15 libffi.8.dylib
lrwxr-xr-x 1 ruki staff 14 6 29 17:15 libffi.dylib -> libffi.8.dylib
-rwxr-xr-x 1 ruki staff 960 6 29 17:15 libffi.la
drwxr-xr-x 3 ruki staff 96 6 29 17:15 pkgconfig

meson

-rwxr-xr-x 1 ruki staff 918912 6 29 17:20 libui.A.dylib
lrwxr-xr-x 1 ruki staff 13 6 29 17:20 libui.dylib -> libui.A.dylib
drwxr-xr-x 3 ruki staff 96 6 29 17:20 pkgconfig
-rwxr-xr-x 1 ruki staff 1242128 6 29 17:25 libglib-2.0.0.dylib
lrwxr-xr-x 1 ruki staff 19 6 29 17:25 libglib-2.0.dylib -> libglib-2.0.0.dylib

各家 still have differences,cmake 搞了two layers of soft chain,autoconf/meson one layer of soft chain。。 Feels like there is no unified specification。。

@waruqi
Copy link
Member

waruqi commented Jul 25, 2023

xmake.lua 上我先做了支持,xmake-io/xmake#4002 等没问题了,后面会同步相关api 和实现到 xmake.sh

@waruqi
Copy link
Member

waruqi commented Jul 25, 2023

@mochaaP xmake.sh 里面我也支持上了,可以试试 xmake-io/xmake.sh#5

tbox 上也更新了 ddb2a4f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants