R. Smyth
R. Smyth

Reputation: 185

C++ linker finds header but cannot find .cpp file (using cmake, gcc)

I am trying to include a project within a project. The relevant structure is as such:

projectA
       /CMakeLists.txt (PA1)
       /src
           /main.cpp
       /req/projectB
                   /CMakeLists.txt (PB1)
                   /src
                       /projb.hpp
                       /projb.cpp
                       /CMakeLists.txt (PB2)

After compiling, linking SUCCEEDS if I comment out everything in projb.cpp, (and define it in the header) but FAILS with undefined reference (to any function defined in projb.cpp).

-(PA1)-

add_subdirectory("req/projectB")

include_directories(${PROJECT_NAME} "req/projectB/src")

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} INTERFACE projectB)

-(PB1)-

add_subdirectory(src)

-(PB2)-

add_library(projectB projb.hpp projb.cpp)

main.cpp

int main() {
    project_b::doStuff();
    return 1;
}

projb.hpp

namespace project_b {

    void doStuff(); // fails
    
    void doStuff() {} // works if nothing defined in .cpp
    // (only one or the other version is declared not both)

} // end namespace

projb.cpp

namespace project_b {
    
    void doStuff() {} // fails with undefined reference error when called from main

} // end namespace

Upvotes: 0

Views: 1288

Answers (2)

R. Smyth
R. Smyth

Reputation: 185

Turns out that another part of projectA which I thought was irrelevant was actually very relevant.

Thus I just needed to add this line:

# projAadep is included by main.cpp from projectA
target_link_libraries(projAdep PRIVATE projectB)

before this line:

target_link_libraries(${PROJECT_NAME} PUBLIC projectB)

My understanding was that by using:

target_link_libraries(${PROJECT_NAME} list of all used libs here)

was all that is necessary.

How discovered this was when I was commenting out various things in order to get the output of make VERBOSE=1 to just include the most relevent parts, it compiled and linked successfully. This then led me to do more testing to figure out why it linked successfully, and so on.

Upvotes: 1

zkoza
zkoza

Reputation: 2861

Libraries following INTERFACE are appended to the link interface and are not used for linking .

see: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

So, I suggest changing INTERFACE to PUBLIC or PRIVATE

Upvotes: 0

Related Questions