Can't build cpp on linux, but it works on windows?

Hi ! I am trying to build a SDL3 + imgui + implot project. It builds and runs fine on windows, but on linux the build fails with this error:

install
└─ install v_1
   └─ compile exe v_1 Debug native-linux 1 errors
error: ld.lld: undefined symbol: void ImPlot::PlotBars<unsigned long>(char const*, unsigned long const*, int, double, double, int, int, int)
    note: referenced by main.cpp:283 (v1/main.cpp:283)
    note:               .zig-cache/o/0874844dfa7ec88f734d22c1de726003/main.o:(SDL_AppIterate)
    note: referenced by main.cpp:284 (v1/main.cpp:284)
    note:               .zig-cache/o/0874844dfa7ec88f734d22c1de726003/main.o:(SDL_AppIterate)
    note: referenced by main.cpp:285 (v1/main.cpp:285)
    note:               .zig-cache/o/0874844dfa7ec88f734d22c1de726003/main.o:(SDL_AppIterate)
    note: did you mean: void ImPlot::PlotBars<signed char>(char const*, signed char const*, int, double, double, int, int, int)
    note: defined in: .zig-cache/o/a9a8c5974db4d6ce2bf45b5b149c2dae/implot_items.o
error: the following command failed with 1 compilation errors:
/home/etienne/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.15.2/zig build-exe .zig-cache/o/3d4ccf5bbe1421f83cf484c8696f0819/v_1_z_lib.o .zig-cache/o/a7732e30b5c6625c0d520bcd1fdd052b/libSDL3.a -cflags -DSDL_MAIN_USE_CALLBACKS=1 -- -x c++ /home/etienne/dev/audio-engine-adventures/v1/main.cpp /home/etienne/dev/audio-engine-adventures/imgui/imgui.cpp /home/etienne/dev/audio-engine-adventures/imgui/imgui_demo.cpp /home/etienne/dev/audio-engine-adventures/imgui/imgui_draw.cpp /home/etienne/dev/audio-engine-adventures/imgui/imgui_tables.cpp /home/etienne/dev/audio-engine-adventures/imgui/imgui_widgets.cpp /home/etienne/dev/audio-engine-adventures/imgui/backends/imgui_impl_sdl3.cpp /home/etienne/dev/audio-engine-adventures/imgui/backends/imgui_impl_sdlrenderer3.cpp /home/etienne/dev/audio-engine-adventures/implot/implot.cpp /home/etienne/dev/audio-engine-adventures/implot/implot_demo.cpp /home/etienne/dev/audio-engine-adventures/implot/implot_items.cpp -x none -ODebug -target native-linux -mcpu native -I .zig-cache/o/a6fb089e932f705ef1065695b36c6e90 -I .zig-cache/o/0522a798b075a79ec017821a6fe250de -I /home/etienne/dev/audio-engine-adventures/v1/ -I /home/etienne/dev/audio-engine-adventures/imgui/ -I /home/etienne/dev/audio-engine-adventures/imgui/backends/ -I /home/etienne/dev/audio-engine-adventures/implot/ -Mroot -lc++ -lc --cache-dir .zig-cache --global-cache-dir /home/etienne/.cache/zig --name v_1 --zig-lib-dir /home/etienne/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.15.2/lib/ --listen=-

Build Summary: 6/9 steps succeeded; 1 failed
install transitive failure
└─ install v_1 transitive failure
   └─ compile exe v_1 Debug native-linux 1 errors

error: the following build command failed with exit code 1:
.zig-cache/o/3471b1820a932654367dd0fd7ccd587a/build /home/etienne/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.15.2/zig /home/etienne/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.15.2/lib /home/etienne/dev/audio-engine-adventures .zig-cache /home/etienne/.cache/zig --seed 0x4c4e9686 -Zab2697dee5ae92e0

The weirdest thing is that the error has nothing to do with linux or windows ! Here is my build.zig just in case, but the error being about templates I doubt it comes from the build.zig file:

const builtin = @import("builtin");
const std = @import("std");

pub fn build(b: *std.Build) anyerror!void {
    // Get the default optimization level.
    const optimize = b.standardOptimizeOption(.{});

    // Get the default target, this is the host computer and os.
    const target = b.standardTargetOptions(.{
        .default_target = std.Target.Query{
            .os_tag = builtin.target.os.tag,
        },
    });

    const run = b.step("run", "Run v1");

    const sdl_dep = b.dependency("sdl", .{
        .target = target,
        .optimize = optimize,
    });
    const sdl_lib = sdl_dep.artifact("SDL3");

    const v1_zig_module = b.addModule("v_1_z", .{
        .root_source_file = b.path("v1/generator.zig"),
        .target = target,
        .optimize = optimize,
    });

    const v1_zig_lib = b.addObject(.{
        .root_module = v1_zig_module,
        .name = "v_1_z_lib",
    });

    const v1_cpp_module = b.addModule("v_1", .{
        .target = target,
        .optimize = optimize,
        .link_libcpp = true,
    });
    v1_cpp_module.addObject(v1_zig_lib);
    v1_cpp_module.linkLibrary(sdl_lib);

    const files: []const []const u8 = &.{
        // Main application code
        "v1/main.cpp",

        // Imgui
        "imgui/imgui.cpp",
        "imgui/imgui_demo.cpp",
        "imgui/imgui_draw.cpp",
        "imgui/imgui_tables.cpp",
        "imgui/imgui_widgets.cpp",

        // Imgui backends
        "imgui/backends/imgui_impl_sdl3.cpp",
        "imgui/backends/imgui_impl_sdlrenderer3.cpp",

        // Implot
        "implot/implot.cpp",
        "implot/implot_demo.cpp",
        "implot/implot_items.cpp",
    };

    const flags: []const []const u8 = &.{
        "-DSDL_MAIN_USE_CALLBACKS=1",
    };

    v1_cpp_module.addCSourceFiles(.{
        .files = files,
        .flags = flags,
        .language = .cpp,
        .root = null,
    });

    v1_cpp_module.addIncludePath(b.path("v1/"));
    v1_cpp_module.addIncludePath(b.path("imgui/"));
    v1_cpp_module.addIncludePath(b.path("imgui/backends/"));
    v1_cpp_module.addIncludePath(b.path("implot/"));

    const v1_exe = b.addExecutable(.{
        .root_module = v1_cpp_module,
        .name = "v_1",
    });

    b.installArtifact(v1_exe);

    const runExe = b.addRunArtifact(v1_exe);
    run.dependOn(&runExe.step);
}

Lastly, I tried with cmake, and I have the same error ! again cmake works fine on windows too !
here is my cmake:

cmake_minimum_required(VERSION 3.16)

# set the output directory for built objects.
# This makes sure that the dynamic library goes into the build directory automatically.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIGURATION>")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIGURATION>")

# prevent installing to system directories. 
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE INTERNAL "")

# Declare the project
project(sdl-synth)

set(SDL_SHARED ON)

add_executable(v1)

# Add your sources to the target
target_sources(v1 
PRIVATE 
    v1/main.cpp

    imgui/imgui.cpp
    imgui/imgui_demo.cpp
    imgui/imgui_draw.cpp
    imgui/imgui_tables.cpp
    imgui/imgui_widgets.cpp

    imgui/backends/imgui_impl_sdl3.cpp
    imgui/backends/imgui_impl_sdlrenderer3.cpp

    implot/implot.cpp
    implot/implot.h
    implot/implot_internal.h
    implot/implot_demo.cpp
    implot/implot_items.cpp
)

target_include_directories(v1 PRIVATE imgui/ imgui/backends/ implot/ v1/ )

target_compile_definitions(v1 PRIVATE SDL_MAIN_USE_CALLBACKS)

# Configure SDL by calling its CMake file.
# we use EXCLUDE_FROM_ALL so that its install targets and configs don't
# pollute upwards into our configuration.
add_subdirectory(SDL)

# Link SDL to our executable. This also makes its include directory available to us. 
target_link_libraries(v1 PUBLIC 
    SDL3::SDL3              # If using satelite libraries, SDL must be the last item in the list. 
)

I therefore believe the problem lies somewhere else but I can’t find where :confused:

I don’t know ImGui, but I would start by trying to understand if the signature of the function can differ via some preprocessor conditionals which assume different values under different systems. In that case you might end up with a mismatch between what your code expects to want to link against, and whatever symbol is actually available in the system-specific library.

EDIT: actually, the linker gives you a clue right below:

As you can see, the signatures differ in their template parameter and second function parameter:

void ImPlot::PlotBars<unsigned long>(char const*, unsigned long const*, int, double, double, int, int, int)
void ImPlot::PlotBars<signed char>  (char const*,   signed char const*, int, double, double, int, int, int)
1 Like