rbaleksandar rbaleksandar - 3 months ago 17
C++ Question

QMake finds library in designated folder however linker doesn't

The state of the project

I'm trying to integrate the

QVTKWidget
in a
qmake
Qt 5.7 project and thus provide my application with some nice support for 3D surface plot charts (the 2D chart feature is currently handled by
Qwt
but I might switch to VTK's 2D charts module if I find it easy enough to integrate).

What has been done so far

I have successfully built the VTK toolkit in both debug and release version (available respectively at
C:\VTK
and
C:\VTKDebug\
. In addition to that I have also already successfully managed to place some VTK content in my
QWidget
by manually specifying which DLL libraries are to be included.

The problem

The issue mentioned in the title comes when I use
qmake
's function
files()
to retrieve ALL shared libraries from
C:\VTK\bin
or
C:\VTKDebug\bin
depending on the build type of the project. The reason for that is that depending on what I include in my application I might need to manually specify 3-4 or maybe 20-30 VTK libraries. For creating a prototype this is quite the manual labour and I would like to skip that part and deal with it later on AFTER I evaluate whether VTK suits my needs or not. The provided
cmake
modules in VTK offer this functionality so you can simply link against
${VTK_LIBRARIES}
if you want to. Currently I don't know of out-of-the-box support for
qmake
projects.

Here is my
pro
file:

QT += core gui
CONFIG += c++11

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Demo
TEMPLATE = app

RESOURCES = resources.qrc

# Variables will store the path to the root directory of each library using the information provided by the respective system environment variables.
MHCP_API = ""
QWT_API = ""
VTK_API = ""

CONFIG(debug, debug|release) {
message(Application will be built in DEBUG mode)
MHCP_API = $$(MCHP_HMI_API_PATH) # TODO Compile the library for debug releases (requires Visual C++)
QWT_API = $$(QWT_PATH) # QWT on my system is compiled in debug_and_release mode which means that both versios of the library are located at the same location (different names though!)
VTK_API = $$(VTK_PATH_DEBUG)
LIBS += -L$$QWT_API\\lib -lqwtd \
-L$$MHCP_API\\lib -lmchp_hmid
}
else {
message(Application will be built in RELEASE mode)
MHCP_API = $$(MCHP_HMI_API_PATH)
QWT_API = $$(QWT_PATH)
VTK_API = $$(VTK_PATH)
LIBS += -L$$QWT_API\\lib -lqwt \
-L$$MHCP_API\\lib -lmchp_hmi
}

message(-----------------------------------------------------------------------------------------)

isEmpty(MHCP_API) { error(MHCP_API variable is empty. Please make sure that MCHP_HMI_API_PATH system variable is set and that you have both reading and writing access to it) }
else { message(MHCP_API root folder set to $$MHCP_API) }

isEmpty(QWT_API) { error(QWT_API variable is empty. Please make sure that QWT system variable is set and that you have reading access to it) }
else { message(QWT_API root folder set to $$QWT_API) }

isEmpty(VTK_API) { error(VTK_API variable is empty. Please make sure that VTK system variable is set and that you have reading access to it) }
else { message(VTK_API root folder set to $$VTK_API) }

message(-----------------------------------------------------------------------------------------)

DEFINES += "VTK_DEFINITIONS"

#LIBS += -L$$VTK_API\\lib -lvtkRenderingCore-7.0 -lvtkRenderingOpenGL2-7.0 -lvtkCommonExecutionModel-7.0 -lvtkCommonCore-7.0 -lvtkViewsQt-7.0 -lvtkGUISupportQt-7.0 -lvtkRenderingQt-7.0 -lvtkChartsCore-7.0 -lvtkFiltersSources-7.0 #-lvtkRenderingOpenGL2-7.0 #FilterSources is required for the SphereSource example

LIBS += -L$$VTK_API\\bin
VTK_API_SHARED_LIB_FILES = $$files($$VTK_API\\bin\\*.dll)
for(FILE, VTK_API_SHARED_LIB_FILES) {
BASENAME = $$basename(FILE)
NO_PREFIX_NAME = $$replace(BASENAME, lib,)
VTK_LIB = $$replace(NO_PREFIX_NAME, .dll,)
message(Found "$$VTK_LIB")
LIBS += -l$$VTK_LIB
}

message(-----------------------------------------------------------------------------------------)
message(Appending $$LIBS)

INCLUDEPATH += $$MHCP_API\\include \
$$QWT_API\\include \
$$VTK_API\\include\\vtk-7.0


HEADERS += device_api.h \
device_api_dynamic.h \
demo.h \
device.h \
misc.h \
device_plot.h

SOURCES += main.cpp\
demo.cpp \
device.cpp \
device_plot.cpp

FORMS += demo.ui

RESOURCES += \
resources.qrc


When I execute
qmake
I see the following message in my Qt Creator (using Qt 5.7 SDK with MinGW 5.3 all 32bit on a 64bit Windows 10 system):

Project MESSAGE: Application will be built in DEBUG mode
Project MESSAGE: -----------------------------------------------------------------------------------------
Project MESSAGE: MHCP_API root folder set to C:\Program Files (x86)\Device\api
Project MESSAGE: QWT_API root folder set to C:\Qwt-6.1.3
Project MESSAGE: VTK_API root folder set to C:\VTKDebug
Project MESSAGE: -----------------------------------------------------------------------------------------
Project MESSAGE: Found vtkalg-7.0
Project MESSAGE: Found vtkChartsCore-7.0
Project MESSAGE: Found vtkCommonColor-7.0
Project MESSAGE: Found vtkCommonComputationalGeometry-7.0
Project MESSAGE: Found vtkCommonCore-7.0
Project MESSAGE: Found vtkCommonDataModel-7.0
Project MESSAGE: Found vtkCommonExecutionModel-7.0
Project MESSAGE: Found vtkCommonMath-7.0
Project MESSAGE: Found vtkCommonMisc-7.0
Project MESSAGE: Found vtkCommonSystem-7.0
Project MESSAGE: Found vtkCommonTransforms-7.0
Project MESSAGE: Found vtkDICOMParser-7.0
Project MESSAGE: Found vtkDomainsChemistry-7.0
Project MESSAGE: Found vtkDomainsChemistryOpenGL2-7.0
Project MESSAGE: Found vtkexoIIc-7.0
Project MESSAGE: Found vtkexpat-7.0
Project MESSAGE: Found vtkFiltersAMR-7.0
Project MESSAGE: Found vtkFiltersCore-7.0
Project MESSAGE: Found vtkFiltersExtraction-7.0
Project MESSAGE: Found vtkFiltersFlowPaths-7.0
Project MESSAGE: Found vtkFiltersGeneral-7.0
Project MESSAGE: Found vtkFiltersGeneric-7.0
Project MESSAGE: Found vtkFiltersGeometry-7.0
Project MESSAGE: Found vtkFiltersHybrid-7.0
Project MESSAGE: Found vtkFiltersHyperTree-7.0
Project MESSAGE: Found vtkFiltersImaging-7.0
Project MESSAGE: Found vtkFiltersModeling-7.0
Project MESSAGE: Found vtkFiltersParallel-7.0
Project MESSAGE: Found vtkFiltersParallelImaging-7.0
Project MESSAGE: Found vtkFiltersProgrammable-7.0
Project MESSAGE: Found vtkFiltersSelection-7.0
Project MESSAGE: Found vtkFiltersSMP-7.0
Project MESSAGE: Found vtkFiltersSources-7.0
Project MESSAGE: Found vtkFiltersStatistics-7.0
Project MESSAGE: Found vtkFiltersTexture-7.0
Project MESSAGE: Found vtkFiltersVerdict-7.0
Project MESSAGE: Found vtkfreetype-7.0
Project MESSAGE: Found vtkGeovisCore-7.0
Project MESSAGE: Found vtkglew-7.0
Project MESSAGE: Found vtkGUISupportQt-7.0
Project MESSAGE: Found vtkGUISupportQtSQL-7.0
Project MESSAGE: Found vtkImagingColor-7.0
Project MESSAGE: Found vtkImagingCore-7.0
Project MESSAGE: Found vtkImagingFourier-7.0
Project MESSAGE: Found vtkImagingGeneral-7.0
Project MESSAGE: Found vtkImagingHybrid-7.0
Project MESSAGE: Found vtkImagingMath-7.0
Project MESSAGE: Found vtkImagingMorphological-7.0
Project MESSAGE: Found vtkImagingSources-7.0
Project MESSAGE: Found vtkImagingStatistics-7.0
Project MESSAGE: Found vtkImagingStencil-7.0
Project MESSAGE: Found vtkInfovisCore-7.0
Project MESSAGE: Found vtkInfovisLayout-7.0
Project MESSAGE: Found vtkInteractionImage-7.0
Project MESSAGE: Found vtkInteractionStyle-7.0
Project MESSAGE: Found vtkInteractionWidgets-7.0
Project MESSAGE: Found vtkIOAMR-7.0
Project MESSAGE: Found vtkIOCore-7.0
Project MESSAGE: Found vtkIOEnSight-7.0
Project MESSAGE: Found vtkIOExodus-7.0
Project MESSAGE: Found vtkIOExport-7.0
Project MESSAGE: Found vtkIOGeometry-7.0
Project MESSAGE: Found vtkIOImage-7.0
Project MESSAGE: Found vtkIOImport-7.0
Project MESSAGE: Found vtkIOInfovis-7.0
Project MESSAGE: Found vtkIOLegacy-7.0
Project MESSAGE: Found vtkIOLSDyna-7.0
Project MESSAGE: Found vtkIOMINC-7.0
Project MESSAGE: Found vtkIOMovie-7.0
Project MESSAGE: Found vtkIONetCDF-7.0
Project MESSAGE: Found vtkIOParallel-7.0
Project MESSAGE: Found vtkIOParallelXML-7.0
Project MESSAGE: Found vtkIOPLY-7.0
Project MESSAGE: Found vtkIOSQL-7.0
Project MESSAGE: Found vtkIOVideo-7.0
Project MESSAGE: Found vtkIOXML-7.0
Project MESSAGE: Found vtkIOXMLParser-7.0
Project MESSAGE: Found vtkjpeg-7.0
Project MESSAGE: Found vtkjsoncpp-7.0
Project MESSAGE: Found vtkxml2-7.0
Project MESSAGE: Found vtkmetaio-7.0
Project MESSAGE: Found vtkNetCDF-7.0
Project MESSAGE: Found vtkNetCDF_cxx-7.0
Project MESSAGE: Found vtkoggtheora-7.0
Project MESSAGE: Found vtkParallelCore-7.0
Project MESSAGE: Found vtkpng-7.0
Project MESSAGE: Found vtkproj4-7.0
Project MESSAGE: Found vtkRenderingAnnotation-7.0
Project MESSAGE: Found vtkRenderingContext2D-7.0
Project MESSAGE: Found vtkRenderingContextOpenGL2-7.0
Project MESSAGE: Found vtkRenderingCore-7.0
Project MESSAGE: Found vtkRenderingFreeType-7.0
Project MESSAGE: Found vtkRenderingImage-7.0
Project MESSAGE: Found vtkRenderingLabel-7.0
Project MESSAGE: Found vtkRenderingLOD-7.0
Project MESSAGE: Found vtkRenderingOpenGL2-7.0
Project MESSAGE: Found vtkRenderingQt-7.0
Project MESSAGE: Found vtkRenderingVolume-7.0
Project MESSAGE: Found vtkRenderingVolumeOpenGL2-7.0
Project MESSAGE: Found vtksys-7.0
Project MESSAGE: Found vtkTestingGenericBridge-7.0
Project MESSAGE: Found vtkTestingIOSQL-7.0
Project MESSAGE: Found vtkTestingRendering-7.0
Project MESSAGE: Found vtktiff-7.0
Project MESSAGE: Found vtkverdict-7.0
Project MESSAGE: Found vtkViewsContext2D-7.0
Project MESSAGE: Found vtkViewsCore-7.0
Project MESSAGE: Found vtkViewsInfovis-7.0
Project MESSAGE: Found vtkViewsQt-7.0
Project MESSAGE: Found vtkz-7.0
Project MESSAGE: Found vtkhdf5-7.0
Project MESSAGE: Found vtkhdf5_hl-7.0
Project MESSAGE: -----------------------------------------------------------------------------------------
Project MESSAGE: Appending -LC:\Qwt-6.1.3\lib -lqwtd -LC:\Program Files (x86)\Device\api\lib -ldevice_apid -LC:\VTKDebug\bin -lvtkalg-7.0 -lvtkChartsCore-7.0 -lvtkCommonColor-7.0 -lvtkCommonComputationalGeometry-7.0 -lvtkCommonCore-7.0 -lvtkCommonDataModel-7.0 -lvtkCommonExecutionModel-7.0 -lvtkCommonMath-7.0 -lvtkCommonMisc-7.0 -lvtkCommonSystem-7.0 -lvtkCommonTransforms-7.0 -lvtkDICOMParser-7.0 -lvtkDomainsChemistry-7.0 -lvtkDomainsChemistryOpenGL2-7.0 -lvtkexoIIc-7.0 -lvtkexpat-7.0 -lvtkFiltersAMR-7.0 -lvtkFiltersCore-7.0 -lvtkFiltersExtraction-7.0 -lvtkFiltersFlowPaths-7.0 -lvtkFiltersGeneral-7.0 -lvtkFiltersGeneric-7.0 -lvtkFiltersGeometry-7.0 -lvtkFiltersHybrid-7.0 -lvtkFiltersHyperTree-7.0 -lvtkFiltersImaging-7.0 -lvtkFiltersModeling-7.0 -lvtkFiltersParallel-7.0 -lvtkFiltersParallelImaging-7.0 -lvtkFiltersProgrammable-7.0 -lvtkFiltersSelection-7.0 -lvtkFiltersSMP-7.0 -lvtkFiltersSources-7.0 -lvtkFiltersStatistics-7.0 -lvtkFiltersTexture-7.0 -lvtkFiltersVerdict-7.0 -lvtkfreetype-7.0 -lvtkGeovisCore-7.0 -lvtkglew-7.0 -lvtkGUISupportQt-7.0 -lvtkGUISupportQtSQL-7.0 -lvtkImagingColor-7.0 -lvtkImagingCore-7.0 -lvtkImagingFourier-7.0 -lvtkImagingGeneral-7.0 -lvtkImagingHybrid-7.0 -lvtkImagingMath-7.0 -lvtkImagingMorphological-7.0 -lvtkImagingSources-7.0 -lvtkImagingStatistics-7.0 -lvtkImagingStencil-7.0 -lvtkInfovisCore-7.0 -lvtkInfovisLayout-7.0 -lvtkInteractionImage-7.0 -lvtkInteractionStyle-7.0 -lvtkInteractionWidgets-7.0 -lvtkIOAMR-7.0 -lvtkIOCore-7.0 -lvtkIOEnSight-7.0 -lvtkIOExodus-7.0 -lvtkIOExport-7.0 -lvtkIOGeometry-7.0 -lvtkIOImage-7.0 -lvtkIOImport-7.0 -lvtkIOInfovis-7.0 -lvtkIOLegacy-7.0 -lvtkIOLSDyna-7.0 -lvtkIOMINC-7.0 -lvtkIOMovie-7.0 -lvtkIONetCDF-7.0 -lvtkIOParallel-7.0 -lvtkIOParallelXML-7.0 -lvtkIOPLY-7.0 -lvtkIOSQL-7.0 -lvtkIOVideo-7.0 -lvtkIOXML-7.0 -lvtkIOXMLParser-7.0 -lvtkjpeg-7.0 -lvtkjsoncpp-7.0 -lvtkxml2-7.0 -lvtkmetaio-7.0 -lvtkNetCDF-7.0 -lvtkNetCDF_cxx-7.0 -lvtkoggtheora-7.0 -lvtkParallelCore-7.0 -lvtkpng-7.0 -lvtkproj4-7.0 -lvtkRenderingAnnotation-7.0 -lvtkRenderingContext2D-7.0 -lvtkRenderingContextOpenGL2-7.0 -lvtkRenderingCore-7.0 -lvtkRenderingFreeType-7.0 -lvtkRenderingImage-7.0 -lvtkRenderingLabel-7.0 -lvtkRenderingLOD-7.0 -lvtkRenderingOpenGL2-7.0 -lvtkRenderingQt-7.0 -lvtkRenderingVolume-7.0 -lvtkRenderingVolumeOpenGL2-7.0 -lvtksys-7.0 -lvtkTestingGenericBridge-7.0 -lvtkTestingIOSQL-7.0 -lvtkTestingRendering-7.0 -lvtktiff-7.0 -lvtkverdict-7.0 -lvtkViewsContext2D-7.0 -lvtkViewsCore-7.0 -lvtkViewsInfovis-7.0 -lvtkViewsQt-7.0 -lvtkz-7.0 -lvtkhdf5-7.0 -lvtkhdf5_hl-7.0


So far, so good. As mentioned things fail at the linking stage namely I get the following errors

cannot find -lvtkalg-7.0
cannot find -lvtkxml2-7.0
cannot find -lvtkz-7.0


even though I can clearly see them in the output from
qmake
:

Project MESSAGE: Appending -LC:\Qwt-6.1.3\lib
-lqwtd -LC:\Program Files (x86)\Device\api\lib -ldevice_apid
-LC:\VTKDebug\bin -lvtkalg-7.0 ... -lvtkxml2-7.0 .. -lvtkz-7.0


I doubt that this actually has anything to do with VTK per se but instead with how my project is structured.




EDIT: I have found out WHY but don't know how to fix it. Basically the mentioned files have the naming convension
libvtkNAMElib-7.0
. So when I do
$$replace(BASENAME, lib,)
both
lib
substrings
are removed which leaves me with
vtkNAME-7.0
which doesn't exists. I discovered this while looking at the mentioned DLL files in Explorer and noticed this nuisance. I'm now looking for a way to replace only the first occurrence of substring.

PS: I'm pretty upset how the VTK toolkit is managed in terms of file structure. Naming conventions for library files doesn't seem to matter that much to the developers (no offence intended with this comment). :-/

Answer

Okay, problem solved. As I've mentioned in the EDIT section at the end of my question the problem is in the weird naming conventions the VTK developers have chosen and the fact that three (at least with my build where not all features are enabled) of those libraries are not conform to the rest.

The libraries which cause the problem are

libvtkalglib-7.0
libvtkxml2lib-7.0
libvtkzlib-7.0

while the rest follow the naming schema

libvtkXXX-7.0

A colleague of mine noticed the patter that ALL files start with libvtk* and not just lib. If edit my regex pattern for replace() to

NO_PREFIX_NAME = $$replace(BASENAME, libvtk, vtk)

I get the desired result since only lib also covers *lib* while libvtk covers *libvtk* which means that *lib-7.0 doesn't fall into the match.

Here is the final DLL file grabbing loop for those who want it:

LIBS    += -L$$VTK_API\\bin
VTK_API_SHARED_LIB_FILES = $$files($$VTK_API\\bin\\*.dll)
for(FILE, VTK_API_SHARED_LIB_FILES) {
    BASENAME = $$basename(FILE)
    NO_PREFIX_NAME = $$replace(BASENAME, libvtk, vtk) # 3 of the VTK libs have the naming convention libvtkXXXlib-7.0 instead of libvtkXXX-7.0
    VTK_LIB = $$replace(NO_PREFIX_NAME, .dll,)
    message(Found "$$VTK_LIB")
    LIBS += -l$$VTK_LIB
}
Comments