I have a C++ project using CMake and QT. I have it running in CLion, but my license is ending and I wanted to run this in Visual Studio Code on Windows.
Project is structured
Proj
CMakeLists.txt
main.cpp
-- src
---- ...
---- ui
---- CMakeLists.txt
Currently ui is independent of other modules thus they are skipped.
CMakeLists.txt have target library Proj_UI_LIB which includes QT.
Main CMakeLists.txt have target executable Proj and link it with Proj_UI_LIB.
Now this is working fine in CLion and I can run the whole project.
However in Visual Studio Code configuration, Proj_UI_LIB build successfully but when building Proj, it is displaying linking errors with QT functions.
! [build] Proj_UI_LIB.vcxproj -> D:DocumentsProgrammingProjbuildsrcuiDebugProj_UI_LIB.lib
[build] main.obj : error LNK2019: unresolved external symbol “__declspec(dllimport) public: __cdecl QApplication::QApplication(int &,char * *,int)” (_imp??0QApplication@@QEAA@AEAHPEAPEADH@Z) referenced in function main [D:DocumentsProgrammingProjbuildProj.vcxproj]
[build] main.obj : error LNK2019: unresolved external symbol “__declspec(dllimport) public: virtual __cdecl QApplication::~QApplication(void)” (_imp??1QApplication@@UEAA@XZ) referenced in function main [D:DocumentsProgrammingProjbuildProj.vcxproj]
[build] main.obj : error LNK2019: unresolved external symbol “__declspec(dllimport) public: static int __cdecl QApplication::exec(void)” (_imp?exec@QApplication@@SAHXZ) referenced in function main [D:DocumentsProgrammingProjbuildProj.vcxproj]
[build] main.obj : error LNK2019: unresolved external symbol “__declspec(dllimport) public: void __cdecl QWidget::show(void)” (_imp?show@QWidget@@QEAAXXZ) referenced in function main [D:DocumentsProgrammingProjbuildProj.vcxproj]
[build] Proj_UI_LIB.lib(mainwindow.obj) : error LNK2019: unresolved external symbol “__declspec(dllimport) void __cdecl qt_assert(char const *,char const *,int)” (_imp?qt_assert@@YAXPEBD0H@Z) referenced in function “private: static unsigned __int64 __cdecl QAnyStringView::encodeType(char const *,__int64)” (??$encodeType@D@QAnyStringView@@CA_KPEBD_J@Z) [D:DocumentsProgrammingProjbuildProj.vcxproj]
…
[build] Proj_UI_LIB.lib(OpenDialog.obj) : error LNK2019: unresolved external symbol “__declspec(dllimport) public: class QString & __cdecl QString::operator=(class QString &&)” (_imp??4QString@@QEAAAEAV0@$$QEAV0@@Z) referenced in function “public: __cdecl radui::OpenDialog::OpenDialog(class QWidget *,class std::basic_string<char,struct std::char_traits,class std::allocator > const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)” (??0OpenDialog@radui@@QEAA@PEAVQWidget@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@1@Z) [D:DocumentsProgrammingProjbuildProj.vcxproj]
[build] Proj_UI_LIB.lib(OpenDialog.obj) : error LNK2019: unresolved external symbol “__declspec(dllimport) public: static class QString __cdecl QFileDialog::getOpenFileName(class QWidget *,class QString const &,class QString const &,class QString const &,class QString *,class QFlags)” (_imp?getOpenFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z) referenced in function “public: class QString __cdecl radui::OpenDialog::openPhoto(void)” (?openPhoto@OpenDialog@radui@@QEAA?AVQString@@XZ) [D:DocumentsProgrammingProjbuildProj.vcxproj]
[build] Proj_UI_LIB.lib(OpenDialog.obj) : error LNK2019: unresolved external symbol “__declspec(dllimport) public: static class QString __cdecl QFileDialog::getExistingDirectory(class QWidget *,class QString const &,class QString const &,class QFlags)” (_imp?getExistingDirectory@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@1V?$QFlags@W4Option@QFileDialog@@@@@Z) referenced in function “public: class QString __cdecl radui::OpenDialog::openDir(void)” (?openDir@OpenDialog@radui@@QEAA?AVQString@@XZ) [D:DocumentsProgrammingProjbuildProj.vcxproj]
Do you know what can be the differences in CLion cmake configuration and Visual Studio Code resulting in linking errors?
This is my main CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(Proj)
set(CMAKE_CXX_STANDARD 23)
IF (WIN32)
set(CMAKE_PREFIX_PATH "D:\lib\Qt\6.6.0\mingw_64\lib\cmake")
ELSE()
set(CMAKE_PREFIX_PATH "/home/rad/lib/Qt/6.4.3/gcc_64/lib/cmake")
ENDIF()
add_subdirectory(src)
add_executable(Proj main.cpp)
# Ideally I don't want to add QT at this level but I am fine if it works
find_package(Qt6 COMPONENTS
Core
Gui
Widgets
LinguistTools
REQUIRED)
target_link_libraries(Proj
Proj_UI_LIB
Qt::Core
Qt::Gui
Qt::Widgets
)
if (WIN32)
set(DEBUG_SUFFIX)
if (MSVC AND CMAKE_BUILD_TYPE MATCHES "Debug")
set(DEBUG_SUFFIX "d")
endif ()
set(QT_INSTALL_PATH "${CMAKE_PREFIX_PATH}")
if (NOT EXISTS "${QT_INSTALL_PATH}/bin")
set(QT_INSTALL_PATH "${QT_INSTALL_PATH}/..")
if (NOT EXISTS "${QT_INSTALL_PATH}/bin")
set(QT_INSTALL_PATH "${QT_INSTALL_PATH}/..")
endif ()
endif ()
if (EXISTS "${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/platforms/")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/platforms/")
endif ()
foreach (QT_LIB Core Gui Widgets)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${QT_INSTALL_PATH}/bin/Qt6${QT_LIB}${DEBUG_SUFFIX}.dll"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${QT_INSTALL_PATH}/bin/Qt6${QT_LIB}${DEBUG_SUFFIX}.dll"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/test")
endforeach (QT_LIB)
if (NOT EXISTS "$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/imageformats/")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/imageformats/")
endif()
foreach (PHOTO_LIB gif ico jpeg svg)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${QT_INSTALL_PATH}/plugins/imageformats/q${PHOTO_LIB}.dll"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/imageformats/")
endforeach (PHOTO_LIB)
endif ()
And this is UI CMakeLists.txt
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
IF (WIN32)
set(CMAKE_PREFIX_PATH "D:\lib\Qt\6.6.0\mingw_64\lib\cmake")
ELSE()
set(CMAKE_PREFIX_PATH "/home/rad/lib/Qt/6.4.3/gcc_64/lib/cmake")
ENDIF()
find_package(Qt6 COMPONENTS
Core
Gui
Widgets
LinguistTools
REQUIRED)
set(TS_FILES
translations/Proj_pl_PL.ts)
qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
set(WIDGETS_SOURCES
widgets/dynamic/Action.h
widgets/static/mainwindow.cpp
widgets/static/mainwindow.h
widgets/static/mainwindow.ui
widgets/dynamic/dirtree.h
widgets/dynamic/dirtree.cpp
widgets/dynamic/dirtree.ui
)
set(UI_SOURCES
OpenDialog.cpp
OpenDialog.h
${TS_FILES}
)
set(MODEL_SOURCES
)
add_library(Proj_UI_LIB
${UI_SOURCES}
${MODEL_SOURCES}
${WIDGETS_SOURCES}
${QM_FILES}
)
# To use C++17 in VSC
if(MSVC)
target_compile_options(Proj_UI_LIB PUBLIC "/Zc:__cplusplus")
endif(MSVC)
target_include_directories(Proj_UI_LIB PUBLIC
../..)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/widgets/dynamic)
target_link_libraries(Proj_UI_LIB
Qt::Core
Qt::Gui
Qt::Widgets
)
I am using target_link_libraries(Proj_UI_LIB Qt::Core Qt::Gui Qt::Widgets)
, I have instructions to copy .dll
files to .exe
location (I even copied them myself), and I don’t understand why this configuration has linking issues with VSC cmake but works fine with CLion.
How can I configure CMakeLists.txt to use the same kit for both instances as I suspect that’s the difference.