[llvm-branch-commits] [clang] [llvm] release/22.x: [cmake] Build libxml from source in release - #222203 (PR #222821)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Sep 10 18:04:37 PDT 2026


https://github.com/theofficialgman created https://github.com/llvm/llvm-project/pull/222821

Backport https://github.com/llvm/llvm-project/pull/221365

Backport https://github.com/llvm/llvm-project/commit/70cf763a42d55dcf89687c9e84478eb007561654

@dyung this is similar to https://github.com/llvm/llvm-project/pull/222203 but on 22.x.
I would greatly appreciate if you could also approve the PR workflow here as well. Running into issues at a downstream project with clang++ hanging during compilation on a cpp file that did not have such issues on 22.1.8. This code change shouldn't be the cause but I can't rule that out without applying it to 22.X as well (can't run the official builds of llvm 23.X to rule the code change out since they only work on ubuntu jammy 22.04 and no other distro and I don't have such an install).

>From b50b67d68204366e6b536353b67e55ca1fba2607 Mon Sep 17 00:00:00 2001
From: Keith Smiley <keithbsmiley at gmail.com>
Date: Wed, 15 Apr 2026 09:23:42 -0700
Subject: [PATCH 1/2] Reapply "[cmake] Add support for statically linking
 libxml2" (#192088)

This applies a fix for windows not discovering libxml

This reverts commit 2a9c32496b5e8e63844597f638bdf67e4732fd35.
---
 clang/cmake/caches/Release.cmake        |  4 ++
 llvm/CMakeLists.txt                     |  2 +
 llvm/cmake/config-ix.cmake              | 14 +++++
 llvm/cmake/modules/FindLibXml2.cmake    | 79 +++++++++++++++++++++++++
 llvm/lib/WindowsManifest/CMakeLists.txt | 10 +++-
 5 files changed, 106 insertions(+), 3 deletions(-)
 create mode 100644 llvm/cmake/modules/FindLibXml2.cmake

diff --git a/clang/cmake/caches/Release.cmake b/clang/cmake/caches/Release.cmake
index efe20a201dbc9..b0bc3ebfe5cb6 100644
--- a/clang/cmake/caches/Release.cmake
+++ b/clang/cmake/caches/Release.cmake
@@ -172,6 +172,10 @@ set_final_stage_var(CPACK_GENERATOR "TXZ" STRING)
 set_final_stage_var(CPACK_ARCHIVE_THREADS "0" STRING)
 
 set_final_stage_var(LLVM_USE_STATIC_ZSTD "ON" BOOL)
+if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux")
+  set_final_stage_var(LLVM_USE_STATIC_LIBXML2 "ON" BOOL)
+endif()
+
 if (LLVM_RELEASE_ENABLE_LTO)
   set_final_stage_var(LLVM_ENABLE_FATLTO "ON" BOOL)
   set_final_stage_var(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_LIST_DIR}/release_cpack_pre_build_strip_lto.cmake" STRING)
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index fcbfed4953832..c8c70df987e83 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -593,6 +593,8 @@ set(LLVM_TARGET_ARCH "host"
 
 set(LLVM_ENABLE_LIBXML2 "ON" CACHE STRING "Use libxml2 if available. Can be ON, OFF, or FORCE_ON")
 
+set(LLVM_USE_STATIC_LIBXML2 "OFF" CACHE BOOL "Use static version of libxml2. Can be ON, or OFF")
+
 option(LLVM_ENABLE_LIBEDIT "Use libedit if available." ON)
 
 option(LLVM_ENABLE_LIBPFM "Use libpfm for performance counters if available." ON)
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index ed2bfa6df68f4..fe5d547dfc1d7 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -227,6 +227,20 @@ if(LLVM_ENABLE_LIBXML2)
     if(LLVM_ENABLE_LIBXML2 STREQUAL FORCE_ON AND NOT HAVE_LIBXML2)
       message(FATAL_ERROR "Failed to configure libxml2")
     endif()
+
+    if(LLVM_USE_STATIC_LIBXML2)
+      if(NOT TARGET LibXml2::LibXml2Static)
+        message(FATAL_ERROR "Failed to find static libxml2 library, but LLVM_USE_STATIC_LIBXML2=ON")
+      endif()
+      cmake_push_check_state()
+      list(APPEND CMAKE_REQUIRED_INCLUDES ${LIBXML2_INCLUDE_DIR})
+      list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBXML2_STATIC_LIBRARY} ${LIBXML2_STATIC_DEPS})
+      check_symbol_exists(xmlReadMemory libxml/xmlreader.h HAVE_LIBXML2_STATIC)
+      cmake_pop_check_state()
+      if(NOT HAVE_LIBXML2_STATIC)
+        message(FATAL_ERROR "Failed to configure static libxml2, but LLVM_USE_STATIC_LIBXML2=ON")
+      endif()
+    endif()
   endif()
   set(LLVM_ENABLE_LIBXML2 "${HAVE_LIBXML2}")
 endif()
