[5/7] build/pkg-config: output driver libs first for static build

Message ID 20200429100831.398-6-bruce.richardson@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series improve DPDK static builds with meson |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Bruce Richardson April 29, 2020, 10:08 a.m. UTC
  When calling pkg-config --static --libs, pkg-config will always output the
regular libs first, and then the extra libs from libraries.private field,
since the assumption is that those are additional dependencies for building
statically that the .a files depend upon.

However, for DPDK, we only link the driver files for static builds, and
those need to come *before* the regular libraries. To get this result, we
need two pkgconfig files for DPDK, one for the shared libs, and a second
for the static libs and drivers, which depends upon the first. Using a
dependency means that the shared libs are printed only after the
libraries.private field rather than before.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 buildtools/pkg-config/meson.build | 32 +++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)
  

Comments

Thomas Monjalon April 29, 2020, 10:30 a.m. UTC | #1
29/04/2020 12:08, Bruce Richardson:
> When calling pkg-config --static --libs, pkg-config will always output the
> regular libs first, and then the extra libs from libraries.private field,
> since the assumption is that those are additional dependencies for building
> statically that the .a files depend upon.
> 
> However, for DPDK, we only link the driver files for static builds, and
> those need to come *before* the regular libraries.

Please could you add the error here?

> To get this result, we
> need two pkgconfig files for DPDK, one for the shared libs, and a second
> for the static libs and drivers, which depends upon the first.

I feel we are doing something wrong.
We should not have two .pc files.
I also know that static linkage is generally badly supported in pkg-config...

Please could you insert the output of pkg-config to help understanding?

Thanks
  
Luca Boccassi April 29, 2020, 10:40 a.m. UTC | #2
On Wed, 2020-04-29 at 11:08 +0100, Bruce Richardson wrote:
> When calling pkg-config --static --libs, pkg-config will always output the
> regular libs first, and then the extra libs from libraries.private field,
> since the assumption is that those are additional dependencies for building
> statically that the .a files depend upon.
> 
> However, for DPDK, we only link the driver files for static builds, and
> those need to come *before* the regular libraries. To get this result, we
> need two pkgconfig files for DPDK, one for the shared libs, and a second
> for the static libs and drivers, which depends upon the first. Using a
> dependency means that the shared libs are printed only after the
> libraries.private field rather than before.

A neat trick! Can we document that the new file is an implementation
detail for internal usage, and that it should not be referenced
directly?
I'm even pondering if it would be possible to install it in a private
directory, need to check if there's a way for Requires to specify
prefixes
  
Bruce Richardson April 29, 2020, 10:54 a.m. UTC | #3
On Wed, Apr 29, 2020 at 12:30:10PM +0200, Thomas Monjalon wrote:
> 29/04/2020 12:08, Bruce Richardson:
> > When calling pkg-config --static --libs, pkg-config will always output
> > the regular libs first, and then the extra libs from libraries.private
> > field, since the assumption is that those are additional dependencies
> > for building statically that the .a files depend upon.
> > 
> > However, for DPDK, we only link the driver files for static builds, and
> > those need to come *before* the regular libraries.
> 
> Please could you add the error here?
>
There is no error, because we work around it. What we do now is that we
list the DPDK libraries in both the Libs and Libs.private sections. Without
that, we'd have the libs first and then the drivers. This doesn't cause any
issues because linking against a .so unnecessarily isn't a problem.
However, it does mean that we require that we put in flags to switch
between dynamic and static linking in the output.
 
> > To get this result, we
> > need two pkgconfig files for DPDK, one for the shared libs, and a second
> > for the static libs and drivers, which depends upon the first.
> 
> I feel we are doing something wrong.
> We should not have two .pc files.
> I also know that static linkage is generally badly supported in pkg-config...
> 

Yes, it's working around a pkgconfig limitation, though also a limitation
in that we don't link against the drivers when we do a shared build.

> Please could you insert the output of pkg-config to help understanding?
> 

