Skip to content

[vcpkg scripts] Enable cross-compilation tool dependency copying#49887

Closed
zynfly wants to merge 1 commit intomicrosoft:masterfrom
zynfly:master
Closed

[vcpkg scripts] Enable cross-compilation tool dependency copying#49887
zynfly wants to merge 1 commit intomicrosoft:masterfrom
zynfly:master

Conversation

@zynfly
Copy link
Contributor

@zynfly zynfly commented Feb 9, 2026

Description

This PR enables automatic copying of tool dependencies when cross-compiling from macOS/Linux to Windows targets with dynamic linkage (e.g., x64-mingw-dynamic).

Problem

When cross-compiling to Windows from non-Windows hosts, tools built with dynamic linkage were missing their vcpkg DLL dependencies in the tools directory. This caused runtime errors when attempting to use these tools on Windows, as they couldn't find required DLLs like libbrotlidec.dll.

Example failure scenario:

# On macOS, build brotli for Windows
./vcpkg install brotli:x64-mingw-dynamic

# Tool directory only contains brotli.exe (missing DLLs)
tools/brotli/
└── brotli.exe  ❌ Cannot run on Windows (missing libbrotlidec.dll, libbrotlienc.dll)

Solution

Enhanced vcpkg_copy_tool_dependencies.cmake to handle cross-compilation scenarios:

  • Windows host: Continues using the existing PowerShell + applocal.ps1 solution (no change)
  • Non-Windows host: Uses objdump to analyze PE dependencies and recursively copy vcpkg DLLs
  • Graceful degradation: If objdump is not available, warns but doesn't fail the build
  • Smart filtering: Only copies vcpkg-managed DLLs, skips system DLLs (kernel32.dll, etc.)
  • Recursive resolution: Handles transitive dependencies (DLL → DLL)

Implementation Details

Added two new internal functions:

  1. z_vcpkg_resolve_pe_dependencies(): Analyzes PE binaries using objdump to extract DLL dependencies, searches for them in vcpkg directories, and copies found DLLs to the tool directory.

  2. z_vcpkg_copy_tool_dependencies_cross_compile(): Coordinates the cross-compilation dependency copying by finding an appropriate objdump tool and recursively processing tool binaries and their dependencies.

The implementation:

  • Detects available objdump variants (MinGW, LLVM, or native)
  • Parses PE import tables to find DLL dependencies
  • Recursively resolves transitive dependencies
  • Only runs for dynamic linkage builds
  • Maintains a "searched" list to prevent infinite loops

Testing

Test package: brotli:x64-mingw-dynamic
Test environment: macOS → Windows x64 (MinGW cross-compilation)
objdump tool: x86_64-w64-mingw32-objdump

Before this change:

tools/brotli/
└── brotli.exe  ❌ Missing dependencies

After this change:

tools/brotli/
├── brotli.exe              ✅
├── libbrotlidec.dll        ✅ Direct dependency
├── libbrotlienc.dll        ✅ Direct dependency
└── libbrotlicommon.dll     ✅ Transitive dependency (DLL → DLL)

Dependency verification:

$ x86_64-w64-mingw32-objdump -p brotli.exe | grep "DLL Name:"
  DLL Name: libbrotlidec.dll     ✅ Copied
  DLL Name: libbrotlienc.dll     ✅ Copied
  DLL Name: KERNEL32.dll          ✅ Skipped (system DLL)
  ...

$ x86_64-w64-mingw32-objdump -p libbrotlidec.dll | grep "DLL Name:"
  DLL Name: libbrotlicommon.dll  ✅ Copied (recursive dependency)
  ...

Compatibility

  • Windows hosts: No change, continues using PowerShell + applocal.ps1
  • Static linkage: Skipped (no DLLs needed)
  • Non-Windows targets: Skipped (no PE format)
  • Backward compatible: All existing builds continue to work

Performance Impact

  • Build time increase: < 1% (negligible)
  • Example: brotli build time remains ~11 seconds
  • Tool overhead: Only runs when necessary (Windows target + dynamic linkage + non-Windows host)

When cross-compiling from macOS/Linux to Windows targets (e.g.,
x64-mingw-dynamic), tools built with dynamic linkage were missing
their vcpkg DLL dependencies, causing runtime errors on Windows.

