CMAKE undefined references when building a console application that uses custom libraries
-
wrote on 5 May 2020, 22:23 last edited by
I am trying to work out CMAKE with my Qt solution. I have a set of libraries that I utilize as a platform to build other applications. Then I have an applications link to those libraries to utilize there functionality. For some reason all of sudden I am getting undefinded references when adding members to class within one of the libraries. Below I show the structure of my libraries and application plus the cmake files plust the output from cmake. any help would be great!
QT Version 5.12.8-
Library Project
- CMakeLists.txt
- Lib 1
- CMakeLists.txt
- src
- Lib 2
- CMakeList.txt
- src
- Lib 3
- CMakeList.txt
- src
-
Application
- CMakeLists.txt
- src
The Library Projects Highest Level CMakeLists.txt File
cmake_minimum_required(VERSION 3.5.0) set(FRAMEWORK_BUILD_VERSION 0.1.0 CACHE STRING "Version of the Framework") set(COMMON_BUILD_VERSION 0.1.0 CACHE STRING "Version of the Common Library") set(INJECTORCLIENT_BUILD_VERSION 0.1.0 CACHE STRING "Version of the Common Library") set(SYSTEMSERVICE_BUILD_VERSION 0.1.0 CACHE STRING "Version of the Common Library") set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) project(RADIANT-SCP-Framework VERSION ${FRAMEWORK_BUILD_VERSION}) add_subdirectory(Common) add_subdirectory(InjectorClient) add_subdirectory(SystemService)
Lib1 CMakeList.txt
project(RADIANT-SCP-Common VERSION ${COMMON_BUILD_VERSION}) find_package(Qt5 COMPONENTS Core REQUIRED) add_library(RADIANT-SCP-Common SHARED src/helloworld.h src/helloworld.cpp src/common_global.h src/utils/logger.h src/utils/logger.cpp) target_link_libraries(RADIANT-SCP-Common PRIVATE Qt5::Core) target_include_directories(RADIANT-SCP-Common PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src") target_compile_definitions(RADIANT-SCP-Common PRIVATE COMMON_LIBRARY) INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src DESTINATION /usr/local/include/RADIANT/SCP/Common FILES_MATCHING PATTERN "*.h") INSTALL(TARGETS RADIANT-SCP-Common LIBRARY DESTINATION /usr/lib)
Application
CMakeList.txt
cmake_minimum_required(VERSION 3.5) project(SRU-Injector-Client LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt5Core) add_executable(SRU-Injector-Client main.cpp ) target_include_directories(SRU-Injector-Client PUBLIC "/usr/local/include/RADIANT") LINK_DIRECTORIES(/usr/lib) target_link_libraries(SRU-Injector-Client RADIANT-SCP-Common) target_link_libraries(SRU-Injector-Client RADIANT-SCP-InjectorClient) target_link_libraries(SRU-Injector-Client Qt5::Core)
Now when I add the STATIC m_logfile member to the logger.h and the implementation to the logger.cpp file. I can build the libraries fine but when I go to build the application .I get an undefined ref.
logger.h#ifndef LOGGER_H #define LOGGER_H #include <QLoggingCategory> #include <stdio.h> #include "../common_global.h" namespace RADIANT{ namespace SCP{ namespace Common{ class COMMON_EXPORT logger { public: static void intializeLogger(const QString &filePath); static void processLogToFile(QtMsgType type, const QMessageLogContext &context, const QString &msg); static void openLogFile(const QString &filePath); static void closeLogFile(); static FILE *m_logFile; }; }}} #endif // LOGGER_H
logger.cpp
#include "logger.h" #include <QDateTime> namespace RADIANT{ namespace SCP{ namespace Common{ void logger::intializeLogger(const QString &filePath) { openLogFile(filePath); qInstallMessageHandler(processLogToFile); } void logger::openLogFile(const QString &filePath) { if(m_logFile == NULL) { m_logFile = fopen(filePath.toLocal8Bit(),"w"); if(m_logFile == NULL) { qDebug() << "Could not open log file %s",filePath; } } else { qDebug() << "%s file is use",filePath; } } void logger::closeLogFile() { fclose(m_logFile); } void logger::processLogToFile(QtMsgType type, const QMessageLogContext &context, const QString &msg) { const char *file = context.file ? context.file : ""; const char *function = context.function ? context.function : ""; // TODO: Change this to get time from the Date Time Manager QString timeStamp = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz"); QString logMessage; std::string s; switch (type) { case QtDebugMsg: logMessage = QString("Debug: %1 (%2:%3, %4)\n").arg(msg).arg(file).arg(context.line).arg(function); break; case QtInfoMsg: logMessage = QString("Info: %1 (%2:%3, %4)\n").arg(msg).arg(file).arg(context.line).arg(function); break; case QtWarningMsg: logMessage = QString("Warning: %1 (%2:%3, %4)\n").arg(msg).arg(file).arg(context.line).arg(function); break; case QtCriticalMsg: logMessage = QString("Critical: %1 (%2:%3, %4)\n").arg(msg).arg(file).arg(context.line).arg(function); break; case QtFatalMsg: logMessage = QString("Fatal: %1 (%2:%3, %4)\n").arg(msg).arg(file).arg(context.line).arg(function); break; } logMessage = timeStamp + " " + logMessage; fprintf(stdout,"%s",logMessage.toLocal8Bit().constData()); if(m_logFile != NULL) fprintf(m_logFile, "%s",logMessage.toLocal8Bit().constData()); } }}}
build output for libraries
-- The C compiler identification is GNU 9.2.1 -- The CXX compiler identification is GNU 9.2.1 -- Check for working C compiler: /usr/bin/gcc -- Check for working C compiler: /usr/bin/gcc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/g++ -- Check for working CXX compiler: /usr/bin/g++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done CMake Warning: Manually-specified variables were not used by the project: QT_QMAKE_EXECUTABLE -- Build files have been written to: /home/developer/src/RADIANT/SCP/radiant.scp.framework/builds/0.1.0/Qt5.12.8/gcc_64/Debug Scanning dependencies of target RADIANT-SCP-Common_autogen [ 7%] Automatic MOC and UIC for target RADIANT-SCP-Common [ 7%] Built target RADIANT-SCP-Common_autogen Scanning dependencies of target RADIANT-SCP-Common [ 15%] Building CXX object Common/CMakeFiles/RADIANT-SCP-Common.dir/RADIANT-SCP-Common_autogen/mocs_compilation.cpp.o [ 23%] Building CXX object Common/CMakeFiles/RADIANT-SCP-Common.dir/src/helloworld.cpp.o [ 30%] Building CXX object Common/CMakeFiles/RADIANT-SCP-Common.dir/src/utils/logger.cpp.o [ 38%] Linking CXX shared library libRADIANT-SCP-Common.so [ 38%] Built target RADIANT-SCP-Common Scanning dependencies of target RADIANT-SCP-InjectorClient_autogen [ 46%] Automatic MOC and UIC for target RADIANT-SCP-InjectorClient [ 46%] Built target RADIANT-SCP-InjectorClient_autogen Scanning dependencies of target RADIANT-SCP-InjectorClient [ 53%] Building CXX object InjectorClient/CMakeFiles/RADIANT-SCP-InjectorClient.dir/RADIANT-SCP-InjectorClient_autogen/mocs_compilation.cpp.o [ 61%] Building CXX object InjectorClient/CMakeFiles/RADIANT-SCP-InjectorClient.dir/src/helloworldinjectorclient.cpp.o [ 69%] Linking CXX shared library libRADIANT-SCP-InjectorClient.so [ 69%] Built target RADIANT-SCP-InjectorClient Scanning dependencies of target RADIANT-SCP-SystemService_autogen [ 76%] Automatic MOC and UIC for target RADIANT-SCP-SystemService [ 76%] Built target RADIANT-SCP-SystemService_autogen Scanning dependencies of target RADIANT-SCP-SystemService [ 84%] Building CXX object SystemService/CMakeFiles/RADIANT-SCP-SystemService.dir/RADIANT-SCP-SystemService_autogen/mocs_compilation.cpp.o [ 92%] Building CXX object SystemService/CMakeFiles/RADIANT-SCP-SystemService.dir/src/helloworldsystemservice.cpp.o [100%] Linking CXX shared library libRADIANT-SCP-SystemService.so [100%] Built target RADIANT-SCP-SystemService [ 7%] Automatic MOC and UIC for target RADIANT-SCP-Common [ 7%] Built target RADIANT-SCP-Common_autogen [ 38%] Built target RADIANT-SCP-Common [ 46%] Automatic MOC and UIC for target RADIANT-SCP-InjectorClient [ 53%] Automatic MOC and UIC for target RADIANT-SCP-SystemService [ 53%] Built target RADIANT-SCP-InjectorClient_autogen [ 53%] Built target RADIANT-SCP-SystemService_autogen [ 76%] Built target RADIANT-SCP-InjectorClient [100%] Built target RADIANT-SCP-SystemService [ 7%] Automatic MOC and UIC for target RADIANT-SCP-Common [ 7%] Built target RADIANT-SCP-Common_autogen [ 38%] Built target RADIANT-SCP-Common [ 46%] Automatic MOC and UIC for target RADIANT-SCP-InjectorClient [ 46%] Built target RADIANT-SCP-InjectorClient_autogen [ 69%] Built target RADIANT-SCP-InjectorClient [ 76%] Automatic MOC and UIC for target RADIANT-SCP-SystemService [ 76%] Built target RADIANT-SCP-SystemService_autogen [100%] Built target RADIANT-SCP-SystemService Install the project... -- Install configuration: "Debug" -- Installing: /usr/local/include/RADIANT/SCP/Common/src -- Installing: /usr/local/include/RADIANT/SCP/Common/src/common_global.h -- Installing: /usr/local/include/RADIANT/SCP/Common/src/utils -- Installing: /usr/local/include/RADIANT/SCP/Common/src/utils/logger.h -- Installing: /usr/local/include/RADIANT/SCP/Common/src/helloworld.h -- Installing: /usr/lib/libRADIANT-SCP-Common.so -- Set runtime path of "/usr/lib/libRADIANT-SCP-Common.so" to "" -- Installing: /usr/local/include/RADIANT/SCP/InjectorClient/src -- Installing: /usr/local/include/RADIANT/SCP/InjectorClient/src/helloworldinjectorclient.h -- Installing: /usr/local/include/RADIANT/SCP/InjectorClient/src/injectorclient_global.h -- Installing: /usr/lib/libRADIANT-SCP-InjectorClient.so -- Set runtime path of "/usr/lib/libRADIANT-SCP-InjectorClient.so" to "" -- Installing: /usr/local/include/RADIANT/SCP/SystemService/src -- Installing: /usr/local/include/RADIANT/SCP/SystemService/src/helloworldsystemservice.h -- Installing: /usr/local/include/RADIANT/SCP/SystemService/src/systemservice_global.h -- Installing: /usr/lib/libRADIANT-SCP-SystemService.so -- Set runtime path of "/usr/lib/libRADIANT-SCP-SystemService.so" to ""
but when I build the application get the undefined error
-- The CXX compiler identification is GNU 9.2.1 -- Check for working CXX compiler: /usr/bin/g++ -- Check for working CXX compiler: /usr/bin/g++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done CMake Warning: Manually-specified variables were not used by the project: CMAKE_C_COMPILER FRAMEWORK_BUILD_VERSION QT_QMAKE_EXECUTABLE Qt5_DIR -- Build files have been written to: /home/developer/src/NextGenCT/SCP/sru-injector-client/builds/0.1.0/Qt5.12.8/gcc_64/Debug Scanning dependencies of target SRU-Injector-Client_autogen [ 25%] Automatic MOC and UIC for target SRU-Injector-Client [ 25%] Built target SRU-Injector-Client_autogen Scanning dependencies of target SRU-Injector-Client [ 50%] Building CXX object CMakeFiles/SRU-Injector-Client.dir/SRU-Injector-Client_autogen/mocs_compilation.cpp.o [ 75%] Building CXX object CMakeFiles/SRU-Injector-Client.dir/main.cpp.o [100%] Linking CXX executable SRU-Injector-Client /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/libRADIANT-SCP-Common.so: undefined reference to `RADIANT::SCP::Common::logger::m_logFile' collect2: error: ld returned 1 exit status make[2]: *** [CMakeFiles/SRU-Injector-Client.dir/build.make:100: SRU-Injector-Client] Error 1 make[1]: *** [CMakeFiles/Makefile2:77: CMakeFiles/SRU-Injector-Client.dir/all] Error 2 make: *** [Makefile:84: all] Error 2
I have tried adding the cpp wrap to libraries CMakeLists.txt file to have it generate the moc files but I did not have any luck with this working
qt_wrap_cpp(RADIANT-SCP-Common src.utils/logger.h src/utils/logger.cpp)
any help would be much apperciated.
-
-
wrote on 6 May 2020, 05:40 last edited by
ok I figured out my problem based on your feedback @Christian-Ehrlicher. I am new c++ and qt and see what I did wrong. After declaring this in the top of the .cpp all was good.
logger.cpp
FILE *logger::m_logFile = NULL;
-
@pjorourke05 said in CMAKE undefined references when building a console application that uses custom libraries:
static FILE *m_logFile;
C basics - where do you declare this variable?
-
wrote on 6 May 2020, 05:14 last edited by
I declare the variable in the header. as show above. but for quick reference see the snippet below
#ifndef LOGGER_H #define LOGGER_H #include <QLoggingCategory> #include <stdio.h> #include "../common_global.h" namespace RADIANT{ namespace SCP{ namespace Common{ { public: ... static FILE *m_logFile;
-
wrote on 6 May 2020, 05:40 last edited by
ok I figured out my problem based on your feedback @Christian-Ehrlicher. I am new c++ and qt and see what I did wrong. After declaring this in the top of the .cpp all was good.
logger.cpp
FILE *logger::m_logFile = NULL;
1/4