diff --git a/llvm/cmake/modules/FindLibXml2.cmake b/llvm/cmake/modules/FindLibXml2.cmake
new file mode 100644
index 0000000000000..a2323b3bfe1a7
--- /dev/null
+++ b/llvm/cmake/modules/FindLibXml2.cmake
@@ -0,0 +1,79 @@
+# Try to find the libxml2 library
+#
+# If successful, the following variables will be defined:
+# LIBXML2_INCLUDE_DIR
+# LIBXML2_LIBRARY
+# LIBXML2_STATIC_LIBRARY
+# LibXml2_FOUND
+#
+# Additionally, the following import targets will be defined:
+# LibXml2::LibXml2
+# LibXml2::LibXml2Static (if the static library is found)
+
+find_package(PkgConfig QUIET)
+if(PkgConfig_FOUND)
+  pkg_check_modules(PC_LIBXML QUIET libxml-2.0)
+endif()
+
+find_path(LIBXML2_INCLUDE_DIR NAMES libxml/xpath.h
+  HINTS
+  ${PC_LIBXML_INCLUDEDIR}
+  ${PC_LIBXML_INCLUDE_DIRS}
+  PATH_SUFFIXES libxml2
+)
+
+if(DEFINED LIBXML2_LIBRARIES AND NOT DEFINED LIBXML2_LIBRARY)
+  set(LIBXML2_LIBRARY "${LIBXML2_LIBRARIES}" CACHE FILEPATH "Path to libxml2 library")
+endif()
+
+find_library(LIBXML2_LIBRARY NAMES xml2 libxml2 libxml2s libxml2_a
+  HINTS
+  ${PC_LIBXML_LIBDIR}
+  ${PC_LIBXML_LIBRARY_DIRS}
+)
+
+find_library(LIBXML2_STATIC_LIBRARY NAMES
+  "${CMAKE_STATIC_LIBRARY_PREFIX}xml2${CMAKE_STATIC_LIBRARY_SUFFIX}"
+  "${CMAKE_STATIC_LIBRARY_PREFIX}libxml2${CMAKE_STATIC_LIBRARY_SUFFIX}"
+  HINTS
+  ${PC_LIBXML_LIBDIR}
+  ${PC_LIBXML_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibXml2
+  REQUIRED_VARS LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR
+  VERSION_VAR PC_LIBXML_VERSION
+)
+
+if(LibXml2_FOUND)
+  if(NOT TARGET LibXml2::LibXml2)
+    add_library(LibXml2::LibXml2 UNKNOWN IMPORTED)
+    set_target_properties(LibXml2::LibXml2 PROPERTIES
+        INTERFACE_INCLUDE_DIRECTORIES "${LIBXML2_INCLUDE_DIR}"
+        IMPORTED_LOCATION "${LIBXML2_LIBRARY}")
+  endif()
+  if(LIBXML2_STATIC_LIBRARY AND NOT TARGET LibXml2::LibXml2Static)
+    add_library(LibXml2::LibXml2Static STATIC IMPORTED)
+    set_target_properties(LibXml2::LibXml2Static PROPERTIES
+        INTERFACE_INCLUDE_DIRECTORIES "${LIBXML2_INCLUDE_DIR}"
+        IMPORTED_LOCATION "${LIBXML2_STATIC_LIBRARY}")
+    # Static libraries need their transitive dependencies for linking.
+    set(LIBXML2_STATIC_DEPS)
+    foreach(lib IN LISTS PC_LIBXML_STATIC_LIBRARIES)
+      if(NOT lib STREQUAL "xml2")
+        list(APPEND LIBXML2_STATIC_DEPS ${lib})
+      endif()
+    endforeach()
+    if(LIBXML2_STATIC_DEPS)
+      set_target_properties(LibXml2::LibXml2Static PROPERTIES
+          INTERFACE_LINK_LIBRARIES "${LIBXML2_STATIC_DEPS}")
+    endif()
+  endif()
+endif()
+
+set(LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR})
+set(LIBXML2_LIBRARIES ${LIBXML2_LIBRARY})
+set(LIBXML2_DEFINITIONS ${PC_LIBXML_CFLAGS_OTHER})
+
+mark_as_advanced(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARY LIBXML2_STATIC_LIBRARY)
diff --git a/llvm/lib/WindowsManifest/CMakeLists.txt b/llvm/lib/WindowsManifest/CMakeLists.txt
index 910132a4c7dec..46fe3b50357b6 100644
--- a/llvm/lib/WindowsManifest/CMakeLists.txt
+++ b/llvm/lib/WindowsManifest/CMakeLists.txt
@@ -1,7 +1,11 @@
 include(GetLibraryName)
 
 if(LLVM_ENABLE_LIBXML2)
