From 44245974c6159899980ca78f94818c8bf6b9853b Mon Sep 17 00:00:00 2001 From: Kaleb Reid <78945904+Kaleb-Reid@users.noreply.github.com> Date: Sun, 15 Mar 2026 16:38:03 -0700 Subject: [PATCH] Allow specifying different sonames under specific conditions --- README.md | 7 ++++--- examples/Makefile | 6 +++--- generate-wrapper.py | 38 +++++++++++++++++++++++++++++++++----- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d4c71cd..6d205b5 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,8 @@ options: Include as they appear inside a program (eg ) (may appear more than once) --include-dir INCLUDE_DIR Directories to add to the compiler include path. - --soname SONAME Soname of the wrapped library (eg libpulse.so.0) + --soname [MACRO,]SONAME + Soname of the wrapped library (eg libpulse.so.0) (may appear more than once). Additional occurences must include a predefined macro prefix (eg __OpenBSD__,libpulse.so). --init-name INIT_NAME Name to use for the initialize function. This will generate an initialize_ function. (eg pulse) --output-header OUTPUT_HEADER @@ -52,8 +53,8 @@ options: Ignore all header files not explicitly mentioned Example usage for wrapping pulse: -generate-wrapper.py --include /usr/include/pulse/pulseaudio.h --sys-include '' --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header pulse.h --output-implementation pulse.c +generate-wrapper.py --include /usr/include/pulse/pulseaudio.h --sys-include '' --soname libpulse.so.0 --soname __OpenBSD__,libpulse.so --omit-prefix _pa_ --init-name pulse --output-header pulse.h --output-implementation pulse.c Example usage for wrapping X: -generate-wrapper.py --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include '' --sys-include '' --sys-include '' --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib.h --output-implementation xlib.c +generate-wrapper.py --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include '' --sys-include '' --sys-include '' --soname libX11.so.6 --soname __OpenBSD__,libX11.so --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib.h --output-implementation xlib.c ``` diff --git a/examples/Makefile b/examples/Makefile index 5666a4e..9a492ab 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -10,10 +10,10 @@ paplay.o: paplay.c pulse-wrap.h sndfile-wrap.h $(CC) -c -o paplay.o paplay.c pulse-wrap.c pulse-wrap.h: - ../generate-wrapper.py --include /usr/include/pulse/pulseaudio.h --sys-include '' --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header pulse-wrap.h --output-implementation pulse-wrap.c + ../generate-wrapper.py --include /usr/include/pulse/pulseaudio.h --sys-include '' --soname libpulse.so.0 --soname __OpenBSD__,libpulse.so --omit-prefix _pa_ --init-name pulse --output-header pulse-wrap.h --output-implementation pulse-wrap.c sndfile-wrap.c sndfile-wrap.h: - ../generate-wrapper.py --include /usr/include/sndfile.h --sys-include '' --soname libsndfile.so.1 --init-name sndfile --output-header sndfile-wrap.h --output-implementation sndfile-wrap.c + ../generate-wrapper.py --include /usr/include/sndfile.h --sys-include '' --soname libsndfile.so.1 --soname __OpenBSD__,libsndfile.so --init-name sndfile --output-header sndfile-wrap.h --output-implementation sndfile-wrap.c paplay: paplay.o sndfile-wrap.o pulse-wrap.o $(CC) paplay.o pulse-wrap.o sndfile-wrap.o -o paplay -ldl @@ -25,7 +25,7 @@ xlib.o: xlib.c xlib-wrap.h $(CC) -c -o xlib.o xlib.c xlib-wrap.c xlib-wrap.h: - ../generate-wrapper.py --ignore-other --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include '' --sys-include '' --sys-include '' --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib-wrap.h --output-implementation xlib-wrap.c + ../generate-wrapper.py --ignore-other --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include '' --sys-include '' --sys-include '' --soname libX11.so.6 --soname __OpenBSD__,libX11.so --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib-wrap.h --output-implementation xlib-wrap.c xlib: xlib.o xlib-wrap.o $(CC) xlib.o xlib-wrap.o -o xlib -ldl diff --git a/generate-wrapper.py b/generate-wrapper.py index 77abc12..e57fe4a 100755 --- a/generate-wrapper.py +++ b/generate-wrapper.py @@ -156,7 +156,7 @@ def generate_header(sysincludes, functions, initname, implementation_headers): retval.append("") return "\n".join(retval) -def write_implementation(filename, soname, sysincludes, initname, functions, sym_definitions, implementation_headers): +def write_implementation(filename, sonames, sysincludes, initname, functions, sym_definitions, implementation_headers): with open(filename, 'w') as file: file.write(generate_header(sysincludes, functions, initname, implementation_headers)) file.write("#include \n") @@ -165,10 +165,30 @@ def write_implementation(filename, soname, sysincludes, initname, functions, sym for sym_definition in sym_definitions: file.write(f"{sym_definition};\n") + first_name = True + fallback_soname = "" + for value in sonames: + if value.count(",") == 0: + fallback_soname = value + continue + macro = value.split(",", 1)[0] + soname = value.split(",", 1)[1] + if first_name: + file.write(f"#ifdef {macro}\n") + first_name = False + else: + file.write(f"#elif defined({macro})\n") + file.write(f"#define SONAME \"{soname}\"\n") + if len(sonames) > 1: + file.write("#else\n") + file.write(f"#define SONAME \"{fallback_soname}\"\n") + if len(sonames) > 1: + file.write("#endif\n") + file.write(f"int initialize_{initname}(int verbose) {{\n") file.write(" void *handle;\n") file.write(" char *error;\n") - file.write(f" handle = dlopen(\"{soname}\", RTLD_LAZY);\n") + file.write(" handle = dlopen(SONAME, RTLD_LAZY);\n") file.write(" if (!handle) {\n") file.write(" if (verbose) {\n") file.write(" fprintf(stderr, \"%s\\n\", dlerror());\n") @@ -219,16 +239,16 @@ def write_header(filename, sysincludes, initname, functions, sym_definitions): formatter_class=argparse.RawDescriptionHelpFormatter, epilog=textwrap.dedent(''' Example usage for wrapping pulse: - %(prog)s --include /usr/include/pulse/pulseaudio.h --sys-include '' --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header pulse.h --output-implementation pulse.c + %(prog)s --include /usr/include/pulse/pulseaudio.h --sys-include '' --soname libpulse.so.0 --soname __OpenBSD__,libpulse.so --omit-prefix _pa_ --init-name pulse --output-header pulse.h --output-implementation pulse.c Example usage for wrapping X: - %(prog)s --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include '' --sys-include '' --sys-include '' --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib.h --output-implementation xlib.c + %(prog)s --include /usr/include/X11/Xlib.h --include /usr/include/X11/Xutil.h --include /usr/include/X11/XKBlib.h --sys-include '' --sys-include '' --sys-include '' --soname libX11.so.6 --soname __OpenBSD__,libX11.so --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header xlib.h --output-implementation xlib.c ''') ) parser.add_argument('--include', action='append', help='Include files to read (may appear more than once)', required=True) parser.add_argument('--sys-include', action='append', help='Include as they appear inside a program (eg ) (may appear more than once)', required=True) parser.add_argument('--include-dir', action='append', help='Directories to add to the compiler include path.', required=False) - parser.add_argument('--soname', help='Soname of the wrapped library (eg libpulse.so.0)', required=True) + parser.add_argument('--soname', action='append', help='Soname of the wrapped library (eg libpulse.so.0) (may appear more than once). Additional occurences must include a predefined macro prefix (eg __OpenBSD__,libpulse.so).', required=True) parser.add_argument('--init-name', help='Name to use for the initialize function. This will generate an initialize_ function. (eg pulse)', required=True) parser.add_argument('--output-header', help='Filename of the header to output', required=True) parser.add_argument('--implementation-header', action='append', help='Header to add to wrapper implementation (eg ) (may appear more than once)', required=False) @@ -253,5 +273,13 @@ def write_header(filename, sysincludes, initname, functions, sym_definitions): if item not in sym_definitions: sym_definitions.append(item) + fallback_count = 0 + for value in args.soname: + if value.count(",") == 0: + fallback_count += 1 + + if fallback_count != 1: + sys.exit("There must be exactly one --soname argument with no predefined macro prefix.") + write_implementation(args.output_implementation, args.soname, args.sys_include, args.init_name, functions, sym_definitions, args.implementation_header) write_header(args.output_header, args.sys_include, args.init_name, functions, sym_definitions)