5
votes

I've been tasked with starting to lay out a C++ cross platform program with CMake. One of our main dependencies involves in-house nuget packages. With our Windows C++ projects, I'd just right click the project and choose Manage Nuget Packages. In the cross platform, there's no such option, and I am struggling to find any relevant information on how I'd go about including those dependencies. Can anyone link me to any good sources of info, or demo?

1
For what it's worth, I feel like Microsoft's C++ team recommends vcpkg over nuget, so perhaps you could investigate that. It might work better. github.com/microsoft/vcpkgzivkan
@Jason CMake 3.15 supports adding Nuget package references, which provides a much simpler solution. See my updated answer.Kevin
Thanks for the update!Jason

1 Answers

5
votes

EDIT: As of CMake 3.15, CMake supports referencing Nuget packages with VS_PACKAGE_REFERENCES. Now, this is a much cleaner solution than the work-around proposed below. To add a Nuget package reference to a CMake target, use the package name and package version separated by an underscore _; here is an example for BouncyCastle version 1.8.5:

set_property(TARGET MyApplication
    PROPERTY VS_PACKAGE_REFERENCES "BouncyCastle_1.8.5"
)

Note, this solution only works for C# or hybrid C#/C++ projects. As mentioned here, Microsoft doesn't support PackageReference for pure C++ projects.


Prior to CMake 3.15, CMake has no built-in commands for Nuget support, so you will have to use the nuget command line utilities to include Nuget dependencies using CMake.

You can use CMake's find_program() to locate the nuget command line utility (once installed), coupled with add_custom_command() or execute_process() to execute nuget commands from CMake. The answers to this question discuss in more detail, but it could essentially look something like this:

# Find Nuget (install the latest CLI here: https://www.nuget.org/downloads).
find_program(NUGET nuget)
if(NOT NUGET)
    message(FATAL "CMake could not find the nuget command line tool. Please install it!")
else()
    # Copy the Nuget config file from source location to the CMake build directory.
    configure_file(packages.config.in packages.config COPYONLY)
    # Run Nuget using the .config file to install any missing dependencies to the build directory.
    execute_process(COMMAND 
        ${NUGET} restore packages.config -SolutionDirectory ${CMAKE_BINARY_DIR}
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
    )
endif()

This assumes you have an existing packages.config file listing the nuget dependencies for your project.

To tie dependencies to a specific target, you (unfortunately) have to use the full path to where nuget placed the assembly/library.

For .NET nuget packages this would look like this:

# Provide the path to the Nuget-installed references.
set_property(TARGET MyTarget PROPERTY 
    VS_DOTNET_REFERENCE_MyReferenceLib
    ${CMAKE_BINARY_DIR}/packages/path/to/nuget/lib/MyReferenceLib.dll
)

For C++-flavored nuget packages, it could look like this:

add_library(MyLibrary PUBLIC
    MySource.cpp
    MyClass1.cpp
    ...
)

# Provide the path to the Nuget-installed libraries.
target_link_libraries(MyLibrary PUBLIC 
    ${CMAKE_BINARY_DIR}/packages/path/to/nuget/lib/MyCppLib.dll
)

As an aside, CMake does support the creation of Nuget packages with CPack. Here is the documentation for the CPack Nuget generator.