Crates.io | cargo-c |
lib.rs | cargo-c |
version | 0.10.5+cargo-0.83.0 |
source | src |
created_at | 2019-06-26 14:55:51.381125 |
updated_at | 2024-10-18 08:43:44.946768 |
description | Helper program to build and install c-like libraries |
homepage | |
repository | https://github.com/lu-zero/cargo-c |
max_upload_size | |
id | 143755 |
size | 217,251 |
cargo applet to build and install C-ABI compatible dynamic and static libraries.
It produces and installs a correct pkg-config file, a static library and a dynamic library, and a C header to be used by any C (and C-compatible) software.
cargo-c may be installed from crates.io.
cargo install cargo-c
The rustc
version supported is the same as the one supported by the cargo
version embedded in the package version, or as set in the
rust-version field.
You must have the cargo build requirements satisfied in order to build cargo-c:
git
pkg-config
(on Unix, used to figure out the host-provided headers/libraries)curl
(on Unix)libssl-dev
package on deb-based distributions)You may pass --features=vendored-openssl
if you have problems building openssl-sys using the host-provided OpenSSL.
cargo install cargo-c --features=vendored-openssl
# build the library, create the .h header, create the .pc file
$ cargo cbuild --destdir=${D} --prefix=/usr --libdir=/usr/lib64
# build the library, create the .h header, create the .pc file, build and run the tests
$ cargo ctest
# build the library, create the .h header, create the .pc file and install all of it
$ cargo cinstall --destdir=${D} --prefix=/usr --libdir=/usr/lib64
For a more in-depth explanation of how cargo-c
works and how to use it for
your crates, read Building Crates so they Look Like C ABI Libraries.
capi.rs
with the C-API you want to expose and use
#[cfg(cargo_c)]
#[cfg(feature="capi")]
to hide it when you build a normal rust library.crate-type
.crate-type
, cargo-c will add the correct library target by itself.capi
to add C-API-specific optional dependencies.
NOTE: It must be always present in
Cargo.toml
cbindgen.toml
and fill it with
at least the include guard and probably you want to set the language to C (it
defaults to C++)cargo-c
and do cargo cinstall --prefix=/usr --destdir=/tmp/some-place
or something along those lines.You may override various aspects of cargo-c
via settings in Cargo.toml
under the package.metadata.capi
key
[package.metadata.capi]
# Configures the minimum required cargo-c version. Trying to run with an
# older version causes an error.
min_version = "0.6.10"
[package.metadata.capi.header]
# Used as header file name. By default this is equal to the crate name.
# The name can be with or without the header filename extension `.h`
name = "new_name"
# Install the header into a subdirectory with the name of the crate. This
# is enabled by default, pass `false` or "" to disable it.
subdirectory = "libfoo-2.0/foo"
# Generate the header file with `cbindgen`, or copy a pre-generated header
# from the `assets` subdirectory. By default a header is generated.
generation = true
# Can be use to disable header generation completely.
# This can be used when generating dynamic modules instead of an actual library.
enabled = true
pkg-config
File Generation[package.metadata.capi.pkg_config]
# Used as the package name in the pkg-config file and defaults to the crate name.
name = "libfoo"
# Used as the pkg-config file name and defaults to the crate name.
filename = "libfoo-2.0"
# Used as the package description in the pkg-config file and defaults to the crate description.
description = "some description"
# Used as the package version in the pkg-config file and defaults to the crate version.
version = "1.2.3"
# Used as the Requires field in the pkg-config file, if defined
requires = "gstreamer-1.0, gstreamer-base-1.0"
# Used as the Requires.private field in the pkg-config file, if defined
requires_private = "gobject-2.0, glib-2.0 >= 2.56.0, gmodule-2.0"
# Strip the include search path from the last n components, useful to support installing in a
# subdirectory but then include with the path. By default it is 0.
strip_include_path_components = 1
[package.metadata.capi.library]
# Used as the library name and defaults to the crate name. This might get
# prefixed with `lib` depending on the target platform.
name = "new_name"
# Used as library version and defaults to the crate version. How this is used
# depends on the target platform.
version = "1.2.3"
# Used to install the library to a subdirectory of `libdir`.
install_subdir = "gstreamer-1.0"
# Used to disable versioning links when installing the dynamic library
versioning = false
# Instead of using semver, select a fixed number of version components for your SONAME version suffix:
# Setting this to 1 with a version of 0.0.0 allows a suffix of `.so.0`
# Setting this to 3 always includes the full version in the SONAME (indicate any update is ABI breaking)
#version_suffix_components = 2
# Add `-Cpanic=abort` to the RUSTFLAGS automatically, it may be useful in case
# something might panic in the crates used by the library.
rustflags = "-Cpanic=abort"
# Used to disable the generation of additional import library file in platforms
# that have the concept such as Windows
import_library = false
[package.metadata.capi.install.data]
# Used to install the data to a subdirectory of `datadir`. By default it is the same as `name`
subdirectory = "foodata"
# Copy the pre-generated data files found in {root_dir}/{from} to {datadir}/{to}/{matched subdirs}
# If {from} is a single path instead of a glob, the destination is {datapath}/{to}.
# datapath is {datadir}/{subdirectory}
asset = [{from="pattern/with/or/without/**/*", to="destination"}]
# Copy the pre-generated data files found in {OUT_DIR}/{from} to {includedir}/{to}/{matched subdirs}
# If {from} is a single path instead of a glob, the destination is {datapath}/{to}.
# datapath is {datadir}/{subdirectory}
generated = [{from="pattern/with/or/without/**/*", to="destination"}]
[package.metadata.capi.install.include]
# Copy the pre-generated includes found in {root_dir}/{from} to {includedir}/{to}/{matched subdirs}
# If {from} is a single path instead of a glob, the destination is {includepath}/{to}.
# includepath is {includedir}/{header.subdirectory}
asset = [{from="pattern/with/or/without/**/*", to="destination"}]
# Copy the pre-generated includes found in {OUT_DIR}/{from} to {includedir}/{to}/{matched subdirs}
# If {from} is a single path instead of a glob, the destination is {includedpath}/{to}.
# includepath is {includedir}/{header.subdirectory}
generated = [{from="pattern/with/or/without/**/*", to="destination"}]
Do not pass RUSTFLAGS
that are managed by cargo through other means, (e.g. the flags driven by [profiles]
or the flags driven by [target.<>]
), cargo-c effectively builds as if the target is always explicitly passed.
staticlib
supportcdylib
supportWhen running on a musl-based system (e.g. Alpine Linux), it could be that using the cdylib
library type results in the following error (as reported here):
Error: CliError { error: Some(cannot produce cdylib for
as the target x86_64-unknown-linux-musl does not support these crate types), exit_code: 101 }
This suggests that Rust was not built with crt-static=false
and it typically happens if Rust has been installed through rustup.
Shared libraries can be enabled manually in this case, by editing the file .cargo/config
like so:
# .cargo/config
[target.x86_64-unknown-linux-musl]
rustflags = [
"-C", "target-feature=-crt-static",
]
However, it is preferred to install Rust through the system package manager instead of rustup (e.g. with apk add rust
), because the provided package should already handle this (see e.g. here).
In order to accomodate Debian's multiarch approach the cargo-c
default for the libdir
is lib/<triplet>
on such system.
Either pass an explicit --libdir
or pass --target
to return to the common libdir=lib
default.
This software has been partially developed in the scope of the H2020 project SIFIS-Home with GA n. 952652.