5

I started playing around with CMake to create a project with Qt and test it with Google Test. At the moment, I succesfully found a way to compile and link all the required libraries. However, I couldn't find a way to link sources to test files with following project structure:

root
|
+-- CMakeLists.txt
+-- src
| |
| +-- CMakeLists.txt
| +-- MyClass.h
| +-- MyClass.cpp
|
+-- test
| |
| +-- CMakeLists.txt
| +-- MyClassTest.cpp
|
+-- lib
  |
  +-- gtest-1.6.0
    |
    +-- CMakeLists.txt

Root CMakeLists.txt contains add_subdirectory for gtest, src and test folders. I have succesfully compiled and run "Hello world" app and simple EXPECT_TRUE(true) test in order to check that each part compiles correctly. Unfortunately, I couldn't find a way to include my source file to tests. Is it possible with the following project structure?

PS I know that it is possible to compile my sources as a library and link it to tests, but I dislike that approach, since it is more appropriate for integration testing, rather then unit testing...

EDIT: Added class names to the tree

ashagi
  • 394
  • 6
  • 15
  • to your PS : it is also appropriate for unit testing. The only difference is the location of the compiled code. But that is your personal preference – BЈовић Dec 10 '12 at 08:38

2 Answers2

2

In the root CMakeLists.txt you can add a include_directories(src) This will then also be used by the tests. Another thing you can do is in the test CMakeLists.txt add a include_directories(${<projectName>_SOURCE_DIR}) where projectName is the name specified using project(myproj) in the src/ CMakeLists.txt (if you specified a project in there of course. Also check the docs about project)

gvd
  • 1,823
  • 13
  • 18
  • include_directories() includes the headers but doesn't link the objects. – ashagi Dec 10 '12 at 08:57
  • 1
    Use ```target_link_libraries(lib_name)``` – gvd Dec 10 '12 at 09:13
  • Ah I see you don't want to link to the library. Personally I would go for that solution and extract any helper methods from the .cpp into a new header file. – gvd Dec 10 '12 at 18:55
  • If I link it as a library, dependencies of a class under a test would be linked together (as a library). And that is what I want to avoid. Tests would help me to see the dependencies and point to the places where I should reduce coupling by introducing interfaces. – ashagi Dec 12 '12 at 04:12
2

You can add a global variable at the level of your root CMakeLists.txt:

set(ALL_SRCS CACHE INTERNAL "mydescription" FORCE)

In the first add_subdirectory(src), you can do:

set(ALL_SRCS ${ALL_SRCS} blabla.cpp CACHE INTERNAL "description")

And in the add_subdirectory(test), you continue with:

set(ALL_SRCS ${ALL_SRCS} bla_test.cpp CACHE INTERNAL "description")

You can then do, add_executable, or library or whatever, with all your sources files.

EDIT: add trick for global variables in CMake.

Kirell
  • 9,228
  • 4
  • 46
  • 61
  • I thought about that. But for some reason, when I leave the scope of subproject, ALL_SRCS returns to its previous value. I tried to log it using message("SRCS: " ${ALL_SRCS}) at the end of each subdir and after add_subdirectory(). – ashagi Dec 10 '12 at 09:39
  • I think this should work better, now, I edited the post for global variables. But I think the recommended way of testing is still by creating a lib of your sources, linked to your test cases. – Kirell Dec 10 '12 at 09:46
  • Thank you! It worked! One more thing: I had to put ${PROJECT_SOURCE_DIR}/src/className.cpp in front of every file. Is it possible to somehow make it work without this prefix? One way around is looping and prepending prefix to it, but it looks hacky. – ashagi Dec 10 '12 at 09:57
  • Looping to add prefix is not so hacky ^^. I can't think of another way. – Kirell Dec 10 '12 at 10:01
  • OK, I will do it that way. Thank you! – ashagi Dec 10 '12 at 10:06