Tutorial: Package a library with kmpkg
This tutorial guides you on how to package a library for kmpkg using a custom overlay. We recommended that you read the Install and use packages with CMake tutorial before proceeding.
Prerequisites
- cmd-powershell
On Windows, this tutorial uses Visual Studio's MSVC as the compiler for C++ development.
1 - Set up kmpkg
-
Clone the repository
The first step is to clone the kmpkg repository from GitHub. The repository contains scripts to acquire the kmpkg executable and a registry of curated open-source libraries maintained by the kmpkg community. To do this, run:
git clone https://github.com/kumose/kmpkg.gitThe kmpkg curated registry is a set of over 2,000 open-source libraries. These libraries have been validated by kmpkg's continuous integration pipelines to work together. While the kmpkg repository does not contain the source code for these libraries, it holds recipes and metadata to build and install them in your system.
-
Run the bootstrap script
Now that you have cloned the kmpkg repository, navigate to the
kmpkgdirectory and execute the bootstrap script:
- cmd
- powershell
- bash
cd kmpkg && bootstrap-kmpkg.bat
cd kmpkg; .\bootstrap-kmpkg.bat
cd kmpkg && ./bootstrap-kmpkg.sh
The bootstrap script performs prerequisite checks and downloads the kmpkg executable.
That's it! kmpkg is set up and ready to use.
2 - Configure the KMPKG_ROOT environment variable
To set the KMPKG_ROOT environment variables, run the following commands:
- bash
- cmd
- powershell
export KMPKG_ROOT=/path/to/kmpkg
export PATH=$KMPKG_ROOT:$PATH
Setting environment variables using the
exportcommand only affects the current shell session. To make this change permanent across sessions, add theexportcommand to your shell's profile script (e.g.,~/.bashrcor~/.zshrc).
set "KMPKG_ROOT=C:\path\to\kmpkg"
set PATH=%KMPKG_ROOT%;%PATH%
Setting environment variables in this manner only affects the current terminal session. To make these changes permanent across all sessions, set them through the Windows System Environment Variables panel.
$env:KMPKG_ROOT="C:\path\to\kmpkg"
$env:PATH="$env:KMPKG_ROOT;$env:PATH"
Setting environment variables in this manner only affects the current terminal session. To make these changes permanent across all sessions, set them through the Windows System Environment Variables panel.
Setting KMPKG_ROOT tells kmpkg where your kmpkg instance is located.
Adding it to PATH ensures you can run kmpkg commands directly from the shell.
3 - Set up the custom overlay
- Create a new directory called
custom-overlaynext to theHello Worldproject you created in the Install and use packages with CMake tutorial. - Within
custom-overlaydirectory, create a folder namedkmpkg-sample-library.
4 - Set up the port files
First, create the kmpkg.json file within the
custom-overlay/kmpkg-sample-library folder with the following content:
{
"name": "kmpkg-sample-library",
"version": "1.0.2",
"description": "A sample C++ library designed to serve as a foundational example for a tutorial on packaging libraries with kmpkg.",
"homepage": "https://github.com/MicrosoftDocs/kmpkg-docs/tree/cmake-sample-lib",
"license": "MIT",
"dependencies": [
"fmt",
{
"name": "kmpkg-cmake",
"host": true
},
{
"name": "kmpkg-cmake-config",
"host": true
}
]
}
The kmpkg.json file serves as a manifest that defines metadata and
dependencies for a C++ library, providing kmpkg with the necessary information
to build, install, and manage the package.
name: Specifies the name of the library. This is used as the package identifier.version: Indicates the version number of the library.homepage: URL to the project's homepage, often its repository. Useful for those who want to know more or contribute.description: Brief text describing what the library does. This is for documentation and users.license: Specifies the license under which the library is distributed.dependencies: An array containing the list of dependencies that the library needs.name:kmpkg-cmake: Specifies a dependency onkmpkg-cmake, which provides CMake functions and macros commonly used in kmpkg ports.host: true: Specifies thatkmpkg-cmakeis a host dependency, meaning it's required for building the package but not for using it.name:kmpkg-cmake-config: Specifies a dependency onkmpkg-cmake-config, which assists in using CMake config scripts.fmt: Specifies a run-time dependency on thefmtlibrary. This meansfmtis required for both building and using the package.
For more information on kmpkg.json, see the following documentation on
manifests.
Now, create the usage file within the custom-overlay\kmpkg-sample-library
directory with the following content:
kmpkg-sample-library provides CMake targets:
find_package(my_sample_lib CONFIG REQUIRED)
target_link_libraries(main PRIVATE my_sample_lib::my_sample_lib)
Providing usage documentation for ports allows users to easily adopt them in
their projects. We highly encourage providing a usage file within the port's
directory (ports/<port name>/usage) that describes the minimal steps necessary
to integrate with a build system. To determine the correct usage instructions it
is recommended to follow upstream's guidance. In the case that upstream does not
provide usage information, it may be necessary to dig through their build system
to find the exported targets.
For more guidance, see handling usage files
Finally, create the portfile.cmake file within the
custom-overlay\kmpkg-sample-library directory with the following content:
kmpkg_check_linkage(ONLY_STATIC_LIBRARY)
kmpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO MicrosoftDocs/kmpkg-docs
REF "${VERSION}"
SHA512 0 # This is a temporary value. We will modify this value in the next section.
HEAD_REF cmake-sample-lib
)
kmpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
)
kmpkg_cmake_install()
kmpkg_cmake_config_fixup(PACKAGE_NAME "my_sample_lib")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
kmpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
This portfile defines how to download, build, install, and package a specific
C++ library from GitHub using kmpkg.
kmpkg_check_linkage(ONLY_STATIC_LIBRARY): Specifies that only static linking is supported for this package.kmpkg_from_github: Starts the function to download the source code from a GitHub repository.OUT_SOURCE_PATH SOURCE_PATH: Sets the directory where the source code will be extracted.REPO MicrosoftDocs/kmpkg-docs: The GitHub repository containing the source code.REF "${VERSION}": The version of the source code to download.SHA512 0: Placeholder for the SHA-512 hash of the source code for integrity verification.HEAD_REF main: Specifies the default branch for the repository.
kmpkg_cmake_configure: Configures the project using CMake, setting up the build.SOURCE_PATH "${SOURCE_PATH}": The path to the source code downloaded earlier.
kmpkg_cmake_install(): Builds and installs the package using CMake.kmpkg_cmake_config_fixup(PACKAGE_NAME "my_sample_lib"): Fixes the CMake package configuration files to be compatible with kmpkg.file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include"): Deletes the include directory from the debug installation to prevent overlap.file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" ...): Copies a usage instruction file to the package's share directory.kmpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE"): Installs the LICENSE file to the package's share directory and renames it to copyright.
For more information, refer to the maintainer guide.
5 - Update SHA512 for portfile.cmake
Run:
kmpkg install kmpkg-sample-library --overlay-ports=C:\path\to\custom-overlay
You will get a long error message. Scan the output until you find:
Downloading https://github.com/MicrosoftDocs/kmpkg-docs/archive/1.0.2.tar.gz -> MicrosoftDocs-kmpkg-docs-1.0.2.tar.gz
Successfully downloaded MicrosoftDocs-kmpkg-docs-1.0.2.tar.gz
error: failing download because the expected SHA512 was all zeros, please change the expected SHA512 to: 4202125968a01219deeee14b81e1d476dab18d968425ba36d640816b0b3db6168f8ccf4120ba20526e9930c8c7294e64d43900ad2aef9d5f28175210d0c3a417
Copy the "Actual hash"
4202125968a01219deeee14b81e1d476dab18d968425ba36d640816b0b3db6168f8ccf4120ba20526e9930c8c7294e64d43900ad2aef9d5f28175210d0c3a417,
and replace the SHA512 value in the portfile.cmake with its value.
Re-run the install command:
kmpkg install kmpkg-sample-library --overlay-ports=C:\path\to\custom-overlay
Computing installation plan...
The following packages will be built and installed:
kmpkg-sample-library:x64-windows -> 1.0.2 -- C:\Users\dev\demo\custom-overlay\kmpkg-sample-library
Detecting compiler hash for triplet x64-windows...
Restored 0 package(s) from C:\Users\dev\AppData\Local\kmpkg\archives in 174 us. Use --debug to see more details.
Installing 1/1 kmpkg-sample-library:x64-windows...
Building kmpkg-sample-library:x64-windows...
-- Installing port from location: C:\Users\dev\demo\custom-overlay\kmpkg-sample-library
-- Note: kmpkg-sample-library only supports static library linkage. Building static library.
-- Using cached Microsoft-kmpkg-docs-1.0.2.tar.gz.
-- Cleaning sources at C:/Users/dev/demo/kmpkg/buildtrees/kmpkg-sample-library/src/1.0.2-2aff836404.clean. Use --editable to skip cleaning for the packages you specify.
-- Extracting source C:/Users/dev/demo/kmpkg/downloads/Microsoft-kmpkg-docs-1.0.2.tar.gz
-- Using source at C:/Users/dev/demo/kmpkg/buildtrees/kmpkg-sample-library/src/1.0.2-2aff836404.clean
-- Configuring x64-windows
-- Building x64-windows-dbg
-- Building x64-windows-rel
-- Installing: C:/Users/dev/demo/kmpkg/packages/kmpkg-sample-library_x64-windows/share/kmpkg-sample-library/usage
-- Installing: C:/Users/dev/demo/kmpkg/packages/kmpkg-sample-library_x64-windows/share/kmpkg-sample-library/copyright
-- Performing post-build validation
Stored binaries in 1 destinations in 94 ms.
Elapsed time to handle kmpkg-sample-library:x64-windows: 6.1 s
Total install time: 6.1 s
kmpkg-sample-library provides CMake targets:
find_package(my_sample_lib CONFIG REQUIRED)
target_link_libraries(main PRIVATE my_sample_lib::my_sample_lib)
6 - Verify the port build
To verify the library builds and links properly, add a new dependency to the
helloworld project created in the install packages tutorial.
Make the following changes to the project's manifest and configuration files.
Modify helloworld/kmpkg.json to add a dependency on kmpkg-sample-library:
{
"dependencies": [
"fmt",
"kmpkg-sample-library"
]
}
Modify helloworld/kmpkg-configuration.json to include the overlay-ports
folder that contains the new port:
{
"default-registry": {
"kind": "git",
"baseline": "45f6e57d3e10ad96b7db206cf7888f736ba5aa61",
"repository": "https://github.com/kumose/kmpkg"
},
"registries": [
{
"kind": "artifact",
"location": "https://github.com/kumose/kmpkg-ce-catalog/archive/refs/heads/main.zip",
"name": "microsoft"
}
],
"overlay-ports": [
"../custom-overlay"
]
}
Next, modify helloworld/CMakeLists.txt and helloworld/main.cpp to use the
new dependency.
Modify the helloworld/CMakeLists.txt with the following content:
cmake_minimum_required(VERSION 3.10)
project(HelloWorld)
find_package(fmt CONFIG REQUIRED)
find_package(my_sample_lib CONFIG REQUIRED) # Add this line
add_executable(HelloWorld helloworld.cpp)
target_link_libraries(HelloWorld PRIVATE fmt::fmt)
target_link_libraries(HelloWorld PRIVATE my_sample_lib::my_sample_lib) # Add this line
Modify the main.cpp with the following content:
#include "my_sample_lib.h" // Replace #include <fmt/core.h> with "my_sample_lib.h"
int main()
{
greet("kmpkg!"); // Replace fmt::print("Hello World!\n) with this line
return 0;
}
Configure, build, and run the application.
- Configure the build using CMake:
cmake --preset=default
- Build the project:
cmake --build build
- Run the application:
./build/HelloWorld
The path to your project's executable may be different, for example: ./build/Debug/HelloWorld.exe.
Hello kmpkg!
Next steps
Now that the kmpkg-sample-library has been packaged as port, the next step is
to add it to the kmpkg curated registry. See, Adding ports to kmpkg
registry.
For more information, see: