Search code examples
linkerlibusblibusb-1.0

Undefined reference to libusb functions


I was given some sample code from a vendor that relies on libusb. I get this when I try to compile using make:

mkdir -p .obj
gcc -I./ -I../libsoccptp/include -std=gnu++11 -pthread -g -o .obj/authentication.o -c authentication.cpp -lusb-1.0 -lusb
gcc -std=gnu++11 -pthread -g -o ../out/bin/authentication .obj/authentication.o -L../out/lib -lsoccptp -L/usr/lib -lusb-1.0 -lstdc++ -lusb-1.0 -lusb
../out/lib/libsoccptp.so: undefined reference to `libusb_has_capability'
../out/lib/libsoccptp.so: undefined reference to `libusb_hotplug_register_callback'
../out/lib/libsoccptp.so: undefined reference to `libusb_handle_events_timeout_completed'
../out/lib/libsoccptp.so: undefined reference to `libusb_hotplug_deregister_callback'
collect2: error: ld returned 1 exit status
Makefile:28: recipe for target '../out/bin/authentication' failed
make: *** [../out/bin/authentication] Error 1

I've found lots of other posts by people with similar problems getting libusb to link correctly. But it seems like the solution for others is just making sure -lusb-1.0 and -lusb are added as arguments to the compiler. Clearly, my vendor has already set up the Makefile to do just that. I've also verified I have the latest version of libusb-1.0 on Ubuntu, which is supposedly the same environment my vendor uses.

Why is it not linking correctly?

For reference, here's the Makefile:

ROOT_DIR ?= ..
OUT ?= ../out
OUT_DIR := $(OUT)/bin
CC := gcc

LIBS := -L${OUT}/lib -lsoccptp -L/usr/lib -lusb-1.0 -lstdc++

override INCLUDES += -I./ -I${ROOT_DIR}/libsoccptp/include

.PHONY: clean

OBJ_DIR := .obj
SOURCES := authentication.cpp shoot_an_image_and_get_it.cpp check_LiveView_status_and_get_images.cpp parser_handling.cpp list_objects.cpp change_camera_setting.cpp
OBJECTS := $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.cpp=.o)))
TARGETS := $(addprefix ${OUT_DIR}/, $(notdir $(basename ${SOURCES})))

all: ${OUT_DIR} $(OBJ_DIR) ${TARGETS}

objs: $(OBJ_DIR) $(OBJECTS)

$(OBJ_DIR)/%.o : %.cpp
    $(CC) $(INCLUDES) -std=gnu++11 -pthread -g -o $@ -c $< -lusb-1.0 -lusb

$(OUT_DIR)/%: $(OBJ_DIR)/%.o
    ${CC} -std=gnu++11 -pthread -g -o $@ $< ${LIBS} -lusb-1.0 -lusb

${OUT_DIR}:
    mkdir -p ${OUT_DIR}

$(OBJ_DIR):
    mkdir -p $(OBJ_DIR)

clean:
    rm -rf ${TARGETS} $(OBJ_DIR)

Solution

  • After discussion with an engineer from the vendor that provided the software, it was determined that I was using a newer version of Ubuntu (v16) then they had developed the software on. When I compiled on the older version (v14), it compiled just fine.

    The engineer wasn't able to explain what changed in Ubuntu 16 that broke their code, but this solved the problem for me for now.