Jack Wilsdon
Jack Wilsdon

Reputation: 7045

CMake add_subdirectory with find_package?

I have the following structure of projects/source:

MyProject
|-MyProject
| |-src
| | |-project.c
| |
| |-CMakeLists.txt
|
|-MyLibrary
  |-include
  | |-hello.h
  |
  |-src
  | |-hello.c
  |
  |-CMakeLists.txt

MyProject/src/project.c includes MyLibrary/include/hello.h, which in turn includes libusb.h from the system (found using CMake).

And I am adding the libusb dependency in MyLibrary/CMakeLists.txt using the following code:

# Find libusb
find_package(LibUsb REQUIRED)

# Include libusb
include_directories(${LIBUSB_INCLUDE_DIR})

# Add dependencies
target_link_libraries(owi535 ${LIBUSB_LIBRARY})

However when compiling MyProject (which includes MyLibrary using add_subdirectory and target_link_libraries), I get an error stating libusb.h cannot be found.

I can compile MyLibrary on it's own, however compiling MyProject requires libusb.h to be in it's include path, which it is not.

Is there a way to make it so that by adding MyLibrary as a dependency, MyProject pulls libusb.h through it? This would mean that I don't need to repeat the find_package code for every project that includes MyLibrary.


The other issue I am having is similar; I am getting an error stating that there are Undefined symbols when calling libusb functions in MyLibrary when I compile MyProject, however when compiling MyLibrary on it's own, there are no errors.

Undefined symbols for architecture x86_64:
  "_libusb_close", referenced from:
      _my_close_method in libMyLibrary.a(hello.c.o)
  "_libusb_exit", referenced from:
      _my_exit_method in libMyLibrary.a(hello.c.o)
  "_libusb_init", referenced from:
      _my_init_method in libMyLibrary.a(hello.c.o)
  "_libusb_open_device_with_vid_pid", referenced from:
      _my_open_method in libMyLibrary.a(hello.c.o)
ld: symbol(s) not found for architecture x86_64

Upvotes: 3

Views: 3939

Answers (1)

John Drouhard
John Drouhard

Reputation: 1259

From the cmake documentation:

PUBLIC and INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES property of <target>.

Targets may populate this property [INTERFACE_INCLUDE_DIRECTORIES] to publish the include directories required to compile against the headers for the target. Consuming targets can add entries to their own INCLUDE_DIRECTORIES property such as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the include directories specified in the interface of foo.

So, you need to use this in MyLibrary/CMakeLists.txt:

target_include_directories(MyLibrary PUBLIC ${LIBUSB_INCLUDE_DIR})

Upvotes: 1

Related Questions