This change enhances vcpkg_copy_tool_dependencies.cmake to handle
cross-compilation scenarios:

- Windows host: continues using PowerShell + applocal.ps1 (no change)
- Non-Windows host: uses objdump to analyze PE dependencies and
  recursively copy vcpkg DLLs to the tool directory
- Gracefully degrades if objdump is not available (warning only)
- Only runs for dynamic linkage (static builds unaffected)

The implementation:
1. Detects available objdump variants (MinGW, LLVM, native)
2. Parses PE import tables to find DLL dependencies
3. Recursively resolves transitive dependencies (DLL → DLL)
4. Copies only vcpkg-managed DLLs (skips system DLLs)

Tested with brotli:x64-mingw-dynamic on macOS, confirming that
brotli.exe now includes all required DLLs (libbrotlidec.dll,
libbrotlienc.dll, libbrotlicommon.dll).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@dg0yt
Copy link
Contributor

dg0yt commented Feb 9, 2026

This topic has been touched before:

  • CMake already has script for dealing with runtime dependencies. IMO they should be called instead of reventing the wheel.
  • vcpkg already has code for dealing with DLLs. IIRC Microsoft wanted to adapt that for DLL deployment.

@zynfly
Copy link
Contributor Author

zynfly commented Feb 9, 2026

This is primarily to address the issue of cross-compilation, rather than the issue of dll handling under Windows.

@dg0yt
Copy link
Contributor

dg0yt commented Feb 9, 2026

This is primarily to address the issue of cross-compilation, rather than the issue of dll handling under Windows.

This is what I read in the initial post. All my points stand.
(And I didn't even mention that powershell is available for linux and macos. Mingw DLL deployment with powershell on linux expected to work.)

@zynfly
Copy link
Contributor Author

zynfly commented Feb 9, 2026

And there is a bug in vcpkg. When executed on macOS/Linux, if the target triplet is still set to Windows, it will invoke Powershell, which can also lead to failures. I initially started working on this to fix the bug.

@zynfly
Copy link
Contributor Author

zynfly commented Feb 9, 2026

This is primarily to address the issue of cross-compilation, rather than the issue of dll handling under Windows.

This is what I read in the initial post. All my points stand. (And I didn't even mention that powershell is available for linux and macos. Mingw DLL deployment with powershell on linux expected to work.)

Yes, it is possible to install pwsh on Linux and macOS, but I don't think it's a good approach. Or maybe vcpkg shouldn't rely on pwsh on these platforms.

@zynfly
Copy link
Contributor Author

zynfly commented Feb 9, 2026

[ if(VCPKG_TARGET_IS_WINDOWS)

](

if(VCPKG_TARGET_IS_WINDOWS)
)

The main issue lies here: as long as the target is Windows, pwsh must be used.

@dg0yt
Copy link
Contributor

dg0yt commented Feb 9, 2026

The main issue lies here: as long as the target is Windows, pwsh must be used.

It is a feature, not an issue: If you install powershell on macOS and build for mingw, it should already work.

@dg0yt
Copy link
Contributor

dg0yt commented Feb 9, 2026

Yes, it is possible to install pwsh on Linux and macOS, but I don't think it's a good approach. Or maybe vcpkg shouldn't rely on pwsh on these platforms.

I agree. I just don't agree to inventing a fourth line of code (custom cmake) in addition to powershell (exists), original cmake (needs cmake glue), and vcpkg (needs C++ code and cmake glue).

@zynfly
Copy link
Contributor Author

zynfly commented Feb 9, 2026

Or should I try using pwsh as a tool for vcpkg?
If there is no pwsh in the system, should I download a tool just for vcpkg to use?

However, there are still some cross-platform libraries, such as Qt, that require special handling.

@zynfly zynfly marked this pull request as draft February 9, 2026 09:39
@zynfly
Copy link
Contributor Author

zynfly commented Feb 9, 2026

@dg0yt https://github.com/zynfly/vcpkg/tree/feature/add-pwsh-tool-clean

If pwsh is not available, let vcpkg download it automatically.
There are still issues with cross-compilation for Qt, which I will fix later.
If possible, I will close the current PR and create a new one, first making pwsh available on all systems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants