libiio not linking on AMD ryzen 2 cpu in c or python program

 * libiio - AD9361 IIO streaming example
 * Copyright (C) 2014 IABG mbH
 * Author: Michael Feilen <>
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <iio.h>

/* helper macros */
#define MHZ(x) ((long long)(x*1000000.0 + .5))
#define GHZ(x) ((long long)(x*1000000000.0 + .5))

#define IIO_ENSURE(expr) { \
	if (!(expr)) { \
		(void) fprintf(stderr, "assertion failed (%s:%d)\n", __FILE__, __LINE__); \
		(void) abort(); \
	} \

/* RX is input, TX is output */
enum iodev { RX, TX };

/* common RX and TX streaming params */
struct stream_cfg {
	long long bw_hz; // Analog banwidth in Hz
	long long fs_hz; // Baseband sample rate in Hz
	long long lo_hz; // Local oscillator frequency in Hz
	const char* rfport; // Port name

/* static scratch mem for strings */
static char tmpstr[64];

/* IIO structs required for streaming */
static struct iio_context *ctx   = NULL;
static struct iio_channel *rx0_i = NULL;
static struct iio_channel *rx0_q = NULL;
static struct iio_channel *tx0_i = NULL;
static struct iio_channel *tx0_q = NULL;
static struct iio_buffer  *rxbuf = NULL;
static struct iio_buffer  *txbuf = NULL;

static bool stop;

/* cleanup and exit */
static void shutdown()
	printf("* Destroying buffers\n");
	if (rxbuf) { iio_buffer_destroy(rxbuf); }
	if (txbuf) { iio_buffer_destroy(txbuf); }

	printf("* Disabling streaming channels\n");
	if (rx0_i) { iio_channel_disable(rx0_i); }
	if (rx0_q) { iio_channel_disable(rx0_q); }
	if (tx0_i) { iio_channel_disable(tx0_i); }
	if (tx0_q) { iio_channel_disable(tx0_q); }

	printf("* Destroying context\n");
	if (ctx) { iio_context_destroy(ctx); }

static void handle_sig(int sig)
	printf("Waiting for process to finish... Got signal %d\n", sig);
	stop = true;

/* check return value of attr_write function */
static void errchk(int v, const char* what) {
	 if (v < 0) { fprintf(stderr, "Error %d writing to channel \"%s\"\nvalue may not be supported.\n", v, what); shutdown(); }

/* write attribute: long long int */
static void wr_ch_lli(struct iio_channel *chn, const char* what, long long val)
	errchk(iio_channel_attr_write_longlong(chn, what, val), what);

/* write attribute: string */
static void wr_ch_str(struct iio_channel *chn, const char* what, const char* str)
	errchk(iio_channel_attr_write(chn, what, str), what);

/* helper function generating channel names */
static char* get_ch_name(const char* type, int id)
	snprintf(tmpstr, sizeof(tmpstr), "%s%d", type, id);
	return tmpstr;

/* returns ad9361 phy device */
static struct iio_device* get_ad9361_phy(void)
	struct iio_device *dev =  iio_context_find_device(ctx, "ad9361-phy");
	IIO_ENSURE(dev && "No ad9361-phy found");
	return dev;

/* finds AD9361 streaming IIO devices */
static bool get_ad9361_stream_dev(enum iodev d, struct iio_device **dev)
	switch (d) {
	case TX: *dev = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); return *dev != NULL;
	case RX: *dev = iio_context_find_device(ctx, "cf-ad9361-lpc");  return *dev != NULL;
	default: IIO_ENSURE(0); return false;

/* finds AD9361 streaming IIO channels */
static bool get_ad9361_stream_ch(enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn)
	*chn = iio_device_find_channel(dev, get_ch_name("voltage", chid), d == TX);
	if (!*chn)
		*chn = iio_device_find_channel(dev, get_ch_name("altvoltage", chid), d == TX);
	return *chn != NULL;

/* finds AD9361 phy IIO configuration channel with id chid */
static bool get_phy_chan(enum iodev d, int chid, struct iio_channel **chn)
	switch (d) {
	case RX: *chn = iio_device_find_channel(get_ad9361_phy(), get_ch_name("voltage", chid), false); return *chn != NULL;
	case TX: *chn = iio_device_find_channel(get_ad9361_phy(), get_ch_name("voltage", chid), true);  return *chn != NULL;
	default: IIO_ENSURE(0); return false;

/* finds AD9361 local oscillator IIO configuration channels */
static bool get_lo_chan(enum iodev d, struct iio_channel **chn)
	switch (d) {
	 // LO chan is always output, i.e. true
	case RX: *chn = iio_device_find_channel(get_ad9361_phy(), get_ch_name("altvoltage", 0), true); return *chn != NULL;
	case TX: *chn = iio_device_find_channel(get_ad9361_phy(), get_ch_name("altvoltage", 1), true); return *chn != NULL;
	default: IIO_ENSURE(0); return false;

/* applies streaming configuration through IIO */
bool cfg_ad9361_streaming_ch(struct stream_cfg *cfg, enum iodev type, int chid)
	struct iio_channel *chn = NULL;

	// Configure phy and lo channels
	printf("* Acquiring AD9361 phy channel %d\n", chid);
	if (!get_phy_chan(type, chid, &chn)) {	return false; }
	wr_ch_str(chn, "rf_port_select",     cfg->rfport);
	wr_ch_lli(chn, "rf_bandwidth",       cfg->bw_hz);
	wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz);

	// Configure LO channel
	printf("* Acquiring AD9361 %s lo channel\n", type == TX ? "TX" : "RX");
	if (!get_lo_chan(type, &chn)) { return false; }
	wr_ch_lli(chn, "frequency", cfg->lo_hz);
	return true;

/* simple configuration and streaming */
/* usage:
 * Default context, assuming local IIO devices, i.e., this script is run on ADALM-Pluto for example
 * URI context, find out the uri by typing `iio_info -s` at the command line of the host PC
 $./a.out usb:x.x.x
int main (int argc, char **argv)
	// Streaming devices
	struct iio_device *tx;
	struct iio_device *rx;

	// RX and TX sample counters
	size_t nrx = 0;
	size_t ntx = 0;

	// Stream configurations
	struct stream_cfg rxcfg;
	struct stream_cfg txcfg;

	// Listen to ctrl+c and IIO_ENSURE
	signal(SIGINT, handle_sig);

	// RX stream config
	rxcfg.bw_hz = MHZ(2);   // 2 MHz rf bandwidth
	rxcfg.fs_hz = MHZ(2.5);   // 2.5 MS/s rx sample rate
	rxcfg.lo_hz = GHZ(2.5); // 2.5 GHz rf frequency
	rxcfg.rfport = "A_BALANCED"; // port A (select for rf freq.)

	// TX stream config
	txcfg.bw_hz = MHZ(1.5); // 1.5 MHz rf bandwidth
	txcfg.fs_hz = MHZ(2.5);   // 2.5 MS/s tx sample rate
	txcfg.lo_hz = GHZ(2.5); // 2.5 GHz rf frequency
	txcfg.rfport = "A"; // port A (select for rf freq.)

	printf("* Acquiring IIO context\n");
	if (argc == 1) {
		IIO_ENSURE((ctx = iio_create_default_context()) && "No context");
	else if (argc == 2) {
		IIO_ENSURE((ctx = iio_create_context_from_uri(argv[1])) && "No context");
	IIO_ENSURE(iio_context_get_devices_count(ctx) > 0 && "No devices");

	printf("* Acquiring AD9361 streaming devices\n");
	IIO_ENSURE(get_ad9361_stream_dev(TX, &tx) && "No tx dev found");
	IIO_ENSURE(get_ad9361_stream_dev(RX, &rx) && "No rx dev found");

	printf("* Configuring AD9361 for streaming\n");
	IIO_ENSURE(cfg_ad9361_streaming_ch(&rxcfg, RX, 0) && "RX port 0 not found");
	IIO_ENSURE(cfg_ad9361_streaming_ch(&txcfg, TX, 0) && "TX port 0 not found");

	printf("* Initializing AD9361 IIO streaming channels\n");
	IIO_ENSURE(get_ad9361_stream_ch(RX, rx, 0, &rx0_i) && "RX chan i not found");
	IIO_ENSURE(get_ad9361_stream_ch(RX, rx, 1, &rx0_q) && "RX chan q not found");
	IIO_ENSURE(get_ad9361_stream_ch(TX, tx, 0, &tx0_i) && "TX chan i not found");
	IIO_ENSURE(get_ad9361_stream_ch(TX, tx, 1, &tx0_q) && "TX chan q not found");

	printf("* Enabling IIO streaming channels\n");

	printf("* Creating non-cyclic IIO buffers with 1 MiS\n");
	rxbuf = iio_device_create_buffer(rx, 1024*1024, false);
	if (!rxbuf) {
		perror("Could not create RX buffer");
	txbuf = iio_device_create_buffer(tx, 1024*1024, false);
	if (!txbuf) {
		perror("Could not create TX buffer");

	printf("* Starting IO streaming (press CTRL+C to cancel)\n");
	while (!stop)
		ssize_t nbytes_rx, nbytes_tx;
		char *p_dat, *p_end;
		ptrdiff_t p_inc;

		// Schedule TX buffer
		nbytes_tx = iio_buffer_push(txbuf);
		if (nbytes_tx < 0) { printf("Error pushing buf %d\n", (int) nbytes_tx); shutdown(); }

		// Refill RX buffer
		nbytes_rx = iio_buffer_refill(rxbuf);
		if (nbytes_rx < 0) { printf("Error refilling buf %d\n",(int) nbytes_rx); shutdown(); }

		// READ: Get pointers to RX buf and read IQ from RX buf port 0
		p_inc = iio_buffer_step(rxbuf);
		p_end = iio_buffer_end(rxbuf);
		for (p_dat = (char *)iio_buffer_first(rxbuf, rx0_i); p_dat < p_end; p_dat += p_inc) {
			// Example: swap I and Q
			const int16_t i = ((int16_t*)p_dat)[0]; // Real (I)
			const int16_t q = ((int16_t*)p_dat)[1]; // Imag (Q)
			((int16_t*)p_dat)[0] = q;
			((int16_t*)p_dat)[1] = i;

		// WRITE: Get pointers to TX buf and write IQ to TX buf port 0
		p_inc = iio_buffer_step(txbuf);
		p_end = iio_buffer_end(txbuf);
		for (p_dat = (char *)iio_buffer_first(txbuf, tx0_i); p_dat < p_end; p_dat += p_inc) {
			// Example: fill with zeros
			// 12-bit sample needs to be MSB aligned so shift by 4
			((int16_t*)p_dat)[0] = 0 << 4; // Real (I)
			((int16_t*)p_dat)[1] = 0 << 4; // Imag (Q)

		// Sample counter increment and status output
		nrx += nbytes_rx / iio_device_get_sample_size(rx);
		ntx += nbytes_tx / iio_device_get_sample_size(tx);
		printf("\tRX %8.2f MSmp, TX %8.2f MSmp\n", nrx/1e6, ntx/1e6);


	return 0;

I am trying to run this example c program to see if I have set up my pluto properly.

$ gcc -liio ad9361-iiostream.c

/usr/bin/ld: /tmp/ccUEciE4.o: in function `shutdown':
ad9361-iiostream.c:(.text+0x2b): undefined reference to `iio_buffer_destroy'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x46): undefined reference to `iio_buffer_destroy'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x6d): undefined reference to `iio_channel_disable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x88): undefined reference to `iio_channel_disable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xa3): undefined reference to `iio_channel_disable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xbe): undefined reference to `iio_channel_disable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xe5): undefined reference to `iio_context_destroy'
/usr/bin/ld: /tmp/ccUEciE4.o: in function `wr_ch_lli':
ad9361-iiostream.c:(.text+0x195): undefined reference to `iio_channel_attr_write_longlong'
/usr/bin/ld: /tmp/ccUEciE4.o: in function `wr_ch_str':
ad9361-iiostream.c:(.text+0x1d7): undefined reference to `iio_channel_attr_write'
/usr/bin/ld: /tmp/ccUEciE4.o: in function `get_ad9361_phy':
ad9361-iiostream.c:(.text+0x252): undefined reference to `iio_context_find_device'
/usr/bin/ld: /tmp/ccUEciE4.o: in function `get_ad9361_stream_dev':
ad9361-iiostream.c:(.text+0x2c4): undefined reference to `iio_context_find_device'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x2f0): undefined reference to `iio_context_find_device'
/usr/bin/ld: /tmp/ccUEciE4.o: in function `get_ad9361_stream_ch':
ad9361-iiostream.c:(.text+0x37e): undefined reference to `iio_device_find_channel'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x3c0): undefined reference to `iio_device_find_channel'
/usr/bin/ld: /tmp/ccUEciE4.o: in function `get_phy_chan':
ad9361-iiostream.c:(.text+0x429): undefined reference to `iio_device_find_channel'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x468): undefined reference to `iio_device_find_channel'
/usr/bin/ld: /tmp/ccUEciE4.o: in function `get_lo_chan':
ad9361-iiostream.c:(.text+0x4fc): undefined reference to `iio_device_find_channel'
/usr/bin/ld: /tmp/ccUEciE4.o:ad9361-iiostream.c:(.text+0x53b): more undefined references to `iio_device_find_channel' follow
/usr/bin/ld: /tmp/ccUEciE4.o: in function `main':
ad9361-iiostream.c:(.text+0x766): undefined reference to `iio_create_default_context'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x7c8): undefined reference to `iio_create_context_from_uri'
/usr/bin/ld: ad9361-iiostream.c:(.text+0x816): undefined reference to `iio_context_get_devices_count'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xaf1): undefined reference to `iio_channel_enable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xb00): undefined reference to `iio_channel_enable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xb0f): undefined reference to `iio_channel_enable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xb1e): undefined reference to `iio_channel_enable'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xb43): undefined reference to `iio_device_create_buffer'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xb85): undefined reference to `iio_device_create_buffer'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xbce): undefined reference to `iio_buffer_push'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xc09): undefined reference to `iio_buffer_refill'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xc44): undefined reference to `iio_buffer_step'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xc57): undefined reference to `iio_buffer_end'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xc74): undefined reference to `iio_buffer_first'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xcd8): undefined reference to `iio_buffer_step'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xceb): undefined reference to `iio_buffer_end'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xd08): undefined reference to `iio_buffer_first'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xd45): undefined reference to `iio_device_get_sample_size'
/usr/bin/ld: ad9361-iiostream.c:(.text+0xd67): undefined reference to `iio_device_get_sample_size'
collect2: error: ld returned 1 exit status

I am on an AMD ryzen 2 dell not sure if cpu type would cause this but I was able to run it on intel in this way before and libiio would link properly. I have iio.h installed into /usr/include so doesn't make sense how the functions can't be imported.