Codeblocks with Qt - something terribly wrong - qt

After creating qt project in codeblocks and running it I'm getting:
Anyone knows how to resolve it?
Thanks

This looks to me like you're building against one version of Qt and linking against another at runtime. Run the QtSDK Maintenance Tool and remove any versions of Qt Desktop that you don't need. You may then need to repoint Codeblocks at the correct headers.
I'm guessing that if you're running from within Codeblocks, you've had to explicitly specify which dlls to use when you run your newly built app. If so, make sure that those are the correct versions (i.e. replace them with dlls from QT INSTALL DIR\Desktop\4.7.x\mingw\bin [though I'm not on my work PC at the moment, so this path may be slightly wrong. Just make sure you're in the correct 4.7.x folder]).
To be honest though, if you're running from Windows, why not use QtCreator? Aside from slightly lacking in terms of GDB integration, it's pretty good and you'd find problems like this are harder to come across.

This is (esp on Windows) a common problem. When installing the Qt SDK, you'll get at least 2 .dll's with the same name but in different versions. It happens, that you link against the intended (dev-)lib but at runtime the version from the Designer/Creator is used.
The easiest way to avoid this, is to deploy the right version of the dll's together with your binaries (.exe and stuff) in a separate folder. This can be achived by modifying your build script. It depends on your build system which is usually qmake/.pro or cmake/CMakeLists.txt.
As for CMake, given an environment variable MYQTDLLDIR containing the path to the files to be deployed you can use something like that:
configure_file($ENV{MYQTDLLDIR}/QtCore4.dll ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
configure_file($ENV{MYQTDLLDIR}/QtGui4.dll ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
documentation stripped from cmake --help-full:
configure_file Copy a file to another location and modify its
contents.
configure_file(
[COPYONLY] [ESCAPE_QUOTES] [#ONLY])
Copies a file to file and substitutes variable
values referenced in the file content. If is a relative
path it is evaluated with respect to the current source directory.
The must be a file, not a directory. If is a
relative path it is evaluated with respect to the current binary
directory. If names an existing directory the input file
is placed in that directory with its original name.
This command replaces any variables in the input file referenced as
${VAR} or #VAR# with their values as determined by CMake. If a
variable is not defined, it will be replaced with nothing. If
COPYONLY is specified, then no variable expansion will take place. If
ESCAPE_QUOTES is specified then any substituted quotes will be C-style
escaped. The file will be configured with the current values of CMake
variables. If #ONLY is specified, only variables of the form #VAR#
will be replaces and ${VAR} will be ignored. This is useful for
configuring scripts that use ${VAR}. Any occurrences of #cmakedefine
VAR will be replaced with either #define VAR or /* #undef VAR */
depending on the setting of VAR in CMake. Any occurrences of
#cmakedefine01 VAR will be replaced with either #define VAR 1 or
#define VAR 0 >depending on whether VAR evaluates to TRUE or FALSE in
CMake
As for qmake you could use INSTALLS (used when make install is called) or execute a "plain command" after linking. Using INSTALLS:
mytarget.path = /output/path
mytarget.files += /path/to/QtCore4.dll
mytarget.files += /path/to/QtGui4.dll
INSTALLS += mytarget
qmake using command execution:
win32 {
EXTRA_BINFILES += \
$${MYQTDLLDIR}/QtCore4.dll \
$${MYQTDLLDIR}/QtGui4.dll
EXTRA_BINFILES_WIN = $${EXTRA_BINFILES}
EXTRA_BINFILES_WIN ~= s,/,\\,g
DESTDIR_WIN = $${DESTDIR}
DESTDIR_WIN ~= s,/,\\,g
for(FILE,EXTRA_BINFILES_WIN){
QMAKE_POST_LINK +=$$quote(cmd /c copy /y $${FILE} $${DESTDIR_WIN}$$escape_expand(\n\t))
}
}

Related

Automatically rebuild dependencies in Qt Creator

Qt Creator (4.6.1) is driving me nuts. My application is split into 3 parts:
the app
the library
a unit tests app
When I change a file within the library and rebuild the application, the compiler does not recompile the library but links with the old version of the library.
Also, when I change the library, recompile it and then compile the app, no compilation takes place because it uses the cached app.
Is there a setting to change that? Here's my project file:
TEMPLATE = subdirs
SUBDIRS += \
app \
lib_mylib \
tests
app.depends = lib_mylib
tests.depends = lib_mylib
The lib is built as a static library:
TEMPLATE = lib
TARGET = mylib
CONFIG += staticlib
I know it's a little late, but I would like to give an a little more extensive answer why this happens and how exactly the other solutions help.
A working solution will be: You use either b.depends += a as you did before or CONFIG += ordered and add PRE_TARGETDEPS += ... to b. (Side note: ordered is not recommended, as it can drastically slow down your builds and is generally considered bad practice)
TL;DR: The reason why this special combination is needed: The app.depends = lib_mylib in the subdirs project ensure that the library is always built before building the app is started, and the PRE_TARGETDEPS ensures that the app is actually beeing rebuild everytime the library changed.
Long explanation:
To understand why that works, we need to understand how qmake handles subdirs. qmake is a Makefile generator, which means it will only create makefiles. So all dependency ordering must be done using the methods make prodives. To understand what happens, we must understand how make works, first.
In make, dependencies are relatively simple:
some_target: dep1 dep2 dep3
some_command
means that if you want to create some_target, make will create dep1, dep2 and dep3 first, in an unspecified order. Once all 3 are finished, some_command is executed.
However, make will optimize this for files. Considering the following:
hello.txt:
echo "creating hello"
echo "hello" > hello.txt
hello2.txt: hello.txt
echo "creating hello2"
echo "hello2" > hello2.txt
Running make will create the both files and print both messages. Running it a second time will do nothing. The reason here is that make keeps tracks of already created files and file changes. Since hello.txt already exists, it is not created again. And since hello.txt has not changed, there is no need to create hello2.txt again. If you now externally change the contents of hello.txt and run make again, hello2.txt will be created anew and you will see the message.
Now with subdirs projects, this gets a little more complicated, as we now need dependencies between multiple different makefiles! This is typically resolved by recursive make calls. For your example, qmake creates the following code (simplified):
lib_mylib: FORCE
$(MAKE) lib_mylib/Makefile
app: lib_mylib FORCE
$(MAKE) app/Makefile
This code will, as expected, create lib_mylib first (blocking, i.e. the lib_mylib will only finish once the whole lib has been built) and after that create app. The FORCE depenency ensures that this command is always run, even if the target already exists.
With those basics in mind, we can now reconstruct what happens for qmake. Using the b.depends += a will generate code as above - it makes shure that all dependencies are built in the correct order, but nothing else! Using the ordered config will simply automatically create those depends rules, so there is no logical difference in how they work.
However, this is not enough to actually rebuild app when lib_mylib changes. It only ensures that lib_mylib is built before make starts building app.
In order to rebuild app, we use the PRE_TARGETDEPS - this adds a dependency as shown before to the make target in the apps makefile
app.exe: mylib.lib:
#linker code
This means that every time lib_mylib changes, app is now rebuilt as well. Using this without the ordered config however can fail, as it is possible that make would first try to build app (which either does nothing, as lib has not changed, or will fail if lib does not already exists) and after that rebuild lib_mylib. Running make a second time will the rebuild app as well - but thats rather inconvenient.
So, thats why we need to combine those two. We need to control the order in which the different makefiles are executed and references the created artifacts from the other makefile - and thats exactly what those commands do.
I have used CONFIG += ordered, DEPENDPATH and PRE_TARGETDEPS to get rid of the same problems. It works for me on linux and on win with MSVC. Try it.
in your project pro file add:
CONFIG += ordered
P.S.: your lib should be listed first. Like :
SUBDIRS += \
lib \
app \
tests
in your exe .pro file add this with correct paths:
DEPENDPATH += $$PWD/../lib
PRE_TARGETDEPS += $$OUT_PWD/../lib/liblib.a
More options and flags is to be found here
Regardless the long and understandable explanation I've tried with
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
dynamiclib \
staticlib \
testlibs
for my rather small and short project and it worked for me.

CMake - Copy DLLs to the runtime output directory

I am trying to create a simple CMake that retrieves the DLLs of Qt and copy it in the directory in which cmake creates my executable.
It works great using g++ or clang, but MSVC (Visual Studio 2017) creates a Debug or Release directory.
I can't find a way to retrieve the path to the real directory in which the executable is written (${CMAKE_CURRENT_BINARY_DIR} returns the directory parent of Release or Debug).
I've seen people using the target property RUNTIME_OUTPUT_DIRECTORY but it is empty when I use it.
Any idea how I can do this ? I do not want to change the output directory, I just want to know its path (so I do not want to change the value of RUNTIME_OUTPUT_DIRECTORY)
Thanks!
In Visual Studio, during configuration step (when CMakeLists.txt files are processed) build type is not set, so no build-type-dependent variable or property is usable directly. Instead, generator-expressions should be used.
E.g., output directory for executable or library target can be extracted with $<TARGET_FILE_DIR:tgt> generator expression. It will return full directory, with "Release/" or "Debug/" already appended.
Note, that generator expressions can be used only when their usage is explicitly allowed in documentation. E.g., they cannot be used in message() command.
Alternatively, you may explicitely set variable CMAKE_RUNTIME_OUTPUT_DIRECTORY, so for every build type will just append appropriate subdirectory to it. But for extracting this subdirectory, you should again resort to generator expressions: $<CONFIG>.
Technically, it is possible to set the same output directory for any build type. But this is not recommended, because a file from one build type will be overwritten by the file from another build type.
Example for Visual Studio 2022 and CMake.
Place this at the end of CMakeLists.txt:
if (WIN32)
add_custom_command(
TARGET qcpp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/include/external/c.dll" "${CMAKE_BINARY_DIR}"
COMMAND_EXPAND_LISTS
)
endif()
See list of CMake variables.
Note the "qcpp" in the preceding command. This is the project name and should match this line at the start:
project ("qcpp")
Appendix A - Testing
To verify, if you generate a Visual Studio Project using mkdir x && cd x && cmake .., you can see that CMake has added a post-build step to the solution config:
As of CMake 3.21+, the $<TARGET_RUNTIME_DLLS:tgt> generator expression can help copy dependent DLLs to the build tree. Quoting the documentation:
List of DLLs that the target depends on at runtime. This is determined by the locations of all the SHARED and MODULE targets in the target's transitive dependencies. Using this generator expression on targets other than executables, SHARED libraries, and MODULE libraries is an error. On non-DLL platforms, it evaluates to an empty string.
This generator expression can be used to copy all of the DLLs that a target depends on into its output directory in a POST_BUILD custom command.
Docs link: https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_RUNTIME_DLLS
An example of how to use this (adapted from the docs) follows:
find_package(foo REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE foo::foo)
if (WIN32)
add_custom_command(
TARGET main POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_RUNTIME_DLLS:main> $<TARGET_FILE_DIR:main>
COMMAND_EXPAND_LISTS
)
endif ()
The if (WIN32) check ensures that $<TARGET_RUNTIME_DLLS:main> won't be empty, which would cause the command to fail (rather than do nothing). COMMAND_EXPAND_LISTS makes sure that the semicolon-delimited list returned by $<TARGET_RUNTIME_DLLS:main> will be split into multiple arguments, rather than passed as a single argument with (escaped) semicolons in it.
Note also that UNKNOWN libraries will be ignored by this generator expression. These are common when using the built-in Find modules, rather than using a library's first-party CMake config-mode package. In these cases, you will have to manually inspect the module variables to find the library paths and add custom commands for each one yourself.
For Qt specifically, I would expect the newer CMake integration in Qt6 to "just work", though I haven't tested it. It might also work in Qt5, but again I haven't tested it.

How to get the actual qmake build destination within the project file?

I'm trying to determine the build directory in the qmake project file, but failed in all my experiments so far :-(
At first I had a very plain foo.pro as QtCreator generates it for a plain Qt5 gui app with a few source files. Then I added an EXTRA_BINFILES list with some data files. They must be copied in the same directory as the executable foo. Without the copy stuff, it looks like this:
QT += core gui xml webkitwidgets widgets
TARGET = foo
TEMPLATE = app
EXTRA_BINFILES += \
foobar.png \
baz.png
SOURCES += \
main.cpp \
# ...
HEADERS += \
# ...
FORMS += \
# ...
When I build that, I get the foo executable (or foo.exe if you want). Mostly straightforward so far. Now I want to copy the EXTRA_BINFILES alongside this executable. The open question is how to get the destination directory. My best idea so far is adding this:
for(FILE, EXTRA_BINFILES) {
QMAKE_POST_LINK += $$quote($${QMAKE_COPY} $$shell_path($${PWD}/$${FILE}) $$shell_path($${OUT_PWD})$$escape_expand(\n\t))
}
This uses the OUT_PWD variable, which automatically points to where the Makefile is generated. This is nice for some scenarios. However, I have to deal with two different scenarios:
Directly compiling from within QtCreator with mostly out-of-the-box build configs. It creates a new build-foo-desktop-release directory, creates the Makefile there and builds the executable there. In this scenario, everything works fine.
Building from command-line with qmake -makefile /my/projects/foo/foo.pro and make in a temporary fresh build directory. This way it creates the Makefile in directly in that build directory but compiles the executable into a release subdirectory`. This obviously breaks my copy code.
For some reasons, it is not an option to get rid of one of those scenarios. I have to deal with both of them within the same project file. It is also not an option to make very technical/tricky things in the project file. It has to remain mostly as 'straightforward' as it is. Overriding some of qmake's own variables in the qmake command-line call is also probably not an option. This is because of the broader context, which is too extensive to explain here.
Is there an option to get the correct path in both scenarios? Something like OUT_PWD but for the executable itself?
Unfortunately, DESTDIR is empty (and as mentioned, it is not an option to forcefully set it). DESTDIR_TARGET is empty as well (otherwise I could combine it with dirname, which would be barely non-tricky enough).
Any hints?
sub_dir = $$_PRO_FILE_PWD_
sub_dir ~= s,^$$re_escape($$PWD),,
PROJECT_BUILD_TREE = $$clean_path($$OUT_PWD)
PROJECT_BUILD_TREE ~= s,$$re_escape($$sub_dir)$,,

What the right variable to use here, that represents the TARGET field in the .pro file

I would like to add a custom command, that will work on the generated binary file (The target field in *.pro file),
But what should I use here, in the Command arguments
I'm afraid this is not possible. QtCreator only handles source and build directory. The QtCreator documentation says:
The following Qt Creator variables are available:
%{buildDir}
%{sourceDir}
Note that the target even doesn't have to be in the build directory. The build directory is where qmake is ran, typically resulting in the target being put there, because in the .pro file one typically specifies TARGET = projectName.
Further note that the QtCreator build steps configuration only works within QtCreator. This should not be used when your custom build steps are needed for other people working without QtCreator (they should only run qmake and make to build your application).
This being said and assuming that you want to define a post-build step, you should look for a solution to define such in the .pro file (by using the $${TARGET} variable) so that qmake will put your buildstep into the Makefile after the linking step.
If you want to execute a command after linkage, let's say call a custom script (batch script on Windows, otherwise a bourne shell script) with the TARGET as an argument, add the following to your .pro file:
win32 {
poststep.commands = #myScript.bat $${TARGET}
}
!win32 {
poststep.commands = #./myScript.sh $${TARGET}
}
QMAKE_EXTRA_TARGETS += poststep

How can I set where a Qt app finds a Qt module?

I would like to include libQtGui.so.4 libQtNetwork.so.4 and libQtCore.so.4 in the same directory as where my app resides. How would I make Qt understand this? y purpose is to have a standalone app that uses shared libraries
Setting the LD_LIBRARY_PATH environment variable is one option. For example:
export LD_LIBRARY_PATH=/path/to/dir/with/libs:$LD_LIBRARY_PATH
Another option is to set the RPATH of your Qt application during linking. Setting the RPATH to the value "$ORIGIN" will cause the dynamic linker to look in the same directory as your Qt application at runtime. For example, if using qmake, add the following snippet to your project file:
unix:!mac{
QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN
QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN/lib
QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN/libs
QMAKE_RPATH=
}
This will set the RPATH to "$ORIGIN:$ORIGIN/lib:$ORIGIN/libs", meaning that the dynamic linker will first look in the location of your Qt application, then in a lib subdirectory at its location, then in a libs subdirectory at its location, and finally in any system defined locations.
UNIX / Linux is going to look in LD_LIBRARY_PATH (if set) first before looking in the system standard libs. So if you set that, you can indeed override. Just like setting the PATH on Windows. Same effect. The ordering matters.
You can add ./ or . to LD_LIBRARY_PATH as well.
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
LD_LIBRARY_PATH and QMAKE_RPATH never worked for me. Instead, I set QMAKE_RPATHDIR in my .pro file. For example after having built and installed (make install) Qt, it has been placed in /usr/local/Trolltech/Qt-4.8.5/lib/. I then write the following in my .pro file:
QMAKE_RPATHDIR += /usr/local/Trolltech/Qt-4.8.5/lib/
Note 1: Relative paths seem not to work. Prefer absolute paths.
Note 2: When you then make, you can see that the following option is given to the linker: -Wl,-rpath,/usr/local/Trolltech/Qt-4.8.5/lib/
Note 3: To be sure that the binary links dynamically to the correct library, you can display the version of Qt at runtime delivered by qVersion().

Resources