Here is the libdpdk.pc contents right now:

  Requires: libbsd
  
  Requires.private: libmlx5, libibverbs, zlib, libmlx4, libcrypto, libisal,
  jansson, libelf
  
  Libs: -L${libdir} -lrte_telemetry -lrte_bpf -lrte_flow_classify
  -lrte_pipeline -lrte_table -lrte_port -lrte_fib -lrte_ipsec -lrte_vhost
  -lrte_stack -lrte_security -lrte_sched -lrte_reorder -lrte_rib -lrte_rawdev
  -lrte_pdump -lrte_power -lrte_member -lrte_lpm -lrte_latencystats -lrte_kni
  -lrte_jobstats -lrte_ip_frag -lrte_gso -lrte_gro -lrte_eventdev -lrte_efd
  -lrte_distributor -lrte_cryptodev -lrte_compressdev -lrte_cfgfile
  -lrte_bitratestats -lrte_bbdev -lrte_acl -lrte_timer -lrte_hash
  -lrte_metrics -lrte_cmdline -lrte_pci -lrte_ethdev -lrte_meter -lrte_net
  -lrte_mbuf -lrte_mempool -lrte_rcu -lrte_ring -lrte_eal -lrte_kvargs
  
  Libs.private: -Wl,--whole-archive -L${libdir} -lrte_common_cpt
  -lrte_common_dpaax -lrte_common_iavf -lrte_common_mlx5
  -lrte_common_octeontx -lrte_common_octeontx2 -lrte_bus_dpaa -lrte_bus_fslmc
  -lrte_bus_ifpga -lrte_bus_pci -lrte_bus_vdev -lrte_bus_vmbus
     <snip>
  -lrte_pmd_mlx5_vdpa -lrte_pmd_dpaa_event -lrte_pmd_dpaa2_event
  -lrte_pmd_octeontx2_event -lrte_pmd_opdl_event -lrte_pmd_skeleton_event
  -lrte_pmd_sw_event -lrte_pmd_dsw_event -lrte_pmd_octeontx_event
  -lrte_pmd_bbdev_null -lrte_pmd_bbdev_turbo_sw -lrte_pmd_bbdev_fpga_lte_fec
  -lrte_pmd_bbdev_fpga_5gnr_fec -Wl,--no-whole-archive -lrte_telemetry
  -lrte_bpf -lrte_flow_classify -lrte_pipeline -lrte_table -lrte_port
  -lrte_fib -lrte_ipsec -lrte_vhost -lrte_stack -lrte_security -lrte_sched
  -lrte_reorder -lrte_rib -lrte_rawdev -lrte_pdump -lrte_power -lrte_member
  -lrte_lpm -lrte_latencystats -lrte_kni -lrte_jobstats -lrte_ip_frag
  -lrte_gso -lrte_gro -lrte_eventdev -lrte_efd -lrte_distributor
  -lrte_cryptodev -lrte_compressdev -lrte_cfgfile -lrte_bitratestats
  -lrte_bbdev -lrte_acl -lrte_timer -lrte_hash -lrte_metrics -lrte_cmdline
  -lrte_pci -lrte_ethdev -lrte_meter -lrte_net -lrte_mbuf -lrte_mempool
  -lrte_rcu -lrte_ring -lrte_eal -lrte_kvargs -Wl,-Bdynamic -pthread -lm -ldl
  -lnuma -lpcap -lIPSec_MB Cflags:-I${includedir} -include rte_config.h
  -march=native
  
The output from pkg-config for this is below, with libs first, then drivers
and libs a second time:

$ PKG_CONFIG_PATH=`pwd`/meson-private pkg-config --static --libs libdpdk
-L/usr/local/lib/x86_64-linux-gnu -lrte_telemetry -lrte_bpf
-lrte_flow_classify -lrte_pipeline -lrte_table -lrte_port -lrte_fib
-lrte_ipsec -lrte_vhost -lrte_stack -lrte_security -lrte_sched
-lrte_reorder -lrte_rib -lrte_rawdev -lrte_pdump -lrte_power -lrte_member
-lrte_lpm -lrte_latencystats -lrte_kni -lrte_jobstats -lrte_ip_frag
-lrte_gso -lrte_gro -lrte_eventdev -lrte_efd -lrte_distributor
-lrte_cryptodev -lrte_compressdev -lrte_cfgfile -lrte_bitratestats
-lrte_bbdev -lrte_acl -lrte_timer -lrte_hash -lrte_metrics -lrte_cmdline
-lrte_pci -lrte_ethdev -lrte_meter -lrte_net -lrte_mbuf -lrte_mempool
-lrte_rcu -lrte_ring -lrte_eal -lrte_kvargs -Wl,--whole-archive
-L/usr/local/lib/x86_64-linux-gnu -lrte_common_cpt -lrte_common_dpaax
-lrte_common_iavf -lrte_common_mlx5 -lrte_common_octeontx
-lrte_common_octeontx2 -lrte_bus_dpaa -lrte_bus_fslmc -lrte_bus_ifpga
-lrte_bus_pci -lrte_bus_vdev -lrte_bus_vmbus -lrte_mempool_bucket
-lrte_mempool_dpaa -lrte_mempool_dpaa2 -lrte_mempool_octeontx
-lrte_mempool_octeontx2 -lrte_mempool_ring -lrte_mempool_stack
-lrte_pmd_af_packet -lrte_pmd_ark -lrte_pmd_atlantic -lrte_pmd_avp
-lrte_pmd_axgbe -lrte_pmd_bond -lrte_pmd_bnx2x -lrte_pmd_bnxt
-lrte_pmd_cxgbe -lrte_pmd_dpaa -lrte_pmd_dpaa2 -lrte_pmd_e1000
-lrte_pmd_ena -lrte_pmd_enetc -lrte_pmd_enic -lrte_pmd_failsafe
-lrte_pmd_fm10k -lrte_pmd_i40e -lrte_pmd_hinic -lrte_pmd_hns3
-lrte_pmd_iavf -lrte_pmd_ice -lrte_pmd_igc -lrte_pmd_ixgbe -lrte_pmd_kni
-lrte_pmd_liquidio -lrte_pmd_memif -lrte_pmd_mlx4 -lrte_pmd_mlx5
-lrte_pmd_netvsc -lrte_pmd_nfp -lrte_pmd_null -lrte_pmd_octeontx
-lrte_pmd_octeontx2 -lrte_pmd_pcap -lrte_pmd_pfe -lrte_pmd_qede
-lrte_pmd_ring -lrte_pmd_sfc -lrte_pmd_softnic -lrte_pmd_tap
-lrte_pmd_thunderx -lrte_pmd_vdev_netvsc -lrte_pmd_vhost -lrte_pmd_virtio
-lrte_pmd_vmxnet3 -lrte_rawdev_dpaa2_cmdif -lrte_rawdev_dpaa2_qdma
-lrte_rawdev_ioat -lrte_rawdev_ntb -lrte_rawdev_octeontx2_dma
-lrte_rawdev_octeontx2_ep -lrte_rawdev_skeleton -lrte_pmd_aesni_gcm
-lrte_pmd_aesni_mb -lrte_pmd_caam_jr -lrte_pmd_ccp -lrte_pmd_dpaa_sec
-lrte_pmd_dpaa2_sec -lrte_pmd_nitrox -lrte_pmd_null_crypto
-lrte_pmd_octeontx_crypto -lrte_pmd_octeontx2_crypto -lrte_pmd_openssl
-lrte_pmd_crypto_scheduler -lrte_pmd_virtio_crypto -lrte_pmd_isal
-lrte_pmd_octeontx_compress -lrte_pmd_qat -lrte_pmd_zlib -lrte_pmd_ifc
-lrte_pmd_mlx5_vdpa -lrte_pmd_dpaa_event -lrte_pmd_dpaa2_event
-lrte_pmd_octeontx2_event -lrte_pmd_opdl_event -lrte_pmd_skeleton_event
-lrte_pmd_sw_event -lrte_pmd_dsw_event -lrte_pmd_octeontx_event
-lrte_pmd_bbdev_null -lrte_pmd_bbdev_turbo_sw -lrte_pmd_bbdev_fpga_lte_fec
-lrte_pmd_bbdev_fpga_5gnr_fec -Wl,--no-whole-archive -lrte_telemetry
-lrte_bpf -lrte_flow_classify -lrte_pipeline -lrte_table -lrte_port
-lrte_fib -lrte_ipsec -lrte_vhost -lrte_stack -lrte_security -lrte_sched
-lrte_reorder -lrte_rib -lrte_rawdev -lrte_pdump -lrte_power -lrte_member
-lrte_lpm -lrte_latencystats -lrte_kni -lrte_jobstats -lrte_ip_frag
-lrte_gso -lrte_gro -lrte_eventdev -lrte_efd -lrte_distributor
-lrte_cryptodev -lrte_compressdev -lrte_cfgfile -lrte_bitratestats
-lrte_bbdev -lrte_acl -lrte_timer -lrte_hash -lrte_metrics -lrte_cmdline
-lrte_pci -lrte_ethdev -lrte_meter -lrte_net -lrte_mbuf -lrte_mempool
-lrte_rcu -lrte_ring -lrte_eal -lrte_kvargs -Wl,-Bdynamic -pthread -lm -ldl
-lnuma -lpcap -lIPSec_MB -L/usr/lib/x86_64-linux-gnu -lbsd
-L/usr/lib/x86_64-linux-gnu -lmlx5 -lpthread -L/usr/lib/x86_64-linux-gnu
-libverbs -lbnxt_re-rdmav22 -lcxgb3-rdmav22 -lcxgb4-rdmav22 -lefa
-lhns-rdmav22 -li40iw-rdmav22 -lmlx4 -lmlx5 -lmthca-rdmav22 -lnes-rdmav22
-locrdma-rdmav22 -lqedr-rdmav22 -lvmw_pvrdma-rdmav22 -lhfi1verbs-rdmav22
-lipathverbs-rdmav22 -lrxe-rdmav22 -lpthread -L/usr/lib/x86_64-linux-gnu
-lnl-3 -libverbs -lbnxt_re-rdmav22 -lcxgb3-rdmav22 -lcxgb4-rdmav22 -lefa
-lhns-rdmav22 -li40iw-rdmav22 -lmlx5 -lmthca-rdmav22 -lnes-rdmav22
-locrdma-rdmav22 -lqedr-rdmav22 -lvmw_pvrdma-rdmav22 -lhfi1verbs-rdmav22
-lipathverbs-rdmav22 -lrxe-rdmav22 -libverbs -lpthread
-L/usr/lib/x86_64-linux-gnu -lnl-3 -lz -lmlx4 -lpthread
-L/usr/lib/x86_64-linux-gnu -libverbs -lbnxt_re-rdmav22 -lcxgb3-rdmav22
-lcxgb4-rdmav22 -lefa -lhns-rdmav22 -li40iw-rdmav22 -lmlx4 -lmlx5
-lmthca-rdmav22 -lnes-rdmav22 -locrdma-rdmav22 -lqedr-rdmav22
-lvmw_pvrdma-rdmav22 -lhfi1verbs-rdmav22 -lipathverbs-rdmav22 -lrxe-rdmav22
-libverbs -lpthread -L/usr/lib/x86_64-linux-gnu -lnl-route-3 -lnl-3
-lcrypto -ldl -pthread -lisal -ljansson -lelf -L/usr/lib/x86_64-linux-gnu
-L/usr/lib/x86_64-linux-gnu -lz
  
