Marcus Höij
Marcus Höij

Reputation: 31

CMake cannot find source files in a different directory

I'm trying to include files from one directory (/source) into test cases in another (/test) but cmake is unable to find any of the files in /source.

The structure of my project:

PrettyDD/
    + CMakeLists.txt
    + external/
        + CMakeLists.txt
        + gmock-1.7.0/
    + source/
        + CMakeLists.txt
        + parser.cpp
        + parser.h
        + main.cpp
        + ...
    + test/
        + CMakeLists.txt
        + test1.cpp

The error message:

marcus@lean-machine:~/Programming/PrettyDD/build$ cmake ../ -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles"
-- Could NOT find Threads (missing:  Threads_FOUND) 
-- Could NOT find Threads (missing:  Threads_FOUND) 
-- Configuring done
CMake Error at test/CMakeLists.txt:12 (add_executable):
  Cannot find source file:

    parser.cpp

  Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
  .hxx .in .txx

/test/CMakeLists.txt:

set(GMOCK_DIR "${CMAKE_SOURCE_DIR}/external/gmock-1.7.0"
    CACHE PATH "The path to the GoogleMock test framework.")

set_property(TARGET gtest APPEND_STRING PROPERTY COMPILE_FLAGS " -w")

include_directories(SYSTEM ${GMOCK_DIR}/gtest/include
                           ${GMOCK_DIR}/include)
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/source")


function(add_gmock_test target)
    add_executable(${target} ${ARGN})
    target_link_libraries(${target} gmock_main)

    add_test(${target} ${target})

    add_custom_command(TARGET ${target}
               POST_BUILD
               COMMAND ${target}
               WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
               COMMENT "Running ${target}" VERBATIM)
endfunction()

add_gmock_test(tests test1.cpp parser.cpp)

I have verified that ${PROJECT_SOURCE_DIR}/source points to the right directory by use of CMake's message().

If I explicitly specify the path to parser.cpp (../source/parser.cpp) in add_gmock_test() then it's able to find the file.

I can also successfully run the test if I first build a library out of parser.cpp (and it's dependencies) in /source/CMakeLists.txt and add it where I link gmock_main.

Why can't CMake find parse.cpp or any other file in /source? What am I doing wrong?

Edited in after DarthB's answer:

Leaving parser.cpp out of add_gmock_test(tests test1.cpp) gives me the following error:

marcus@lean-machine:~/Programming/PrettyDD/build$ make
[ 55%] Built target PrettyDD
[ 66%] Built target gmock
[ 83%] Built target gmock_main
[ 88%] Built target gtest
[ 94%] Built target gtest_main
Linking CXX executable tests
CMakeFiles/tests.dir/test1.cpp.o: In function `Parser_Construct_Test::TestBody()':
/home/marcus/Programming/PrettyDD/test/test1.cpp:7: undefined reference to `Parser::Parser()'
collect2: error: ld returned 1 exit status
test/CMakeFiles/tests.dir/build.make:86: recipe for target 'test/tests' failed
make[2]: *** [test/tests] Error 1
CMakeFiles/Makefile2:316: recipe for target 'test/CMakeFiles/tests.dir/all' failed
make[1]: *** [test/CMakeFiles/tests.dir/all] Error 2
Makefile:86: recipe for target 'all' failed
make: *** [all] Error 2

This is what test1.cpp looks like:

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "parser.h"

TEST(Parser, Construct) {
  Parser parser;
}

parser.cpp:s constructor:

Parser::Parser() {
    createFunctionMap();
}

declared in parser.h as:

class Parser {
public:
    Parser();
    ...

There should be nothing wrong with the constructor as the program itself runs fine. So why am I getting this error?

Upvotes: 3

Views: 10205

Answers (1)

DarthB
DarthB

Reputation: 381

include_directories() only changes the compiler parameters for include directories, that means you can include "parser.h" somewhere in your test code using

#include "parser.h" 

and .../PrettyDD/source is searched for this file.

I do not think parser.cpp contains test code. So it should not be part of your test project:

add_gmock_test(tests test1.cpp)

Should be enough. Otherwise you should rethink your project structure.

Alternatively you can also use:

add_gmock_test(tests test1.cpp ../source/parser.cpp)

EDIT:

Regarding the question in the comments. Nearly every cmake commands' parameter is either relative to ${CMAKE_CURRENT_SOURCE_DIR} or ${CMAKE_CURRENT_BINARY_DIR}. As far as I know there is no "include_directories" for cmake commands but when listing source files we can also use the taget_sources() command.

That means if a CMakeLists.txt is the same folder as the source files it should work to write:

target_sources(tests parser.cpp)

inside the CMakeLists.txt file of the 'source' folder.

Maybe there are problems because the target is not know yet. I only used target_sources() in sub folders of the project containing the source. Whereby I use a structure similar to:

  • libs
    • myLib
      • src
      • inc

whereby the src and inc folder also contain a CMakeLists.txt file that explicit lists the source files using target_sources() command.

Upvotes: 2

Related Questions