Skip to main content

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

info

On Windows, this tutorial uses Visual Studio's MSVC as the compiler for C++ development.

1 - Set up kmpkg

  1. 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.git

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

  2. Run the bootstrap script

    Now that you have cloned the kmpkg repository, navigate to the kmpkg directory and execute the bootstrap script:

cd kmpkg && bootstrap-kmpkg.bat

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:

export KMPKG_ROOT=/path/to/kmpkg
export PATH=$KMPKG_ROOT:$PATH

Setting environment variables using the export command only affects the current shell session. To make this change permanent across sessions, add the export command to your shell's profile script (e.g., ~/.bashrc or ~/.zshrc).

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

  1. Create a new directory called custom-overlay next to the Hello World project you created in the Install and use packages with CMake tutorial.
  2. Within custom-overlay directory, create a folder named kmpkg-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 on kmpkg-cmake, which provides CMake functions and macros commonly used in kmpkg ports.
  • host: true: Specifies that kmpkg-cmake is a host dependency, meaning it's required for building the package but not for using it.
  • name: kmpkg-cmake-config: Specifies a dependency on kmpkg-cmake-config, which assists in using CMake config scripts.
  • fmt: Specifies a run-time dependency on the fmt library. This means fmt is 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.

  1. Configure the build using CMake:
cmake --preset=default
  1. Build the project:
cmake --build build
  1. 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: