Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

Generate versioned shared library on Linux#487

Open
iamazeem wants to merge 6 commits intomainfrom
versioned-shared-lib-for-linux
Open

Generate versioned shared library on Linux#487
iamazeem wants to merge 6 commits intomainfrom
versioned-shared-lib-for-linux

Conversation

@iamazeem
Copy link
Collaborator

@iamazeem iamazeem commented Nov 18, 2025

Related: #438 | #479

For RPM zsv-devel package, the versioned shared library has been required in the review.

After this change, make install will generate the versioned shared library along with its symlinks:

├── libzsv.so -> libzsv.so.1        (symlink from link name to SO name)
├── libzsv.so.1 -> libzsv.so.1.1.0  (symlink from SO name to real)
└── libzsv.so.1.1.0                 (real lib)

Under build directory, only libzsv.so.1.1.0 is generated.
The symlinks are generated only for the installation directory.

SONAME verification with objdump:

$ objdump -p libzsv.so | grep SONAME
  SONAME               libzsv.so.1

NOTE: A new release will be required to proceed with the packaging.

Signed-off-by: Azeem Sajid [email protected]

@iamazeem iamazeem requested a review from liquidaty November 18, 2025 17:21
@iamazeem iamazeem self-assigned this Nov 18, 2025
@iamazeem iamazeem marked this pull request as ready for review November 18, 2025 17:31
Copy link
Owner

@liquidaty liquidaty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sufficiently familiar with this practice to opine very deeply on this approach, other than that I agree with this in general, and am good with these changes so long as you are comfortable that the manner of implementation conforms to industry standard / best practices.

@iamazeem
Copy link
Collaborator Author

UPDATE

Tried to build and test the shared library on Fedora and ran into undefined reference issues.

lib_test.c

#include <stdio.h>
#include <zsv.h>

int main() {
  printf("zsv_lib_version: %s\n", zsv_lib_version());
  return 0;
}

Compile and link:

$ gcc lib_test.c -o lib_test -lzsv
/usr/sbin/ld: /tmp/cc0N9dPk.o: in function `main':
lib_test.c:(.text+0x5): undefined reference to `zsv_lib_version'
collect2: error: ld returned 1 exit status

Checked libzsv.so with nm and found out the symbols are exported but local:

$ nm -C /usr/lib/libzsv.so | grep zsv_lib_version
0000000000003ee0 t zsv_lib_version

Observe the lowercase t above.
The same is true for all the other exported zsv_* symbols :

$ nm -C /usr/lib/libzsv.so | grep zsv_
00000000000047b0 t zsv_abort
0000000000004810 t zsv_cell_count
0000000000005c90 t zsv_cum_scanned_length
0000000000005560 t zsv_delete
0000000000004be0 t zsv_finish
00000000000048c0 t zsv_get_cell
0000000000000460 t zsv_get_cell_1
00000000000048d0 t zsv_get_cell_len
0000000000004900 t zsv_get_cell_str
00000000000004b0 t zsv_get_cell_with_overwrite
0000000000003ee0 t zsv_lib_version
0000000000005630 t zsv_new
0000000000005380 t zsv_next_row
0000000000005cd0 t zsv_parse_bytes
0000000000004170 t zsv_parse_more
0000000000005bd0 t zsv_parse_status_desc
0000000000004bb0 t zsv_peek
0000000000000440 t zsv_pull_row
00000000000048a0 t zsv_quoted
00000000000047c0 t zsv_row_is_blank
0000000000005cc0 t zsv_row_length_raw_bytes
0000000000002710 t zsv_scan
0000000000000820 t zsv_scan_delim_pull
0000000000005c80 t zsv_scanned_length
0000000000004850 t zsv_set_context
0000000000004940 t zsv_set_fixed_offsets
0000000000004890 t zsv_set_input
0000000000004880 t zsv_set_read
0000000000004820 t zsv_set_row_handler
0000000000003ec0 t zsv_set_scan_filter
0000000000003f00 t zsv_strencode
0000000000000600 t zsv_strencode.constprop.0
00000000000024b0 t zsv_throwaway_row

According to nm user manual:

The symbol type.  At least the following types are used;
others are, as well, depending on the object file format.  If
lowercase, the symbol is usually local; if uppercase, the
symbol is global (external).  

Here's a related SO thread:
https://stackoverflow.com/questions/37531846/nm-symbol-output-t-vs-t-in-a-shared-so-library

The root cause is -fvisibility=hidden added by CFLAGS_VISIBILITY_HIDDEN:

zsv/configure

Line 671 in 93376e5

tryflag CFLAGS_VISIBILITY_HIDDEN -fvisibility=hidden

zsv/configure

Line 826 in 93376e5

CFLAGS_VISIBILITY_HIDDEN = $CFLAGS_VISIBILITY_HIDDEN

zsv/src/Makefile

Lines 164 to 166 in 93376e5

${LIBZSV_SHARED_BUILD}: zsv.c zsv_internal.c
@mkdir -p `dirname "$@"`
${CC} ${CFLAGS} ${CFLAGS_VISIBILITY_HIDDEN} -DZSV_BUILD_SHARED -DZSV_VERSION=\"${VERSION}\" -I${INCLUDE_DIR} ${ZSV_OBJ_OPTS} -shared -fPIC -o $@ $< -I../app/external/sqlite3

Removing CFLAGS_VISIBILITY_HIDDEN fixed it:

${LIBZSV_SHARED_BUILD}: zsv.c zsv_internal.c
	@mkdir -p `dirname "$@"`
-	${CC} ${CFLAGS} ${CFLAGS_VISIBILITY_HIDDEN} -DZSV_BUILD_SHARED -DZSV_VERSION=\"${VERSION}\" -I${INCLUDE_DIR} ${ZSV_OBJ_OPTS} -shared -fPIC ${LDFLAGS} -o $@ $< -I../app/external/sqlite3
+	${CC} ${CFLAGS} -DZSV_BUILD_SHARED -DZSV_VERSION=\"${VERSION}\" -I${INCLUDE_DIR} ${ZSV_OBJ_OPTS} -shared -fPIC ${LDFLAGS} -o $@ $< -I../app/external/sqlite3
	@echo Built $@

nm output for zsv_lib_version (observe uppercase T now):

$ nm -C /usr/lib/libzsv.so | grep zsv_lib_version
00000000000007a0 T zsv_lib_version

Verified the rest and the ones marked as t are indeed internal APIs (static):

$ nm -C /usr/lib/libzsv.so | grep zsv_
0000000000003cf0 T zsv_abort
0000000000003d50 T zsv_cell_count
0000000000005970 T zsv_cum_scanned_length
0000000000005270 T zsv_delete
0000000000004920 T zsv_finish
0000000000004600 T zsv_get_cell
00000000000004e0 t zsv_get_cell_1
0000000000004610 T zsv_get_cell_len
0000000000004640 T zsv_get_cell_str
0000000000000530 t zsv_get_cell_with_overwrite
00000000000007a0 T zsv_lib_version
0000000000005310 T zsv_new
00000000000050d0 T zsv_next_row
00000000000059b0 T zsv_parse_bytes
00000000000036b0 T zsv_parse_more
00000000000058b0 T zsv_parse_status_desc
00000000000048f0 T zsv_peek
00000000000004c0 t zsv_pull_row
00000000000045e0 T zsv_quoted
0000000000003d00 T zsv_row_is_blank
00000000000059a0 T zsv_row_length_raw_bytes
0000000000002010 t zsv_scan
0000000000000a30 t zsv_scan_delim_pull
0000000000005960 T zsv_scanned_length
0000000000004590 T zsv_set_context
0000000000004680 T zsv_set_fixed_offsets
00000000000045d0 T zsv_set_input
00000000000045c0 T zsv_set_read
0000000000004560 T zsv_set_row_handler
0000000000000780 T zsv_set_scan_filter
00000000000007c0 T zsv_strencode
0000000000003d60 t zsv_throwaway_row

ldconfig output (lib directory here in local testing, will be lib64 with the RPM package):

$ ldconfig -p | grep zsv
	libzsv.so.1 (libc6,x86-64) => /lib/libzsv.so.1
	libzsv.so (libc6,x86-64) => /lib/libzsv.so

The test program compiled, linked and ran successfully:

$ gcc lib_test.c -o lib_test -lzsv
$ ./lib_test 
zsv_lib_version: 1.1.0

@iamazeem iamazeem requested a review from liquidaty November 19, 2025 06:56
@iamazeem
Copy link
Collaborator Author

Removed ldconfig in f7c7ff2 to avoid sudo for make install.
ldconfig will be added in the post install stage of the RPM devel package.

@iamazeem
Copy link
Collaborator Author

RE: #490 and #487 (comment) above

Looks like both are related.
Setting -fvisibility=hidden with CFLAGS_VISIBILITY_HIDDEN if the APIs are marked __attribute__((visibility("default"))) is desirable but the latter is not setting hence the warnings in #490.
Setting ZSV_EXPORT to __attribute__((visibility("default"))) seems to be the right fix here.

@iamazeem
Copy link
Collaborator Author

Verified that this PR also fixes #489 and #490.

@iamazeem
Copy link
Collaborator Author

@liquidaty: Need another look by you to finalize this.
Tested locally with GCC and MinGW on Ubuntu and Fedora.

@liquidaty
Copy link
Owner

On the surface looks fine to me; I don't see any reason these changes would impact performance but generally with any compiler flag changes I prefer to check benchmarks to ensure expected performance. I've recently updated the benchmark tests in origin/select-parallel so will plan to look at this after that branch has been merged in, which hopefully will happen within a couple days.

@iamazeem
Copy link
Collaborator Author

Sounds good.
Please keep this in mind as part of the next release.
The RPM package uses the released source. Thanks!

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 this pull request may close these issues.

2 participants