MSVC Dependencies: Update [As of July 2026]

As a follow-up to the earlier post from February, I believe enough has changed to make a new post. Most importantly, xrepo/xmake has become more feasible as a source to get the dependencies from instead of vcpkg, with several packages getting added recently.

At the moment, I’ve had a python script for installing the dependencies using vcpkg, found at testardourdeps/vcpkg-build/InstallDependencies.vcpkg.py at main · EZ4Stephen/testardourdeps · GitHub. (Once someone verifies this to work, I’ll share it as text here.) This gets most dependencies from vcpkg, plus a few from some port overlays. So far, I haven’t received confirmation of this script working fully for anyone else, and at least one issue faced was that gperf made use of autotools as its build system, and long story short (based on discussion in the previous post), seems like running this script would fail on a non-NTFS drive.

(Note that the above script doesn’t install MSVC, and currently the installed pkgconf from vcpkg needs to be renamed to pkg-config to be used, and then you add the path of pkg-config to path. Then llvm-nm also needs to be in path, which can be done by opening developer PS/CMD. And then the .pc files’ folder needs to be set as pkg_config_path.)

But in the past few months, I have also been working on getting the dependencies to be available from xrepo. While I’m not fully there to building ardour from xrepo’s packages due to some linking errors and missing headers, the installation process seems easier.

To get the packages from xrepo:

  1. Install xmake by following instructions from here.
  2. Copy the following into an xmake.lua file:
set_policy("package.sync_requires_to_deps", true)
add_requireconfs("**", {configs = {shared = true}, system = false})

if is_mode("debug") then
    add_requireconfs("**", {configs = {debug = true}})
end

-- Host tools
if is_subhost("windows") then
    add_requires("pkgconf")
else
    add_requires("pkg-config")
end
add_requires("gperf", {host = true})

-- Library deps
add_requires("libcurl")
add_requires("libogg")
add_requires("libflac")
add_requires("libopus")
add_requires("libvorbis")
add_requires("libsndfile")
add_requires("zlib")
add_requires("bzip2")
add_requires("lz4")
add_requires("zstd")
add_requires("openssl3")
add_requires("libarchive")
add_requires("liblo")
add_requires("utfcpp")
add_requires("taglib")
add_requires("vamp-plugin-sdk")
add_requires("libusb")
add_requires("rubberband")
add_requires("jack2")
add_requires("fftw")
add_requires("aubio")
add_requires("libxml2")
add_requires("cppunit")
add_requires("libwebsockets")
add_requires("portaudio", {configs = {asio = true}})
add_requires("libsamplerate")
add_requires("lv2")
add_requires("serd")
add_requires("zix")
add_requires("sord")
add_requires("sratom")
add_requires("lilv")
add_requires("libjpeg-turbo")
add_requires("boost")
add_requires("libffi")
add_requires("libintl")
add_requires("pcre2")
add_requires("glib")
add_requires("fribidi")
add_requires("freetype")
add_requires("harfbuzz", {configs = {glib = true}})
add_requires("expat")
add_requires("fontconfig")
add_requires("libpng")
add_requires("pixman")
add_requires("cairo")
add_requires("pango")
add_requires("libsigcplusplus <3.0.0")
add_requires("glibmm <2.68.0")
add_requires("cairomm <1.16.0")
add_requires("pangomm <2.48.0")
if is_plat("windows") then
    add_requires("pthreads4w")
    add_requires("wingetopt")
end

target("collect_deps")
    set_kind("phony")
    after_load(function()
        import("core.project.project")
        import("core.project.config")
        local dest = path.join(os.projectdir(), config.mode() or "release")
        local subdirs = {"include", "lib"}
        if is_plat("windows") then table.insert(subdirs, "bin") end
        for _, pkg in pairs(project.required_packages()) do
            local dir = pkg:installdir()
            if dir and os.isdir(dir) then
                for _, sub in ipairs(subdirs) do
                    local src = path.join(dir, sub)
                    if os.isdir(src) then
                        for _, fp in ipairs(os.files(path.join(src, "**"))) do
                            local tgt = path.join(dest, sub, path.relative(fp, src))
                            os.mkdir(path.directory(tgt))
                            os.cp(fp, tgt)
                        end
                    end
                end
            end
        end
    end)
  1. In a terminal, go to where the xmake.lua file is located, then run xmake f, then press Enter. (or, run xmake f -y to not need to press another key.)

This should take <25 minutes (at most, it should still take less time than vcpkg), and likely boost will be the last package that gets installed, after which the terminal will take a few seconds to copy the files into a folder called “release”.

But this time, pkg-config is in release/bin, the includes are in release/include, and the .pc files are in release/lib/pkgconfig. Accordingly you can set your path and pkg_config_path variables (and pass the include and lib folders to Ardour’s configure using --also-include and --also-libdir.)

Current (known) catches

  1. jack and libusb’s .pc files are incorrectly named. They will not be detected during configure.
  2. libintl has a malformed line in its include header (at least for windows/mingw shared builds?) in line 52, which would generate some warnings.
  3. You also need to pass the release/include/pthread folder into --also-include for pthread.h.
  4. In its current state, you will face errors during the build phase of Ardour:
    The link step of pbd currently gives unresolved external symbol __imp_libintl_dgettext.
    If it reaches temporal, it’ll say some boost headers are missing.

I’m in the process of getting these issues fixed upstream (to be specific, xmake-io/xmake-repo), but in the meantime if someone were to try installing these packages on Windows, the above steps to install the dependencies should be easy to run.

(Also note: I did mark some of the script as being for windows, just in case someone were to test the above on another platform. I cannot confirm all packages exist for any other platform on xrepo, and any package(s) missing will give an error beforehand.)

Few other commands to know:

xrepo update-repo: Updates your local copy of xmake-repo files to what’s latest.
xrepo remove --all -y Uninstall all packages (from cache)
ri -r -fo .xmake and ri -r -fo release: Delete generated/copied folders/files. (Powershell)
xmake require libusb (as example): Install a single package. Running xmake f would only create and populate the release folder of what’s installed, and listed as add_requires() in the file.

Boost package is fixed.

@EZ4Stephen Have you or @x42 ever heard of the Conan package manager It’s an open source, cross platform package manager, compatible with MSVC and other compilers and (if I’m reading the blurb correctly) it allows you to use your own sources if you need to build a specific version of a library whose version isn’t available from the official repo. Worth a look…?

I’ve already briefly covered conan in one or more replies in a different post:

Have you tried getting the packages from xmake/xrepo yet though? Seen if you get any problems? Currently glibmm might get an error while being built*, and I’m hoping to get that fixed, but otherwise, the above script should work just fine.

*Due to a PR getting merged earlier today that added -lintl to the .pc files of glib.

Sorry Stephen, I’m busy with other things now so I won’t have time for xmake and xrepo. I believe Harrison are taking on some new programmers and one of those might spend some time getting their head around your stuff. I don’t know when though.

Hi Stephen. I’m busy from Tuesday onwards so t thought I might try this for you at the weekend. I’ve just tried installing xmake but it insists on installing onto my C: drive where I’m really low on disk space. Do you know if it’s possible to install xmake on some other drive?

Try downloading and extracting one of the .zip’s from a release at Releases · xmake-io/xmake · GitHub, like xmake-master.win64.zip or xmake-v3.0.9.win64.zip.

Hi Stephen, that worked fine here (not even any problem with libffi !!)

The only big version discrepancy I noticed was was that Ardour’s using version 2.6.7 of harfbuzz compared to your build which seems to be building version 13.1.1

Another small issue here was that in your instructions you say to run the lua script form a terminal, which I took to mean a normal Windows terminal but for whatever reason that wouldn’t work for me (a path problem possibly). I switched to PowerShell and that worked fine.

[Edit…] BTW does xmake actually build the libraries or just download pre-built binaries? There are no object files or source files here. Just lib files, dll’s and header files :confounded:

It does build the libraries. Even the pre-built stuff was… built? Probably in CI or elsewhere. Sometimes packages are gotten from elsewhere (homebrew, or the pacman repo for mingw), but those are not all cases.

