Cannot find -l"Project_Name": No such file or directory
-
As mentioned https://forum.qt.io/topic/140152/cmake-build-type-specified-building/, I am currently learning how Unit Tests work and how to work with QTest Framework.
I have made a sample Raspberry Pi GPIO program with Widgets on Ubuntu and an example from KDAB for unit testing with Qt.
TheCMakeLists.txt
file is auto generated by creating a new Project from QtCreator. I created a folder called tests and in it I added anotherCMakeLists.txt
file which was tested using the KDAB example(https://github.com/KDAB/kdabtv/tree/master/Qt-Widgets-and-more/UnitTests).
If I build the main project withoutadd_subdirectory(tests)
, it builds perfectly and works fine. If I add the tests project as well, I get an error saying:error: cannot find -lUnitTestProj: No such file or directory error: collect2: error: ld returned 1 exit status
The Main Project CMakeLists.txt file:
cmake_minimum_required(VERSION 3.5) project(UnitTestProj VERSION 0.1 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(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED Test) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED Test) find_library(WIRINGPI_LIBRARIES NAMES wiringPi) set(PROJECT_SOURCES main.cpp my_window.cpp my_window.h my_window.ui resources/resource.qrc stack_comm.h stack_comm.cpp ) add_subdirectory(tests) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(${PROJECT_NAME} MANUAL_FINALIZATION ${PROJECT_SOURCES} ) # Define target properties for Android with Qt 6 as: # set_property(TARGET UnitTestProj APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR # ${CMAKE_CURRENT_SOURCE_DIR}/android) # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation else() if(ANDROID) add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES} ) # Define properties for Android with Qt 5 after find_package() calls as: # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") else() add_executable(${PROJECT_NAME} ${PROJECT_SOURCES} ) endif() endif() target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets ${WIRINGPI_LIBRARIES}) set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) #Setting Executable Name set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "Unit Test Output" ) if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(${PROJECT_NAME}) endif()
Test folder CMakeLists.txt is:
enable_testing() function(SETUP_TESTS) foreach(_testname ${ARGN}) add_executable(${_testname} test_${_testname}.cpp ) add_test(NAME ${_testname} COMMAND ${_testname}) target_link_libraries(${_testname} Qt${QT_MAJOR_VERISION}::Test UnitTestProj) endforeach() endfunction() SETUP_TESTS( stack_comm )
Where am I doing it wrong? Thanks.
-
You can not link an executable against another one. You can only link a executable against a library. So create a library (without your main.cpp) and then your main executable (main.cpp) which links against this library. And this lib can then also be used for the tests.
-
@Christian-Ehrlicher Could you kindly show me an example with my CMakeLists.txt?
set(PROJECT_SOURCES_WITHOUT_MAIN # main.cpp my_window.cpp my_window.h my_window.ui resources/resource.qrc stack_comm.h stack_comm.cpp ) add_library(MyLib SHARED ${PROJECT_SOURCES_WITHOUT_MAIN}) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(${PROJECT_NAME} MANUAL_FINALIZATION ${PROJECT_SOURCES_WITHOUT_MAIN} ) # Define target properties for Android with Qt 6 as: # set_property(TARGET GWA_FAT_Simulator APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR # ${CMAKE_CURRENT_SOURCE_DIR}/android) # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation else() if(ANDROID) add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES_WITHOUT_MAIN} ) # Define properties for Android with Qt 5 after find_package() calls as: # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") else() add_executable(${PROJECT_NAME} ${PROJECT_SOURCES_WITHOUT_MAIN} ) endif() endif() target_link_libraries(MyLib PRIVATE Qt${QT_VERSION_MAJOR}::Widgets ${WIRINGPI_LIBRARIES}) add_executable(MyProjLib main.cpp) target_link_libraries(MyProjLib MyLib) add_subdirectory(tests)
After this, I get this error:
fatal error: QMainWindow: No such file or directory 4 | #include <QMainWindow> | ^~~~~~~~~~~~~
I think the concept of linking is a bit unclear to me.
-
@Kevin470 said in Cannot find -l"Project_Name": No such file or directory:
After this, I get this error:
fatal error: QMainWindow: No such file or directoryWhen compiling which source file? I would guess main.cpp. You link privately against Qt::Widgets in your library but this is wrong since your public headers include the Qt widgets headers so you also have to link public against the widgets lib.
-
@Christian-Ehrlicher Thank you so much. It took a while for me to understand what you meant. But I got it. I made it a lot simpler this time and wrote the CMakeLists.txt file as below and it works.
cmake_minimum_required(VERSION 3.16) project(UnitTestProj VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED Test) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED Test) find_library(WIRINGPI_LIBRARIES NAMES wiringPi) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) add_library(MyLibSources SHARED # main.cpp my_window.cpp my_window.h my_window.ui resources/resource.qrc stack_comm.h stack_comm.cpp ) target_link_libraries(MyLibSources Qt${QT_VERSION_MAJOR}::Widgets ${WIRINGPI_LIBRARIES}) add_executable(MyTarget main.cpp) target_link_libraries(MyTarget MyLibSources) add_subdirectory(tests) set_target_properties(MyTarget PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) #Setting Executable Name set_target_properties(MyTarget PROPERTIES OUTPUT_NAME "Unit Test Output" )
-
@Christian-Ehrlicher Thank you once again. I have one more question. How does one run the tests in the beginning and then run the main function from the project. So far from what I have done, if the
add_subdirectory(tests)
is active, theQMAIN_TEST()
Function runs instead of the actualmain.cpp
right? Should I just comment outadd_subdirectory(tests)
every time I do not need to run the tests?These are my CMakeLists.txt files currently:
cmake_minimum_required(VERSION 3.16) project(UnitTestProj VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED Test) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED Test) find_library(WIRINGPI_LIBRARIES NAMES wiringPi) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) add_library(MyLibSources SHARED # main.cpp my_window.cpp my_window.h my_window.ui resources/resource.qrc stack_comm.h stack_comm.cpp ) target_link_libraries(MyLibSources Qt${QT_VERSION_MAJOR}::Widgets ${WIRINGPI_LIBRARIES}) add_executable(MyTarget main.cpp) target_link_libraries(MyTarget MyLibSources) add_subdirectory(tests) set_target_properties(MyTarget PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) #Setting Executable Name set_target_properties(MyTarget PROPERTIES OUTPUT_NAME "Unit Test Output" )
Tests folder
enable_testing() function(SETUP_TESTS) foreach(_testname ${ARGN}) add_executable(${_testname} test_${_testname}.cpp ) add_test(NAME ${_testname} COMMAND ${_testname}) target_link_libraries(${_testname} Qt${QT_MAJOR_VERISION}::Test MyLibSources) endforeach() endfunction() SETUP_TESTS( stack_comm )
-
You can select in your IDE which program should be run. The IDE will not run more than one executable.
You can run all tests on the command line with 'make test' or 'cmake --test' (iirc)