Skip to content

Cannot use pugixml.hpp in C++20 module #700

@Sergiovan

Description

@Sergiovan

Pugixml causes compilation errors when included in the global module fragment of a C++20 (or higher) module file.

The error is that pugixml exposes TU-local entities, e.g. pugi::parse_default, since they has internal linkage and are named by multiple functions using them as default parameters.

Tested with pugixml 1.15-3 installed via the Arch package manager, in addition to cmake 4.3, ninja 1.13.2 and gcc 15.2.1.

Minimal reproduction (requires cmake, ninja, gcc, and of course pugixml):
File example.cpp

module; 

#include <pugixml.hpp>

export module example;

export struct example {
  pugi::xml_node node; // < Commenting this line stops the errors
};

File CMakeLists.txt (might need to adjust it to find pugixml if not installed)

cmake_minimum_required(VERSION 4.0)

project(example
    VERSION 0.0.1
    DESCRIPTION "Pugixml header not working example"
    LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED YES)

set(CMAKE_CXX_SCAN_FOR_MODULES ON)

set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fdiagnostics-color=always")

add_library(external STATIC)
target_sources(external
  PUBLIC
    FILE_SET all_my_moduels TYPE CXX_MODULES
    FILES
        example.cpp
)
target_link_libraries(external PUBLIC pugixml)

Put in some directory, then run cmake -GNinja . followed by cmake --build .. This will fail to compile.

[0/1] Re-running CMake...
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /data/code/tests/pugixml-issue
[3/5] Building CXX object CMakeFiles/external.dir/external_module.cpp.o
FAILED: [code=1] CMakeFiles/external.dir/external_module.cpp.o CMakeFiles/external.dir/external.gcm
/usr/bin/c++   -fdiagnostics-color=always -std=gnu++23 -MD -MT CMakeFiles/external.dir/external_module.cpp.o -MF CMakeFiles/external.dir/external_module.cpp.o.d -fmodules-ts -fmodule-mapper=CMakeFiles/external.dir/external_module.cpp.o.modmap -MD -fdeps-format=p1689r5 -x c++ -o CMakeFiles/external.dir/external_module.cpp.o -c /data/code/tests/pugixml-issue/external_module.cpp
In file included from /data/code/tests/pugixml-issue/external_module.cpp:3:
/usr/include/pugixml.hpp:680:34: error: ‘pugi::xml_parse_result pugi::xml_node::append_buffer(const void*, size_t, unsigned int, pugi::xml_encoding)’ exposes TU-local entity ‘pugi::parse_default’
  680 |                 xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
      |                                  ^~~~~~~~~~~~~
/usr/include/pugixml.hpp:242:28: note: ‘pugi::parse_default’ declared with internal linkage
  242 |         const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol;
      |                            ^~~~~~~~~~~~~
/usr/include/pugixml.hpp:761:22: error: ‘void pugi::xml_node::print(pugi::xml_writer&, const pugi::char_t*, unsigned int, pugi::xml_encoding, unsigned int) const’ exposes TU-local entity ‘pugi::format_default’
  761 |                 void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
      |                      ^~~~~
/usr/include/pugixml.hpp:298:28: note: ‘pugi::format_default’ declared with internal linkage
  298 |         const unsigned int format_default = format_indent;
      |                            ^~~~~~~~~~~~~~
/usr/include/pugixml.hpp:765:22: error: ‘void pugi::xml_node::print(std::basic_ostream<char>&, const pugi::char_t*, unsigned int, pugi::xml_encoding, unsigned int) const’ exposes TU-local entity ‘pugi::format_default’
  765 |                 void print(std::basic_ostream<char>& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
      |                      ^~~~~
/usr/include/pugixml.hpp:298:28: note: ‘pugi::format_default’ declared with internal linkage
  298 |         const unsigned int format_default = format_indent;
      |                            ^~~~~~~~~~~~~~
/usr/include/pugixml.hpp:766:22: error: ‘void pugi::xml_node::print(std::basic_ostream<wchar_t>&, const pugi::char_t*, unsigned int, unsigned int) const’ exposes TU-local entity ‘pugi::format_default’
  766 |                 void print(std::basic_ostream<wchar_t>& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const;
      |                      ^~~~~
/usr/include/pugixml.hpp:298:28: note: ‘pugi::format_default’ declared with internal linkage
  298 |         const unsigned int format_default = format_indent;
      |                            ^~~~~~~~~~~~~~
ninja: build stopped: subcommand failed.

PR #644 seems to contain a solution for this issue, although I believe simply changing the const to constexpr should be enough.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions