Prebuilt Dependencies

A Jam project can take third-party libraries from a prebuilt dependency bundle instead of from the system or from sources in the tree. A bundle is a directory of already compiled headers and libraries for one platform. The published bundles might include zlib, libpng, libjpeg, FreeType or OpenSSL.

The bundle is placed under the prebuilt directory in the project root. Each platform has its own subdirectory, for example prebuilt/windows-x64-msvc-md. Those files contain no absolute paths, so the directory can be moved or unpacked as a whole.

Prebuilt libraries are used only when passing –with-prebuilt or –fetch-prebuilt. They do not replace the compiler, and they do not change the global compiler or linker flags. See Basic Jam Usage for the rest of the configure and build process.

Using Prebuilt Dependencies

The usual first-time command downloads the matching bundle if needed, then configures the build:

jam.bat configure --fetch-prebuilt
./jam.sh configure --fetch-prebuilt

If the bundle is already on disk, pass –with-prebuilt instead. Jam picks the platform folder from the current OS, CPU and toolset. The command fails if that folder is missing. No network access is performed.

./jam.sh configure --with-prebuilt

Either flag may take an explicit platform name. That pins the folder under prebuilt, still without downloading with –with-prebuilt:

./jam.sh configure --with-prebuilt=windows-x64-msvc-md
./jam.sh configure --with-prebuilt=macos-arm64-clang
./jam.sh configure --fetch-prebuilt=windows-x64-msvc-md

–fetch-prebuilt already selects prebuilt libraries; –with-prebuilt is not required next to it. Do not combine –fetch-prebuilt with –with-prebuilt=name. Fetch always writes into the platform folder under prebuilt. A stale folder is refreshed only by –fetch-prebuilt; –with-prebuilt will not contact the network.

The platform folder name is os-arch-toolset, with an extra suffix on Windows. Jam builds it from TARGET_OS, TARGET_OSPLAT and TOOLSET:

  • nt / win32 become windows; macosx becomes macos
  • x86_64 / amd64 become x64; aarch64 becomes arm64
  • Visual Studio toolsets vc* become msvc

Examples:

  • windows-x64-msvc-md
  • windows-x64-msvc-mdd
  • macos-arm64-clang
  • linux-x64-clang

Windows always has a suffix for the C runtime. A debug build without optimization maps to mdd, otherwise md. Other operating systems omit the suffix until a second runtime variant exists. The project's debug/release setting and that Windows suffix are separate: on Linux and macOS the same folder is used for both debug and release builds.

The default location is prebuilt/ <name> in the project root. The download uses the release tag PREBUILT_RELEASE (default prebuilt-1). The zip URL is:

https://github.com/Pt-Framework/Pt/releases/download/<PREBUILT_RELEASE>/<name>.zip

Settings made explicitly always win. If any of the five package variables are set on the command line or in the environment, or if a flag is passed that builds that package from sources in the tree, prebuilt paths are not applied to that package. The following commands keep a hand-chosen zlib or build zlib from sources, while still using the bundle for the other libraries:

./jam.sh configure --with-prebuilt -sZLIB_INCLUDES=/opt/zlib/include
./jam.sh configure --fetch-prebuilt --with-inline-zlib

Flags such as –with-inline-zlib, –with-inline-libpng, –with-inline-libjpeg and –with-inline-freetype skip the corresponding Configure probe and build that package from sources in the tree.

Configure looks for each library in this order:

User settings / --with-inline-xxx
        |
        |  else, if a prebuilt folder was selected
        v
Prebuilt paths  ->  one package Configure probe
        |
        |  else (prebuilt not selected), or probe failed
        v
System / compiler paths / pkg-config
        |
        |  else
        v
Sources in the tree

When prebuilt libraries are selected, the system is not consulted for packages listed in the bundle. When they are not selected, prebuilt is not consulted at all. There is no fallback from one platform folder to another. If the chosen folder is missing, configure reports an error. If a package probe against the bundle fails, that package falls back to sources in the tree.

Bundle Directory Layout

One platform is one directory and one zip. Each library lives in its own subdirectory, named after PREBUILT_PACKAGES (zlib, png, jpeg, freetype, openssl).

prebuilt/<name>/
  jam/
    packages.jam
  zlib/
    include/zlib.h
    lib/zlib.lib          (or libz.a / libz.dylib)
    bin/zlib.dll          (omitted for static)
  png/
    include/png.h
    lib/png16.lib
    bin/libpng16.dll
  jpeg/
    include/...
    lib/...
    bin/...
  freetype/
    include/ft2build.h
    include/freetype2/...
    lib/freetype.lib
    bin/freetype.dll
  openssl/
    include/openssl/...
    lib/libssl.lib libcrypto.lib
    bin/...

