0
$\begingroup$

Rosanswers logo

I am working on implementing a client library from swift, utilizing CMake's swift support, and I'm running into issues with interface files. Unlike C/C++, swift interfaces are not declared in source code. From the swift files, the compiler generates both the .so file and a swiftmodule file, which defines the external interface for other targets to include. Working off of the swift cmake examples, I accomplished this as so:

cmake_minimum_required(VERSION 3.15.1)

project(rclswift_common Swift)

find_package(ament_cmake REQUIRED)

add_library(RclSwiftCommon
  "swift/Interfaces.swift"
)

set_target_properties(RclSwiftCommon PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR})

install(
  TARGETS RclSwiftCommon
  EXPORT RclSwiftCommon
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
  RUNTIME DESTINATION bin
)

ament_export_targets(RclSwiftCommon HAS_LIBRARY_TARGET)

ament_package()

The set_target_properties makes sure that the generated swift modules are included with the target. However, when I use ament_export_targets, I get the following error from ament_export_targets:

CMake Error in CMakeLists.txt:
  Target "RclSwiftCommon" INTERFACE_INCLUDE_DIRECTORIES property contains
  path:

    "/home/alex/ros2/build/rclswift_common"

  which is prefixed in the build directory.


CMake Generate step failed.  Build files cannot be regenerated correctly.

Why won't ament let me include from the build directory, and is there any workaround I can implement to achieve a working setup?


Originally posted by atyshka on ROS Answers with karma: 43 on 2020-07-23

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

Just to clarify in the beginning that I have no idea about Swift - so all of the following is just me extrapolating from how CMake works for C / C++.

The exported target will use the property INTERFACE_INCLUDE_DIRECTORIES when downstream packages try to find headers (in C / C++). Since the build directory can potentially be deleted after package rclswift_common has been built and installed the property shouldn't point to a build directory.

For C++ projects you commonly need some include directories to build a packages and other include directories for downstream packages to use the installed headers, e.g. https://github.com/ros2/rcl/blob/2a4d2f40fe8c5d6d0f33655d4c4f077ce8793825/rcl/CMakeLists.txt#L68-L70 (you will find the same pattern in almost all ROS core packages in Foxy and newer):

target_include_directories(
  your_library_target PUBLIC
  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
  "$<INSTALL_INTERFACE:include>")

The $<BUILD_INTERFACE:... could also or additionally point to something under CMAKE_CURRENT_BINARY_DIR.

If you need to declare include directories for downstream packages you also need to install some files which you expect to be used by downstream packages.

For C++ that would be the header files. Maybe for Swift you have to install swift/Interfaces.swift? Assuming you would install that file to include you need to declare the INSTALL_INTERFACE on the target like this:

target_include_directories(
  RclSwiftCommon PUBLIC
  "$<INSTALL_INTERFACE:include>")

Originally posted by Dirk Thomas with karma: 16276 on 2020-07-24

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by atyshka on 2020-07-24:
Thank you Dirk! I was able to successfully implement something working based off that:

set_target_properties(RclSwiftCommon PROPERTIES Swift_MODULE_DIRECTORY modules)

target_include_directories(RclSwiftCommon PUBLIC  
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/modules>  
$<INSTALL_INTERFACE:modules> )
install(
  DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules/
  DESTINATION modules
)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.