Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Building static library doesn't merge the static libraries depends with it on Ubuntu



  • hi all ,
    I am building a SDK as a static library and this SDK depends on other libraries.
    Now when I build the SDK its size is much smaller than the depends libs and when I test it with another program it results in a linking error because it can't find the depends functions which mean it doesn't add the libs to the SDK.
    What I am doing wrong ?
    Thanks in advance.

    .pro of the depends :

    #-------------------------------------------------
    #
    # Project created by QtCreator 2018-08-14T12:57:54
    #
    #-------------------------------------------------
    
    QT       -= gui
    QT += network concurrent xml xmlpatterns
    
    CONFIG += c++11
    
    TARGET = EnablerMockup
    TEMPLATE = lib
    CONFIG += staticlib
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which has been marked as deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
            nuzi.cpp
    
    HEADERS += \
            nuzi.h
    
    unix {
        target.path = /usr/lib
        INSTALLS += target
    }
    unix:!macx: LIBS += -L$$PWD/../../OpenSSL/linux/x64/lib/ -lcrypto
    
    INCLUDEPATH += $$PWD/../../OpenSSL/linux/x64/include
    DEPENDPATH += $$PWD/../../OpenSSL/linux/x64/include
    
    unix:!macx: PRE_TARGETDEPS += $$PWD/../../OpenSSL/linux/x64/lib/libcrypto.a
    
    unix:!macx: LIBS += -L$$PWD/../../OpenSSL/linux/x64/lib/ -lssl
    
    INCLUDEPATH += $$PWD/../../OpenSSL/linux/x64/include
    DEPENDPATH += $$PWD/../../OpenSSL/linux/x64/include
    
    unix:!macx: PRE_TARGETDEPS += $$PWD/../../OpenSSL/linux/x64/lib/libssl.a
    
    

    as you can see this library depend on openssl static libs which of size > 5mb and 700kb while the lib generated of this depend is 33kb ?!!!

    Qt SignalR :
    SignalR client using Qt and c++

    CMake files of the SDK :

    #Cid-Sdk-qt Target
    	
    	
    	#Config Dependance Paths Based on Processor Architecture and Operation System.	
    	if (CMAKE_SYSTEM_PROCESSOR MATCHES "(amd64)|(AMD64)|(x86_64)|(x64)")
    		#set(OS_ARCH "x64" )
    		SET_PROPERTY(GLOBAL PROPERTY OS_ARCH_GLOBAL "x64")
    	elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)")
    		#set(OS_ARCH "x86" CACHE INTERNAL "")
    		SET_PROPERTY(GLOBAL PROPERTY OS_ARCH_GLOBAL "x86")
    	endif ()
    	
    	set (LIBS "")
    	
    	if (CMAKE_SYSTEM_NAME MATCHES "(windows)|(WINDOWS)|(Windows)")
    
    		#set(OS_NAME "win" CACHE INTERNAL  "")
    		SET_PROPERTY(GLOBAL PROPERTY OS_NAME_GLOBAL "win")
    		#set(LIB_STATIC_FORMAT "lib"  CACHE INTERNAL  "")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_STATIC_FORMAT_GLOBAL "lib")
    		#set(LIB_DYNAMIC_FORMAT "lib" CACHE INTERNAL  "")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_DYNAMIC_FORMAT_GLOBAL "lib")
    		#set(LIB_WORD "" CACHE INTERNAL  "")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_WORD_GLOBAL "")
    		
    		#Get OS_ARCH, OS_NAME, LIB_WORD,LIB_STATIC_FORMAT,LIB_DYNAMIC_FORMAT and Values 
    		GET_PROPERTY(OS_ARCH GLOBAL PROPERTY OS_ARCH_GLOBAL)
    		GET_PROPERTY(OS_NAME GLOBAL PROPERTY OS_NAME_GLOBAL)
    		GET_PROPERTY(LIB_STATIC_FORMAT GLOBAL PROPERTY LIB_STATIC_FORMAT_GLOBAL)
    		GET_PROPERTY(LIB_DYNAMIC_FORMAT GLOBAL PROPERTY LIB_DYNAMIC_FORMAT_GLOBAL)
    		GET_PROPERTY(LIB_WORD GLOBAL PROPERTY LIB_WORD_GLOBAL)
    
    		#We need it for openssl
    		set (LIBS crypt32.lib)
    
    
    		
    	elseif (CMAKE_SYSTEM_NAME MATCHES "(Darwin)|(darwin)|(Macos)|(macos)")
    
    		SET_PROPERTY(GLOBAL PROPERTY OS_NAME_GLOBAL "mac")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_STATIC_FORMAT_GLOBAL "a")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_DYNAMIC_FORMAT_GLOBAL "dylib")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_WORD_GLOBAL "lib")
    		
    		#Get OS_ARCH, OS_NAME, LIB_WORD,LIB_STATIC_FORMAT,LIB_DYNAMIC_FORMAT and  Values.
    		GET_PROPERTY(OS_ARCH GLOBAL PROPERTY OS_ARCH_GLOBAL)
    		GET_PROPERTY(OS_NAME GLOBAL PROPERTY OS_NAME_GLOBAL)
    		GET_PROPERTY(LIB_STATIC_FORMAT GLOBAL PROPERTY LIB_STATIC_FORMAT_GLOBAL)
    		GET_PROPERTY(LIB_DYNAMIC_FORMAT GLOBAL PROPERTY LIB_DYNAMIC_FORMAT_GLOBAL)
    		GET_PROPERTY(LIB_WORD GLOBAL PROPERTY LIB_WORD_GLOBAL)
    		
    		
    	elseif (CMAKE_SYSTEM_NAME MATCHES "(Linux)|(linux)|(Unix)|(unix)")
    
    		SET_PROPERTY(GLOBAL PROPERTY OS_NAME_GLOBAL "linux")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_STATIC_FORMAT_GLOBAL "a")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_DYNAMIC_FORMAT_GLOBAL "so")
    		SET_PROPERTY(GLOBAL PROPERTY LIB_WORD_GLOBAL "lib")
    		
    		#Get OS_ARCH, OS_NAME, LIB_WORD,LIB_STATIC_FORMAT,LIB_DYNAMIC_FORMAT and  Values.
    		GET_PROPERTY(OS_ARCH GLOBAL PROPERTY OS_ARCH_GLOBAL)
    		GET_PROPERTY(OS_NAME GLOBAL PROPERTY OS_NAME_GLOBAL)
    		GET_PROPERTY(LIB_STATIC_FORMAT GLOBAL PROPERTY LIB_STATIC_FORMAT_GLOBAL)
    		GET_PROPERTY(LIB_DYNAMIC_FORMAT GLOBAL PROPERTY LIB_DYNAMIC_FORMAT_GLOBAL)
    		GET_PROPERTY(LIB_WORD GLOBAL PROPERTY LIB_WORD_GLOBAL)
    		
    		
    	endif ()
    
    
    		#Get Openssl from CID Dependencies
    		set(OPENSSL_CRYPTO_LIBRARY "${PROJECT_SOURCE_DIR}/../OpenSSL/${OS_NAME}/${OS_ARCH}/lib/libcrypto.${LIB_STATIC_FORMAT}")
    		set(OPENSSL_SSL_LIBRARY    "${PROJECT_SOURCE_DIR}/../OpenSSL/${OS_NAME}/${OS_ARCH}/lib/libssl.${LIB_STATIC_FORMAT}")
    		set(OPENSSL_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../OpenSSL/${OS_NAME}/${OS_ARCH}/include")
    
    
    	add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Nl.Aet.Cid.Client.Sdk)
    	add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Nl.Aet.Cid.Client.Sdk.Core)
    	add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Nl.Aet.Cid.Client.Sdk.Desktop)
    	add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Nl.Aet.Cid.Client.Sdk.Web)
    	add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Nl.Aet.Cid.Sdk.Desktop.Gateway)
    	add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Nl.Aet.Cid.Sdk.Web.Gateway)
    
    	#Add Lib
            add_library(cid-sdk-qt STATIC
    			$<TARGET_OBJECTS:Nl.Aet.Cid.Client.Sdk>
    			$<TARGET_OBJECTS:Nl.Aet.Cid.Client.Sdk.Core>
    			$<TARGET_OBJECTS:Nl.Aet.Cid.Client.Sdk.Desktop>
    			$<TARGET_OBJECTS:Nl.Aet.Cid.Client.Sdk.Web>
    			$<TARGET_OBJECTS:Nl.Aet.Cid.Sdk.Desktop.Gateway>
    			$<TARGET_OBJECTS:Nl.Aet.Cid.Sdk.Web.Gateway>
    			dummy.cpp
    			)
    
    	target_compile_options(cid-sdk-qt PRIVATE ${COMPILE_OPTIONS})
    	target_compile_definitions(cid-sdk-qt PUBLIC CID_SDK_LIBRARY)
    
    	#Install the library to CID_Debug DIR
    	install(TARGETS cid-sdk-qt DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/tests/Tester/CID_Debug)
    
    #	install(TARGETS cid-sdk-qt
    #		RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/tests/Tester/CID_Debug
    #		LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/tests/Tester/CID_Debug)
    
    
    	message("CID-SDK Project")
    	message("OS : " ${OS_NAME})
    	message("OS Architecture : " ${OS_ARCH})
    	message("OpenSSL Path : " ${OPENSSL_INCLUDE_DIR})
    	message("OpenSSL Libcrypto Path : " ${OPENSSL_CRYPTO_LIBRARY})
    	message("OpenSSL Libssl Path : " ${OPENSSL_SSL_LIBRARY})
    
    	#Linking between Targets to create one library
    	target_link_libraries(cid-sdk-qt PUBLIC
    			Nl.Aet.Cid.Client.Sdk
    			Nl.Aet.Cid.Client.Sdk.Core
    			Nl.Aet.Cid.Client.Sdk.Desktop
    			Nl.Aet.Cid.Client.Sdk.Web
    			Nl.Aet.Cid.Sdk.Desktop.Gateway
    			Nl.Aet.Cid.Sdk.Web.Gateway)
    
    

    There is 5 cmake files to other modules of the SDK but it will get realy big if I post it here so I will stop at this.


  • Lifetime Qt Champion

    Hi,

    Do you have the development packages of these libraries installed on your system ?



  • I just build them from sources and add the libs to the SDK cmakelist.txt file.


  • Lifetime Qt Champion

    And you only build them statically ?



  • IIRC, on linux, when you're linking statically, only used symbols from the static library ends up in the final binary. Then, if you're linking a static lib A in the B library, which you're ending up using in a executable, you'll be missing each symbol defined in lib A which is not used in lib B. This also appears if you're linking several static libraries, let's say A, B and C, in an executable, with B and C using A, then you'll miss symbols defined in A but not used neither in B nor in C.



  • If you're looking to create "one library and in the darkness bind them" ;) - you want to archive the dependent libraries into yours.

    Unlike with shared libraries, a static library is a loose collection of object files - this means that when your library code referencing other libraries - whoever uses your library is expected to have those other libraries as well.

    On *nix systems you can have accomplish this with a 'post link' (even though there's no actual linking) via something like:

    QMAKE_POST_LINK += libtool -static -o $$DESTDIR/myaggregatedsdk.a $$DESTDIR/mysdk.a $$PWD/../dependencies/libs/libsomeotherlibrary.a $$[QT_INSTALL_LIBS]/libQt5Core.a 
    

    That made up example combines your sdk library, some other library, and just as an example of something a bit more advance - how to aggregate a Qt static library into your library (if you have build the static libraries.)

    On Windows using Visual Studio's nmake system - it's slightly different - you don't do it after you build, instead you pass some flags to nmake and it does it during the build process:

    QMAKE_LIBFLAGS += /OUT:$$TARGET "$$PWD/../dependencies/libs/somelibrary.lib" "$$[QT_INSTALL_LIBS]/Qt5Core.lib" "$$[QT_INSTALL_LIBS]/Qt5Network.lib"
    

    Be careful doing this type of thing though because you'll likely need to have many versions of your library available (especially on Windows.)

    There's a reason that this is an unusual request - and sometimes it's the right thing to do, but if you're not ABSOLUTELY certain you need to do this - then you should avoid it and go one of two ways.

    Either stick with providing your static library and listing the other libraries as dependencies that others must obtain in order to build - or build a shared library (which is quite often the best solution.)

    Sometimes, when building an SDK, you must support all forms though (which is why I had to do this myself once.)

    Hope this helps.


Log in to reply