Enable macOS support for dynamic load

Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
Matthew Ballance 2026-06-07 14:33:55 +00:00
parent b332c736df
commit 0d6a68f79e
3 changed files with 24 additions and 10 deletions

View File

@ -738,12 +738,19 @@ public:
if (v3Global.opt.vpi()) {
// Runtime VPI library loading (+verilator+vpi+<lib>) needs platform-specific
// link flags. Resolve them with $(UNAME_S)
// link flags so the dlopen'd library can resolve the executable's VPI symbols.
// Resolve them with $(UNAME_S).
of.puts("# Runtime VPI library loading (+verilator+vpi+) link requirements\n");
// -rdynamic exports the executable's VPI symbols to the dlopen'd library;
// -ldl provides dlopen/dlsym.
of.puts("ifeq ($(UNAME_S),Linux)\n");
of.puts(/**/ "LDFLAGS += -rdynamic\n");
of.puts(/**/ "LDLIBS += -ldl\n");
of.puts("endif\n");
// macOS analog of -rdynamic; dlopen/dlsym live in libSystem so no -ldl needed.
of.puts("ifeq ($(UNAME_S),Darwin)\n");
of.puts(/**/ "LDFLAGS += -Wl,-export_dynamic\n");
of.puts("endif\n");
of.puts("\n");
}
}

View File

@ -7,6 +7,7 @@
# SPDX-FileCopyrightText: 2025 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import platform
import vltest_bootstrap
test.scenarios('vlt')
@ -15,10 +16,15 @@ test.scenarios('vlt')
# Also compile a VPI shared library to be loaded at runtime via +verilator+vpi+.
test.compile(make_pli=True, verilator_flags2=["--binary --vpi --public-flat-rw"])
# With --vpi and an executable (--binary implies --exe), the Makefile must, on Linux,
# export the executable's symbols (-rdynamic) and link libdl for the generated loader's
# dlopen/dlsym calls. These are gated on $(UNAME_S) so macOS/Windows are unaffected.
# With --vpi and an executable (--binary implies --exe), the Makefile must export the
# executable's symbols so the generated loader's dlopen'd library can resolve them.
# The flags are gated on $(UNAME_S): -rdynamic/-ldl on Linux, -Wl,-export_dynamic on
# macOS (Windows is unaffected, runtime loading is unsupported there).
mk = test.obj_dir + "/V" + test.name + ".mk"
if platform.system() == 'Darwin':
test.file_grep(mk, r'ifeq \(\$\(UNAME_S\),Darwin\)')
test.file_grep(mk, r'LDFLAGS \+= -Wl,-export_dynamic')
else:
test.file_grep(mk, r'ifeq \(\$\(UNAME_S\),Linux\)')
test.file_grep(mk, r'LDFLAGS \+= -rdynamic')
test.file_grep(mk, r'LDLIBS \+= -ldl')

View File

@ -21,9 +21,10 @@ test.compile(make_main=False, verilator_make_gmake=False, verilator_flags2=["--v
test.file_grep(test.obj_dir + "/V" + test.name + "_classes.mk", r'VM_VPI = 1')
# Without --exe there is no executable to export symbols from or to dlopen into,
# so the runtime-VPI link flags must not be emitted into the Makefile at all.
# so the runtime-VPI link flags must not be emitted into the Makefile on any platform.
mk = test.obj_dir + "/V" + test.name + ".mk"
test.file_grep_not(mk, r'-rdynamic')
test.file_grep_not(mk, r'-ldl')
test.file_grep_not(mk, r'-rdynamic') # Linux
test.file_grep_not(mk, r'-ldl') # Linux
test.file_grep_not(mk, r'-export_dynamic') # macOS
test.passes()