use anyhow::Result;
use bindgen::{
Bindings,
Builder,
};
use cc::Build;
use std::{
env,
path::Path,
};
#[cfg(target_os = "windows")]
fn os_build() -> Result<()> {
use std::path::PathBuf;
let out_dir_s: String = env::var("OUT_DIR")?;
let out_dir: &Path = Path::new(&out_dir_s);
let libdpdk_path: String = env::var("LIBDPDK_PATH")?;
let include_path: String = format!("{}{}", libdpdk_path, "\\include");
let library_path: String = format!("{}{}", libdpdk_path, "\\lib");
let libraries: Vec<&str> = vec![
"librte_bitratestats",
"librte_bus_auxiliary",
"librte_bus_pci",
"librte_bus_vdev",
"librte_cfgfile",
"librte_cmdline",
"librte_common_iavf",
"librte_common_idpf",
"librte_common_mlx5",
"librte_cryptodev",
"librte_crypto_mlx5",
"librte_dmadev",
"librte_dma_idxd",
"librte_dma_ioat",
"librte_dma_skeleton",
"librte_eal",
"librte_ethdev",
"librte_gpudev",
"librte_gro",
"librte_gso",
"librte_hash",
"librte_kvargs",
"librte_latencystats",
"librte_mbuf",
"librte_mempool",
"librte_mempool_ring",
"librte_mempool_stack",
"librte_meter",
"librte_metrics",
"librte_net",
"librte_net_e1000",
"librte_net_i40e",
"librte_net_iavf",
"librte_net_ice",
"librte_net_ixgbe",
"librte_net_mlx5",
"librte_net_octeon_ep",
"librte_net_vmxnet3",
"librte_pci",
"librte_rcu",
"librte_ring",
"librte_security",
"librte_stack",
"librte_telemetry",
"librte_timer",
"mlx5devx",
];
let cflags: &str = "-mavx";
println!("cargo:rustc-link-search={}", library_path);
for lib in &libraries {
println!("cargo:rustc-link-lib=static:-bundle,+whole-archive={}", lib);
}
println!("cargo:rustc-link-lib=dylib={}", "setupapi");
println!("cargo:rustc-link-lib=dylib={}", "dbghelp");
println!("cargo:rustc-link-lib=dylib={}", "mincore");
let bindings: Bindings = Builder::default()
.clang_arg(&format!("-I{}", include_path))
.allowlist_recursively(true)
.allowlist_function("rte_auxiliary_register")
.allowlist_function("rte_delay_us_block")
.allowlist_function("rte_eal_init")
.allowlist_function("rte_eth_conf")
.allowlist_function("rte_eth_dev_configure")
.allowlist_function("rte_eth_dev_count_avail")
.allowlist_function("rte_eth_dev_flow_ctrl_get")
.allowlist_function("rte_eth_dev_flow_ctrl_set")
.allowlist_function("rte_eth_dev_get_mtu")
.allowlist_function("rte_eth_dev_info_get")
.allowlist_function("rte_eth_dev_is_valid_port")
.allowlist_function("rte_eth_dev_set_mtu")
.allowlist_function("rte_eth_dev_socket_id")
.allowlist_function("rte_eth_dev_start")
.allowlist_function("rte_eth_find_next_owned_by")
.allowlist_function("rte_eth_link_get_nowait")
.allowlist_function("rte_eth_macaddr_get")
.allowlist_function("rte_eth_promiscuous_enable")
.allowlist_function("rte_eth_rx_burst")
.allowlist_function("rte_eth_rx_queue_setup")
.allowlist_function("rte_eth_tx_burst")
.allowlist_function("rte_eth_tx_queue_setup")
.allowlist_function("rte_mempool_avail_count")
.allowlist_function("rte_mempool_create_empty")
.allowlist_function("rte_mempool_free")
.allowlist_function("rte_mempool_in_use_count")
.allowlist_function("rte_mempool_mem_iter")
.allowlist_function("rte_mempool_obj_iter")
.allowlist_function("rte_mempool_populate_default")
.allowlist_function("rte_pktmbuf_clone")
.allowlist_function("rte_pktmbuf_init")
.allowlist_function("rte_pktmbuf_pool_create")
.allowlist_function("rte_pktmbuf_pool_init")
.allowlist_function("rte_pktmbuf_prepend")
.allowlist_function("rte_socket_id")
.allowlist_function("rte_strerror")
.allowlist_type("rte_eth_fc_conf")
.allowlist_type("rte_eth_rxconf")
.allowlist_type("rte_eth_txconf")
.allowlist_type("rte_ether_addr")
.allowlist_type("rte_mbuf")
.allowlist_type("rte_mempool")
.allowlist_type("rte_pktmbuf_pool_private")
.allowlist_var("RTE_ETH_DEV_NO_OWNER")
.allowlist_var("RTE_ETH_LINK_FULL_DUPLEX")
.allowlist_var("RTE_ETH_LINK_UP")
.allowlist_var("RTE_ETH_MQ_RX_RSS")
.allowlist_var("RTE_ETH_MQ_TX_NONE")
.allowlist_var("RTE_ETH_RSS_IP")
.allowlist_var("RTE_ETH_RX_OFFLOAD_IPV4_CKSUM")
.allowlist_var("RTE_ETH_RX_OFFLOAD_TCP_CKSUM")
.allowlist_var("RTE_ETH_RX_OFFLOAD_UDP_CKSUM")
.allowlist_var("RTE_ETH_TX_OFFLOAD_MULTI_SEGS")
.allowlist_var("RTE_ETH_TX_OFFLOAD_TCP_CKSUM")
.allowlist_var("RTE_ETH_TX_OFFLOAD_UDP_CKSUM")
.allowlist_var("RTE_ETHER_MAX_JUMBO_FRAME_LEN")
.allowlist_var("RTE_ETHER_MAX_JUMBO_FRAME")
.allowlist_var("RTE_ETHER_MAX_LEN")
.allowlist_var("RTE_MAX_ETHPORTS")
.allowlist_var("RTE_MBUF_DEFAULT_BUF_SIZE")
.allowlist_var("RTE_PKTMBUF_HEADROOM")
.clang_arg(cflags)
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate_comments(false)
.generate()?;
let bindings_out: PathBuf = out_dir.join("bindings.rs");
bindings.write_to_file(bindings_out)?;
let mut builder: Build = cc::Build::new();
builder.opt_level(3);
builder.flag("-march=native");
builder.file("inlined.c");
builder.include(include_path);
builder.compile("inlined");
Ok(())
}
#[cfg(target_os = "linux")]
fn os_build() -> Result<()> {
use std::process::Command;
let out_dir_s = env::var("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir_s);
println!("cargo:rerun-if-env-changed=PKG_CONFIG_PATH");
let cflags_bytes = Command::new("pkg-config")
.args(&["--cflags", "libdpdk"])
.output()
.unwrap_or_else(|e| panic!("Failed pkg-config cflags: {:?}", e))
.stdout;
let mut cflags = String::from_utf8(cflags_bytes).unwrap();
if cflags.is_empty() {
cflags = env::var("CFLAGS").unwrap_or_else(|_| String::from(""));
if cflags.is_empty() {
panic!("CFLAGS is empty or not set");
}
}
let mut header_locations = vec![];
for flag in cflags.split(' ') {
if flag.starts_with("-I") {
let header_location = flag[2..].trim();
header_locations.push(header_location);
}
}
let ldflags_bytes = Command::new("pkg-config")
.args(&["--libs", "libdpdk"])
.output()
.unwrap_or_else(|e| panic!("Failed pkg-config ldflags: {:?}", e))
.stdout;
let ldflags = String::from_utf8(ldflags_bytes).unwrap();
let mut library_location = None;
let mut lib_names = vec![];
for flag in ldflags.split(' ') {
if flag.starts_with("-L") {
library_location = Some(&flag[2..]);
} else if flag.starts_with("-l") {
lib_names.push(&flag[2..]);
}
}
#[cfg(feature = "mlx5")]
{
lib_names.extend(&["rte_net_mlx5", "rte_bus_pci", "rte_bus_vdev", "rte_common_mlx5"]);
}
if let Some(location) = library_location {
println!("cargo:rustc-link-search=native={}", location);
}
for lib_name in &lib_names {
println!("cargo:rustc-link-lib=dylib={}", lib_name);
}
let mut builder: Builder = Builder::default();
for header_location in &header_locations {
builder = builder.clang_arg(&format!("-I{}", header_location));
}
let bindings: Bindings = builder
.allowlist_recursively(true)
.allowlist_function("rte_auxiliary_register")
.allowlist_function("rte_delay_us_block")
.allowlist_function("rte_eal_init")
.allowlist_function("rte_eth_conf")
.allowlist_function("rte_eth_dev_configure")
.allowlist_function("rte_eth_dev_count_avail")
.allowlist_function("rte_eth_dev_flow_ctrl_get")
.allowlist_function("rte_eth_dev_flow_ctrl_set")
.allowlist_function("rte_eth_dev_get_mtu")
.allowlist_function("rte_eth_dev_info_get")
.allowlist_function("rte_eth_dev_is_valid_port")
.allowlist_function("rte_eth_dev_set_mtu")
.allowlist_function("rte_eth_dev_socket_id")
.allowlist_function("rte_eth_dev_start")
.allowlist_function("rte_eth_find_next_owned_by")
.allowlist_function("rte_eth_link_get_nowait")
.allowlist_function("rte_eth_macaddr_get")
.allowlist_function("rte_eth_promiscuous_enable")
.allowlist_function("rte_eth_rx_burst")
.allowlist_function("rte_eth_rx_queue_setup")
.allowlist_function("rte_eth_tx_burst")
.allowlist_function("rte_eth_tx_queue_setup")
.allowlist_function("rte_mempool_avail_count")
.allowlist_function("rte_mempool_create_empty")
.allowlist_function("rte_mempool_free")
.allowlist_function("rte_mempool_in_use_count")
.allowlist_function("rte_mempool_mem_iter")
.allowlist_function("rte_mempool_obj_iter")
.allowlist_function("rte_mempool_populate_default")
.allowlist_function("rte_pktmbuf_clone")
.allowlist_function("rte_pktmbuf_init")
.allowlist_function("rte_pktmbuf_pool_create")
.allowlist_function("rte_pktmbuf_pool_init")
.allowlist_function("rte_pktmbuf_prepend")
.allowlist_function("rte_socket_id")
.allowlist_function("rte_strerror")
.allowlist_type("rte_eth_fc_conf")
.allowlist_type("rte_eth_rxconf")
.allowlist_type("rte_eth_txconf")
.allowlist_type("rte_ether_addr")
.allowlist_type("rte_mbuf")
.allowlist_type("rte_mempool")
.allowlist_type("rte_pktmbuf_pool_private")
.allowlist_var("RTE_ETH_DEV_NO_OWNER")
.allowlist_var("RTE_ETH_LINK_FULL_DUPLEX")
.allowlist_var("RTE_ETH_LINK_UP")
.allowlist_var("RTE_ETH_MQ_RX_RSS")
.allowlist_var("RTE_ETH_MQ_TX_NONE")
.allowlist_var("RTE_ETH_RSS_IP")
.allowlist_var("RTE_ETH_RX_OFFLOAD_IPV4_CKSUM")
.allowlist_var("RTE_ETH_RX_OFFLOAD_TCP_CKSUM")
.allowlist_var("RTE_ETH_RX_OFFLOAD_UDP_CKSUM")
.allowlist_var("RTE_ETH_TX_OFFLOAD_MULTI_SEGS")
.allowlist_var("RTE_ETH_TX_OFFLOAD_TCP_CKSUM")
.allowlist_var("RTE_ETH_TX_OFFLOAD_UDP_CKSUM")
.allowlist_var("RTE_ETHER_MAX_JUMBO_FRAME_LEN")
.allowlist_var("RTE_ETHER_MAX_JUMBO_FRAME")
.allowlist_var("RTE_ETHER_MAX_LEN")
.allowlist_var("RTE_MAX_ETHPORTS")
.allowlist_var("RTE_MBUF_DEFAULT_BUF_SIZE")
.allowlist_var("RTE_PKTMBUF_HEADROOM")
.clang_arg("-mavx")
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate_comments(false)
.generate()
.unwrap_or_else(|e| panic!("Failed to generate bindings: {:?}", e));
let bindings_out = out_dir.join("bindings.rs");
bindings.write_to_file(bindings_out).expect("Failed to write bindings");
let mut builder: Build = cc::Build::new();
builder.opt_level(3);
builder.pic(true);
builder.flag("-march=native");
builder.file("inlined.c");
for header_location in &header_locations {
builder.include(header_location);
}
builder.compile("inlined");
Ok(())
}
fn main() {
match os_build() {
Ok(()) => {},
Err(e) => panic!("Failed to generate bindings: {:?}", e),
}
}