Installing your C library for end users
Every just-makeit project is also a distributable C library.
Prerequisites
The end user needs the following tools — just-makeit itself is not required:
| Tool | Minimum version | Notes |
|---|---|---|
| CMake | 3.16 | Build system; drives configure + install |
| A C99 compiler | GCC 8 / Clang 10 / MSVC 2019 | gcc or clang on Linux/macOS |
| pkg-config | any | For pkg-config consumers only |
Linux (Debian/Ubuntu):
sudo apt-get install cmake gcc pkg-config
macOS (Homebrew):
brew install cmake pkg-config
# gcc ships with Xcode Command Line Tools: xcode-select --install
Windows (MSYS2/MinGW):
pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-pkg-config
Overview
Every just-makeit project ships a lib<project>.so in addition to its Python
extensions. The same C code drives both: each component compiles once as a
CMake OBJECT library and links into both the Python .so and the combined
shared library. End users who don't use Python at all can consume it via the
standard mechanisms below.
This applies to all project layouts — standalone objects (just-makeit object),
multi-type modules (just-makeit module + just-makeit object --module), or a mix of both.
What gets installed
$PREFIX/
├── include/
│ ├── my_project.h # umbrella header — include this
│ ├── component_a/
│ │ └── component_a_core.h
│ └── component_b/
│ └── component_b_core.h
├── lib/
│ ├── libmy_project.so # shared library
│ ├── pkgconfig/
│ │ └── my-project.pc # pkg-config descriptor
│ └── cmake/my_project/
│ ├── my_project-config.cmake
│ └── my_project-config-version.cmake
Build and install
Set the install prefix before building — cmake bakes the prefix into the
generated my-project.pc at configure time.
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build build
cmake --install build
For a non-root local install substitute any writable path:
cmake -S . -B build -DCMAKE_INSTALL_PREFIX="$HOME/.local"
cmake --install build
Note:
make && make testcallscmake -B buildinternally with the default prefix. If you ranmakefirst, re-run thecmake -S .line above before installing to regenerate the.pcfile with the correct prefix.
Using with pkg-config
pkg-config --cflags --libs my-project # verify it resolves
Compile a consumer:
gcc $(pkg-config --cflags my-project) \
consumer.c \
$(pkg-config --libs my-project) \
-lm -o consumer
Linux /
--as-needednote: Split--cflagsand--libswith the source file between them. GNU ld on Debian/Ubuntu uses--as-neededby default, which silently drops any shared library that appears before the object files referencing it. If you merge them with the source last ($(pkg-config --cflags --libs my-project) consumer.c) you will get undefined-reference errors at link time even though the library is present.
If you installed to a non-standard prefix, point pkg-config at it:
export PKG_CONFIG_PATH="$HOME/.local/lib/pkgconfig"
Using with CMake
cmake_minimum_required(VERSION 3.16)
project(my_consumer C)
find_package(my_project REQUIRED)
add_executable(consumer consumer.c)
target_link_libraries(consumer PRIVATE my_project::my_project_lib m)
Configure with the prefix if it's not on the default search path:
cmake -B build -DCMAKE_PREFIX_PATH="$HOME/.local"
cmake --build build
Runtime loading (rpath)
The installed .so is not automatically on the dynamic linker's search path
unless you installed to /usr/local (or ran ldconfig after a system-wide
install).
For a custom prefix, embed the library path in the binary at link time:
pkg-config:
LIB_DIR=$(pkg-config --variable=libdir my-project)
gcc $(pkg-config --cflags my-project) \
consumer.c \
$(pkg-config --libs my-project) \
-Wl,-rpath,"$LIB_DIR" \
-lm -o consumer
CMake: set INSTALL_RPATH_USE_LINK_PATH or CMAKE_BUILD_RPATH:
set_target_properties(consumer PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON)
Or pass it on the command line:
cmake -B build \
-DCMAKE_PREFIX_PATH="$HOME/.local" \
-DCMAKE_BUILD_RPATH="$HOME/.local/lib"
Alternatively, set LD_LIBRARY_PATH at runtime (useful for quick testing,
not for deployment):
LD_LIBRARY_PATH="$HOME/.local/lib" ./consumer
Verifying the install
# headers present
ls $PREFIX/include/my_project.h
# library present and has expected symbols
nm -D $PREFIX/lib/libmy_project.so | grep component_a_create
# pkg-config resolves
pkg-config --modversion my-project