Bruce Richardson April 29, 2020, 11:03 a.m. UTC | #4
On Wed, Apr 29, 2020 at 11:40:33AM +0100, Luca Boccassi wrote:
> On Wed, 2020-04-29 at 11:08 +0100, Bruce Richardson wrote:
> > When calling pkg-config --static --libs, pkg-config will always output the
> > regular libs first, and then the extra libs from libraries.private field,
> > since the assumption is that those are additional dependencies for building
> > statically that the .a files depend upon.
> > 
> > However, for DPDK, we only link the driver files for static builds, and
> > those need to come *before* the regular libraries. To get this result, we
> > need two pkgconfig files for DPDK, one for the shared libs, and a second
> > for the static libs and drivers, which depends upon the first. Using a
> > dependency means that the shared libs are printed only after the
> > libraries.private field rather than before.
> 
> A neat trick! Can we document that the new file is an implementation
> detail for internal usage, and that it should not be referenced
> directly?
> I'm even pondering if it would be possible to install it in a private
> directory, need to check if there's a way for Requires to specify
> prefixes
> 
That would be great, if there was a way to hide it. I also take it from
your feedback that a package needing multiple .pc files is not an issue for
debian packaging?
  
Luca Boccassi April 29, 2020, 11:12 a.m. UTC | #5
On Wed, 2020-04-29 at 12:03 +0100, Bruce Richardson wrote:
> On Wed, Apr 29, 2020 at 11:40:33AM +0100, Luca Boccassi wrote:
> > On Wed, 2020-04-29 at 11:08 +0100, Bruce Richardson wrote:
> > > When calling pkg-config --static --libs, pkg-config will always output the
> > > regular libs first, and then the extra libs from libraries.private field,
> > > since the assumption is that those are additional dependencies for building
> > > statically that the .a files depend upon.
> > > 
> > > However, for DPDK, we only link the driver files for static builds, and
> > > those need to come *before* the regular libraries. To get this result, we
> > > need two pkgconfig files for DPDK, one for the shared libs, and a second
> > > for the static libs and drivers, which depends upon the first. Using a
> > > dependency means that the shared libs are printed only after the
> > > libraries.private field rather than before.
> > 
> > A neat trick! Can we document that the new file is an implementation
> > detail for internal usage, and that it should not be referenced
> > directly?
> > I'm even pondering if it would be possible to install it in a private
> > directory, need to check if there's a way for Requires to specify
> > prefixes
> > 
> That would be great, if there was a way to hide it. I also take it from
> your feedback that a package needing multiple .pc files is not an issue for
> debian packaging?

