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.
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.cppFile
CMakeLists.txt(might need to adjust it to find pugixml if not installed)Put in some directory, then run
cmake -GNinja .followed bycmake --build .. This will fail to compile.PR #644 seems to contain a solution for this issue, although I believe simply changing the
consttoconstexprshould be enough.