Search code examples
dockervcpkg

vcpkg install vs docker caching


I am trying to understand how vcpkg can integrate with docker caching mechanism.

Here is my first naive attempt:

% cat Dockerfile
[...]
RUN vcpkg.exe install libpng # neat caching to prevent (re)compilation
WORKDIR c:/app
COPY . . # anything after this line will be (re)compiled
RUN cmake -S . -B build

My app contains a vcpkg.json file:

{
  "name": "my-proj",
  "version": "0.1.0",
  "dependencies": [
    {
      "name": "libpng"
    },
[...]

The line vcpkg.exe install libpng is a nice trick since upon the next run, docker will directly re-use the cache and will not redo the complete libpng rebuild.

Now my question is what if I need to vcpkg install a private dependency ? For example a public or private project that is not listed on the main vcpkg registry ?

Per documentation I cannot specify an alternate registry (vcpkg-configuration.json):

Is there another simple solution to build a dependency and cache it so that it is not re-build on the cmake -S . -B build line ?


Solution

  • Now my question is what if I need to vcpkg install a private dependency ?

    The command line option you are looking for in classic mode is --overlay-ports=<path-to-directory-with-more-ports>.

    Typical steps would be:

    WORKDIR c:/deps
    RUN git clone https://github.com/example/my-vcpkg-registry
    RUN git clone https://github.com/microsoft/vcpkg
    RUN .\vcpkg\bootstrap-vcpkg.bat # -disable-metrics
    # VCPKG_DEFAULT_BINARY_CACHE or CLI option --binarysource=<config> can be used to configure binary caching. (where vcpkg stores and retrieves already build packages)
    # Binary caching is enabled by default into `%SOMEDEFAULT%/vcpkg` so you probably want to control that to keep the docker size minimal
    # X_VCPKG_ASSET_SOURCES or --x-asset-sources=<config> in addition to VCPKG_DOWNLOADS or --downloads-root=<path> can be used to control where vcpkg obtains already cached sources/tools from
    
    RUN .\vcpkg\vcpkg.exe install libpng private_port --overlay-ports=./my-vcpkg-registry
    # at this point libpng/private_port is properly installed in docker 
    # you probably want to remove packages/, buildtrees/ and downloads/ from the vcpkg root here to keep the docker container minimal
    
    ---- # Split here. You would provide the above as its own docker image and import it for the below or you have an external binary cache setup which vcpkg can pull/push to. 
    
    WORKDIR c:/app
    # anything after this line will be (re)compiled
    COPY . . 
    RUN cmake -S . -B build
    

    Is there another simple solution to build a dependency and cache it so that it is not re-build on the cmake -S . -B build line ?

    Binary Caching:
    https://learn.microsoft.com/en-us/vcpkg/users/binarycaching
    If it is in the cache it will reinstall (if necessary) but not rebuild.
    Having an ABI match however can be hard if you don't completely control all tools going into the hash calculation.