首页 > 解决方案 > CMake linking error (undefined reference to function)

问题描述

I'm working on C/C++ cross platform application. I'm using CMake for build process.

The project structure below is simplified, narrowing to the issue.

├── CMakeLists.txt 
├── Common_libs
│   ├── CMakeLists.txt
│   └── File_Process_... (.cc/.h, 4 each)
└── MAIN
    ├── CMakeLists.txt
    └── (Other subdirs and sources/headers)

./CMakeLists.txt:(Common_libs)

# CMakeLists.txt : CMake project, include source and define
# project specific logic here.
#

set(PKG_NAME File_Process)

add_library(${PKG_NAME} STATIC
    include/File_Process_Interface.h
    include/File_Process_Types.h
    include/FP_Directory.h
    include/FP_File.h
    include/FP_FileLP.h
    include/FP_Includes.h
    include/Filestruct.h
    ../../MAIN/error.h
    source/File_Process_Factory.cpp
    source/FP_Directory.cpp
    source/FP_File.cpp
    source/FP_FileLP.cpp)

target_include_directories(${PKG_NAME} PUBLIC include)
target_include_directories(${PKG_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/Common/Resources/3RD_PARTYLibrary/include)
    
if (WIN32)
    target_include_directories(${PKG_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/Common/Resources/Windows/Includes)
    install(TARGETS ${PKG_NAME} ARCHIVE DESTINATION ${CMAKE_SOURCE_DIR}/Common_libs/dist/${CMAKE_BUILD_TYPE}/Win/)
else()
    SET(CMAKE_CXX_FLAGS "-std=c++11")
    install(TARGETS ${PKG_NAME} ARCHIVE DESTINATION ${CMAKE_SOURCE_DIR}/Common_libs/dist/${CMAKE_BUILD_TYPE}/Linux/)
endif(WIN32)

target_include_directories(${PKG_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

File_Process_Interface.h

namespace AppExecutable{
    namespace Common {
        class File_Process_Factory {
        public:

            enum File_ProcessObjectType {
                FP_File, FP_Directory, FP_FileLP, Automatic_Detection
            };

        
            static IFile_Process* Create(File_ProcessObjectType type = FP_File, std::string source = "");
        };

    }
}

File_Process_Factory.cpp

namespace AppExecutable{
    namespace Common {

        IFile_Process* File_Process_Factory::Create(File_ProcessObjectType type, std::string source) {
            switch (type) {
            case File_Process_Factory::Automatic_Detection:
                struct stat st;

                if (stat(source.c_str(), &st) == -1) {
                    return NULL;
                }
                else {
                    if (S_ISDIR(st.st_mode)) {
                        return (IFile_Process*) (new Common::FP_Directory());
                    }
                    else {
                        if (source.rfind(".xyz") == (source.length() - 4)) {
                            return (IFile_Process*) (new Common::FP_FileLP());
                        }
                        else {
                            return (IFile_Process*) (new Common::FP_File());
                        }
                    }
                }
                //return (IFile_Process*)new Common::Automatic_Detection();
                break;
            case File_Process_Factory::FP_File:
                return (IFile_Process*) (new Common::FP_File());
                break;
            case File_Process_Factory::FP_Directory:
                return (IFile_Process*) (new Common::FP_Directory());
                break;
            case File_Process_Factory::FP_FileList:
                return (IFile_Process*) (new  Common::FP_FileLP());
                break;
            default:
                throw ("Unknown File_ProcessObjectType");
            }
        }

./CMakeLists.txt:(MAIN)

cmake_minimum_required (VERSION 3.8)
project(AppExecutable C CXX)
cmake_policy(SET CMP0015 NEW)

    if (WIN32)
        include_directories(MAIN
                            MAIN/shared)
        link_directories(../Common_libs/dist/${CMAKE_BUILD_TYPE}/Win/)
    else()
        include_directories(MAIN
                            MAIN/shared)
endif(WIN32)

file(GLOB SOURCES
    *.cpp
    shared/*.cpp
    shared/*.c)
# Add source to this project's executable.
if (WIN32)
    add_executable (AppExecutable ${SOURCES})
    install(TARGETS AppExecutable DESTINATION  ${CMAKE_SOURCE_DIR}/Application/Windows/)
    target_link_libraries(AppExecutable File_Process)
else()
    add_executable (AppExecutable ${SOURCES})
    install(TARGETS AppExecutable DESTINATION  ${CMAKE_SOURCE_DIR}/Application/Linux/)
    target_link_libraries(AppExecutable File_Process)
endif(WIN32)

SET_TARGET_PROPERTIES(AppExecutable PROPERTIES  DEBUG_POSTFIX "_debug")

Finally, when I do make, the following error is generated:

[ 33%] Built target Common_libs
[ 38%] Linking CXX executable AppExecutable 
CMakeFiles/AppExecutable.dir/MAIN/FileEntry.cpp.o: In function `AppExecutable::Common::FileEntry::FileSimulation(int, char**)':
FileEntry.cpp:(.text+0xaa9): undefined reference to `AppExecutable::Common::File_Process_Factory::Create(AppExecutable::Common::File_Process_Factory::File_ProcessObjectType, std::string)'
collect2: error: ld returned 1 exit status
make[2]: *** [AppExecutable/AppExecutable] Error 1
make[1]: *** [AppExecutable/CMakeFiles/AppExecutable.dir/all] Error 2
make: *** [all] Error 2

link.txt

/opt/gcc54/bin/g++  -std=c++11 -O3 -DNDEBUG  -static-libgcc -static-libstdc++ CMakeFiles/AppExecutable.dir/Output_App.cpp.o CMakeFiles/AppExecutable.dir/FileEntry.cpp.o CMakeFiles/AppExecutable.dir/AppExecutable.cpp.o CMakeFiles/AppExecutable.dir/ABCBaseClass.cpp.o CMakeFiles/AppExecutable.dir/ABCControl.cpp.o CMakeFiles/AppExecutable.dir/shared/CsvReader.c.o CMakeFiles/AppExecutable.dir/shared/OutputInterface.cpp.o CMakeFiles/AppExecutable.dir/shared/DataBlock.cpp.o CMakeFiles/AppExecutable.dir/shared/lElement.cpp.o CMakeFiles/AppExecutable.dir/shared/lParser.cpp.o CMakeFiles/AppExecutable.dir/shared/lParserCApi.cpp.o CMakeFiles/AppExecutable.dir/shared/ssupport.cpp.o CMakeFiles/AppExecutable.dir/shared/lVersionParser.c.o  -o AppExecutable  ../Common_libs/libFile_Process.a

I'm able to generate executable in Windows, I'm having issue on linux. I've been trying to fix this for some time. Why it is showing errors if it has already been built before the linkage?

标签: c++cmakelinkerg++

解决方案


推荐阅读