cmake undefined reference to function

13,951

The directory subdir1 doesn't generate a binary. Add this:

project(Example)
add_library(Example Example.cpp)

instead of your add_sources. After this, you need to tell the project that uses it to link against it:

TARGET_LINK_LIBRARIES(subdir2 Example)

If your names differ, document yourself on the functionalities of these commands.

Share:
13,951
E-rich
Author by

E-rich

Software engineer at Magnetek, Inc.

Updated on July 08, 2022

Comments

  • E-rich
    E-rich almost 2 years

    The project structure below is a simplified example. I tried to boil it down to the minimal amount of files to reproduce my issue.

    .
    ├── CMakeLists.txt
    ├── subdir1
    │   ├── CMakeLists.txt
    │   └── subsubdir1
    │       ├── CMakeLists.txt
    │       ├── Example.cpp
    │       └── Example.h
    └── subdir2
        ├── CMakeLists.txt
        ├── main.cpp
        └── subsubdir1
            ├── CMakeLists.txt
            ├── ExampleCreator.cpp
            └── ExampleCreator.h
    

    ./CMakeLists.txt

    cmake_minimum_required(VERSION 2.8)
    project(test)
    
    macro(add_sources)
        file (RELATIVE_PATH _relPath "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
        foreach (_src ${ARGN})
            if (_relPath)
                list (APPEND SRCS "${_relPath}/${_src}")
            else()
                list (APPEND SRCS "${_src}")
            endif()
        endforeach()
        if (_relPath)
            # propagate SRCS to parent directory
            set (SRCS ${SRCS} PARENT_SCOPE)
        endif()
    endmacro()
    
    add_subdirectory(subdir1)
    add_subdirectory(subdir2)
    
    add_executable(test ${SRCS})
    

    subdir1/CMakeLists.txt

    add_subdirectory(subsubdir1)
    

    subdir1/subsubdir1/CMakeLists.txt

    add_sources(Example.cpp)
    

    subdir1/subsubdir1/Example.h

    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    
    class Example
    {
    public:
        Example();
        virtual ~Example();
    };
    
    #endif
    

    subdir1/subsubdir1/Example.cpp

    #include <stdio.h>
    #include "Example.h"
    
    Example::Example()
    {
        printf("Inside Example constructor\n");
    }
    
    Example::~Example()
    {
    }
    

    subdir2/CMakeLists.txt

    add_subdirectory(subsubdir1)
    add_sources(main.cpp)
    

    subdir2/main.cpp

    #include "subsubdir1/ExampleCreator.h"
    
    int main(int argc, char** argv)
    {
        ExampleCreator creator;
        return 0;
    }
    

    subdir2/subsubdir1/CMakeLists.txt

    add_sources(ExampleCreator.cpp)
    

    subdir2/subsubdir1/ExampleCreator.h

    #ifndef EXAMPLE_CREATOR_H
    #define EXAMPLE_CREATOR_H
    
    class ExampleCreator
    {
    public:
        ExampleCreator();
        virtual ~ExampleCreator();
    };
    
    #endif
    

    subdir2/subsubdir1/ExampleCreator.cpp

    #include "ExampleCreator.h"
    #include "../../subdir1/subsubdir1/Example.h"
    
    ExampleCreator::ExampleCreator()
    {
        Example* ex1 = new Example();
    }
    
    ExampleCreator::~ExampleCreator()
    {
    }
    

    I'm hoping this is a really simple lack of understanding of how CMake handles dependencies. This compiles without error, but fails during linking. The make output below shows that Example.cpp isn't even compiling and I don't understand why.

    user>:~/src/test/build$ make
    Scanning dependencies of target test
    [ 50%] Building CXX object CMakeFiles/test.dir/subdir2/subsubdir1/ExampleCreator.cpp.o
    [100%] Building CXX object CMakeFiles/test.dir/subdir2/main.cpp.o
    Linking CXX executable test
    CMakeFiles/test.dir/subdir2/subsubdir1/ExampleCreator.cpp.o: In function `ExampleCreator::ExampleCreator()':
    ExampleCreator.cpp:(.text+0x2b): undefined reference to `Example::Example()'
    collect2: ld returned 1 exit status
    make[2]: *** [test] Error 1
    make[1]: *** [CMakeFiles/test.dir/all] Error 2
    make: *** [all] Error 2
    

    All the sources are appended to the SRCS variable in the root CMakeLists.txt file from what I can tell. So, why isn't Example.cpp getting compiled? or linked?

  • E-rich
    E-rich over 11 years
    This worked, but I don't understand why I need to make a library and link against as opposed to just adding the source directly to the executable. I didn't need the project(Example) btw.
  • Luchian Grigore
    Luchian Grigore over 11 years
    @E-rich you didn't add the sources in the project that actually needed the symbols.