41

In our workflow, we can have a module A that is composed of several header files, module A not producing any binary (side note: it will obviously be used by other modules, that include some of the headers from module A to produce binaries).

A good example would be a header-only library, for which CMake 3 introduces a good support thanks to the notion of INTERFACE library (see this SO answer, and CMake's documentation of the feature).

We can make an interface library target out of module A:

add_library(module_A INTERFACE)

That gives us all the nice features of CMakes targets (it is possible to use it as another target's dependency, to export it, to transitively forward requirements etc.)

But in this case, the headers in module A do not show up in our IDE (Xcode, yet we expect it to be the same with most/every other IDE).

This proves to be a major drawback in the workflow, since we need the files composing module A to be shown in the IDE for edition. Is it possible to achieve that ?

Community
  • 1
  • 1
Ad N
  • 7,930
  • 6
  • 36
  • 80
  • Ah deleted my comment. Good question. – IdeaHat Nov 20 '14 at 14:16
  • @IdeaHat Thank you for your interest in the question, and your suggestion. Sadly, the `INTERFACE` form of `add_library` command does not expect any *file* argument (see [the last form in the documentation](http://www.cmake.org/cmake/help/v3.0/command/add_library.html?highlight=add_library)). In fact, we do not necessarily need an `INTERFACE`, but this is the only **mutable** non-binary target we are aware of. [For the context, IdeaHat was wondering if we could provide the header files to the `add_library` command in its `INTERFACE` form] – Ad N Nov 20 '14 at 14:18
  • A hack way would to make a dummy custom target (never built, or no build steps) with these files as source...for my personal education, do you have a link to CMake's definition of mutable? – IdeaHat Nov 20 '14 at 14:23
  • @IdeaHat I will look to that approach, agreeing it would be the hackish way ; ) Regarding the notion of target mutability, I did not find a definition in the documentation, but by inference from [the Pseudo Targets documentation](http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#id20), my guess would be that: a mutable target can have (at least *some of*) its properties written to. [some of is referring to the notion of "white listed" properties, eg. limiting which properties can be written to on an `INTERFACE`]. – Ad N Nov 20 '14 at 14:28
  • Yeah...I'm actually not sure what the interface library gives you over the add target, other than being more semantically correct. My experience with CMake thus far has been it will always work, but your build scripts often end up a little hackaliscous if you want it to work well :-( – IdeaHat Nov 20 '14 at 14:44
  • 2
    Its captured under feature request http://www.cmake.org/Bug/view.php?id=15234 – IdeaHat Nov 20 '14 at 14:46
  • Could you configure the target somehow with the add_custom_target command? I'm not sure that I understand all the details in your implementation, but this a useful way, IMHO, to expand the CMake capabilities. You can always combine this CMake command with the command line CMake executable to copy, move or delete source files around. – KlingonJoe Mar 23 '15 at 15:15
  • FWIW here is the link to the feature request in their new tracker https://gitlab.kitware.com/cmake/cmake/issues/15234 – mat007 Apr 03 '17 at 11:27

2 Answers2

25

Several months down the line, I did not find a way to directly list the header files for an INTERFACE library.

Since the question still has some views, here is what I ended up doing (i.e. what appears like the lesser hack currently available).

Imagine module A is a header only library. In the CMakeLists.txt declaring its target:

# Define 'modA_headers' variable to list all the header files
set(modA_headers 
  utility.h
  moreUtilities.h
  ...)

add_library(moduleA INTERFACE) # 'moduleA' is an INTERFACE pseudo target

#
# From here, the target 'moduleA' can be customised
#
target_include_directories(moduleA ...) # Transitively forwarded
install(TARGETS moduleA ...)

#
#  HACK: have the files showing in the IDE, under the name 'moduleA_ide'
#
add_custom_target(moduleA_ide SOURCES ${modA_headers})

I do not accept this answer, since I expect further releases of CMake to offer a more semantically correct approach, which will then be accepted : )

Ad N
  • 7,930
  • 6
  • 36
  • 80
  • Was looking for a way to do that for quite a while now and your solution finally got me through. Thanks! – nh_ Apr 15 '16 at 20:28
16

You can use the new target_sources command in CMake 3.1.

add_library(moduleA INTERFACE)
target_include_directories(moduleA INTERFACE ...)
target_sources(moduleA INTERFACE 
  ${CMAKE_CURRENT_SOURCE_DIR}/utility.h
  ${CMAKE_CURRENT_SOURCE_DIR}/moreUtilities.h
)

It is also transitive.

http://www.cmake.org/cmake/help/v3.1/command/target_sources.html#command:target_sources

The limitation of not being able to export targets which have INTERFACE_SOURCES has been lifted for CMake 3.3.

steveire
  • 10,694
  • 1
  • 37
  • 48
  • 9
    This works in the sense that the headers will be added to other existing projects that link to your library, but doesn't work if you don't have any projects that link with your library. So if you have a test project with an executable that links to your INTERFACE library, then such project will contain the library headers along with it's sources. – Francisco Aguilera May 10 '15 at 02:00
  • 4
    This is a very good point raised by @FranciscoAguilera. steveire, is there still no good solution for that to date? – Ela782 Dec 09 '16 at 01:43
  • 1
    I know it's been a while but I am not sure I understand your comment completely @FranciscoAguilera. First sentence "This works in the sense that the headers will be added to other existing projects that link to your library" I understand this is the positive case where it will work as expected. Second sentence "doesn't work if you don't have any projects that link with your library"? This part I don't understand. A header only library doesn't make much sense to compile standalone IMO. Then the last sentence about the test project: does this refer to the first sentence or the second? – Satrapes Dec 10 '19 at 23:01
  • @Satrapes, I believe, he has meant that headers of the library won't be shown under the library target itself, but will be shown under the target linked to the library instead. In real world applications where multiple targets (executables, tests, other libraries, etc...) link against the same library, it means, there will be multiple copies of the same (library) headers in different places — under each target – oficsu May 26 '23 at 01:31