-  set(imported_libs LibXml2::LibXml2)
+  if(LLVM_USE_STATIC_LIBXML2)
+    set(imported_libs LibXml2::LibXml2Static)
+  else()
+    set(imported_libs LibXml2::LibXml2)
+  endif()
 endif()
 
 add_llvm_component_library(LLVMWindowsManifest
@@ -24,10 +28,10 @@ if(LLVM_ENABLE_LIBXML2)
   # CMAKE_BUILD_TYPE is only meaningful to single-configuration generators.
   if(CMAKE_BUILD_TYPE)
     string(TOUPPER ${CMAKE_BUILD_TYPE} build_type)
-    get_property(libxml2_library TARGET LibXml2::LibXml2 PROPERTY LOCATION_${build_type})
+    get_property(libxml2_library TARGET ${imported_libs} PROPERTY LOCATION_${build_type})
   endif()
   if(NOT libxml2_library)
-    get_property(libxml2_library TARGET LibXml2::LibXml2 PROPERTY LOCATION)
+    get_property(libxml2_library TARGET ${imported_libs} PROPERTY LOCATION)
   endif()
   get_library_name(${libxml2_library} libxml2_library)
   set_property(TARGET LLVMWindowsManifest PROPERTY LLVM_SYSTEM_LIBS ${libxml2_library})

>From cc83ac540fbce94689a45dfffaf6e3d4d3ce754b Mon Sep 17 00:00:00 2001
From: Keith Smiley <keithbsmiley at gmail.com>
Date: Fri, 4 Sep 2026 15:50:22 -0700
Subject: [PATCH 2/2] Build libxml from source in release

With 23.x we started linking a static libxml in release builds to avoid
requiring that to be installed, and the varying names of that library on
different linux distros. That broke more than it fixed because the
static libxml in our docker images are built targeting ICU, and ICU's
shared library version changes quickly, so even between 2 ubuntu
versions the binaries will not work.

With this change we now build from source in the release build, which is
already what windows does, and we disable ICU / iconv since those don't
seem vital for the windows manifest use case. This seems easier than
building a libxml out of band in our CI images that do the release
builds.

Fixes https://github.com/llvm/llvm-project/issues/215764
---
 clang/cmake/caches/Release.cmake        |  1 +
 llvm/CMakeLists.txt                     |  2 +
 llvm/cmake/config-ix.cmake              |  6 +-
 llvm/cmake/modules/LibXml2.cmake        | 74 +++++++++++++++++++++++++
 llvm/lib/WindowsManifest/CMakeLists.txt |  2 +-
 5 files changed, 83 insertions(+), 2 deletions(-)
 create mode 100644 llvm/cmake/modules/LibXml2.cmake

diff --git a/clang/cmake/caches/Release.cmake b/clang/cmake/caches/Release.cmake
index b0bc3ebfe5cb6..fb2d33a7be868 100644
--- a/clang/cmake/caches/Release.cmake
+++ b/clang/cmake/caches/Release.cmake
@@ -173,6 +173,7 @@ set_final_stage_var(CPACK_ARCHIVE_THREADS "0" STRING)
 
 set_final_stage_var(LLVM_USE_STATIC_ZSTD "ON" BOOL)
 if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux")
+  set_final_stage_var(LLVM_BUILD_LIBXML2 "ON" BOOL)
   set_final_stage_var(LLVM_USE_STATIC_LIBXML2 "ON" BOOL)
 endif()
 
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index c8c70df987e83..3936cff87cecb 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -595,6 +595,8 @@ set(LLVM_ENABLE_LIBXML2 "ON" CACHE STRING "Use libxml2 if available. Can be ON,
 
 set(LLVM_USE_STATIC_LIBXML2 "OFF" CACHE BOOL "Use static version of libxml2. Can be ON, or OFF")
 
+option(LLVM_BUILD_LIBXML2 "Download and build a static libxml2 instead of finding an installed library" OFF)
+
 option(LLVM_ENABLE_LIBEDIT "Use libedit if available." ON)
 
 option(LLVM_ENABLE_LIBPFM "Use libpfm for performance counters if available." ON)
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index fe5d547dfc1d7..7a8724c81a4a4 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -209,7 +209,11 @@ if(LLVM_ENABLE_ZSTD)
   endif()
 endif()
 
-if(LLVM_ENABLE_LIBXML2)
+if(LLVM_ENABLE_LIBXML2 AND LLVM_BUILD_LIBXML2)
+  include(LibXml2)
+  # The external project is built later, so it cannot be link-tested here.
+  set(LLVM_ENABLE_LIBXML2 1)
+elseif(LLVM_ENABLE_LIBXML2)
   if(LLVM_ENABLE_LIBXML2 STREQUAL FORCE_ON)
     find_package(LibXml2 REQUIRED)
   elseif(NOT LLVM_USE_SANITIZER MATCHES "Memory.*")
diff --git a/llvm/cmake/modules/LibXml2.cmake b/llvm/cmake/modules/LibXml2.cmake
new file mode 100644
index 0000000000000..2edc43947a4b7
--- /dev/null
+++ b/llvm/cmake/modules/LibXml2.cmake
@@ -0,0 +1,74 @@
+# Build libxml2 from source when LLVM_BUILD_LIBXML2=TRUE
+include(ExternalProject)
+
+set(LIBXML2_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/libxml2/src/libxml2")
+set(LIBXML2_BINARY_DIR "${LIBXML2_SOURCE_DIR}-build")
+
+set(libxml2_library_dir "${LIBXML2_BINARY_DIR}/lib/${CMAKE_CFG_INTDIR}")
+set(libxml2_library_name libxml2)
+if(MSVC)
+  set(libxml2_library_name libxml2s)
+  set(libxml2_debug_postfix "$<$<CONFIG:Debug>:d>")
+endif()
+set(LIBXML2_BUILT_LIBRARY "${libxml2_library_dir}/${libxml2_library_name}${CMAKE_STATIC_LIBRARY_SUFFIX}")
+
+if(LLVM_ENABLE_ZLIB)
+  # Use the same headers and library selected by LLVM, including for Debug builds.
+  set(libxml2_zlib_args
+    -DZLIB_INCLUDE_DIR:PATH=${ZLIB_INCLUDE_DIR}
+    -DZLIB_LIBRARY:FILEPATH=$<TARGET_LINKER_FILE:ZLIB::ZLIB>
+    -DZLIB_LIBRARY_RELEASE:FILEPATH=$<TARGET_LINKER_FILE:ZLIB::ZLIB>
+    -DZLIB_LIBRARY_DEBUG:FILEPATH=$<TARGET_LINKER_FILE:ZLIB::ZLIB>)
+endif()
+
+ExternalProject_Add(libxml2
+  PREFIX libxml2
+  GIT_REPOSITORY https://github.com/GNOME/libxml2.git
+  GIT_TAG v2.15.1
+  GIT_SHALLOW TRUE
+  CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
+             -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY:PATH=<BINARY_DIR>/lib
+             -DBUILD_SHARED_LIBS=OFF
+             -DLIBXML2_WITH_PYTHON=OFF
+             -DLIBXML2_WITH_PROGRAMS=OFF
+             -DLIBXML2_WITH_TESTS=OFF
+             # Avoid dynamic deps on ICU / iconv
+             -DLIBXML2_WITH_ICU=OFF
+             -DLIBXML2_WITH_ICONV=OFF
+             -DLIBXML2_WITH_MODULES=OFF
+             -DLIBXML2_WITH_ZLIB=${LLVM_ENABLE_ZLIB}
+  CMAKE_CACHE_ARGS -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
+                   -DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE}
+                   -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=${LLVM_ENABLE_PIC}
+                   ${libxml2_zlib_args}
+  BUILD_BYPRODUCTS "${libxml2_library_dir}/${libxml2_library_name}${libxml2_debug_postfix}${CMAKE_STATIC_LIBRARY_SUFFIX}"
+  UPDATE_COMMAND ""
+  INSTALL_COMMAND ""
+)
+
+# Imported include directories must exist at generation time, before the
+# external project's download and configure steps have run.
+file(MAKE_DIRECTORY "${LIBXML2_SOURCE_DIR}/include" "${LIBXML2_BINARY_DIR}")
+add_library(LibXml2::LibXml2Static STATIC IMPORTED GLOBAL)
+set_target_properties(LibXml2::LibXml2Static PROPERTIES
+  IMPORTED_LOCATION "${LIBXML2_BUILT_LIBRARY}"
+  INTERFACE_INCLUDE_DIRECTORIES "${LIBXML2_SOURCE_DIR}/include;${LIBXML2_BINARY_DIR}"
+)
+add_dependencies(LibXml2::LibXml2Static libxml2)
+
+find_package(Threads REQUIRED)
+target_link_libraries(LibXml2::LibXml2Static INTERFACE Threads::Threads)
+if(LLVM_ENABLE_ZLIB)
+  target_link_libraries(LibXml2::LibXml2Static INTERFACE ZLIB::ZLIB)
+endif()
+if(UNIX)
+  target_link_libraries(LibXml2::LibXml2Static INTERFACE m)
+endif()
+if(WIN32)
+  target_link_libraries(LibXml2::LibXml2Static INTERFACE bcrypt)
+  target_compile_definitions(LibXml2::LibXml2Static INTERFACE LIBXML_STATIC)
+endif()
+if(MSVC)
+  set_property(TARGET LibXml2::LibXml2Static PROPERTY IMPORTED_LOCATION_DEBUG
+    "${libxml2_library_dir}/libxml2sd${CMAKE_STATIC_LIBRARY_SUFFIX}")
+endif()
diff --git a/llvm/lib/WindowsManifest/CMakeLists.txt b/llvm/lib/WindowsManifest/CMakeLists.txt
index 46fe3b50357b6..25d6009a06837 100644
--- a/llvm/lib/WindowsManifest/CMakeLists.txt
+++ b/llvm/lib/WindowsManifest/CMakeLists.txt
@@ -1,7 +1,7 @@
 include(GetLibraryName)
 
 if(LLVM_ENABLE_LIBXML2)
-  if(LLVM_USE_STATIC_LIBXML2)
+  if(LLVM_BUILD_LIBXML2 OR LLVM_USE_STATIC_LIBXML2)
     set(imported_libs LibXml2::LibXml2Static)
   else()
     set(imported_libs LibXml2::LibXml2)



More information about the llvm-branch-commits mailing list