I want to build a simple Qt project on Windows which consists of one main.cpp file and a dll.
I have no problems with building it using CMake:
project(app)
cmake_minimum_required(VERSION 2.6.0)
find_package(Qt4 REQUIRED QtCore QtGui QtXml)
...
add_executable(app main.cpp)
target_link_libraries(app ${QT_LIBRARIES} my_dll.dll)
Then I try to build it using qmake:
...
SOURCES += main.cpp
win32:{
LIBS += -L"my_dll.dll"
}
In this case the build fails and I get linker errors like undefined reference to 'my_function#8', where my_function is a function in my_dll.dll.
When I open my_dll.dll with Dependency Walker I can see that all function names are not decorated. I don't know why qmake tries to resolve function names with '#8' at the end.
This is what CMake writes to the log on linking:
C:\MinGW\bin\g++.exe -g -Wl,--whole-archive CMakeFiles\app.dir/objects.a -Wl,--no-whole-archive -o app.exe -Wl,--out-implib,libapp.dll.a -Wl,--major-image-version,0,--minor-image-version,0 C:\QT\2010.02.1\qt\lib\libQtGuid4.a C:\QT\2010.02.1\qt\lib\libQtXmld4.a C:\QT\2010.02.1\qt\lib\libQtCored4.a -l,my_dll -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
Also it gives some warnings:
Warning: resolving _my_fucntion#8 by linking to _my_function
Use --enable-stdcall-fixup to disable these warnings
Use --disable-stdcall-fixup to disable these fixups
And this is what qmake says:
g++ -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mthreads -Wl -o debug/aap1.exe debug/main.o -L'c:/Qt/2010.02.1/qt/lib' -lmingw32 -lqtmaind -Lmy_dll.dll -lQtXmld4 -lQtGuid4 -lQtCored4
How can I build my project using qmake?
Related
I'm trying to build a simple application
using the freetype library on Windows 64.
Freetype lib was compiled from src on windows 64
simple programm
#include <ft2build.h>
#include FT_FREETYPE_H
int main (int argc, char** argv) {
FT_Library ft;
if (FT_Init_FreeType(&ft) != 0) {
//err
}
}
Added environment variable FREETYPE_DIR
and cmake script
cmake_minimum_required(VERSION 3.22)
cmake_path(CONVERT $ENV{COMPILER} TO_CMAKE_PATH_LIST COMPILER)
set(CMAKE_CXX_COMPILER "${COMPILER}/clang++.exe")
set(CMAKE_C_COMPILER "${COMPILER}/clang.exe")
set(CMAKE_RC_COMPILER "${COMPILER}/llvm-rc.exe")
set(CMAKE_BUILD_TYPE Release)
set(EXECUTABLE_OUTPUT_PATH "../bin")
project (text)
file(GLOB SRC
"./src/main.cpp"
)
find_package(Freetype MODULE REQUIRED)
add_executable (${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME}
PRIVATE "./include"
PRIVATE ${FREETYPE_INCLUDE_DIRS}
)
target_link_libraries(${PROJECT_NAME}
Freetype::Freetype
)
but I'm stuck, get a linker error, although freetype library is linked
ninja: Entering directory `./build'
[1/1] cmd.exe /C "cd . &&
C:\PROGRA~2\MICROS~2\2022\BUILDT~1\VC\Tools\Llvm\x64\bin\CLANG_~1.EXE -fuse-ld=lld-link
-nostartfiles -nostdlib -O3 -DNDEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -
Xlinker /subsystem:console CMakeFiles/text.dir/src/main.cpp.obj -o
D:\git\cpp\opengl\drawtext\bin\text.exe -Xlinker /MANIFEST:EMBED -Xlinker
/implib:D:\git\cpp\opengl\drawtext\bin\text.lib -Xlinker
/pdb:D:\git\cpp\opengl\drawtext\bin\text.pdb -Xlinker /version:0.0 D:/source/freetype-
2.12.1/build/x86_64/Release/lib/freetype.lib -lkernel32 -luser32 -lgdi32 -lwinspool -
lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
FAILED: D:/git/cpp/opengl/drawtext/bin/text.exe
cmd.exe /C "cd . &&
C:\PROGRA~2\MICROS~2\2022\BUILDT~1\VC\Tools\Llvm\x64\bin\CLANG_~1.EXE -fuse-ld=lld-link
-nostartfiles -nostdlib -O3 -DNDEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrt -
Xlinker /subsystem:console CMakeFiles/text.dir/src/main.cpp.obj -o
D:\git\cpp\opengl\drawtext\bin\text.exe -Xlinker /MANIFEST:EMBED -Xlinker
/implib:D:\git\cpp\opengl\drawtext\bin\text.lib -Xlinker
/pdb:D:\git\cpp\opengl\drawtext\bin\text.pdb -Xlinker /version:0.0 D:/source/freetype-
2.12.1/build/x86_64/Release/lib/freetype.lib -lkernel32 -luser32 -lgdi32 -lwinspool -
lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
lld-link: error: undefined symbol: FT_Init_FreeType
>>> referenced by CMakeFiles/text.dir/src/main.cpp.obj:(main)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
Find the workaround, recompile freetype lib via Microsoft cl.exe instead of clang.
I am trying to learn how to use SDL and I've been trying to get my app to run on other systems. when I try to compile using g++ -I src/include -L src/lib -o main main.cpp -lmingw32 -lSDL2main -lSDL2 -static-libgcc -static-libstdc++ -static I get a massive bunch of SDL errors saying undefined and the app doesn't finish compiling. However when running without -static it will compile but not include libc. How would I fix this issue while still being able to run on other systems without them installed?
I am also using MinGW-w64 for GCC
You're missing some flags. Running pkg-config --libs --static sdl2 will tell you the right flags.
If you don't have pkg-config installed (you could get it from MSYS2), you can look up the flags manually in the file called sdl2.pc, which is shipped with SDL2.
For me this command prints -L/mingw64/lib -lSDL2main -lmingw32 -lSDL2main -lSDL2 -mwindows -lmingw32 -ldinput8 -lshell32 -lsetupapi -ladvapi32 -luuid -lversion -loleaut32 -lole32 -limm32 -lwinmm -lgdi32 -luser32 -lm -Wl,--no-undefined -lmingw32 -lSDL2main -lSDL2 -mwindows.
You also need -static, even though it doesn't appear in the output. You can remove -static-libgcc -static-libstdc++, since they're implied by -static.
On the computer where it was built, it runs fine, but on other computers an error saying that the DLL could not be found appears.
this is my CMakeLists.txt file:
find_package(SDL2 REQUIRED)
find_library(SDL_MIXER_LIBRARY
NAMES SDL2_mixer
HINTS
ENV SDLMIXERDIR
ENV SDLDIR
PATH_SUFFIXES lib
)
target_link_libraries(SpaceCadetPinball SDL2::SDL2 SDL2_mixer)
target_compile_options(SpaceCadetPinball PUBLIC -lmingw64 -lSDL2main -lSDL2 -lSDL2_mixer -mwindows -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -static-libgcc)
error list:
SDL2_mixer.dll
libstdc++-6.dll
libwinpthread-1.dll
libgcc_s_seh-1.dll
How do I build these as static libraries so that I can use them on other machines?
I have been trying to get wxWidgets working on Cygwin. So far I have had success by using a mingw compiler available through the cygwin installer.
The build seemed to work fine. The configure message I used was:
configure --host=i686-w64-mingw32 --build=i686-pc-cygwin --enable-static --disable-shared
After that I ran a make and make install and got no errors.
Next I grabbed an example from a tutorial and ran:
i686-w64-mingw32-g++ -c -o hello_world.o hello_world.cpp CXX_FLAGS
i686-w64-mingw32-g++ -o a hello_world.o CXX_FLAGS LIBS
where CXX_FLAGS and LIBS are generated from wx-config -cxxflags and wx-config --libs. This works fine, but when I try to run the executable I get this error:
C:/Users/sam/Documents/cpp/wxwidgets_tutorial/a.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory
The libraries I build should be static, so I'm not sure what to do with this message. Any help is greatly appreciated!
Some more info:
wx-config --cxxflags gives the output:
-I/usr/local/lib/wx/include/i686-w64-mingw32-msw-unicode-static-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -D__WXMSW__ -mthreads
wx-config --libs give the output:
-L/usr/local/lib -Wl,--subsystem,windows -mwindows /usr/local/lib/libwx_mswu_xrc-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_mswu_webview-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_mswu_qa-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_baseu_net-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_mswu_html-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_mswu_adv-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_mswu_core-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_baseu_xml-3.0-i686-w64-mingw32.a /usr/local/lib/libwx_baseu-3.0-i686-w64-mingw32.a -lpng -ljpeg -ltiff -lexpat -lwxregexu-3.0-i686-w64-mingw32 -lz -lrpcrt4 -loleaut32 -lole32 -luuid -lwinspool -lwinmm -lshell32 -lcomctl32 -lcomdlg32 -ladvapi32 -lwsock32 -lgdi32
ls /usr/local/lib:
libwx_baseu_net-3.0-i686-w64-mingw32.a
libwx_baseu_xml-3.0-i686-w64-mingw32.a
libwx_baseu-3.0-i686-w64-mingw32.a
libwx_mswu_adv-3.0-i686-w64-mingw32.a
libwx_mswu_aui-3.0-i686-w64-mingw32.a
libwx_mswu_core-3.0-i686-w64-mingw32.a
libwx_mswu_gl-3.0-i686-w64-mingw32.a
libwx_mswu_html-3.0-i686-w64-mingw32.a
libwx_mswu_media-3.0-i686-w64-mingw32.a
libwx_mswu_propgrid-3.0-i686-w64-mingw32.a
libwx_mswu_qa-3.0-i686-w64-mingw32.a
libwx_mswu_ribbon-3.0-i686-w64-mingw32.a
libwx_mswu_richtext-3.0-i686-w64-mingw32.a
libwx_mswu_stc-3.0-i686-w64-mingw32.a
libwx_mswu_webview-3.0-i686-w64-mingw32.a
libwx_mswu_xrc-3.0-i686-w64-mingw32.a
libwxregexu-3.0-i686-w64-mingw32.a
libwxscintilla-3.0-i686-w64-mingw32.a
wx
EDIT:
Following VZ's advise, I added /usr/i686-w64-mingw32/sys-root/mingw/bin to my path... It compiles!
However when run, the program does not open any window, just exits immediately. Is this still a library problem?
You need to copy the required DLLs (at least libstdc++-6.dll and libgcc_s_sjlj-1.dll) from /usr/i686-w64-mingw32/sys-root/mingw/bin to a directory in your PATH or the application directory (or add this directory itself to your PATH, of course).
You can use cygcheck or (native) dependency walker tool to find which DLL is actually missing.
I'm currently switching the build system of my Qt application from qmake to cmake. While trying to cross-compile for Windows with MinGW (static Qt build), I came across a strange problem I cannot explain:
CMakeLists.txt:
project(noble)
cmake_minimum_required(VERSION 2.8.5)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
find_package(Boost COMPONENTS program_options thread REQUIRED)
find_package(Qt4 REQUIRED QtCore QtGui)
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
find_package(Armadillo)
find_package(Qwt6 REQUIRED)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
include(${QT_USE_FILE})
set(LIBRARIES
${Qwt6_Qt4_LIBRARY}
${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
${Boost_LIBRARIES}
${BLAS_LIBRARIES}
${LAPACK_LIBRARIES}
)
set(DEFINITIONS
${QT_DEFINITIONS}
${BLAS_LINKER_FLAGS}
${LAPACK_LINKER_FLAGS}
-DBOOST_THREAD_USE_LIB
)
add_subdirectory(src)
add_subdirectory(plugins)
src/CMakeLists.txt:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(noble_SOURCES
#file names...
)
set(noble_HEADERS
#file names...
)
set(noble_FORMS
#file names...
)
QT4_WRAP_UI(noble_FORMS_HEADERS ${noble_FORMS})
QT4_WRAP_CPP(noble_HEADERS_MOC ${noble_HEADERS})
include_directories(
${Boost_INCLUDE_DIRS}
${ARMADILLO_INCLUDE_DIRS}
${Qwt6_INCLUDE_DIR}
)
add_definitions(${DEFINITIONS})
add_executable(noble
${noble_SOURCES}
${noble_HEADERS_MOC}
${noble_FORMS_HEADERS}
)
target_link_libraries(noble
${LIBRARIES}
-lQtGui -lQtCore
-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-fopenmp
)
I am now trying to get rid of the manually set compiler flags right in the end. If I omit the -lQtGui -lQtCore I get a whole bunch of undefined references like
/home/mjung/Programme/mingw-cross-env-2.21/usr/lib/gcc/i686-pc-mingw32/4.6.0/../../../../i686-pc-mingw32/lib/libQtGui.a(qapplication.o):qapplication.cpp:(.text+0x2340): undefined reference to `QBasicTimer::stop()'
If i keep these flags, the program compiles fine.
The strange thing now is the following:
cmake's g++ call with -lQtGui -lQtCore flags:
/home/mjung/Programme/mingw-cross-env-2.21/usr/bin/i686-pc-mingw32-g++
-Wl,--whole-archive
CMakeFiles/noble.dir/objects.a
-Wl,--no-whole-archive
-o ../noble.exe
-Wl,--out-implib,../libnoble.dll.a
-Wl,--major-image-version,0,--minor-image-version,0
/home/mjung/Programme/windows_builds/usr/lib/libqwt.a
-Wl,-Bstatic
-lQtCore -lQtGui
-lboost_program_options-mt
-lboost_thread-mt
-Wl,-Bdynamic
/home/mjung/Programme/windows_builds/usr/lib/libblas.a
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a
/home/mjung/Programme/windows_builds/usr/lib/libblas.a
-lQtGui -lQtCore
-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-fopenmp
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a
-lQtGui -lQtCore
-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
cmake's g++ call without -lQtGui -lQtCore flags:
/home/mjung/Programme/mingw-cross-env-2.21/usr/bin/i686-pc-mingw32-g++
-Wl,--whole-archive
CMakeFiles/noble.dir/objects.a
-Wl,--no-whole-archive
-o ../noble.exe
-Wl,--out-implib,../libnoble.dll.a
-Wl,--major-image-version,0,--minor-image-version,0
/home/mjung/Programme/windows_builds/usr/lib/libqwt.a
-Wl,-Bstatic
-lQtCore -lQtGui
-lboost_program_options-mt
-lboost_thread-mt
-Wl,-Bdynamic
/home/mjung/Programme/windows_builds/usr/lib/libblas.a
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a
/home/mjung/Programme/windows_builds/usr/lib/libblas.a
-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-fopenmp
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a
-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
Even if I do not set the compiler flags manually the FindQt4.cmake script still sets them. But this doesn't seem to be enough. I absolutely don't understand why it makes a difference if the flags are set once automatically, or three times, if I add them manually. Does this have something to do with the order of the flags?
Do you have any ideas? Any help is appreciated.
UPDATE:
Nevermind...
I just changed the order of the libraries from
set(LIBRARIES
${Qwt6_Qt4_LIBRARY}
${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
${Boost_LIBRARIES}
${BLAS_LIBRARIES}
${LAPACK_LIBRARIES}
)
to
set(LIBRARIES
${Qwt6_Qt4_LIBRARY}
${QT_QTGUI_LIBRARY}
${QT_QTCORE_LIBRARY}
${Boost_LIBRARIES}
${BLAS_LIBRARIES}
${LAPACK_LIBRARIES}
)
I do not quite understand why it has to be this way round, but now it works...
PS: I would have posted this as an answer, but I am not allowed to do so yet, due to lack of reputation.
Many architectures do a single pass through the library list when linking. i.e. If you have an undefined symbol, a library that's later in the link list must define it. The linker won't search 'backwards' through the library list to resolve the symbol.
In this case, QtGui has a dependency on QtCore. QtCore therefore must appear after QtGui in the link list.
The easiest way around this is to use the ${QT_LIBRARIES} cmake variable that gets magically defined when you do the FIND_PACKAGE(Qt4...). It has all the relevant Qt libs in the right order for the link.
FindQt4 CMake documentation