2

For my research project I am setting up a project (coom) to benchmark a set of algorithms on a data structure. For unit testing I settled on Bandit, which leaves me with a project structure that looks as follows:

+ root
|-- CMakeLists.txt
|-+ external/
| \-- bandit/
|-+ src/
| |-- CMakeLists.txt
| |-- node.cpp
| \-- node.h 
\-+ test/
  |-- CMakeLists.txt
  |-- test.cpp
  \-- test_node.cpp

From my experience with other languages, this seems to me a standard project structure? The test/ folder contains unit tests for the logic in src/ and no dependencies are intermixed with the source and test code, but are instead in external/.

The testing files I want to look as follows (with irrelevant parts removed)

// test/test.cpp
#include <bandit/bandit.h>
(...)

#include "test_node.cpp"

int main(int argc, char* argv[]) {
  (...)
}
// test/test_node.cpp
#include <coom/node.h>
(...)

But my problem is, that when I try to compile with cmake .. and the subsequent Makefile, they are unable to find the source code in src/ where I get the compiler error:

fatal error: coom/node.h: No such file or directory. 

I would expect the test/CMakeLists.txt should look somewhat like the following:

# test/CMakeLists.txt
add_executable (test_unit test.cpp)
target_link_libraries(test_unit coom)

I cannot figure out how to setup the CMakeLists.txt and src/CMakeLists.txt to ensure I get the desired outcome above. Currently they look as follows:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project (coom VERSION 0.1)

# ============================================================================ #
# Dependencies
(...)

# ============================================================================ #
# COOM project
add_subdirectory (src)
add_subdirectory (test)
# src/CMakeLists.txt
# ============================================================================ #
# Link up files for the library
set(HEADERS
  node.h
)

set(SOURCES
  node.cpp
)

add_library(coom ${HEADERS} ${SOURCES})

I can see from other projects, that it is possible to link the src/ directory with some libname/ prefix, but I cannot discern from their CMakeLists.txt files what I am doing wrong. I have looked at writing a coom.pc.in file and providing an install-target, and tried to set_target_properties with either FOLDER coom or PREFIX coom, but neither worked. I can hack an include_directory(../src) into the test/CMakeLists.txt to be able to include the file via an #include <node.cpp>, but that screams I'm doing something inherently wrong.

I'm at this point very much pulling my hairs out, and the CMake documentation is of very little help to me.

1 Answers1

1

Your coom target has no include directories defined. You can define the include directories to use for this target (with target_include_directories()), and propagate these include directories so they are visible to the consuming test_unit target (by using PUBLIC):

# src/CMakeLists.txt
# ============================================================================ #
# Link up files for the library
set(HEADERS
  node.h
)

set(SOURCES
  node.cpp
)

add_library(coom ${HEADERS} ${SOURCES})

target_include_directories(coom PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Furthermore, the file path to the node.h header is coom/src/node.h, not coom/node.h. But, because you now have coom/src as an public include directory, you can use the following to include the node.h header in your test file:

#include <node.h>
Kevin
  • 16,549
  • 8
  • 60
  • 74
  • With regards to the `coom/src/node.h` and `coom/node.h` I see I made my question unclear by using the same name twice. The latter was the intention with the current file structure. Maybe that is just not possible? The `target_include_directories` works (and is prettier than all I've tried at this point), but is it best practice? Maybe I did something wrong in with the folder structure? – Steffan Sølvsten Apr 13 '20 at 12:58
  • 1
    No, I don't think CMake or the compilers support this "aliasing" a prefix (for lack of a better term), unless you do something hacky with sym-linking the directory. `coom/node.h` simply isn't a valid path to the header file, so the compiler will not know how to find it. There have been similar questions asked here already about this, such as [this](https://stackoverflow.com/q/38879819/3987854). You could instead use the top-level CMake directory in `target_include_directories()`, then include the header using `src/node.h`. Perhaps, you could rename the `src` directory to `coom`? – Kevin Apr 13 '20 at 13:12
  • @SteffanSølvsten All that said, the use of `target_include_directories()` is standard CMake practice for adding include directories to the compilation of a specific target. I added a link to the documentation in my response. – Kevin Apr 13 '20 at 13:19
  • 2
    It explains why the TPIE dependency have their src/ folder named tpie/. Thanks for the reference to the other question; irritating that my searches about "prefix" didn't bring it up. Thanks for the thorough answer. – Steffan Sølvsten Apr 13 '20 at 13:28