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 Answers
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.