Search code examples
unit-testingcmakecompilationheaderinclude

Specify individual header files for CMake instead of full directory


I have searched the internet and cannot find a way to add individual include files for my build. Is this not possible? I have very little experience with Make, so I don't know if this limitation comes from Make.

The reason I want this is because I am trying to unittest a legacy codebase without changing the code itself. Hence, I am trying to inject the mocks by compilation. To achieve this, I need my project to mix/match between the 'real' and the 'mock' header files.

As a temporary fix I have put the header files in separate folders, and this proof of concept seems to work. However, this solution seems rather ugly?

P.S. I'm using gtest/gmock, and I don't want to use the templating style dependency injection they suggest.


Solution

  • This is not a limitation of cmake or make, all C++ compilers look up headers from a sorted list of folders, taking the first header file that is found.

    You can change that list with the include folder parameters and they will be searched in the order they are added. This can be very difficult to achieve because the lookup order is different depending on whether your legacy headers use #include "file.h" or #include <file.h>. Read more about that in the manual of your compiler or here.

    If your legacy header use #include <>

    The easiest would probably be to create a custom include folder into your build folder for every configuration and make sure that this folder has priority. Then only copy the mock header into this folder.

    file(COPY test/mymock1.h DESTINATION mock/)
    target_include_directories(
      mytest BEFORE
      PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/mock
    )
    

    If your legacy header use #include ""

    You are screwed because the compiler searches first in the physical folder the other header is in. You have to make sure your mock header replaces the non-mock header in the directory, probably just like you are already doing.