Default locations, relative to PREBUILT_ROOT:

  • Headers: /include
  • Libraries: /lib
  • Binaries: /bin

PREBUILT_PACKAGE_INCLUDES. is set only when that layout is not enough (FreeType's include/freetype2). The native lib/ and bin/ directories are kept complete. There are no version directories and no debug/ folder inside an md tree. Library names stay the same for a given platform folder (zlib.lib in both md and mdd).

The directory can be moved as a whole because it contains no absolute paths. The project sets PREBUILT_ROOT before including jam/packages.jam.

The packages.jam Manifest

Each bundle contains one Jam data file at jam/packages.jam. It assigns variables only: no rules and no toolset flags. The rules that use those variables live in jam/prebuilt.jam.

Names that describe the whole bundle use the prefix PREBUILT_. Names that vary by package use PREBUILT_PACKAGE_ plus a dotted package name, for example PREBUILT_PACKAGE_LIBS.zlib, which is read as $(PREBUILT_PACKAGE_LIBS.).

Bundle-wide variables:

  • PREBUILT_SCHEMA is the file format version. The project requires 1.
  • PREBUILT_ID is the same string as the directory and zip name.
  • PREBUILT_LINKAGE is shared or static. Prebuilt-LinkLibs uses this when deciding whether to also link packages that this one depends on.
  • PREBUILT_PACKAGES lists the package names that have dotted keys.

Per-package variables. Omit empty lists. Values are names, tokens, or paths relative to PREBUILT_ROOT, never raw flags (-l, -I, -D, -framework, /LIBPATH):

  • PREBUILT_PACKAGE_LIBS.: library names inside the bundle (zlib, png16, ssl crypto). Not -lssl or zlib.lib.
  • PREBUILT_PACKAGE_DEPENDS.: other packages in this bundle that this one needs.
  • PREBUILT_PACKAGE_SYSLIBS.: OS linker names that are not in the zip (crypt32, ws2_32). Jam applies FLinkLibs.
  • PREBUILT_PACKAGE_FRAMEWORKS.: macOS framework names.
  • PREBUILT_PACKAGE_DEFINES.: preprocessor tokens, not -D.
  • PREBUILT_PACKAGE_INCLUDES.: include paths relative to PREBUILT_ROOT, only if not /include.
  • PREBUILT_PACKAGE_LIBPATH.: library paths relative to PREBUILT_ROOT, only if not /lib.
  • PREBUILT_PACKAGE_LINKFLAGS.: extra linker flags.
  • PREBUILT_PACKAGE_VERSION.: version string for documentation.

PREBUILT_PACKAGE_DEPENDS lists every needed package in the same bundle. If png is in the bundle, zlib is in the bundle too. The project walks that list for include paths (always), for files to copy (when asked), and for extra link libraries (static linking only). There are no version ranges, no optional dependencies, and no search for a package outside the bundle.

The file does not set ZLIB_LINKLIBS or SSL_LINKLIBS. Mapping package names to those project variables is done in jam/prebuilt.jam.

Example:

# prebuilt/<name>/jam/packages.jam
if ! $(PREBUILT_PACKAGES_JAM_INCLUDED) {
PREBUILT_PACKAGES_JAM_INCLUDED = true ;
PREBUILT_SCHEMA = 1 ;
PREBUILT_ID = windows-x64-msvc-md ;
PREBUILT_LINKAGE = shared ;
PREBUILT_PACKAGES = zlib png jpeg freetype openssl ;
PREBUILT_PACKAGE_LIBS.zlib = zlib ;
PREBUILT_PACKAGE_VERSION.zlib = 1.3.1 ;
PREBUILT_PACKAGE_LIBS.png = png16 ;
PREBUILT_PACKAGE_DEPENDS.png = zlib ;
PREBUILT_PACKAGE_VERSION.png = 1.6.43 ;
PREBUILT_PACKAGE_LIBS.jpeg = jpeg ;
PREBUILT_PACKAGE_VERSION.jpeg = 3.0.3 ;
PREBUILT_PACKAGE_LIBS.freetype = freetype ;
PREBUILT_PACKAGE_DEPENDS.freetype = png zlib ;
PREBUILT_PACKAGE_VERSION.freetype = 2.13.2 ;
PREBUILT_PACKAGE_LIBS.openssl = ssl crypto ;
PREBUILT_PACKAGE_SYSLIBS.openssl = crypt32 ws2_32 advapi32 user32 ;
PREBUILT_PACKAGE_VERSION.openssl = 3.3.1 ;
}

A macOS bundle uses a three-part PREBUILT_ID such as macos-arm64-clang. The Windows mdd folder uses PREBUILT_ID = windows-x64-msvc-mdd, the same linkage, and different files on disk.

Configure Integration

Every package Configure rule has the same arguments:

*-Configure INCLUDES : C++FLAGS : LINKLIBS : LIBDIR : LINKFLAGS

If any of those is set, pkg-config is skipped and the first link attempt uses the passed libraries. If all five are empty, pkg-config and name guessing run. On success the five *_ variables are set.

Prebuilt-Import sets PREBUILT_ROOT and includes jam/packages.jam. It does not touch C++FLAGS, LINKFLAGS, or ZLIB_*.

For each package, if the bundle is loaded and sources in the tree were not requested, empty variables are filled from the bundle, then Configure is called once:

Load zlib.jam ;
if --with-inline-zlib in $(ARGV)
{
WITH_BUILTIN_ZLIB = yes ;
}
if ! $(WITH_BUILTIN_ZLIB)
{
if $(PREBUILT_ROOT)
{
ZLIB_INCLUDES ?= [ Prebuilt-Includes zlib ] ;
ZLIB_C++FLAGS ?= [ Prebuilt-CxxFlags zlib ] ;
ZLIB_LINKLIBS ?= [ Prebuilt-LinkLibs zlib ] ;
ZLIB_LIBDIR ?= [ Prebuilt-LibPath zlib ] ;
ZLIB_LINKFLAGS ?= [ Prebuilt-LinkFlags zlib ] ;
}
WITH_ZLIB = [ ZLib-Configure $(ZLIB_INCLUDES) : $(ZLIB_C++FLAGS) :
$(ZLIB_LINKLIBS) : $(ZLIB_LIBDIR) : $(ZLIB_LINKFLAGS) ] ;
}
if ! $(WITH_ZLIB)
{
WITH_BUILTIN_ZLIB = yes ;
}

The same pattern is used for png (PNG_*), jpeg (JPEG_*), FreeType (FREETYPE_*), and OpenSSL. The zip package name is openssl; the Jam variables stay SSL_*, as OpenSsl-Configure already uses. Flags that select sources in the tree are handled before the prebuilt or system probe.

Package name to variable mapping:

  • zlib -> ZLIB_*
  • png -> PNG_*
  • jpeg -> JPEG_*
  • freetype -> FREETYPE_*
  • openssl -> SSL_*

*_LIBDIR is required. Setting only *_LINKLIBS leaves the linker without FLibPath of the package's lib/ directory. CheckDependencyLinkC++ turns LIBDIR into *_LINKFLAGS.

Jamfiles do not mention PREBUILT_ROOT. They keep using the five package variables:

SubDirHdrs $(PNG_INCLUDES) ;
LinkFlags mylib : $(PNG_LINKFLAGS) ;
LinkLibs mylib : $(PNG_LINKLIBS) ;
ObjectC++Flags PngReader.cpp PngWriter.cpp : $(PNG_C++FLAGS) ;

Whether a package was found or built from sources is still the usual WITH_* / WITH_BUILTIN_* variables, as without prebuilt libraries.

Include directories always cover dependent packages as well. png.h includes zlib.h, and a Jamfile can call SubDirHdrs without adding ZLIB_INCLUDES. Therefore Prebuilt-Includes png returns png/include and zlib/include. That walk follows PREBUILT_PACKAGE_DEPENDS for both shared and static bundles. Prebuilt-Includes freetype returns FreeType's include dirs plus png and zlib.

Link lines do not always add dependent packages:

  • Shared: PREBUILT_PACKAGE_LIBS and PREBUILT_PACKAGE_SYSLIBS of the named packages only, plus PREBUILT_PACKAGE_FRAMEWORKS as -framework name
  • Static: the same, after also collecting the packages listed in PREBUILT_PACKAGE_DEPENDS
  • MSVC shared OpenSSL still needs crypt32 ws2_32 advapi32 user32 on the line (PREBUILT_PACKAGE_SYSLIBS)

Jam Rules

The rules live in jam/prebuilt.jam, loaded once per project. The bundle file is jam/packages.jam. Toolset helpers stay in the project: FLinkLibs, FIncludes, FDefines, FLibPath.

  • Prebuilt-Tuple ( abi ? )
    Builds the platform folder name from TARGET_OS, TARGET_OSPLAT and TOOLSET, with an optional extra suffix such as md.
  • Prebuilt-Fetch ( url : dest )
    Downloads url when the remote url.manifest differs from dest/manifest. Replaces dest with the unzipped archive. The caller must run Fetch-Configure first.
  • Prebuilt-Import ( root )
    Sets PREBUILT_ROOT, includes jam/packages.jam, and exits if PREBUILT_SCHEMA is not 1.
  • Prebuilt-Depends ( packages + )
    Walks PREBUILT_PACKAGE_DEPENDS without duplicates. Named packages first, dependencies last.
  • Prebuilt-Includes ( packages + )
    Include directories of those packages and the packages they depend on. Uses PREBUILT_PACKAGE_INCLUDES. when set, otherwise //include.
  • Prebuilt-CxxFlags ( packages + )
    [ FDefines $(PREBUILT_PACKAGE_DEFINES.) ] for the named packages only.
  • Prebuilt-LinkLibs ( packages + )
    Shared: PREBUILT_PACKAGE_LIBS, PREBUILT_PACKAGE_SYSLIBS and PREBUILT_PACKAGE_FRAMEWORKS of the named packages. Static: the same over the packages returned by Prebuilt-Depends. Always passed through FLinkLibs. Frameworks are appended as -framework name.
  • Prebuilt-LibPath ( packages + )
    //lib, or PREBUILT_PACKAGE_LIBPATH.. Shared: named packages. Static: those packages and the ones they depend on.
  • Prebuilt-LinkFlags ( packages + )
    Extra flags from PREBUILT_PACKAGE_LINKFLAGS. only. Does not duplicate FLibPath; CheckDependencyLinkC++ adds that from LIBDIR.
  • Prebuilt-Packages
    All package names exported by the bundle (PREBUILT_PACKAGES).
  • Prebuilt-Bin ( packages + ) / Prebuilt-Lib ( packages + )
    All files below the native bin/ or lib/ directory of each named package. These rules do not walk dependencies.

Deployment

Prebuilt bundles keep complete native bin/ and lib/ directories. They do not say which files to install. A package bin/ can contain programs as well as runtime libraries; Linux and macOS shared libraries commonly remain in lib/.

The project chooses which packages to copy and whether to take bin/ or lib/, then stages or installs with its own rules. For every package:

local packages = [ Prebuilt-Packages ] ;
local sources = [ Prebuilt-Bin $(packages) ] ;
sources += [ Prebuilt-Lib $(packages) ] ;
for local src in $(sources)
{
local dest = $(src:BS) ;
File $(dest) : $(src) ;
MakeLocate $(dest) : $(LOCATE_TARGET) ;
Clean clean : $(dest) ;
InstallFile $(BINDIR) : $(src) ;
}

For a smaller set, pass package names to Prebuilt-Bin or Prebuilt-Lib. To include files from packages that one of them depends on, first use local packages = [ Prebuilt-Depends openssl ] ;.

Note
Windows mdd is not redistributable. The debug CRT (MSVCP*D.dll, VCRUNTIME*D.dll) is not in the Visual C++ redistributable. Release products use md. Local debug builds may place mdd DLLs next to the executable.

Creating Prebuilt Dependencies

A bundle can be written by hand: fill the per-package directories, write jam/packages.jam, and point –with-prebuilt at the platform folder under prebuilt. Conan is not required. packages.jam is KEY = value assignments and is readable without running Jam.

A generator, including one driven by Conan in CI, writes the same layout:

  • One directory per package: /include, /lib, /bin
  • jam/packages.jam: library names to PREBUILT_PACKAGE_LIBS, other packages in this bundle to PREBUILT_PACKAGE_DEPENDS, OS linker names to PREBUILT_PACKAGE_SYSLIBS, macOS frameworks to PREBUILT_PACKAGE_FRAMEWORKS, extra include dirs to PREBUILT_PACKAGE_INCLUDES
  • Complete lib/ and bin/ directories, without sorting or moving files
  • Do not emit ZLIB_INCLUDES / PNG_LINKLIBS from the generator; that mapping is jam/prebuilt.jam
  • Windows: two zips, windows-x64-msvc-md and windows-x64-msvc-mdd
  • macOS / Linux: one folder name without a runtime suffix until a second variant exists
  • Check: zlib/include/zlib.h, zlib/lib/zlib.lib or libz.a, bin/ when shared, jam/packages.jam, no version directories, no absolute machine paths