Package C++ project with 'namespace' for the zig build system

Using zig 0.14.1, I would like to package minidocx to use as an import module.

The code in all the .cpp and .hpp files is inside a namesapce:

namespace MINIDOCX_NAMESPACE
{
  FileType getFileType(const FileName& filename)
  {
    const std::string ext = filename.extension().string();

    if (ext == ".jpg" || ext == ".jpeg")
      return FileType::JPG;
...
}

Using those files as is, zig build gives a multitude of unknown type errors:

install
└─ install minidocx_lib
   └─ zig build-lib minidocx_lib Debug native 59 errors
C:\Users\user\AppData\Local\zig\p\N-V-__8AABCu9wDFsoiqNYXxBSIZIyYCvgRCd-seu9mCETpV\src/utils/file.cpp:15:3: error: unknown type name 'FileType'
  FileType getFileType(const FileName& filename)
  ^
C:\Users\user\AppData\Local\zig\p\N-V-__8AABCu9wDFsoiqNYXxBSIZIyYCvgRCd-seu9mCETpV\src/utils/file.cpp:15:30: error: unknown type name 'FileName'
  FileType getFileType(const FileName& filename)
                             ^

However, if I remove all the mentions of namespace MINIDOCX_NAMESPACE in those files, the build is successful.

I looked for C++ projects with namespace as examples in allyourcodebase repositories, such as Tracy, but I could not find anything out of the ordinary.

Here is the build.zig that works when I remove the mentions of namespace:

    const upstream = b.dependency("minidocx", .{});

    const minidocx_mod = b.createModule(.{
        .target = target,
        .optimize = optimize,
        .pic = pie,
        .strip = strip,
        .link_libc = true,
        .link_libcpp = true,
    });

    const c_src: []const []const u8 = &.{
        "src/packaging/package.cpp",
        "src/packaging/part.cpp",
        "src/utils/exceptions.cpp",
        "src/utils/file.cpp",
        "src/utils/string.cpp",
        "src/utils/zip.cpp",
        "src/word/main/container.cpp",
        "src/word/main/document.cpp",
        "src/word/main/paragraph.cpp",
        "src/word/main/table.cpp",
        "3rdparty/pugixml-1.13/pugixml.cpp",
    };

    minidocx_mod.addCSourceFiles(.{
        .root = upstream.path(""),
        .files = c_src,
        .flags = &.{"-std=c++20"},
    });
    minidocx_mod.addIncludePath(upstream.path("include/minidocx"));
    minidocx_mod.addIncludePath(upstream.path("3rdparty/pugixml-1.13"));
    minidocx_mod.addIncludePath(upstream.path("3rdparty/miniz-3.0.2"));

    const minidocx_lib = b.addLibrary(.{
        .name = "minidocx_lib",
        .linkage = linkage,
        .root_module = minidocx_mod,
    });

    b.installArtifact(minidocx_lib);

The namespace MINIDOCX_NAMESPACE in the header seems to expect that MINIDOCX_NAMESPACE is a C preprocessor define, e.g. when you look at the CMakeLists.txt the default is md:

Not sure why it doesn’t simply use the MINIDOCX_NAMESPACE as namespace name when that define doesn’t exist, but first thing I would try is adding a define to the C++ build step:

    minidocx_mod.addCSourceFiles(.{
        .root = upstream.path(""),
        .files = c_src,
        .flags = &.{"-std=c++20", "-DMINIDOCX_NAMESPACE=md"},
    });
2 Likes

Thanks a lot, that was indeed the issue

1 Like