[Development] Improving CMake support for static builds

Kyle Edwards kyle.edwards at kitware.com
Tue Oct 16 18:02:21 CEST 2018


On Fri, 2018-10-12 at 14:37 -0700, Thiago Macieira wrote:
> On Friday, 12 October 2018 11:32:10 PDT Jean-Michaël Celerier wrote:
> > 
> > > 
> > >  but there is no information for the
> > flags needed to link against system libraries (freetype, harfbuzz,
> > etc.)
> > 
> > it would be so nice to add them ! currently I have to use the
> > following
> > chthonic horror:
> > https://github.com/OSSIA/score/blob/master/base/app/StaticApp.cmake
> > 
> > I think that in Qt the pkg-config files are generated by a perl
> > script,
> > maybe the same could be used for static builds ?
> syncqt only generates the headers and the .pri files that qmake uses
> to find 
> the headers.
> 
> The pkg-config files and the libtool files are generated by qmake
> itself.
> 

I've done a lot of experimentation, and I've gotten my code to look
like this:

-------------------------------------------------------------

diff --git a/mkspecs/features/create_cmake.prf
b/mkspecs/features/create_cmake.prf
index 2ed708e..abab6ea 100644
--- a/mkspecs/features/create_cmake.prf
+++ b/mkspecs/features/create_cmake.prf
@@ -180,6 +180,8 @@ CMAKE_MKSPEC = $$[QMAKE_XSPEC]
 sorted_deps = $$sort_depends(QT.$${MODULE}.depends, QT.)
 mod_deps =
 lib_deps =
+mod_link_flags =
+mod_libs =
 aux_mod_deps =
 aux_lib_deps =
 # Until CMake 3.0 is the minimum requirement of Qt 5, we need to
filter
@@ -195,8 +197,19 @@ for (dep, sorted_deps) {
         aux_lib_deps += Qt5::$$cdep
     }
 }
+for (lib, QT.$${MODULE}_private.libraries) {
+    for (flag, QMAKE_LIBS_$$upper($${lib})) {
+        contains(flag, "^-l.*$") {
+            mod_libs *= $$str_member($$flag, 2, -1)
+        } else {
+            mod_link_flags *= flag
+        }
+    }
+}
 CMAKE_MODULE_DEPS = $$join(mod_deps, ";")
 CMAKE_QT5_MODULE_DEPS = $$join(lib_deps, ";")
+CMAKE_MODULE_LINK_FLAGS = $$join(mod_link_flags, ";")
+CMAKE_MODULE_LIBS = $$join(mod_libs, ";")
 CMAKE_INTERFACE_MODULE_DEPS = $$join(aux_mod_deps, ";")
 CMAKE_INTERFACE_QT5_MODULE_DEPS = $$join(aux_lib_deps, ";")
 
diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
index 3ed6dd5..444bf0f 100644
--- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
@@ -67,6 +67,16 @@
macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration
LIB_LOCATI
         # For backward compatibility with CMake < 2.8.12
         \"IMPORTED_LINK_INTERFACE_LIBRARIES_${Configuration}\"
\"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
     )
+!!IF !isEmpty(CMAKE_STATIC_TYPE)
+!!IF !isEmpty(CMAKE_MODULE_LINK_FLAGS)
+
+    if(CMAKE_VERSION VERSION_GREATER_EQUAL \"3.13\")
+        set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
+            \"INTERFACE_LINK_OPTIONS\"
\"${_Qt5$${CMAKE_MODULE_NAME}_LINK_FLAGS}\"
+        )
+    endif()
+!!ENDIF
+!!ENDIF
 
 !!IF !isEmpty(CMAKE_WINDOWS_BUILD)
 !!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
@@ -215,6 +225,26 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
 !!ENDIF
 
 !!IF !isEmpty(CMAKE_STATIC_TYPE)
+!!IF !isEmpty(CMAKE_MODULE_LINK_FLAGS)
+    set(_Qt5$${CMAKE_MODULE_NAME}_LINK_FLAGS
\"$${CMAKE_MODULE_LINK_FLAGS}\")
+
+!!ENDIF
+!!IF !isEmpty(CMAKE_MODULE_LIBS)
+    set(_Qt5$${CMAKE_MODULE_NAME}_LIBS \"$${CMAKE_MODULE_LIBS}\")
+
+    foreach(_l ${_Qt5$${CMAKE_MODULE_NAME}_LIBS})
+        find_library(_Qt5$${CMAKE_MODULE_NAME}_${_l}_lpath ${_l})
+        if(_Qt5$${CMAKE_MODULE_NAME}_${_l}_lpath)
+            set(_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES
+                ${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}
+                ${_Qt5$${CMAKE_MODULE_NAME}_${_l}_lpath}
+            )
+        else()
+            message(FATAL_ERROR \"Could not find -l${_l}\")
+        endif()
+    endforeach()
+
+!!ENDIF
     add_library(Qt5::$${CMAKE_MODULE_NAME} STATIC IMPORTED)
     set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX")
 !!ELSE

-------------------------------------------------------------

So anything that links against a static Qt module in CMake will inherit
all of the "libs" that the module depends on. However, the downstream
targets still aren't receiving crucial libraries like -lpthread, which
is still causing link errors. Looking through the qmake scripts, it
looks like "thread" is a "feature" rather than a "lib", and I'm not
sure what would be the best approach to include "features" in the CMake
script. Would someone who's more familiar with the workings of the
qmake scripts be able to assist me here?

Kyle



More information about the Development mailing list