Yeah it's fine, we can ship as many as we want - just concerned about
it being used by mistake, but documenting it should be enough
  

Patch

diff --git a/buildtools/pkg-config/meson.build b/buildtools/pkg-config/meson.build
index 85d59972d..f08ca54ed 100644
--- a/buildtools/pkg-config/meson.build
+++ b/buildtools/pkg-config/meson.build
@@ -10,17 +10,33 @@  pkg_extra_cflags = ['-include', 'rte_config.h'] + machine_args
 if is_freebsd
 	pkg_extra_cflags += ['-D__BSD_VISIBLE']
 endif
-pkg.generate(name: meson.project_name(),
-	filebase: 'lib' + meson.project_name().to_lower(),
+
+# When calling pkg-config --static --libs, pkg-config will always output the
+# regular libs first, and then the extra libs from libraries.private field,
+# since the assumption is that those are additional dependencies for building
+# statically that the .a files depend upon. However, for DPDK, we only link
+# the driver files for static builds, and those need to come *before* the
+# regular libraries. To get this result, we need two pkgconfig files for DPDK,
+# one for the shared libs, and a second for the static libs and drivers, which
+# depends upon the first. Using a dependency means that the shared libs are
+# printed only after the libraries.private field rather than before.
+pkg.generate(name: 'dpdk-libs',
+	filebase: 'libdpdk-libs',
+	description: 'The Data Plane Development Kit (DPDK), libraries only.',
 	version: meson.project_version(),
+	subdirs: [get_option('include_subdir_arch'), '.'],
+	extra_cflags: pkg_extra_cflags,
 	libraries: dpdk_libraries,
-	libraries_private: dpdk_drivers + dpdk_static_libraries +
-			['-Wl,-Bdynamic'] + dpdk_extra_ldflags,
-	requires: libbsd, # apps using rte_string_fns.h may need this if enabled
-	                  # if libbsd is not enabled, then this is blank
+	libraries_private: dpdk_extra_ldflags)
+
+pkg.generate(name: 'DPDK', # main DPDK pkgconfig file
+	filebase: 'libdpdk',
+	version: meson.project_version(),
 	description: '''The Data Plane Development Kit (DPDK).
 Note that CFLAGS might contain an -march flag higher than typical baseline.
 This is required for a number of static inline functions in the public headers.''',
-	subdirs: [get_option('include_subdir_arch'), '.'],
-	extra_cflags: pkg_extra_cflags
+	requires: ['libdpdk-libs', libbsd], # may need libbsd for string funcs
+	                  # if libbsd is not enabled, then this is blank
+	libraries_private: dpdk_drivers + dpdk_static_libraries +
+			['-Wl,-Bdynamic']
 )