Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: Allow multiple cc_imports per pkgconfig file (#208)
Some packages, like `krb5-multidev`, include several .so files to link
against in their pkg-config files:
```
prefix=/usr
exec_prefix=${prefix}
libdir=${prefix}/lib/x86_64-linux-gnu/mit-krb5
includedir=${prefix}/include/mit-krb5

defccname=FILE:/tmp/krb5cc_%{uid}
defktname=FILE:/etc/krb5.keytab
defcktname=FILE:/etc/krb5/user/%{euid}/client.keytab

Name: mit-krb5
Description: An implementation of Kerberos network authentication
Version: 1.20.1
Cflags: -isystem ${includedir}
Libs: -L${libdir} -lkrb5 -lk5crypto -lcom_err
Libs.private: -lkrb5support
```

So, instead of assuming that we have one cc_library per pkgconfig file,
we just collect all the declarations and create one `cc_import` target
for each.

Some design considerations:

### Does this violate the private-ness of `Libs.private`?

All `cc_imports` we create have private visibility already, so I don't
think it does.

### Why not depend on other debian packages exporting those libraries?

Since those files are already in the package
(https://packages.debian.org/sid/amd64/krb5-multidev/filelist), I assume
the intention is to link against the `.so` files distributed in the
`krb-multidev` package, and not to pull other deb packages. This could
be false, of course, if a user has already installed those packages and
for some reason the linker finds their SO files first, but I think
that's a bug in the definition of the krb5-multidev package, not this
implementation.

Plus, it has the added benefit that, if the debian package in question
doesn't include an appropriate .so file, we just don't create the
cc_import.
  • Loading branch information
blorente authored and thesayyn committed Mar 10, 2026
commit 498cb472c9aa60bcd3708fdd17789be934bda448
58 changes: 31 additions & 27 deletions apt/private/deb_import.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -272,36 +272,40 @@ so_library(
includes += pkgc.includes
link_paths += pkgc.link_paths

if not pkgc.libname or pkgc.libname + "_import" in import_targets:
if len(pkgc.libnames) == 0:
continue

subtarget = pkgc.libname + "_import"
import_targets.append(subtarget)

# Look for a static archive
# for ar in a_files:
# if ar.endswith(pkgc.libname + ".a"):
# static_lib = '":%s"' % ar
# break

# Look for a dynamic library
IGNORE = ["libfl"]
for so_lib in so_files:
if pkgc.libname and pkgc.libname not in IGNORE and so_lib.endswith(pkgc.libname + ".so"):
shared_lib = '":%s"' % so_lib
break
for libname in pkgc.libnames:
if libname + "_import" in import_targets:
continue

build_file_content += _CC_IMPORT_TMPL.format(
name = subtarget,
shared_lib = shared_lib,
static_lib = static_lib,
hdrs = [],
includes = {
"external/.." + include: True
for include in includes + ["/usr/include", "/usr/include/x86_64-linux-gnu"]
}.keys(),
linkopts = pkgc.linkopts,
)
subtarget = libname + "_import"
import_targets.append(subtarget)

# Look for a static archive
# for ar in a_files:
# if ar.endswith(pkgc.libname + ".a"):
# static_lib = '":%s"' % ar
# break

# Look for a dynamic library
IGNORE = ["libfl"]
for so_lib in so_files:
if libname and libname not in IGNORE and so_lib.endswith(libname + ".so"):
shared_lib = '":%s"' % so_lib
break

build_file_content += _CC_IMPORT_TMPL.format(
name = subtarget,
shared_lib = shared_lib,
static_lib = static_lib,
hdrs = [],
includes = {
"external/.." + include: True
for include in includes + ["/usr/include", "/usr/include/x86_64-linux-gnu"]
}.keys(),
linkopts = pkgc.linkopts,
)

build_file_content += _CC_LIBRARY_TMPL.format(
name = target_name,
Expand Down
16 changes: 9 additions & 7 deletions apt/private/pkgconfig.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def process_pcconfig(pc):
includes = []
link_paths = []
defines = []
libname = None
libnames = []

IGNORE = [
"-licui18n",
Expand All @@ -105,8 +105,8 @@ def process_pcconfig(pc):
link_paths.append(linkpath)
linkopts.append("-Wl,-rpath=" + arg.removeprefix("-L"))
continue
elif arg.startswith("-l") and not libname:
libname = "lib" + arg.removeprefix("-l")
elif arg.startswith("-l"):
libnames.append("lib" + arg.removeprefix("-l"))
continue
elif arg in IGNORE:
continue
Expand All @@ -118,7 +118,9 @@ def process_pcconfig(pc):
if arg in IGNORE:
continue
elif arg.startswith("-l"):
linkopts.append(arg)
# The cc_imports we create based on these names are private already,
# so we don't need to do anything special for `Libs.private`.
libnames.append("lib" + arg.removeprefix("-l"))

if "Cflags" in directives:
cflags = _trim(directives["Cflags"]).split(" ")
Expand Down Expand Up @@ -148,14 +150,14 @@ def process_pcconfig(pc):
"/usr/include",
]

return (libname, includedir, libdir, linkopts, link_paths, includes, defines)
return (libnames, includedir, libdir, linkopts, link_paths, includes, defines)

def pkgconfig(rctx, path):
pc = parse_pc(rctx.read(path))
(libname, includedir, libdir, linkopts, link_paths, includes, defines) = process_pcconfig(pc)
(libnames, includedir, libdir, linkopts, link_paths, includes, defines) = process_pcconfig(pc)

return struct(
libname = libname,
libnames = libnames,
includedir = includedir,
libdir = libdir,
linkopts = linkopts,
Expand Down