From 20eb17e0c2f00fefa4806062c6762ab4cee2a123 Mon Sep 17 00:00:00 2001 From: "Patrick Nelson (VS)" Date: Wed, 19 Aug 2026 10:28:00 -0700 Subject: [PATCH 1/5] Fix 599 (Ubuntu 26.04 compat) by statically linking libxml2.so --- THIRD-PARTY-NOTICES.txt | 23 ++++++++ src/CMakeLists.txt | 53 ++++++++++++++++++- src/Common.Lib/CMakeLists.txt | 8 ++- src/InstrumentationEngine.Lib/CMakeLists.txt | 10 ++-- .../InstrumentationEngine.nuspec | 1 + src/InstrumentationEngine/CMakeLists.txt | 5 +- src/Tests/CommonLibTests/CMakeLists.txt | 4 +- .../CMakeLists.txt | 4 +- .../CMakeLists.txt | 4 +- src/build.sh | 12 ++--- .../components/libxml2/cgmanifest.json | 17 ++++++ 11 files changed, 114 insertions(+), 27 deletions(-) create mode 100644 THIRD-PARTY-NOTICES.txt create mode 100644 src/unix/docker/context/components/libxml2/cgmanifest.json diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt new file mode 100644 index 00000000..99937cc1 --- /dev/null +++ b/THIRD-PARTY-NOTICES.txt @@ -0,0 +1,23 @@ +libxml2 +======= + +Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. +Copyright (C) The Libxml2 Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8b2baf39..4741492a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,8 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -# Require at least version 3.14 of CMake -cmake_minimum_required(VERSION 3.14) +# Require at least version 3.18 of CMake +cmake_minimum_required(VERSION 3.18) IF(NOT EXISTS "${CMAKE_INSTALL_PREFIX}" OR NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}") message(FATAL_ERROR "Required property CMAKE_INSTALL_PREFIX not correctly defined.") @@ -233,6 +233,53 @@ function(generate_exports_file inputFilename versionName outputFilename) PROPERTIES GENERATED TRUE) endfunction() +function(fetch_libxml2) + include(FetchContent) + + set(BUILD_SHARED_LIBS OFF) + set(LIBXML2_WITH_C14N OFF) + set(LIBXML2_WITH_CATALOG OFF) + set(LIBXML2_WITH_DEBUG OFF) + set(LIBXML2_WITH_DOCS OFF) + set(LIBXML2_WITH_HTML OFF) + set(LIBXML2_WITH_HTTP OFF) + set(LIBXML2_WITH_ICU OFF) + set(LIBXML2_WITH_MODULES OFF) + set(LIBXML2_WITH_OUTPUT OFF) + set(LIBXML2_WITH_PATTERN OFF) + set(LIBXML2_WITH_PROGRAMS OFF) + set(LIBXML2_WITH_PYTHON OFF) + set(LIBXML2_WITH_READER OFF) + set(LIBXML2_WITH_REGEXPS OFF) + set(LIBXML2_WITH_RELAXNG OFF) + set(LIBXML2_WITH_SCHEMAS OFF) + set(LIBXML2_WITH_SCHEMATRON OFF) + set(LIBXML2_WITH_TESTS OFF) + set(LIBXML2_WITH_WRITER OFF) + set(LIBXML2_WITH_XINCLUDE OFF) + set(LIBXML2_WITH_XPATH OFF) + set(LIBXML2_WITH_XPTR OFF) + set(LIBXML2_WITH_ZLIB OFF) + + FetchContent_Declare( + libxml2 + URL https://download.gnome.org/sources/libxml2/2.15/libxml2-2.15.3.tar.xz + URL_HASH SHA256=78262a6e7ac170d6528ebfe2efccdf220191a5af6a6cd61ea4a9a9a5042c7a07 + ) + FetchContent_MakeAvailable(libxml2) + + set_target_properties(LibXml2 PROPERTIES + C_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN true + ) + + if(CMAKE_SYSTEM_NAME STREQUAL Linux) + target_link_options(LibXml2 INTERFACE + "LINKER:--exclude-libs,libxml2.a" + ) + endif() +endfunction() + macro (fetch_google_test) include(FetchContent) FetchContent_Declare( @@ -365,6 +412,8 @@ add_library_pal(coreclrpal true ${CORECLR_PAL_ROOT}/lib/${CMAKE_BUILD_TYPE}/libc add_library_pal(palrt true ${CORECLR_PAL_ROOT}/lib/${CMAKE_BUILD_TYPE}/libpalrt.a) add_library_pal(corguids false ${CORECLR_PAL_ROOT}/lib/${CMAKE_BUILD_TYPE}/libcorguids.a) +fetch_libxml2() + add_subdirectory(unix/src) add_subdirectory(unix/src/atl) add_subdirectory(Common.Lib) diff --git a/src/Common.Lib/CMakeLists.txt b/src/Common.Lib/CMakeLists.txt index 0ded00b4..81cbef2c 100644 --- a/src/Common.Lib/CMakeLists.txt +++ b/src/Common.Lib/CMakeLists.txt @@ -3,9 +3,8 @@ cmake_minimum_required(VERSION 3.14) project(Common.Lib) -find_package(LibXml2 REQUIRED) -include_directories(. ${LIBXML2_INCLUDE_DIR}) +include_directories(.) build_init(CPP Common.Lib) #note: we purposfully exclude windows-only files, @@ -28,4 +27,9 @@ add_lib(${PROJECT_NAME} ${src_files} ) +target_link_libraries(${PROJECT_NAME} + PUBLIC + LibXml2::LibXml2 +) + #target_compile_options(Common.Lib PUBLIC "-H") \ No newline at end of file diff --git a/src/InstrumentationEngine.Lib/CMakeLists.txt b/src/InstrumentationEngine.Lib/CMakeLists.txt index ad1843e1..6b48c406 100644 --- a/src/InstrumentationEngine.Lib/CMakeLists.txt +++ b/src/InstrumentationEngine.Lib/CMakeLists.txt @@ -3,9 +3,8 @@ cmake_minimum_required(VERSION 3.14) project(InstrumentationEngine.Lib) -find_package(LibXml2 REQUIRED) -include_directories(. ${LIBXML2_INCLUDE_DIR}) +include_directories(.) build_init(CPP InstrumentationEngine.Lib) @@ -30,4 +29,9 @@ add_lib(${PROJECT_NAME} true # use_redefines false # hide_symbols ${src_files} - ) \ No newline at end of file + ) + +target_link_libraries(${PROJECT_NAME} + PRIVATE + LibXml2::LibXml2 +) \ No newline at end of file diff --git a/src/InstrumentationEngine.NuGet/InstrumentationEngine.nuspec b/src/InstrumentationEngine.NuGet/InstrumentationEngine.nuspec index b93b5be8..16e906e4 100644 --- a/src/InstrumentationEngine.NuGet/InstrumentationEngine.nuspec +++ b/src/InstrumentationEngine.NuGet/InstrumentationEngine.nuspec @@ -26,6 +26,7 @@ + diff --git a/src/InstrumentationEngine/CMakeLists.txt b/src/InstrumentationEngine/CMakeLists.txt index 7d4eeed9..6ab5a242 100644 --- a/src/InstrumentationEngine/CMakeLists.txt +++ b/src/InstrumentationEngine/CMakeLists.txt @@ -5,9 +5,7 @@ cmake_minimum_required(VERSION 2.8.12) project(InstrumentationEngine) -find_package(LibXml2 REQUIRED) - -include_directories(. ../InstrumentationEngine.Lib ${LIBXML2_INCLUDE_DIR}) +include_directories(. ../InstrumentationEngine.Lib) build_init(CPP InstrumentationEngine) @@ -90,7 +88,6 @@ endif() target_link_libraries(${PROJECT_NAME} pthread stdc++ - ${LIBXML2_LIBRARIES} ${CORECLRPAL} ${LINUXPAL} ${ATL} diff --git a/src/Tests/CommonLibTests/CMakeLists.txt b/src/Tests/CommonLibTests/CMakeLists.txt index 1e272b92..96287d3e 100644 --- a/src/Tests/CommonLibTests/CMakeLists.txt +++ b/src/Tests/CommonLibTests/CMakeLists.txt @@ -7,10 +7,9 @@ cmake_minimum_required(VERSION 3.14) fetch_google_test() project(Common.LibTests) -find_package(LibXml2 REQUIRED) # the midl directory is needed to replace the rpc headers referenced by midl generated headers. -include_directories(. ${REPOSITORY_ROOT}/src/unix/inc/midl ${REPOSITORY_ROOT}/src ${LIBXML2_INCLUDE_DIR}) +include_directories(. ${REPOSITORY_ROOT}/src/unix/inc/midl ${REPOSITORY_ROOT}/src) build_init(CPP Common.LibTests) @@ -29,7 +28,6 @@ add_executable( target_link_libraries( ${PROJECT_NAME} - ${LIBXML2_LIBRARIES} Common.Lib gtest_main ) diff --git a/src/Tests/InstrEngineTests/NaglerInstrumentationMethod/CMakeLists.txt b/src/Tests/InstrEngineTests/NaglerInstrumentationMethod/CMakeLists.txt index fc94ca72..9d7b4609 100644 --- a/src/Tests/InstrEngineTests/NaglerInstrumentationMethod/CMakeLists.txt +++ b/src/Tests/InstrEngineTests/NaglerInstrumentationMethod/CMakeLists.txt @@ -4,9 +4,8 @@ cmake_minimum_required(VERSION 3.14) project(NaglerInstrumentationEngine) -find_package(LibXml2 REQUIRED) -include_directories(. ${REPOSITORY_ROOT}/src ${LIBXML2_INCLUDE_DIR}) +include_directories(. ${REPOSITORY_ROOT}/src) # don't use the PAL for tests build_init(CPP InstrumentationEngine) @@ -47,7 +46,6 @@ target_link_libraries( ${PROJECT_NAME} pthread stdc++ - ${LIBXML2_LIBRARIES} Common.Lib ) diff --git a/src/Tests/InstrumentationEngineLibTests/CMakeLists.txt b/src/Tests/InstrumentationEngineLibTests/CMakeLists.txt index c08989b6..a85cb400 100644 --- a/src/Tests/InstrumentationEngineLibTests/CMakeLists.txt +++ b/src/Tests/InstrumentationEngineLibTests/CMakeLists.txt @@ -7,9 +7,8 @@ cmake_minimum_required(VERSION 3.14) fetch_google_test() project(InstrumentationEngine.LibTests) -find_package(LibXml2 REQUIRED) -include_directories(. ${REPOSITORY_ROOT}/src ${LIBXML2_INCLUDE_DIR}) +include_directories(. ${REPOSITORY_ROOT}/src) # don't use the PAL for tests build_init(CPP InstrumentationEngine.LibTests) @@ -58,7 +57,6 @@ target_link_libraries( ${PROJECT_NAME} pthread stdc++ - ${LIBXML2_LIBRARIES} ${CORECLRPAL} ${LINUXPAL} ${ATL} diff --git a/src/build.sh b/src/build.sh index 6e695f67..e1e17ed7 100755 --- a/src/build.sh +++ b/src/build.sh @@ -134,15 +134,13 @@ get_cmake() echo "found cmake version $cmakeVersion" cmakeMajor=$(echo $cmakeVersion | sed 's/^.*[^0-9]\([0-9]*\)\..*$/\1'/) cmakeMinor=$(echo $cmakeVersion | sed 's/^.*[^0-9]*\.\([0-9]*\)\..*$/\1'/) - if (( $cmakeMajor > 3 )); then - if (( $cmakeMinor >= 14 )); then - # found sufficient cmake, continue. - echo $cmakeLocation - return - fi + if (( $cmakeMajor > 3 || ($cmakeMajor == 3 && $cmakeMinor >= 18) )); then + # found sufficient cmake, continue. + echo $cmakeLocation + return fi - echo "Insufficient cmake version. Ensure cmake version 3.14 or later is installed" + echo "Insufficient cmake version. Ensure cmake version 3.18 or later is installed" exit 1 } diff --git a/src/unix/docker/context/components/libxml2/cgmanifest.json b/src/unix/docker/context/components/libxml2/cgmanifest.json new file mode 100644 index 00000000..0937099c --- /dev/null +++ b/src/unix/docker/context/components/libxml2/cgmanifest.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json.schemastore.org/component-detection-manifest.json", + "Registrations": [ + { + "Component": { + "Type": "other", + "other": { + "Name": "libxml2", + "Version": "2.15.3", + "DownloadUrl": "https://download.gnome.org/sources/libxml2/2.15/libxml2-2.15.3.tar.xz", + "SHA256CHECK": "78262a6e7ac170d6528ebfe2efccdf220191a5af6a6cd61ea4a9a9a5042c7a07" + } + }, + "DevelopmentDependency": false + } + ] +} From 8cbd19b647b098f69f37d9cbe8cc65c4ebe7c042 Mon Sep 17 00:00:00 2001 From: "Patrick Nelson (VS)" Date: Wed, 19 Aug 2026 11:26:32 -0700 Subject: [PATCH 2/5] PR Feedback --- THIRD-PARTY-NOTICES.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt index 99937cc1..ab372aa7 100644 --- a/THIRD-PARTY-NOTICES.txt +++ b/THIRD-PARTY-NOTICES.txt @@ -1,3 +1,20 @@ +NOTICES AND INFORMATION +Do Not Translate or Localize + +This software incorporates material from third parties. +Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, +or you may send a check or money order for US $5.00, including the product name, +the open source component name, platform, and version number, to: + +Source Code Compliance Team +Microsoft Corporation +One Microsoft Way +Redmond, WA 98052 +USA + +Notwithstanding any other terms, you may reverse engineer this software to the extent +required to debug changes to any libraries licensed under the GNU Lesser General Public License. + libxml2 ======= From 5b09accd7467c32bc4e8adb3c045f807e0882f3d Mon Sep 17 00:00:00 2001 From: "Patrick Nelson (VS)" Date: Thu, 20 Aug 2026 09:06:24 -0700 Subject: [PATCH 3/5] Use vcpkg instead of direct download from gnome --- build/yaml/steps/linux/binaries.yaml | 11 ++++ src/CMakeLists.txt | 60 ++++--------------- src/build.sh | 53 +++++++++++++++- .../context/components/cmake/cgmanifest.json | 6 +- .../components/libxml2/cgmanifest.json | 17 ------ .../context/components/vcpkg/cgmanifest.json | 15 +++++ src/unix/docker/docker-build.sh | 17 ++++++ .../dockerfiles/build/alpine/Dockerfile | 29 +++++++-- .../dockerfiles/build/ubuntu/Dockerfile | 20 ++++++- src/vcpkg.json | 15 +++++ 10 files changed, 163 insertions(+), 80 deletions(-) delete mode 100644 src/unix/docker/context/components/libxml2/cgmanifest.json create mode 100644 src/unix/docker/context/components/vcpkg/cgmanifest.json create mode 100644 src/vcpkg.json diff --git a/build/yaml/steps/linux/binaries.yaml b/build/yaml/steps/linux/binaries.yaml index 07c31b80..e3d87421 100644 --- a/build/yaml/steps/linux/binaries.yaml +++ b/build/yaml/steps/linux/binaries.yaml @@ -13,12 +13,23 @@ steps: scriptLocation: inlineScript inlineScript: 'az acr login --name proddiagbuild' +# Restore vcpkg source and binary caches +- task: Cache@2 + displayName: Restore vcpkg cache + inputs: + key: '"vcpkg" | "$(Agent.OS)" | "$(Distro)" | src/vcpkg.json | src/unix/docker/context/components/vcpkg/cgmanifest.json' + restoreKeys: | + "vcpkg" | "$(Agent.OS)" | "$(Distro)" + path: $(Pipeline.Workspace)/vcpkg-cache + # Build binaries - task: Bash@3 displayName: Docker Build inputs: filePath: src/unix/docker/docker-build.sh arguments: $(Distro) $(Configuration) $(Platform) verbose + env: + VCPKG_CACHE_ROOT: $(Pipeline.Workspace)/vcpkg-cache # Cleanup containers - task: Bash@3 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4741492a..b35f7929 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,8 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -# Require at least version 3.18 of CMake -cmake_minimum_required(VERSION 3.18) +# Require at least version 3.14 of CMake +cmake_minimum_required(VERSION 3.14) IF(NOT EXISTS "${CMAKE_INSTALL_PREFIX}" OR NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}") message(FATAL_ERROR "Required property CMAKE_INSTALL_PREFIX not correctly defined.") @@ -233,53 +233,6 @@ function(generate_exports_file inputFilename versionName outputFilename) PROPERTIES GENERATED TRUE) endfunction() -function(fetch_libxml2) - include(FetchContent) - - set(BUILD_SHARED_LIBS OFF) - set(LIBXML2_WITH_C14N OFF) - set(LIBXML2_WITH_CATALOG OFF) - set(LIBXML2_WITH_DEBUG OFF) - set(LIBXML2_WITH_DOCS OFF) - set(LIBXML2_WITH_HTML OFF) - set(LIBXML2_WITH_HTTP OFF) - set(LIBXML2_WITH_ICU OFF) - set(LIBXML2_WITH_MODULES OFF) - set(LIBXML2_WITH_OUTPUT OFF) - set(LIBXML2_WITH_PATTERN OFF) - set(LIBXML2_WITH_PROGRAMS OFF) - set(LIBXML2_WITH_PYTHON OFF) - set(LIBXML2_WITH_READER OFF) - set(LIBXML2_WITH_REGEXPS OFF) - set(LIBXML2_WITH_RELAXNG OFF) - set(LIBXML2_WITH_SCHEMAS OFF) - set(LIBXML2_WITH_SCHEMATRON OFF) - set(LIBXML2_WITH_TESTS OFF) - set(LIBXML2_WITH_WRITER OFF) - set(LIBXML2_WITH_XINCLUDE OFF) - set(LIBXML2_WITH_XPATH OFF) - set(LIBXML2_WITH_XPTR OFF) - set(LIBXML2_WITH_ZLIB OFF) - - FetchContent_Declare( - libxml2 - URL https://download.gnome.org/sources/libxml2/2.15/libxml2-2.15.3.tar.xz - URL_HASH SHA256=78262a6e7ac170d6528ebfe2efccdf220191a5af6a6cd61ea4a9a9a5042c7a07 - ) - FetchContent_MakeAvailable(libxml2) - - set_target_properties(LibXml2 PROPERTIES - C_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN true - ) - - if(CMAKE_SYSTEM_NAME STREQUAL Linux) - target_link_options(LibXml2 INTERFACE - "LINKER:--exclude-libs,libxml2.a" - ) - endif() -endfunction() - macro (fetch_google_test) include(FetchContent) FetchContent_Declare( @@ -412,7 +365,14 @@ add_library_pal(coreclrpal true ${CORECLR_PAL_ROOT}/lib/${CMAKE_BUILD_TYPE}/libc add_library_pal(palrt true ${CORECLR_PAL_ROOT}/lib/${CMAKE_BUILD_TYPE}/libpalrt.a) add_library_pal(corguids false ${CORECLR_PAL_ROOT}/lib/${CMAKE_BUILD_TYPE}/libcorguids.a) -fetch_libxml2() +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + find_package(LibXml2 CONFIG REQUIRED) + target_link_options(LibXml2::LibXml2 INTERFACE + "LINKER:--exclude-libs,libxml2.a" + ) +else() + find_package(LibXml2 REQUIRED) +endif() add_subdirectory(unix/src) add_subdirectory(unix/src/atl) diff --git a/src/build.sh b/src/build.sh index e1e17ed7..15fcb77b 100755 --- a/src/build.sh +++ b/src/build.sh @@ -134,13 +134,13 @@ get_cmake() echo "found cmake version $cmakeVersion" cmakeMajor=$(echo $cmakeVersion | sed 's/^.*[^0-9]\([0-9]*\)\..*$/\1'/) cmakeMinor=$(echo $cmakeVersion | sed 's/^.*[^0-9]*\.\([0-9]*\)\..*$/\1'/) - if (( $cmakeMajor > 3 || ($cmakeMajor == 3 && $cmakeMinor >= 18) )); then + if (( $cmakeMajor > 3 || ($cmakeMajor == 3 && $cmakeMinor >= 14) )); then # found sufficient cmake, continue. echo $cmakeLocation return fi - echo "Insufficient cmake version. Ensure cmake version 3.18 or later is installed" + echo "Insufficient cmake version. Ensure cmake version 3.14 or later is installed" exit 1 } @@ -188,6 +188,10 @@ locate_build_tools() cmake_extra_defines="$cmake_extra_defines -DCLR_CMAKE_LINUX_ID=$ID" fi + if [[ -n "$__VcpkgInstalledDir" ]]; then + cmake_extra_defines="$cmake_extra_defines -DCMAKE_PREFIX_PATH=$__VcpkgInstalledDir/$__VcpkgTriplet" + fi + locate_google_test $echo "found google version '$__GoogleTestTag' test at '$__GoogleTestUrl'" } @@ -357,6 +361,47 @@ restore_build_dependencies() fi } +restore_vcpkg_dependencies() +{ + if [ -z "$VCPKG_ROOT" ] || [ ! -x "$VCPKG_ROOT/vcpkg" ]; then + echo "ERROR: VCPKG_ROOT must point to a bootstrapped vcpkg installation." + exit 1 + fi + + __VcpkgInstalledDir="$__IntermediatesDir/vcpkg_installed" + __VcpkgTriplet=x64-linux + + "$VCPKG_ROOT/vcpkg" install \ + --x-manifest-root="$EnlistmentRoot/src" \ + --x-install-root="$__VcpkgInstalledDir" \ + --triplet="$__VcpkgTriplet" \ + --clean-after-build + + if [ $? -ne 0 ]; then + echo "ERROR: vcpkg dependency restore failed." + exit 1 + fi +} + +configure_vcpkg_cache() +{ + local cacheRoot="${VCPKG_CACHE_ROOT:-$EnlistmentRoot/out/vcpkg-cache}" + + mkdir -p "$cacheRoot/assets" "$cacheRoot/archives" + if [ $? -ne 0 ]; then + echo "ERROR: Unable to create vcpkg cache at '$cacheRoot'." + exit 1 + fi + + if [ -z "$X_VCPKG_ASSET_SOURCES" ]; then + export X_VCPKG_ASSET_SOURCES="clear;x-azurl,file://$cacheRoot/assets/,,readwrite" + fi + + if [ -z "$VCPKG_BINARY_SOURCES" ]; then + export VCPKG_BINARY_SOURCES="clear;files,$cacheRoot/archives,readwrite" + fi +} + # Set default clang version set_clang_path_and_version() { @@ -568,6 +613,10 @@ setup_dirs check_prereqs restore_build_dependencies +if [ "$OSName" == "Linux" ]; then + configure_vcpkg_cache + restore_vcpkg_dependencies +fi pwd diff --git a/src/unix/docker/context/components/cmake/cgmanifest.json b/src/unix/docker/context/components/cmake/cgmanifest.json index 53febb0a..077ad2c2 100644 --- a/src/unix/docker/context/components/cmake/cgmanifest.json +++ b/src/unix/docker/context/components/cmake/cgmanifest.json @@ -6,9 +6,9 @@ "Type": "other", "other": { "Name": "cmake", - "Version": "3.20.2", - "DownloadUrl": " https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz", - "SHA256CHECK": "aecf6ecb975179eb3bb6a4a50cae192d41e92b9372b02300f9e8f1d5f559544e" + "Version": "3.31.10", + "DownloadUrl": "https://github.com/Kitware/CMake/releases/download/v3.31.10/cmake-3.31.10.tar.gz", + "SHA256CHECK": "cf06fadfd6d41fa8e1ade5099e54976d1d844fd1487ab99942341f91b13d3e29" } }, "DevelopmentDependency": true diff --git a/src/unix/docker/context/components/libxml2/cgmanifest.json b/src/unix/docker/context/components/libxml2/cgmanifest.json deleted file mode 100644 index 0937099c..00000000 --- a/src/unix/docker/context/components/libxml2/cgmanifest.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/component-detection-manifest.json", - "Registrations": [ - { - "Component": { - "Type": "other", - "other": { - "Name": "libxml2", - "Version": "2.15.3", - "DownloadUrl": "https://download.gnome.org/sources/libxml2/2.15/libxml2-2.15.3.tar.xz", - "SHA256CHECK": "78262a6e7ac170d6528ebfe2efccdf220191a5af6a6cd61ea4a9a9a5042c7a07" - } - }, - "DevelopmentDependency": false - } - ] -} diff --git a/src/unix/docker/context/components/vcpkg/cgmanifest.json b/src/unix/docker/context/components/vcpkg/cgmanifest.json new file mode 100644 index 00000000..a5f31485 --- /dev/null +++ b/src/unix/docker/context/components/vcpkg/cgmanifest.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/component-detection-manifest.json", + "Registrations": [ + { + "Component": { + "Type": "git", + "git": { + "RepositoryUrl": "https://github.com/microsoft/vcpkg", + "CommitHash": "2d318737bc7daa8a872f4469955a0559686f7580" + } + }, + "DevelopmentDependency": true + } + ] +} diff --git a/src/unix/docker/docker-build.sh b/src/unix/docker/docker-build.sh index 03967a7c..e96e76c4 100644 --- a/src/unix/docker/docker-build.sh +++ b/src/unix/docker/docker-build.sh @@ -104,6 +104,23 @@ invoke_build() fi docker_run_args="$docker_run_args -v $LocalBuildPath:/root/ClrInstrumentationEngine/build:ro" + local VcpkgCachePath="${VCPKG_CACHE_ROOT:-${TMPDIR:-/tmp}/clrie-vcpkg-cache}" + mkdir -p "$VcpkgCachePath" + if [ $? -ne 0 ]; then + echo "ERROR: failed to create vcpkg cache at '$VcpkgCachePath'." + exit 1 + fi + docker_run_args="$docker_run_args -v $VcpkgCachePath:/root/ClrInstrumentationEngine/out/vcpkg-cache" + docker_run_args="$docker_run_args --env VCPKG_CACHE_ROOT=/root/ClrInstrumentationEngine/out/vcpkg-cache" + + if [[ -n "$X_VCPKG_ASSET_SOURCES" ]]; then + docker_run_args="$docker_run_args --env X_VCPKG_ASSET_SOURCES" + fi + + if [[ -n "$VCPKG_BINARY_SOURCES" ]]; then + docker_run_args="$docker_run_args --env VCPKG_BINARY_SOURCES" + fi + build_cmd="bash /root/ClrInstrumentationEngine/src/build.sh $__BuildArch $__BuildType clean $__UnprocessedBuildArgs" docker_run_args="$docker_run_args --net=host $__DockerImage $build_cmd" diff --git a/src/unix/docker/dockerfiles/build/alpine/Dockerfile b/src/unix/docker/dockerfiles/build/alpine/Dockerfile index cdbf73d8..c620f81e 100644 --- a/src/unix/docker/dockerfiles/build/alpine/Dockerfile +++ b/src/unix/docker/dockerfiles/build/alpine/Dockerfile @@ -35,11 +35,14 @@ RUN wget -O dotnet.tar.gz https://builds.dotnet.microsoft.com/dotnet/Sdk/$DOTNET && dotnet help # CLR Instrumentation Engine Build Prerequisites -RUN apk update \ - && apk add --no-cache libxml2-dev - -# Add jq to make it easer to read json in shell scripts -RUN apk add --no-cache jq +RUN apk add --no-cache \ + git \ + jq \ + ninja \ + patchelf \ + pkgconf \ + unzip \ + zip # Install newer version of cmake. We need to run make commands inside the directory # that it is extracted to, so WORKDIR is the easiest context to use. @@ -62,4 +65,18 @@ RUN cmakeurl=$(cat cgmanifest.json | jq '.Registrations[0].Component.other.Downl # Delete the cmake installer it is no longer needed. WORKDIR / -RUN rm -rf /usr/share/cmakeinst \ No newline at end of file +RUN rm -rf /usr/share/cmakeinst + +ENV VCPKG_ROOT=/opt/vcpkg +ENV VCPKG_FORCE_SYSTEM_BINARIES=1 +ENV PATH="$VCPKG_ROOT:$PATH" + +COPY "components/vcpkg/cgmanifest.json" /tmp/vcpkg-cgmanifest.json +RUN vcpkg_repo=$(jq -r '.Registrations[0].Component.git.RepositoryUrl' /tmp/vcpkg-cgmanifest.json) \ + && vcpkg_commit=$(jq -r '.Registrations[0].Component.git.CommitHash' /tmp/vcpkg-cgmanifest.json) \ + && git init "$VCPKG_ROOT" \ + && git -C "$VCPKG_ROOT" remote add origin "$vcpkg_repo" \ + && git -C "$VCPKG_ROOT" fetch --depth 1 origin "$vcpkg_commit" \ + && git -C "$VCPKG_ROOT" checkout --detach FETCH_HEAD \ + && "$VCPKG_ROOT/bootstrap-vcpkg.sh" -disableMetrics \ + && rm /tmp/vcpkg-cgmanifest.json \ No newline at end of file diff --git a/src/unix/docker/dockerfiles/build/ubuntu/Dockerfile b/src/unix/docker/dockerfiles/build/ubuntu/Dockerfile index ddf5f670..6c62322b 100644 --- a/src/unix/docker/dockerfiles/build/ubuntu/Dockerfile +++ b/src/unix/docker/dockerfiles/build/ubuntu/Dockerfile @@ -68,9 +68,25 @@ RUN apt-get update \ clang-3.9 \ cmake \ git \ - libxml2-dev \ make \ - jq + jq \ + ninja-build \ + pkg-config \ + unzip \ + zip + +ENV VCPKG_ROOT=/opt/vcpkg +ENV PATH="$VCPKG_ROOT:$PATH" + +COPY "components/vcpkg/cgmanifest.json" /tmp/vcpkg-cgmanifest.json +RUN vcpkg_repo=$(jq -r '.Registrations[0].Component.git.RepositoryUrl' /tmp/vcpkg-cgmanifest.json) \ + && vcpkg_commit=$(jq -r '.Registrations[0].Component.git.CommitHash' /tmp/vcpkg-cgmanifest.json) \ + && git init "$VCPKG_ROOT" \ + && git -C "$VCPKG_ROOT" remote add origin "$vcpkg_repo" \ + && git -C "$VCPKG_ROOT" fetch --depth 1 origin "$vcpkg_commit" \ + && git -C "$VCPKG_ROOT" checkout --detach FETCH_HEAD \ + && "$VCPKG_ROOT/bootstrap-vcpkg.sh" -disableMetrics \ + && rm /tmp/vcpkg-cgmanifest.json # Git now checks for repository ownership RUN git config --global --add safe.directory /root/ClrInstrumentationEngine/out/Linux/Intermediate/x64.Debug/_deps/googletest-src diff --git a/src/vcpkg.json b/src/vcpkg.json new file mode 100644 index 00000000..6f1fd513 --- /dev/null +++ b/src/vcpkg.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "name": "clr-instrumentation-engine-native-dependencies", + "version-string": "1.0", + "builtin-baseline": "2d318737bc7daa8a872f4469955a0559686f7580", + "dependencies": [ + { + "name": "libxml2", + "default-features": false, + "features": [ + "iconv" + ] + } + ] +} From 03adc0ceae63b973754314edcf218a1581276c3e Mon Sep 17 00:00:00 2001 From: "Patrick Nelson (VS)" Date: Thu, 20 Aug 2026 13:31:59 -0700 Subject: [PATCH 4/5] Add Linux build image pipeline Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 91fc1ee3-05d7-4c21-8dae-9ab4fd12b8c7 --- build/yaml/pipelines/build_images.yaml | 81 ++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 build/yaml/pipelines/build_images.yaml diff --git a/build/yaml/pipelines/build_images.yaml b/build/yaml/pipelines/build_images.yaml new file mode 100644 index 00000000..528df429 --- /dev/null +++ b/build/yaml/pipelines/build_images.yaml @@ -0,0 +1,81 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# Build Pipeline: Linux Build Images +# Manually rebuilds and publishes the Ubuntu and Alpine images used by Linux CI. + +trigger: none +pr: none + +name: $(date:yyyyMMdd)$(rev:rr) + +parameters: +- name: ImageTag + displayName: Container image tag + type: string + default: latest + +variables: + TeamName: ClrInstrumentationEngine + RegistryName: proddiagbuild + RegistryServer: proddiagbuild.azurecr.io + +jobs: +- job: BuildImages + displayName: Build Linux images + + pool: + ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Ubuntu20.04 + os: linux + ${{ else }}: + vmImage: ubuntu-latest + + steps: + - checkout: self + clean: true + + - bash: | + set -e + if [[ ! "$IMAGE_TAG" =~ ^[A-Za-z0-9_.-]+$ ]]; then + echo "Invalid image tag: $IMAGE_TAG" + exit 1 + fi + displayName: Validate image tag + env: + IMAGE_TAG: ${{ parameters.ImageTag }} + + - task: AzureCLI@2 + displayName: Docker login + inputs: + azureSubscription: 'VS Diagnostics Dev (ProdDiagBuild)' + scriptType: bash + scriptLocation: inlineScript + inlineScript: az acr login --name $(RegistryName) + + - bash: | + set -e + image="$(RegistryServer)/clrie-build-ubuntu:$IMAGE_TAG" + docker build --pull \ + --label "org.opencontainers.image.revision=$(Build.SourceVersion)" \ + --tag "$image" \ + --file src/unix/docker/dockerfiles/build/ubuntu/Dockerfile \ + src/unix/docker/context + docker push "$image" + displayName: Build and push Ubuntu image + env: + IMAGE_TAG: ${{ parameters.ImageTag }} + + - bash: | + set -e + image="$(RegistryServer)/clrie-build-alpine:$IMAGE_TAG" + docker build --pull \ + --label "org.opencontainers.image.revision=$(Build.SourceVersion)" \ + --tag "$image" \ + --file src/unix/docker/dockerfiles/build/alpine/Dockerfile \ + src/unix/docker/context + docker push "$image" + displayName: Build and push Alpine image + env: + IMAGE_TAG: ${{ parameters.ImageTag }} From 8f79d188a24c98c609fbcb5fcd6c71572dc4cefe Mon Sep 17 00:00:00 2001 From: "Patrick Nelson (VS)" Date: Mon, 24 Aug 2026 10:38:17 -0700 Subject: [PATCH 5/5] Use 1ES container image pipeline Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 91fc1ee3-05d7-4c21-8dae-9ab4fd12b8c7 --- build/yaml/pipelines/build_images.yaml | 135 ++++++++++++++----------- 1 file changed, 77 insertions(+), 58 deletions(-) diff --git a/build/yaml/pipelines/build_images.yaml b/build/yaml/pipelines/build_images.yaml index 528df429..6f5cd251 100644 --- a/build/yaml/pipelines/build_images.yaml +++ b/build/yaml/pipelines/build_images.yaml @@ -14,68 +14,87 @@ parameters: displayName: Container image tag type: string default: latest +- name: RegistryServiceConnection + displayName: ACR Docker service connection + type: string + default: 'VS Diagnostics Dev (ProdDiagBuild)' variables: - TeamName: ClrInstrumentationEngine - RegistryName: proddiagbuild - RegistryServer: proddiagbuild.azurecr.io +- name: TeamName + value: ClrInstrumentationEngine + readonly: true +- name: ImageTag + value: ${{ parameters.ImageTag }} + readonly: true -jobs: -- job: BuildImages - displayName: Build Linux images +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release - pool: - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: name: AzurePipelines-EO image: 1ESPT-Ubuntu20.04 os: linux - ${{ else }}: - vmImage: ubuntu-latest - - steps: - - checkout: self - clean: true - - - bash: | - set -e - if [[ ! "$IMAGE_TAG" =~ ^[A-Za-z0-9_.-]+$ ]]; then - echo "Invalid image tag: $IMAGE_TAG" - exit 1 - fi - displayName: Validate image tag - env: - IMAGE_TAG: ${{ parameters.ImageTag }} - - - task: AzureCLI@2 - displayName: Docker login - inputs: - azureSubscription: 'VS Diagnostics Dev (ProdDiagBuild)' - scriptType: bash - scriptLocation: inlineScript - inlineScript: az acr login --name $(RegistryName) - - - bash: | - set -e - image="$(RegistryServer)/clrie-build-ubuntu:$IMAGE_TAG" - docker build --pull \ - --label "org.opencontainers.image.revision=$(Build.SourceVersion)" \ - --tag "$image" \ - --file src/unix/docker/dockerfiles/build/ubuntu/Dockerfile \ - src/unix/docker/context - docker push "$image" - displayName: Build and push Ubuntu image - env: - IMAGE_TAG: ${{ parameters.ImageTag }} - - - bash: | - set -e - image="$(RegistryServer)/clrie-build-alpine:$IMAGE_TAG" - docker build --pull \ - --label "org.opencontainers.image.revision=$(Build.SourceVersion)" \ - --tag "$image" \ - --file src/unix/docker/dockerfiles/build/alpine/Dockerfile \ - src/unix/docker/context - docker push "$image" - displayName: Build and push Alpine image - env: - IMAGE_TAG: ${{ parameters.ImageTag }} + + stages: + - stage: BuildImages + displayName: Build Linux images + + jobs: + - job: BuildUbuntuImage + displayName: Build and publish Ubuntu image + + templateContext: + authenticatedContainerRegistries: + - serviceConnection: ${{ parameters.RegistryServiceConnection }} + + outputs: + - output: containerImage + image: proddiagbuild.azurecr.io/clrie-build-ubuntu:$(ImageTag) + targetPath: $(Build.ArtifactStagingDirectory) + artifactName: ubuntu-image + + steps: + - checkout: self + clean: true + + - task: 1ES.BuildContainerImage@1 + displayName: Build Ubuntu image + inputs: + image: proddiagbuild.azurecr.io/clrie-build-ubuntu:$(ImageTag) + path: $(Build.SourcesDirectory)/src/unix/docker/context + dockerfile: $(Build.SourcesDirectory)/src/unix/docker/dockerfiles/build/ubuntu/Dockerfile + enableNetwork: true + useBuildKit: true + + - job: BuildAlpineImage + displayName: Build and publish Alpine image + + templateContext: + authenticatedContainerRegistries: + - serviceConnection: ${{ parameters.RegistryServiceConnection }} + + outputs: + - output: containerImage + image: proddiagbuild.azurecr.io/clrie-build-alpine:$(ImageTag) + targetPath: $(Build.ArtifactStagingDirectory) + artifactName: alpine-image + + steps: + - checkout: self + clean: true + + - task: 1ES.BuildContainerImage@1 + displayName: Build Alpine image + inputs: + image: proddiagbuild.azurecr.io/clrie-build-alpine:$(ImageTag) + path: $(Build.SourcesDirectory)/src/unix/docker/context + dockerfile: $(Build.SourcesDirectory)/src/unix/docker/dockerfiles/build/alpine/Dockerfile + enableNetwork: true + useBuildKit: true