#Using the same func symbol from different dynamic link libraries

1 messages · Page 1 of 1 (latest)

static stag
#

I want to bench the cblas_dgemm function from MKL, BLIS, and OpenBLAS in the same exe file. All of them are dynamic link libraries installed on the system, and their cblas_dgemm function symbol are identical. So, I wrote a middle layer to distinguish them, but I found that the finally compiled executable cannot tell them apart and only uses the first linked library. How should I solve this problem?

#

build.zig

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const bench_exe = b.addExecutable(.{
        .name = "bench",
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/bench.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{},
        }),
    });

    const bench_mkl_lib = b.addLibrary(.{
        .name = "bench_mkl",
        .linkage = .dynamic,
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/bench_mkl.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{},
        }),
    });
    bench_mkl_lib.linkLibC();
    bench_mkl_lib.addSystemIncludePath(.{ .cwd_relative = "/usr/include/mkl" });
    bench_mkl_lib.linkSystemLibrary("mkl_intel_thread");
    bench_mkl_lib.linkSystemLibrary("mkl_rt");
    bench_mkl_lib.linkSystemLibrary("mkl_core");
    bench_mkl_lib.linkSystemLibrary("mkl_intel_lp64");

    b.installArtifact(bench_mkl_lib);

    bench_exe.root_module.linkLibrary(bench_mkl_lib);

    b.installArtifact(bench_exe);

    const bench_step = b.step("bench", "bench");
    const bench_cmd = b.addRunArtifact(bench_exe);
    bench_step.dependOn(&bench_cmd.step);
    bench_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        bench_cmd.addArgs(args);
    }
}

#
const bench_openblas_lib = b.addLibrary(.{
        .name = "bench_openblas",
        .linkage = .dynamic,
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/bench_openblas.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{},
        }),
    });
    bench_openblas_lib.linkLibC();
    bench_openblas_lib.linkSystemLibrary("openblas");

    b.installArtifact(bench_openblas_lib);

    bench_exe.root_module.linkLibrary(bench_openblas_lib);

    const bench_blis_lib = b.addLibrary(.{
        .name = "bench_blis",
        .linkage = .dynamic,
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/bench_blis.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{},
        }),
    });
    bench_blis_lib.linkLibC();
    bench_blis_lib.addSystemIncludePath(.{ .cwd_relative = "/usr/include/x86_64-linux-gnu/blis-openmp" });
    bench_blis_lib.linkSystemLibrary("blis");

    b.installArtifact(bench_blis_lib);

    bench_exe.root_module.linkLibrary(bench_blis_lib);
#

bench_blis.zig

const std = @import("std");
const c = @cImport(@cInclude("cblas.h"));

export fn blis_dgemm(M: c_int, N: c_int, K: c_int, alpha: f64, A: [*c]const f64, lda: c_int, B: [*c]const f64, ldb: c_int, beta: f64, C: [*c]f64, ldc: c_int) void {
    c.cblas_dgemm(c.CblasRowMajor, c.CblasNoTrans, c.CblasNoTrans, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
}
#

bench.zig

extern fn mkl_dgemm(M: c_int, N: c_int, K: c_int, alpha: f64, A: [*c]const f64, lda: c_int, B: [*c]const f64, ldb: c_int, beta: f64, C: [*c]f64, ldc: c_int) void;

extern fn blis_dgemm(M: c_int, N: c_int, K: c_int, alpha: f64, A: [*c]const f64, lda: c_int, B: [*c]const f64, ldb: c_int, beta: f64, C: [*c]f64, ldc: c_int) void;

extern fn openblas_dgemm(M: c_int, N: c_int, K: c_int, alpha: f64, A: [*c]const f64, lda: c_int, B: [*c]const f64, ldb: c_int, beta: f64, C: [*c]f64, ldc: c_int) void;

const std = @import("std");

pub fn main() !void {
 // ...
}
crystal thicket
#

you can extern "name" fn foo() void;
to get foo from the libname library

#

you should probably have a namespace for each library.
there is also const foo = @extern(T, .{ .name = "bar", .library_name = "baz});

static stag
#

@crystal thicket
I tried it, but it still doesn’t work—the executable only uses the first linked library.