What’s responsible for what you see is the target("collect_deps")... in the script I shared. If you want to find the actual location of any package, you could run xmake require --info glibmm<2.68, for example (from the directory that has the xmake.lua)

From running that you’ll see cachedir (and installdir?) Though if your command has < maybe you copy and paste the cache dir and like, go back to …packages\2607\g.

The reason I’m raising it is because the very first solution I suggested was to use pre-built binaries and @x42 argued very strongly against it. I must admit I never understood what the problem was.

Even if the packages come from different repos presumably the binaries aren’t getting built by the different repos?

The problem was that in the past this was a zip of the complete build stack, with local paths that did not translate to other machines. So to recreate it one had to use the exact same disk layout and also the same architecture.

Ah, I get it now (though surely the same problem exists for a package manager build?)

In case it helps, my MSVC builds used to cope with that scenario in the form of a small perl script and a text file which allowed developers to specify their own preferred destination folders. A pre-build step made sure the compiler and linker became aware of the user’s preferences and a post build step copied any built libs and DLL’s to whichever folders the developer specified. Admittedly I didn’t copy any header files but I’m sure that’d be possible too.

[Correction…] I’ve just remembered that I do copy the header files but not always. For example if they’ve already been copied during a Release build they don’t get copied again for a Debug build.

Sorry Stephen but I think we’ve hit a major problem here with xmake/xrepo. Here’s an example:-

You’ve asked for pango at version 1.57.1. Pango depends on cairo which you’ve specified to be version 1.18.0

Suppose someone else also wants pango 1.57.1 but they need it to be built against a different version of cairo. If xmake is only delivering pre-built binaries, how can it possibly guarantee that both your builds will work? At the very least, one of you risks encountering linker problems (in fact you mentioned having linker problems in another thread…)

Even worse, both of you risk having subtle runtime issues that’ll be very difficult to track down. Or am I missing something?

I’m not sure which versions of packages support pre-built packages; that information is in GitHub - xmake-mirror/build-artifacts · GitHub. But it is certainly possible to download multiple versions of the same package, precompiled or otherwise.

You can also add ,{build = true} in the add_requires individually or in other ways (e.g.: add_requires("boost", {build = true}), to build all packages from scratch. As I’ve stated earlier, glibmm would fail to build due to a current bug in the .pc file of glib, but that should be fixed later today.

I’ve got today and tomorrow available when I can test this again but you’ll need to adapt your script to building from source Stephen. Using pango and cairo again as an example…

If you build the support libs locally, like Robin does and vcpkg does (and I do) you can guarantee that pango will get built against whichever version of cairo you selected. There’s no such guarantee if you’re downloading pre-built binaries from an external source.

Personally, I think precompiled packages from a package manager are convenient, but to set all packages to be built from source, change:
add_requireconfs("**", {configs = {shared = true}, system = false})
to
add_requireconfs("**", {configs = {shared = true}, system = false, build = true}).

(Of course it’ll take longer to build all packages)

(You may need to run xmake f -c, which would clear the package cache before attempting to build the packages.)

Okay, one minor problem…

xmake f -c doesn’t clear the existing libs / DLL’s and header files so when I subsequently run xmake f it finishes almost immediately (presumably assuming that everything’s up to date?)

Ah, you’d have to run xrepo remove --all -y first. For some reason if you successfully built any amount of packages without error then run xmake f again, somewhere the logic makes it not build/rebuild the remaining packages, and instead runs the target("collect_deps") which copies things to the folder named release.

Then you can delete the “release” folder (though not deleting it would only make the rebuild overwrite those files once building is done), then run xmake f -c.

I didn’t mention this logic earlier in my first comment, because ideally one would only have to run the script once.

That’s fine - that’s what testing is for :grinning:

Hmmm… running xrepo remove --all -y gave me this error:-

xrepo : File H:\xmake-stuff\gnu-windows\src\xmake\xrepo.ps1 cannot be loaded because running scripts is disabled on this system.

Any ideas? I can run your lua script okay…